@hyperdrive.bot/cli 1.0.13 → 1.0.17

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 (157) hide show
  1. package/README.md +4526 -780
  2. package/dist/commands/deploy.d.ts +18 -0
  3. package/dist/commands/deploy.js +239 -0
  4. package/dist/commands/deployment/create.js +10 -2
  5. package/dist/commands/domain/{switch.d.ts → set-production.d.ts} +1 -1
  6. package/dist/commands/domain/set-production.js +27 -0
  7. package/dist/commands/git/list-open-prs.d.ts +12 -0
  8. package/dist/commands/git/list-open-prs.js +87 -0
  9. package/dist/commands/hook/add.d.ts +22 -0
  10. package/dist/commands/hook/add.js +299 -0
  11. package/dist/commands/hook/list.d.ts +11 -0
  12. package/dist/commands/hook/list.js +111 -0
  13. package/dist/commands/hook/logs.d.ts +13 -0
  14. package/dist/commands/hook/logs.js +124 -0
  15. package/dist/commands/hook/remove.d.ts +12 -0
  16. package/dist/commands/hook/remove.js +115 -0
  17. package/dist/commands/hook/toggle.d.ts +12 -0
  18. package/dist/commands/hook/toggle.js +125 -0
  19. package/dist/commands/init.d.ts +1 -1
  20. package/dist/commands/init.js +49 -9
  21. package/dist/commands/module/bindings.d.ts +14 -0
  22. package/dist/commands/module/bindings.js +125 -0
  23. package/dist/commands/module/create.d.ts +3 -0
  24. package/dist/commands/module/create.js +156 -78
  25. package/dist/commands/module/list.d.ts +1 -0
  26. package/dist/commands/module/list.js +22 -1
  27. package/dist/commands/module/sync.d.ts +29 -0
  28. package/dist/commands/module/sync.js +409 -0
  29. package/dist/commands/module/unlink.d.ts +11 -0
  30. package/dist/commands/module/unlink.js +77 -0
  31. package/dist/commands/module/update.d.ts +10 -0
  32. package/dist/commands/module/update.js +168 -5
  33. package/dist/commands/network/discover.d.ts +12 -0
  34. package/dist/commands/network/discover.js +210 -0
  35. package/dist/commands/network/get.d.ts +13 -0
  36. package/dist/commands/network/get.js +90 -0
  37. package/dist/commands/{auth/logout.d.ts → network/list.d.ts} +2 -9
  38. package/dist/commands/network/list.js +71 -0
  39. package/dist/commands/network/register.d.ts +16 -0
  40. package/dist/commands/network/register.js +144 -0
  41. package/dist/commands/parameter/sync.d.ts +13 -0
  42. package/dist/commands/parameter/sync.js +69 -1
  43. package/dist/commands/project/sync.d.ts +5 -11
  44. package/dist/commands/project/sync.js +12 -381
  45. package/dist/commands/seed.d.ts +93 -0
  46. package/dist/commands/seed.js +324 -0
  47. package/dist/commands/service/backup.d.ts +17 -0
  48. package/dist/commands/service/backup.js +156 -0
  49. package/dist/commands/service/backups.d.ts +14 -0
  50. package/dist/commands/service/backups.js +110 -0
  51. package/dist/commands/service/bind.d.ts +16 -0
  52. package/dist/commands/service/bind.js +106 -0
  53. package/dist/commands/service/bindings.d.ts +13 -0
  54. package/dist/commands/service/bindings.js +78 -0
  55. package/dist/commands/service/clone.d.ts +19 -0
  56. package/dist/commands/service/clone.js +153 -0
  57. package/dist/commands/service/create.d.ts +16 -0
  58. package/dist/commands/service/create.js +212 -0
  59. package/dist/commands/service/get.d.ts +13 -0
  60. package/dist/commands/service/get.js +97 -0
  61. package/dist/commands/service/list.d.ts +12 -0
  62. package/dist/commands/service/list.js +86 -0
  63. package/dist/commands/service/register.d.ts +21 -0
  64. package/dist/commands/service/register.js +215 -0
  65. package/dist/commands/service/restore.d.ts +19 -0
  66. package/dist/commands/service/restore.js +158 -0
  67. package/dist/commands/service/seed.d.ts +17 -0
  68. package/dist/commands/service/seed.js +173 -0
  69. package/dist/commands/service/templates.d.ts +10 -0
  70. package/dist/commands/service/templates.js +66 -0
  71. package/dist/commands/service/unbind.d.ts +15 -0
  72. package/dist/commands/service/unbind.js +74 -0
  73. package/dist/commands/stage/create.d.ts +23 -0
  74. package/dist/commands/stage/create.js +145 -6
  75. package/dist/commands/stage/delete.d.ts +11 -0
  76. package/dist/commands/stage/delete.js +85 -0
  77. package/dist/commands/stage/deploy.d.ts +34 -0
  78. package/dist/commands/stage/deploy.js +294 -0
  79. package/dist/commands/stage/ensure-branches.d.ts +23 -0
  80. package/dist/commands/stage/ensure-branches.js +101 -0
  81. package/dist/commands/stage/list.js +4 -0
  82. package/dist/commands/stage/status.d.ts +14 -0
  83. package/dist/commands/stage/status.js +100 -0
  84. package/dist/commands/{jira → tracker}/connect.js +32 -23
  85. package/dist/commands/tracker/hook/add.d.ts +25 -0
  86. package/dist/commands/tracker/hook/add.js +284 -0
  87. package/dist/commands/{jira → tracker}/hook/list.js +20 -11
  88. package/dist/commands/{jira/hook/add.d.ts → tracker/hook/logs.d.ts} +2 -3
  89. package/dist/commands/tracker/hook/logs.js +126 -0
  90. package/dist/commands/{jira → tracker}/hook/remove.js +9 -8
  91. package/dist/commands/{jira → tracker}/hook/toggle.js +14 -12
  92. package/dist/commands/tracker/project/init.d.ts +17 -0
  93. package/dist/commands/tracker/project/init.js +178 -0
  94. package/dist/commands/tracker/project/link-module.d.ts +17 -0
  95. package/dist/commands/tracker/project/link-module.js +287 -0
  96. package/dist/commands/tracker/project/list-modules.d.ts +11 -0
  97. package/dist/commands/tracker/project/list-modules.js +117 -0
  98. package/dist/commands/tracker/project/list.d.ts +10 -0
  99. package/dist/commands/tracker/project/list.js +90 -0
  100. package/dist/commands/tracker/project/status.d.ts +13 -0
  101. package/dist/commands/tracker/project/status.js +168 -0
  102. package/dist/commands/tracker/project/unlink-module.d.ts +13 -0
  103. package/dist/commands/tracker/project/unlink-module.js +251 -0
  104. package/dist/commands/{jira → tracker}/status.js +3 -3
  105. package/dist/lib/ensure-branches.d.ts +53 -0
  106. package/dist/lib/ensure-branches.js +149 -0
  107. package/dist/lib/git-providers/github.d.ts +16 -0
  108. package/dist/lib/git-providers/github.js +157 -0
  109. package/dist/lib/git-providers/gitlab.d.ts +16 -0
  110. package/dist/lib/git-providers/gitlab.js +148 -0
  111. package/dist/lib/git-providers/index.d.ts +67 -0
  112. package/dist/lib/git-providers/index.js +39 -0
  113. package/dist/lib/lambda-warmer.d.ts +106 -0
  114. package/dist/lib/lambda-warmer.js +189 -0
  115. package/dist/services/hyperdrive-sigv4.d.ts +359 -5
  116. package/dist/services/hyperdrive-sigv4.js +177 -12
  117. package/dist/utils/hook-flow.d.ts +60 -3
  118. package/dist/utils/hook-flow.js +437 -2
  119. package/dist/utils/hook-normalize.d.ts +6 -0
  120. package/dist/utils/hook-normalize.js +33 -0
  121. package/dist/utils/lifecycle-poller.d.ts +32 -0
  122. package/dist/utils/lifecycle-poller.js +72 -0
  123. package/dist/utils/retry.d.ts +43 -0
  124. package/dist/utils/retry.js +88 -0
  125. package/dist/utils/summary-display.js +1 -1
  126. package/dist/utils/tracker-project-flow.d.ts +84 -0
  127. package/dist/utils/tracker-project-flow.js +564 -0
  128. package/package.json +41 -13
  129. package/dist/commands/auth/login.d.ts +0 -16
  130. package/dist/commands/auth/login.js +0 -179
  131. package/dist/commands/auth/logout.js +0 -116
  132. package/dist/commands/auth/refresh.d.ts +0 -6
  133. package/dist/commands/auth/refresh.js +0 -66
  134. package/dist/commands/auth/status.d.ts +0 -6
  135. package/dist/commands/auth/status.js +0 -63
  136. package/dist/commands/config/get.d.ts +0 -9
  137. package/dist/commands/config/get.js +0 -37
  138. package/dist/commands/config/set.d.ts +0 -10
  139. package/dist/commands/config/set.js +0 -48
  140. package/dist/commands/config/show.d.ts +0 -6
  141. package/dist/commands/config/show.js +0 -10
  142. package/dist/commands/domain/current.d.ts +0 -6
  143. package/dist/commands/domain/current.js +0 -18
  144. package/dist/commands/domain/list.d.ts +0 -6
  145. package/dist/commands/domain/list.js +0 -42
  146. package/dist/commands/domain/switch.js +0 -40
  147. package/dist/commands/jira/hook/add.js +0 -147
  148. package/dist/services/tenant-service.d.ts +0 -127
  149. package/dist/services/tenant-service.js +0 -396
  150. package/dist/utils/auth-flow.d.ts +0 -147
  151. package/dist/utils/auth-flow.js +0 -479
  152. package/oclif.manifest.json +0 -3519
  153. /package/dist/commands/{jira → tracker}/connect.d.ts +0 -0
  154. /package/dist/commands/{jira → tracker}/hook/list.d.ts +0 -0
  155. /package/dist/commands/{jira → tracker}/hook/remove.d.ts +0 -0
  156. /package/dist/commands/{jira → tracker}/hook/toggle.d.ts +0 -0
  157. /package/dist/commands/{jira → tracker}/status.d.ts +0 -0
@@ -6,6 +6,27 @@ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
6
6
  import { basename, join } from 'node:path';
7
7
  import open from 'open';
8
8
  import { HyperdriveSigV4Service } from '../../services/hyperdrive-sigv4.js';
9
+ const FRAMEWORK_MODULE_TYPE_MAP = {
10
+ actix: 'backend',
11
+ angular: 'frontend',
12
+ aspnet: 'backend',
13
+ django: 'backend',
14
+ express: 'backend',
15
+ fastapi: 'backend',
16
+ fastify: 'backend',
17
+ flask: 'backend',
18
+ gin: 'backend',
19
+ koa: 'backend',
20
+ nextjs: 'frontend',
21
+ rails: 'backend',
22
+ react: 'frontend',
23
+ serverless: 'backend',
24
+ 'serverless-express': 'backend',
25
+ 'serverless-nestjs': 'backend',
26
+ spring: 'backend',
27
+ svelte: 'frontend',
28
+ vue: 'frontend',
29
+ };
9
30
  export default class ModuleCreate extends Command {
10
31
  static description = 'Create a new project';
11
32
  static examples = [
@@ -47,6 +68,14 @@ export default class ModuleCreate extends Command {
47
68
  installCommand: Flags.string({
48
69
  description: 'Install command',
49
70
  }),
71
+ json: Flags.boolean({
72
+ default: false,
73
+ description: 'Output raw JSON response (requires all flags to be provided, skips interactive prompts)',
74
+ }),
75
+ 'module-type': Flags.string({
76
+ description: 'Module deployment type (determines API Gateway vs CloudFront vs CDK)',
77
+ options: ['backend', 'frontend', 'cdk'],
78
+ }),
50
79
  name: Flags.string({
51
80
  description: 'Name of the project',
52
81
  }),
@@ -64,6 +93,9 @@ export default class ModuleCreate extends Command {
64
93
  slug: Flags.string({
65
94
  description: 'Slug of the project',
66
95
  }),
96
+ subdomain: Flags.string({
97
+ description: 'Subdomain prefix for custom domain URLs (e.g., "api", "app", "www", "" for apex)',
98
+ }),
67
99
  sourceDirectory: Flags.string({
68
100
  description: 'Source code directory (e.g., src, lib, . for root) - default: src for Lambda, . for static',
69
101
  }),
@@ -72,9 +104,12 @@ export default class ModuleCreate extends Command {
72
104
  }),
73
105
  };
74
106
  async run() {
75
- this.log(chalk.green('🚀 Let\'s create a new Hyperdrive project!'));
76
107
  const { flags } = await this.parse(ModuleCreate);
77
- const responses = await this.promptUser(flags);
108
+ const isJson = flags.json;
109
+ if (!isJson) {
110
+ this.log(chalk.green('🚀 Let\'s create a new Hyperdrive project!'));
111
+ }
112
+ const responses = isJson ? {} : await this.promptUser(flags);
78
113
  const service = new HyperdriveSigV4Service(flags.domain);
79
114
  const combinedData = { ...flags, ...responses };
80
115
  try {
@@ -82,7 +117,7 @@ export default class ModuleCreate extends Command {
82
117
  const sourceLocation = combinedData.sourceLocation;
83
118
  const gitInfo = this.parseGitUrl(sourceLocation);
84
119
  let gitConfig = {};
85
- if (gitInfo) {
120
+ if (gitInfo && !isJson) {
86
121
  this.log(chalk.blue(`\n🔍 Checking access to ${gitInfo.provider} repository...`));
87
122
  const accessResult = await service.gitCheckRepoAccess({
88
123
  provider: gitInfo.provider,
@@ -145,6 +180,11 @@ export default class ModuleCreate extends Command {
145
180
  gitConfig = {};
146
181
  }
147
182
  }
183
+ // Map kebab-case flag to camelCase API field
184
+ if (combinedData['module-type']) {
185
+ combinedData.moduleType = combinedData['module-type'];
186
+ delete combinedData['module-type'];
187
+ }
148
188
  // Filter out undefined values and ensure all required fields are strings
149
189
  const cleanedData = Object.fromEntries(Object.entries({ ...combinedData, ...gitConfig }).filter(([_, value]) => value !== undefined));
150
190
  // Convert sourceLocation from SSH to HTTPS format (API requirement)
@@ -162,10 +202,14 @@ export default class ModuleCreate extends Command {
162
202
  }
163
203
  const result = await service.moduleCreate(cleanedData);
164
204
  writeFileSync('.hyperdrive.json', JSON.stringify(result, null, 2), 'utf8');
205
+ if (isJson) {
206
+ this.log(JSON.stringify(result, null, 2));
207
+ return;
208
+ }
165
209
  this.log(chalk.blue('✨ Project created successfully! Here are the details:'));
166
210
  this.log(JSON.stringify(result, null, 2));
167
- // Post-create: Offer Dockerfile generation
168
- if (gitInfo && result.slug) {
211
+ // Post-create: Offer Dockerfile generation (skip for CDK modules)
212
+ if (gitInfo && result.slug && combinedData.moduleType !== 'cdk') {
169
213
  await this.offerDockerfileGeneration(service, result.slug);
170
214
  }
171
215
  }
@@ -381,7 +425,8 @@ export default class ModuleCreate extends Command {
381
425
  this.log(chalk.white(` hyperdrive module dockerfile --slug ${slug}`));
382
426
  }
383
427
  async promptUser(flags) {
384
- const prompts = [];
428
+ let prompts = [];
429
+ const isCdk = flags['module-type'] === 'cdk';
385
430
  if (!flags.name) {
386
431
  prompts.push({
387
432
  message: chalk.yellow('📛 Enter the project name:'),
@@ -411,89 +456,122 @@ export default class ModuleCreate extends Command {
411
456
  validate: (input) => Boolean(input) || 'Default branch is required.',
412
457
  });
413
458
  }
414
- if (!flags.runtime) {
415
- prompts.push({
416
- choices: [
417
- { name: 'Node.js', value: 'nodejs' },
418
- { name: 'Python', value: 'python' },
419
- { name: 'Go', value: 'go' },
420
- { name: 'Rust', value: 'rust' },
421
- { name: 'Java', value: 'java' },
422
- { name: '.NET', value: 'dotnet' },
423
- { name: 'Ruby', value: 'ruby' },
424
- ],
425
- default: 'nodejs',
426
- message: chalk.yellow('⚡ What is the runtime?'),
427
- name: 'runtime',
428
- type: 'list',
429
- });
430
- }
431
- if (!flags.runtimeVersion) {
432
- prompts.push({
433
- default: '20',
434
- message: chalk.yellow('📦 What runtime version? (e.g., 20 for Node, 3.12 for Python)'),
435
- name: 'runtimeVersion',
436
- });
459
+ // Skip runtime/buildRuntime/framework prompts for CDK modules
460
+ if (!isCdk) {
461
+ if (!flags.runtime) {
462
+ prompts.push({
463
+ choices: [
464
+ { name: 'Node.js', value: 'nodejs' },
465
+ { name: 'Python', value: 'python' },
466
+ { name: 'Go', value: 'go' },
467
+ { name: 'Rust', value: 'rust' },
468
+ { name: 'Java', value: 'java' },
469
+ { name: '.NET', value: 'dotnet' },
470
+ { name: 'Ruby', value: 'ruby' },
471
+ ],
472
+ default: 'nodejs',
473
+ message: chalk.yellow('⚡ What is the runtime?'),
474
+ name: 'runtime',
475
+ type: 'list',
476
+ });
477
+ }
478
+ if (!flags.runtimeVersion) {
479
+ prompts.push({
480
+ default: '20',
481
+ message: chalk.yellow('📦 What runtime version? (e.g., 20 for Node, 3.12 for Python)'),
482
+ name: 'runtimeVersion',
483
+ });
484
+ }
485
+ if (!flags.buildRuntime) {
486
+ prompts.push({
487
+ choices: [
488
+ { name: 'Node.js', value: 'nodejs' },
489
+ { name: 'Python', value: 'python' },
490
+ { name: 'Go', value: 'go' },
491
+ { name: 'Rust', value: 'rust' },
492
+ { name: 'Java', value: 'java' },
493
+ { name: '.NET', value: 'dotnet' },
494
+ { name: 'Ruby', value: 'ruby' },
495
+ ],
496
+ default: 'nodejs',
497
+ message: chalk.yellow('🐳 What build runtime should be used for the Docker template?'),
498
+ name: 'buildRuntime',
499
+ type: 'list',
500
+ });
501
+ }
502
+ if (!flags.framework) {
503
+ prompts.push({
504
+ choices: [
505
+ { name: 'Serverless Framework (sls deploy)', value: 'serverless' },
506
+ { name: 'Serverless + Express (serverless-http)', value: 'serverless-express' },
507
+ { name: 'Serverless + NestJS', value: 'serverless-nestjs' },
508
+ { name: 'Express.js', value: 'express' },
509
+ { name: 'Fastify', value: 'fastify' },
510
+ { name: 'Koa', value: 'koa' },
511
+ { name: 'Next.js', value: 'nextjs' },
512
+ { name: 'React', value: 'react' },
513
+ { name: 'Vue', value: 'vue' },
514
+ { name: 'Angular', value: 'angular' },
515
+ { name: 'Svelte', value: 'svelte' },
516
+ { name: 'Flask', value: 'flask' },
517
+ { name: 'Django', value: 'django' },
518
+ { name: 'FastAPI', value: 'fastapi' },
519
+ { name: 'Gin (Go)', value: 'gin' },
520
+ { name: 'Actix (Rust)', value: 'actix' },
521
+ { name: 'Spring (Java)', value: 'spring' },
522
+ { name: 'ASP.NET', value: 'aspnet' },
523
+ { name: 'Rails', value: 'rails' },
524
+ { name: 'Other', value: 'other' },
525
+ ],
526
+ message: chalk.yellow('🏗️ What is the framework?'),
527
+ name: 'framework',
528
+ type: 'list',
529
+ });
530
+ }
437
531
  }
438
- if (!flags.buildRuntime) {
532
+ // Collect framework answer before subdomain/moduleType prompts (needed for inference)
533
+ const answers = prompts.length > 0 ? await inquirer.prompt(prompts) : {};
534
+ prompts = [];
535
+ const resolvedFramework = (flags.framework || answers.framework);
536
+ const resolvedSlug = (flags.slug || answers.slug);
537
+ if (flags.subdomain === undefined) {
439
538
  prompts.push({
440
- choices: [
441
- { name: 'Node.js', value: 'nodejs' },
442
- { name: 'Python', value: 'python' },
443
- { name: 'Go', value: 'go' },
444
- { name: 'Rust', value: 'rust' },
445
- { name: 'Java', value: 'java' },
446
- { name: '.NET', value: 'dotnet' },
447
- { name: 'Ruby', value: 'ruby' },
448
- ],
449
- default: 'nodejs',
450
- message: chalk.yellow('🐳 What build runtime should be used for the Docker template?'),
451
- name: 'buildRuntime',
452
- type: 'list',
539
+ default: resolvedSlug || '',
540
+ message: chalk.yellow('🌐 Subdomain prefix (leave empty for apex/root domain):'),
541
+ name: 'subdomain',
453
542
  });
454
543
  }
455
- if (!flags.framework) {
544
+ if (!flags['module-type']) {
545
+ const inferredType = resolvedFramework ? FRAMEWORK_MODULE_TYPE_MAP[resolvedFramework] : undefined;
456
546
  prompts.push({
457
547
  choices: [
458
- { name: 'Serverless Framework (sls deploy)', value: 'serverless' },
459
- { name: 'Serverless + Express (serverless-http)', value: 'serverless-express' },
460
- { name: 'Serverless + NestJS', value: 'serverless-nestjs' },
461
- { name: 'Express.js', value: 'express' },
462
- { name: 'Fastify', value: 'fastify' },
463
- { name: 'Koa', value: 'koa' },
464
- { name: 'Next.js', value: 'nextjs' },
465
- { name: 'React', value: 'react' },
466
- { name: 'Vue', value: 'vue' },
467
- { name: 'Angular', value: 'angular' },
468
- { name: 'Svelte', value: 'svelte' },
469
- { name: 'Flask', value: 'flask' },
470
- { name: 'Django', value: 'django' },
471
- { name: 'FastAPI', value: 'fastapi' },
472
- { name: 'Gin (Go)', value: 'gin' },
473
- { name: 'Actix (Rust)', value: 'actix' },
474
- { name: 'Spring (Java)', value: 'spring' },
475
- { name: 'ASP.NET', value: 'aspnet' },
476
- { name: 'Rails', value: 'rails' },
477
- { name: 'Other', value: 'other' },
548
+ { name: 'Backend (API Gateway)', value: 'backend' },
549
+ { name: 'Frontend (CloudFront)', value: 'frontend' },
550
+ { name: 'CDK (Infrastructure)', value: 'cdk' },
478
551
  ],
479
- message: chalk.yellow('🏗️ What is the framework?'),
480
- name: 'framework',
552
+ ...(inferredType ? { default: inferredType } : {}),
553
+ message: chalk.yellow('🏗️ What is the module deployment type?'),
554
+ name: 'moduleType',
481
555
  type: 'list',
482
556
  });
483
557
  }
484
- if (!flags.buildCommand) {
485
- prompts.push({
486
- message: chalk.yellow('🔨 What is the build command?'),
487
- name: 'buildCommand',
488
- });
489
- }
490
- if (!flags.runCommand) {
491
- prompts.push({
492
- message: chalk.yellow('🚀 What is the command to run the application in production/live environments?'),
493
- name: 'runCommand',
494
- });
558
+ // Skip build/run command prompts for CDK modules
559
+ if (!isCdk) {
560
+ if (!flags.buildCommand) {
561
+ prompts.push({
562
+ message: chalk.yellow('🔨 What is the build command?'),
563
+ name: 'buildCommand',
564
+ });
565
+ }
566
+ if (!flags.runCommand) {
567
+ prompts.push({
568
+ message: chalk.yellow('🚀 What is the command to run the application in production/live environments?'),
569
+ name: 'runCommand',
570
+ });
571
+ }
495
572
  }
496
- return inquirer.prompt(prompts);
573
+ const laterAnswers = prompts.length > 0 ? await inquirer.prompt(prompts) : {};
574
+ return { ...answers, ...laterAnswers };
497
575
  }
498
576
  suggestSlug() {
499
577
  const packagePath = join(process.cwd(), 'package.json');
@@ -4,6 +4,7 @@ export default class ModuleList extends Command {
4
4
  static examples: string[];
5
5
  static flags: {
6
6
  domain: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
8
  };
8
9
  run(): Promise<void>;
9
10
  }
@@ -2,23 +2,40 @@ import { Command, Flags } from '@oclif/core';
2
2
  import chalk from 'chalk';
3
3
  import { HyperdriveSigV4Service } from '../../services/hyperdrive-sigv4.js';
4
4
  import { printTable } from '../../utils/table.js';
5
+ const MODULE_TYPE_DISPLAY = {
6
+ backend: 'Backend',
7
+ cdk: 'CDK',
8
+ frontend: 'Frontend',
9
+ };
5
10
  export default class ModuleList extends Command {
6
11
  static description = 'List all modules/projects';
7
12
  static examples = [
8
13
  '<%= config.bin %> <%= command.id %>',
14
+ '<%= config.bin %> <%= command.id %> --json',
9
15
  ];
10
16
  static flags = {
11
17
  domain: Flags.string({
12
18
  char: 'd',
13
19
  description: 'Tenant domain (for multi-domain setups)',
14
20
  }),
21
+ json: Flags.boolean({
22
+ default: false,
23
+ description: 'Output raw JSON response',
24
+ }),
15
25
  };
16
26
  async run() {
17
27
  const { flags } = await this.parse(ModuleList);
28
+ const isJson = flags.json;
18
29
  try {
19
30
  const service = new HyperdriveSigV4Service(flags.domain);
20
- this.log(chalk.blue('🔍 Fetching modules...'));
31
+ if (!isJson) {
32
+ this.log(chalk.blue('🔍 Fetching modules...'));
33
+ }
21
34
  const modules = await service.moduleList();
35
+ if (isJson) {
36
+ this.log(JSON.stringify(modules, null, 2));
37
+ return;
38
+ }
22
39
  if (!modules || modules.length === 0) {
23
40
  this.log(chalk.yellow('⚠️ No modules found'));
24
41
  return;
@@ -35,6 +52,10 @@ export default class ModuleList extends Command {
35
52
  minWidth: 15,
36
53
  get: (row) => chalk.cyan(row.slug),
37
54
  },
55
+ moduleType: {
56
+ header: 'Type',
57
+ get: (row) => MODULE_TYPE_DISPLAY[row.moduleType] || 'Backend',
58
+ },
38
59
  framework: {
39
60
  header: 'Framework',
40
61
  },
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Module Sync Command
3
+ *
4
+ * Generates structured architecture summaries for modules.
5
+ * For each module: clone → detect _bmad or invoke Claude → validate YAML → upload via API.
6
+ * Replaces the deprecated `project sync` command with module-level ownership.
7
+ */
8
+ import { Command } from '@oclif/core';
9
+ export default class ModuleSync extends Command {
10
+ static args: {
11
+ module: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
12
+ };
13
+ static description: string;
14
+ static examples: string[];
15
+ static flags: {
16
+ all: import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
+ domain: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
19
+ };
20
+ run(): Promise<void>;
21
+ private syncAllModules;
22
+ private syncSingleModule;
23
+ private syncModule;
24
+ private detectBmadDocs;
25
+ private runClaude;
26
+ private validateYaml;
27
+ private readGutEntities;
28
+ private mergeEntityRegistries;
29
+ }