@launch77/cli 1.4.4 → 1.6.0

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 (195) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cli.js +16 -17
  3. package/dist/cli.js.map +1 -1
  4. package/dist/infrastructure/package-resolver.d.ts +12 -2
  5. package/dist/infrastructure/package-resolver.d.ts.map +1 -1
  6. package/dist/infrastructure/package-resolver.js +29 -2
  7. package/dist/infrastructure/package-resolver.js.map +1 -1
  8. package/dist/infrastructure/package-resolver.test.js +3 -3
  9. package/dist/infrastructure/package-resolver.test.js.map +1 -1
  10. package/dist/infrastructure/template.d.ts +0 -1
  11. package/dist/infrastructure/template.d.ts.map +1 -1
  12. package/dist/infrastructure/template.js.map +1 -1
  13. package/dist/modules/app/commands/create-app.d.ts +1 -1
  14. package/dist/modules/app/commands/create-app.d.ts.map +1 -1
  15. package/dist/modules/app/commands/create-app.js +9 -14
  16. package/dist/modules/app/commands/create-app.js.map +1 -1
  17. package/dist/modules/app/commands/delete-app.d.ts +1 -1
  18. package/dist/modules/app/commands/delete-app.js +2 -2
  19. package/dist/modules/app/commands/delete-app.js.map +1 -1
  20. package/dist/modules/app/index.d.ts +3 -5
  21. package/dist/modules/app/index.d.ts.map +1 -1
  22. package/dist/modules/app/index.js +2 -4
  23. package/dist/modules/app/index.js.map +1 -1
  24. package/dist/modules/app/lib/app-template-resolver.d.ts.map +1 -1
  25. package/dist/modules/app/lib/app-template-resolver.js +15 -0
  26. package/dist/modules/app/lib/app-template-resolver.js.map +1 -1
  27. package/dist/modules/app/lib/manifest-schema.d.ts +0 -7
  28. package/dist/modules/app/lib/manifest-schema.d.ts.map +1 -1
  29. package/dist/modules/app/lib/manifest-schema.js +0 -2
  30. package/dist/modules/app/lib/manifest-schema.js.map +1 -1
  31. package/dist/modules/app/services/app-svc.d.ts.map +1 -1
  32. package/dist/modules/app/services/app-svc.js +36 -6
  33. package/dist/modules/app/services/app-svc.js.map +1 -1
  34. package/dist/modules/app/services/manifest-svc.d.ts +2 -2
  35. package/dist/modules/app/services/manifest-svc.d.ts.map +1 -1
  36. package/dist/modules/app/services/manifest-svc.js +9 -50
  37. package/dist/modules/app/services/manifest-svc.js.map +1 -1
  38. package/dist/modules/app/types/app-types.d.ts +2 -5
  39. package/dist/modules/app/types/app-types.d.ts.map +1 -1
  40. package/dist/modules/app/types/app-types.js +1 -4
  41. package/dist/modules/app/types/app-types.js.map +1 -1
  42. package/dist/modules/catalog/commands/generate.d.ts +1 -1
  43. package/dist/modules/catalog/commands/generate.d.ts.map +1 -1
  44. package/dist/modules/catalog/commands/generate.js +1 -1
  45. package/dist/modules/catalog/commands/generate.js.map +1 -1
  46. package/dist/modules/catalog/commands/scan.d.ts +1 -1
  47. package/dist/modules/catalog/commands/scan.d.ts.map +1 -1
  48. package/dist/modules/catalog/commands/scan.js +4 -4
  49. package/dist/modules/catalog/commands/scan.js.map +1 -1
  50. package/dist/modules/catalog/services/catalog-svc.d.ts +2 -2
  51. package/dist/modules/catalog/services/catalog-svc.d.ts.map +1 -1
  52. package/dist/modules/catalog/services/catalog-svc.js +2 -2
  53. package/dist/modules/catalog/services/catalog-svc.js.map +1 -1
  54. package/dist/modules/deploy/commands/deploy-init-action.d.ts.map +1 -1
  55. package/dist/modules/deploy/commands/deploy-init-action.js +21 -20
  56. package/dist/modules/deploy/commands/deploy-init-action.js.map +1 -1
  57. package/dist/modules/deploy/commands/deploy-logs-action.d.ts.map +1 -1
  58. package/dist/modules/deploy/commands/deploy-logs-action.js +16 -13
  59. package/dist/modules/deploy/commands/deploy-logs-action.js.map +1 -1
  60. package/dist/modules/deploy/commands/deploy-status-action.d.ts.map +1 -1
  61. package/dist/modules/deploy/commands/deploy-status-action.js +16 -13
  62. package/dist/modules/deploy/commands/deploy-status-action.js.map +1 -1
  63. package/dist/modules/library/commands/delete-library.d.ts +3 -0
  64. package/dist/modules/library/commands/delete-library.d.ts.map +1 -0
  65. package/dist/modules/library/commands/delete-library.js +111 -0
  66. package/dist/modules/library/commands/delete-library.js.map +1 -0
  67. package/dist/modules/library/errors/library-errors.d.ts +7 -0
  68. package/dist/modules/library/errors/library-errors.d.ts.map +1 -0
  69. package/dist/modules/library/errors/library-errors.js +13 -0
  70. package/dist/modules/library/errors/library-errors.js.map +1 -0
  71. package/dist/modules/library/index.d.ts +5 -0
  72. package/dist/modules/library/index.d.ts.map +1 -0
  73. package/dist/modules/library/index.js +7 -0
  74. package/dist/modules/library/index.js.map +1 -0
  75. package/dist/modules/library/services/library-svc.d.ts +9 -0
  76. package/dist/modules/library/services/library-svc.d.ts.map +1 -0
  77. package/dist/modules/library/services/library-svc.js +38 -0
  78. package/dist/modules/library/services/library-svc.js.map +1 -0
  79. package/dist/modules/library/types/library-types.d.ts +7 -0
  80. package/dist/modules/library/types/library-types.d.ts.map +1 -0
  81. package/dist/modules/library/types/library-types.js +2 -0
  82. package/dist/modules/library/types/library-types.js.map +1 -0
  83. package/dist/modules/plugin/commands/delete-plugin.d.ts +3 -0
  84. package/dist/modules/plugin/commands/delete-plugin.d.ts.map +1 -0
  85. package/dist/modules/plugin/commands/delete-plugin.js +113 -0
  86. package/dist/modules/plugin/commands/delete-plugin.js.map +1 -0
  87. package/dist/modules/plugin/errors/plugin-errors.d.ts +12 -0
  88. package/dist/modules/plugin/errors/plugin-errors.d.ts.map +1 -1
  89. package/dist/modules/plugin/errors/plugin-errors.js +18 -0
  90. package/dist/modules/plugin/errors/plugin-errors.js.map +1 -1
  91. package/dist/modules/plugin/index.d.ts +1 -0
  92. package/dist/modules/plugin/index.d.ts.map +1 -1
  93. package/dist/modules/plugin/index.js +1 -0
  94. package/dist/modules/plugin/index.js.map +1 -1
  95. package/dist/modules/plugin/lib/plugin-resolver.d.ts.map +1 -1
  96. package/dist/modules/plugin/lib/plugin-resolver.js +13 -2
  97. package/dist/modules/plugin/lib/plugin-resolver.js.map +1 -1
  98. package/dist/modules/plugin/lib/plugin-resolver.test.js +2 -0
  99. package/dist/modules/plugin/lib/plugin-resolver.test.js.map +1 -1
  100. package/dist/modules/plugin/services/plugin-svc.d.ts +5 -1
  101. package/dist/modules/plugin/services/plugin-svc.d.ts.map +1 -1
  102. package/dist/modules/plugin/services/plugin-svc.js +44 -3
  103. package/dist/modules/plugin/services/plugin-svc.js.map +1 -1
  104. package/dist/modules/plugin/services/plugin-svc.test.js +12 -6
  105. package/dist/modules/plugin/services/plugin-svc.test.js.map +1 -1
  106. package/dist/modules/plugin/types/plugin-types.d.ts +6 -0
  107. package/dist/modules/plugin/types/plugin-types.d.ts.map +1 -1
  108. package/dist/templates/plugin/package.json.hbs +1 -1
  109. package/dist/templates/plugin/plugin.json.hbs +1 -3
  110. package/dist/utils/validation.d.ts +3 -7
  111. package/dist/utils/validation.d.ts.map +1 -1
  112. package/dist/utils/validation.js +7 -31
  113. package/dist/utils/validation.js.map +1 -1
  114. package/package.json +1 -1
  115. package/src/cli.ts +16 -17
  116. package/src/infrastructure/package-resolver.test.ts +3 -3
  117. package/src/infrastructure/package-resolver.ts +31 -2
  118. package/src/infrastructure/template.ts +0 -1
  119. package/src/modules/app/commands/create-app.ts +9 -17
  120. package/src/modules/app/commands/delete-app.ts +2 -2
  121. package/src/modules/app/index.ts +3 -5
  122. package/src/modules/app/lib/app-template-resolver.ts +16 -0
  123. package/src/modules/app/lib/manifest-schema.ts +0 -5
  124. package/src/modules/app/services/app-svc.ts +46 -7
  125. package/src/modules/app/services/manifest-svc.ts +8 -57
  126. package/src/modules/app/types/app-types.ts +2 -9
  127. package/src/modules/catalog/commands/generate.ts +1 -1
  128. package/src/modules/catalog/commands/scan.ts +4 -4
  129. package/src/modules/catalog/services/catalog-svc.ts +4 -4
  130. package/src/modules/deploy/commands/deploy-init-action.ts +23 -20
  131. package/src/modules/deploy/commands/deploy-logs-action.ts +19 -13
  132. package/src/modules/deploy/commands/deploy-status-action.ts +19 -13
  133. package/src/modules/library/commands/delete-library.ts +126 -0
  134. package/src/modules/library/errors/library-errors.ts +13 -0
  135. package/src/modules/library/index.ts +11 -0
  136. package/src/modules/library/services/library-svc.ts +50 -0
  137. package/src/modules/library/types/library-types.ts +7 -0
  138. package/src/modules/plugin/commands/delete-plugin.ts +128 -0
  139. package/src/modules/plugin/errors/plugin-errors.ts +20 -0
  140. package/src/modules/plugin/index.ts +1 -0
  141. package/src/modules/plugin/lib/plugin-resolver.test.ts +2 -0
  142. package/src/modules/plugin/lib/plugin-resolver.ts +13 -2
  143. package/src/modules/plugin/services/plugin-svc.test.ts +12 -6
  144. package/src/modules/plugin/services/plugin-svc.ts +55 -5
  145. package/src/modules/plugin/types/plugin-types.ts +8 -0
  146. package/src/utils/validation.ts +10 -38
  147. package/templates/plugin/package.json.hbs +1 -1
  148. package/templates/plugin/plugin.json.hbs +1 -3
  149. package/dist/modules/app/commands/generate-manifest.d.ts +0 -3
  150. package/dist/modules/app/commands/generate-manifest.d.ts.map +0 -1
  151. package/dist/modules/app/commands/generate-manifest.js +0 -62
  152. package/dist/modules/app/commands/generate-manifest.js.map +0 -1
  153. package/dist/modules/app/commands/validate-manifest.d.ts +0 -3
  154. package/dist/modules/app/commands/validate-manifest.d.ts.map +0 -1
  155. package/dist/modules/app/commands/validate-manifest.js +0 -68
  156. package/dist/modules/app/commands/validate-manifest.js.map +0 -1
  157. package/dist/modules/startup/commands/create-startup.d.ts +0 -3
  158. package/dist/modules/startup/commands/create-startup.d.ts.map +0 -1
  159. package/dist/modules/startup/commands/create-startup.js +0 -43
  160. package/dist/modules/startup/commands/create-startup.js.map +0 -1
  161. package/dist/modules/startup/errors/startup-errors.d.ts +0 -13
  162. package/dist/modules/startup/errors/startup-errors.d.ts.map +0 -1
  163. package/dist/modules/startup/errors/startup-errors.js +0 -25
  164. package/dist/modules/startup/errors/startup-errors.js.map +0 -1
  165. package/dist/modules/startup/index.d.ts +0 -5
  166. package/dist/modules/startup/index.d.ts.map +0 -1
  167. package/dist/modules/startup/index.js +0 -7
  168. package/dist/modules/startup/index.js.map +0 -1
  169. package/dist/modules/startup/services/startup-service.d.ts +0 -7
  170. package/dist/modules/startup/services/startup-service.d.ts.map +0 -1
  171. package/dist/modules/startup/services/startup-service.js +0 -43
  172. package/dist/modules/startup/services/startup-service.js.map +0 -1
  173. package/dist/modules/startup/types/startup-types.d.ts +0 -8
  174. package/dist/modules/startup/types/startup-types.d.ts.map +0 -1
  175. package/dist/modules/startup/types/startup-types.js +0 -2
  176. package/dist/modules/startup/types/startup-types.js.map +0 -1
  177. package/dist/modules/startup/utils/startup-validators.d.ts +0 -8
  178. package/dist/modules/startup/utils/startup-validators.d.ts.map +0 -1
  179. package/dist/modules/startup/utils/startup-validators.js +0 -17
  180. package/dist/modules/startup/utils/startup-validators.js.map +0 -1
  181. package/dist/templates/startup/apps/.gitkeep +0 -8
  182. package/dist/utils/monorepo.d.ts +0 -19
  183. package/dist/utils/monorepo.d.ts.map +0 -1
  184. package/dist/utils/monorepo.js +0 -100
  185. package/dist/utils/monorepo.js.map +0 -1
  186. package/src/modules/app/commands/generate-manifest.ts +0 -75
  187. package/src/modules/app/commands/validate-manifest.ts +0 -78
  188. package/src/modules/startup/commands/create-startup.ts +0 -53
  189. package/src/modules/startup/errors/startup-errors.ts +0 -23
  190. package/src/modules/startup/index.ts +0 -11
  191. package/src/modules/startup/services/startup-service.ts +0 -57
  192. package/src/modules/startup/types/startup-types.ts +0 -8
  193. package/src/modules/startup/utils/startup-validators.ts +0 -19
  194. package/src/utils/monorepo.ts +0 -137
  195. package/templates/startup/apps/.gitkeep +0 -8
@@ -159,9 +159,9 @@ describe('PluginService', () => {
159
159
 
160
160
  const result = await (service as any).validatePluginTargets(pluginDir, 'test-plugin', 'app')
161
161
  expect(result).toEqual({
162
- name: 'test-plugin',
163
- version: '1.0.0',
164
162
  targets: ['app', 'library'],
163
+ pluginDependencies: undefined,
164
+ libraryDependencies: undefined,
165
165
  })
166
166
  })
167
167
 
@@ -175,8 +175,11 @@ describe('PluginService', () => {
175
175
  })
176
176
 
177
177
  const result = await (service as any).validatePluginTargets(pluginDir, 'multi-target-plugin', 'library')
178
- expect(result.targets).toContain('library')
179
- expect(result.targets).toHaveLength(4)
178
+ expect(result).toEqual({
179
+ targets: ['app', 'library', 'plugin', 'app-template'],
180
+ pluginDependencies: undefined,
181
+ libraryDependencies: undefined,
182
+ })
180
183
  })
181
184
 
182
185
  test('should handle plugin.json with optional fields (pluginDependencies, libraryDependencies)', async () => {
@@ -191,8 +194,11 @@ describe('PluginService', () => {
191
194
  })
192
195
 
193
196
  const result = await (service as any).validatePluginTargets(pluginDir, 'full-plugin', 'app')
194
- expect(result.pluginDependencies).toEqual({ 'other-plugin': '^1.0.0' })
195
- expect(result.libraryDependencies).toEqual({ react: '^18.0.0' })
197
+ expect(result).toEqual({
198
+ targets: ['app'],
199
+ pluginDependencies: { 'other-plugin': '^1.0.0' },
200
+ libraryDependencies: { react: '^18.0.0' },
201
+ })
196
202
  })
197
203
 
198
204
  // Error scenarios - test exact error messages
@@ -3,14 +3,18 @@ import * as fs from 'fs/promises'
3
3
 
4
4
  import chalk from 'chalk'
5
5
  import { execa } from 'execa'
6
+ import fsExtra from 'fs-extra'
6
7
  import { readPluginMetadata } from '@launch77/plugin-runtime'
7
8
 
8
9
  import { downloadNpmPackage } from '../../../infrastructure/npm-package.js'
9
- import { PluginInstallationError, InvalidPluginContextError, createInvalidContextError, MissingPluginTargetsError, createInvalidTargetError, NpmInstallationError, PluginResolutionError } from '../errors/plugin-errors.js'
10
+ import * as npm from '../../../infrastructure/npm.js'
11
+ import { validateWorkspaceContext } from '../../../utils/launch77-validation.js'
12
+ import { validateAppName } from '../../../utils/validation.js'
13
+ import { PluginInstallationError, InvalidPluginContextError, createInvalidContextError, MissingPluginTargetsError, createInvalidTargetError, NpmInstallationError, PluginResolutionError, PluginDirectoryNotFoundError, InvalidPluginNameError } from '../errors/plugin-errors.js'
10
14
  import { PluginResolver } from '../lib/plugin-resolver.js'
11
15
 
12
16
  import type { Launch77Context, Launch77LocationType, Launch77PackageManifest, InstalledPluginMetadata, PluginMetadata } from '@launch77/plugin-runtime'
13
- import type { InstallPluginRequest, InstallPluginResult } from '../types/plugin-types.js'
17
+ import type { InstallPluginRequest, InstallPluginResult, DeletePluginRequest, DeletePluginResult } from '../types/plugin-types.js'
14
18
 
15
19
  /**
16
20
  * Map location type to target string
@@ -50,7 +54,7 @@ export class PluginService {
50
54
  /**
51
55
  * Validate plugin name, resolve its location, and download if needed
52
56
  */
53
- private async validateAndResolvePlugin(pluginName: string, workspaceRoot: string, logger: (message: string) => void): Promise<{ pluginPath: string; source: 'local' | 'npm'; npmPackage?: string }> {
57
+ private async validateAndResolvePlugin(pluginName: string, workspaceRoot: string, logger: (message: string) => void): Promise<{ pluginPath: string; source: 'local' | 'npm'; npmPackage?: string; version: string }> {
54
58
  logger(chalk.blue(`\n🔍 Resolving plugin "${pluginName}"...`))
55
59
  logger(` ├─ Validating plugin name...`)
56
60
 
@@ -64,15 +68,23 @@ export class PluginService {
64
68
  const resolution = await this.pluginResolver.resolveLocation(pluginName, workspaceRoot)
65
69
 
66
70
  let pluginPath: string
71
+ let version: string
67
72
 
68
73
  if (resolution.source === 'local') {
69
74
  logger(` │ └─ ${chalk.green('✓')} Found local plugin`)
70
75
  pluginPath = resolution.localPath!
76
+ version = resolution.version! // Local plugins always have version after verification
71
77
  } else {
72
78
  logger(` │ └─ ${chalk.dim('Not found locally')}`)
73
79
  logger(` ├─ Resolving to npm package: ${chalk.cyan(resolution.npmPackage)}`)
74
80
 
75
81
  pluginPath = await this.downloadNpmPlugin(resolution.npmPackage!, workspaceRoot, logger)
82
+
83
+ // Read version from downloaded package
84
+ const packageJsonPath = path.join(pluginPath, 'package.json')
85
+ const packageJsonContent = await fs.readFile(packageJsonPath, 'utf-8')
86
+ const packageJson = JSON.parse(packageJsonContent)
87
+ version = packageJson.version
76
88
  }
77
89
 
78
90
  logger(` └─ ${chalk.green('✓')} Plugin resolved\n`)
@@ -81,6 +93,7 @@ export class PluginService {
81
93
  pluginPath,
82
94
  source: resolution.source,
83
95
  npmPackage: resolution.npmPackage,
96
+ version,
84
97
  }
85
98
  }
86
99
 
@@ -130,7 +143,7 @@ export class PluginService {
130
143
  const { pluginName } = request
131
144
 
132
145
  const currentTarget = this.validateContext(context)
133
- const { pluginPath, source, npmPackage } = await this.validateAndResolvePlugin(pluginName, context.workspaceRoot, logger)
146
+ const { pluginPath, source, npmPackage, version } = await this.validateAndResolvePlugin(pluginName, context.workspaceRoot, logger)
134
147
  const metadata = await this.validatePluginTargets(pluginPath, pluginName, currentTarget)
135
148
 
136
149
  const packagePath = this.getPackagePath(context)
@@ -143,7 +156,7 @@ export class PluginService {
143
156
  await this.writePluginManifest(packagePath, {
144
157
  pluginName,
145
158
  packageName,
146
- version: metadata.version,
159
+ version,
147
160
  source,
148
161
  })
149
162
 
@@ -250,4 +263,41 @@ export class PluginService {
250
263
  throw new PluginInstallationError(`Failed to write plugin manifest: ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error : undefined)
251
264
  }
252
265
  }
266
+
267
+ /**
268
+ * Delete a plugin from the workspace
269
+ */
270
+ async deletePlugin(request: DeletePluginRequest, context: Launch77Context): Promise<DeletePluginResult> {
271
+ const { pluginName } = request
272
+
273
+ // 1. Validate plugin name (reusing app name validation since format is the same)
274
+ const nameValidation = validateAppName(pluginName)
275
+ if (!nameValidation.valid) {
276
+ throw new InvalidPluginNameError(nameValidation.errorMessage || 'Invalid plugin name')
277
+ }
278
+
279
+ // 2. Validate workspace context
280
+ const contextValidation = validateWorkspaceContext(context)
281
+ if (!contextValidation.valid) {
282
+ throw new Error(contextValidation.errorMessage || 'Invalid workspace context')
283
+ }
284
+
285
+ // 3. Determine plugin path
286
+ const pluginPath = path.join(context.workspaceRoot, 'plugins', pluginName)
287
+
288
+ // 4. Check if plugin exists
289
+ if (!(await fsExtra.pathExists(pluginPath))) {
290
+ throw new PluginDirectoryNotFoundError(pluginName, pluginPath)
291
+ }
292
+
293
+ // 5. Delete the plugin directory
294
+ await fsExtra.remove(pluginPath)
295
+
296
+ // 6. Update dependencies
297
+ await npm.install(context.workspaceRoot)
298
+
299
+ return {
300
+ pluginName,
301
+ }
302
+ }
253
303
  }
@@ -19,3 +19,11 @@ export interface HookResult {
19
19
  templateVariables?: Record<string, string>
20
20
  hookContext?: Record<string, string>
21
21
  }
22
+
23
+ export interface DeletePluginRequest {
24
+ pluginName: string
25
+ }
26
+
27
+ export interface DeletePluginResult {
28
+ pluginName: string
29
+ }
@@ -2,7 +2,7 @@ import * as path from 'path'
2
2
 
3
3
  import chalk from 'chalk'
4
4
 
5
- import type { MonorepoContext } from './monorepo.js'
5
+ import type { Launch77Context } from '@launch77/plugin-runtime'
6
6
 
7
7
  /**
8
8
  * Validation result with helpful error messages
@@ -12,50 +12,22 @@ export interface ValidationResult {
12
12
  errorMessage?: string
13
13
  }
14
14
 
15
- /**
16
- * Validate that we're in a startup context (for create-app)
17
- */
18
- export function validateStartupContext(context: MonorepoContext): ValidationResult {
19
- if (!context.isValid) {
20
- return {
21
- valid: false,
22
- errorMessage: 'Must be run from within a Launch77 monorepo (could not find .launch-monorepo-root.md)',
23
- }
24
- }
25
-
26
- if (context.location !== 'startup-root' && context.location !== 'startup-app') {
27
- return {
28
- valid: false,
29
- errorMessage: `Command must be run from a startup directory.\n\n` + `${chalk.gray('Current location:')} ${context.location}\n` + `${chalk.gray('Expected:')} Within startups/<startup-name>/\n\n` + `${chalk.yellow('Navigate to a startup first:')}\n` + ` cd startups/<startup-name>/\n\n` + `${chalk.yellow('Or create a startup:')}\n` + ` launch77 create-startup <startup-name>`,
30
- }
31
- }
32
-
33
- if (!context.appsDir) {
34
- return {
35
- valid: false,
36
- errorMessage: `Could not determine apps directory for location: ${context.location}\n` + `This is a bug. Please report it.`,
37
- }
38
- }
39
-
40
- return { valid: true }
41
- }
42
-
43
15
  /**
44
16
  * Validate that we're inside an app directory (for plugin:install)
45
17
  */
46
- export function validateAppContext(context: MonorepoContext): ValidationResult {
18
+ export function validateAppContext(context: Launch77Context): ValidationResult {
47
19
  if (!context.isValid) {
48
20
  return {
49
21
  valid: false,
50
- errorMessage: 'Must be run from within a Launch77 monorepo (could not find .launch-monorepo-root.md)',
22
+ errorMessage: 'Must be run from within a Launch77 workspace (could not find .launch77/workspace.json)',
51
23
  }
52
24
  }
53
25
 
54
- // Must be inside an app, not just a startup
55
- if (context.location !== 'startup-app') {
26
+ // Must be inside an app
27
+ if (context.locationType !== 'workspace-app') {
56
28
  return {
57
29
  valid: false,
58
- errorMessage: `plugin:install must be run from within an app directory.\n\n` + `${chalk.gray('Current location:')} ${context.location}\n` + `${chalk.gray('Expected:')} startups/<startup-name>/apps/<app-name>/\n\n` + `${chalk.yellow('Navigate to an app directory:')}\n` + ` cd startups/<startup-name>/apps/<app-name>/\n\n` + `${chalk.yellow('Or create an app first:')}\n` + ` cd startups/<startup-name>/\n` + ` launch77 app:create api <app-name>`,
30
+ errorMessage: `plugin:install must be run from within an app directory.\n\n` + `${chalk.gray('Current location:')} ${context.locationType}\n` + `${chalk.gray('Expected:')} apps/<app-name>/\n\n` + `${chalk.yellow('Navigate to an app directory:')}\n` + ` cd apps/<app-name>/\n\n` + `${chalk.yellow('Or create an app first:')}\n` + ` launch77 app:create <template> <app-name>`,
59
31
  }
60
32
  }
61
33
 
@@ -73,16 +45,16 @@ export function validateAppContext(context: MonorepoContext): ValidationResult {
73
45
  * Get the app directory path
74
46
  * Returns null if not in an app context
75
47
  */
76
- export function getAppDirectory(context: MonorepoContext): string | null {
77
- if (context.location !== 'startup-app') {
48
+ export function getAppDirectory(context: Launch77Context): string | null {
49
+ if (context.locationType !== 'workspace-app') {
78
50
  return null
79
51
  }
80
52
 
81
- if (!context.monorepoRoot || !context.startupName || !context.appName) {
53
+ if (!context.workspaceRoot || !context.appName) {
82
54
  return null
83
55
  }
84
56
 
85
- return path.join(context.monorepoRoot, 'startups', context.startupName, 'apps', context.appName)
57
+ return path.join(context.workspaceRoot, 'apps', context.appName)
86
58
  }
87
59
 
88
60
  /**
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@{{workspaceName}}/plugin-{{pluginName}}",
3
- "version": "1.0.0",
3
+ "version": "0.0.1",
4
4
  "description": "{{description}}",
5
5
  "license": "UNLICENSED",
6
6
  "private": true,
@@ -1,7 +1,5 @@
1
1
  {
2
- "name": "{{pluginName}}",
3
- "version": "1.0.0",
4
- "description": "{{description}}",
2
+ "targets": ["app", "library"],
5
3
  "pluginDependencies": {},
6
4
  "libraryDependencies": {}
7
5
  }
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function generateManifestCommand(): Command;
3
- //# sourceMappingURL=generate-manifest.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate-manifest.d.ts","sourceRoot":"","sources":["../../../../src/modules/app/commands/generate-manifest.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAQnC,wBAAgB,uBAAuB,IAAI,OAAO,CA8DjD"}
@@ -1,62 +0,0 @@
1
- /* eslint-disable no-console */
2
- import * as path from 'path';
3
- import chalk from 'chalk';
4
- import { Command } from 'commander';
5
- import fs from 'fs-extra';
6
- import ora from 'ora';
7
- import { detectLaunch77Context } from '../../../utils/launch77-context.js';
8
- import { ManifestService } from '../services/manifest-svc.js';
9
- import { APP_TYPES, APP_TYPES_LIST } from '../types/app-types.js';
10
- export function generateManifestCommand() {
11
- const command = new Command('app:generate-manifest')
12
- .description('Generate a manifest for an existing app (run from app directory)')
13
- .requiredOption('-t, --type <type>', `App type (${APP_TYPES_LIST})`)
14
- .option('-p, --port <port>', 'Port for API apps (defaults to 4000)')
15
- .option('-f, --force', 'Overwrite existing manifest')
16
- .action(async (options) => {
17
- try {
18
- const context = await detectLaunch77Context(process.cwd());
19
- if (context.locationType !== 'workspace-app') {
20
- throw new Error('Must be run from within an app directory (e.g., apps/myapp)');
21
- }
22
- // Validate app type
23
- if (!APP_TYPES.includes(options.type)) {
24
- throw new Error(`Invalid app type: ${options.type}. Supported types: ${APP_TYPES_LIST}`);
25
- }
26
- const appPath = process.cwd();
27
- const appName = context.appName;
28
- console.log(chalk.blue(`\n🔍 Generating manifest for app: ${appName}\n`));
29
- // Check if manifest already exists
30
- const launchDir = path.join(appPath, '.launch');
31
- const manifestPath = path.join(launchDir, 'app.json');
32
- if ((await fs.pathExists(manifestPath)) && !options.force) {
33
- console.log(chalk.yellow('⚠️ Manifest already exists at .launch/app.json'));
34
- console.log(chalk.gray('Use --force to overwrite'));
35
- return;
36
- }
37
- // Get port
38
- const port = options.port || (options.type === 'api' ? '4000' : '3000');
39
- // Generate manifest
40
- const manifestSpinner = ora('Generating manifest...').start();
41
- const manifestService = new ManifestService();
42
- const manifest = manifestService.generateManifest(options.type, appName, context, { port });
43
- // Ensure .launch directory exists
44
- await fs.ensureDir(launchDir);
45
- // Write manifest
46
- await fs.writeJSON(manifestPath, manifest, { spaces: 2 });
47
- manifestSpinner.succeed('Manifest generated');
48
- console.log(chalk.green(`\n✅ Manifest created at .launch/app.json`));
49
- console.log(chalk.gray('\nManifest details:'));
50
- console.log(chalk.gray(' Type:'), manifest.type);
51
- console.log(chalk.gray(' Name:'), manifest.name);
52
- console.log(chalk.gray(' Package:'), manifest.package);
53
- }
54
- catch (error) {
55
- const message = error instanceof Error ? error.message : String(error);
56
- console.error(chalk.red('Error:'), message);
57
- process.exit(1);
58
- }
59
- });
60
- return command;
61
- }
62
- //# sourceMappingURL=generate-manifest.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate-manifest.js","sourceRoot":"","sources":["../../../../src/modules/app/commands/generate-manifest.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function validateManifestCommand(): Command;
3
- //# sourceMappingURL=validate-manifest.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validate-manifest.d.ts","sourceRoot":"","sources":["../../../../src/modules/app/commands/validate-manifest.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAInC,wBAAgB,uBAAuB,IAAI,OAAO,CAqEjD"}
@@ -1,68 +0,0 @@
1
- /* eslint-disable no-console */
2
- import * as path from 'path';
3
- import chalk from 'chalk';
4
- import { Command } from 'commander';
5
- import { ManifestService } from '../services/manifest-svc.js';
6
- export function validateManifestCommand() {
7
- const command = new Command('app:validate-manifest')
8
- .description('Validate a Launch77 manifest file')
9
- .option('--path <folder>', 'Path to search for manifest (defaults to current directory)')
10
- .action(async (options) => {
11
- try {
12
- const searchPath = options.path ? path.resolve(options.path) : process.cwd();
13
- console.log(chalk.blue('🔍 Searching for Launch77 manifest (.launch/app.json)...\n'));
14
- const manifestService = new ManifestService();
15
- const { manifest, manifestPath, appRoot } = await manifestService.loadManifest(searchPath);
16
- console.log(chalk.green('✅ Valid manifest found!\n'));
17
- console.log(chalk.gray('Path:'), manifestPath);
18
- console.log(chalk.gray('App root:'), appRoot);
19
- console.log();
20
- console.log(chalk.cyan('Manifest details:'));
21
- console.log(chalk.gray(' Schema version:'), manifest.schemaVersion);
22
- console.log(chalk.gray(' App type:'), manifest.type);
23
- console.log(chalk.gray(' Package:'), manifest.package);
24
- if ('name' in manifest && manifest.name) {
25
- console.log(chalk.gray(' Name:'), manifest.name);
26
- }
27
- // Check if deployment field exists
28
- if (manifest.deployment) {
29
- console.log(chalk.gray(' Deployment platform:'), manifest.deployment.platform);
30
- if (manifest.deployment.connected) {
31
- console.log(chalk.gray(' Connected:'), 'Yes');
32
- if (manifest.deployment.projectName) {
33
- console.log(chalk.gray(' Project:'), manifest.deployment.projectName);
34
- }
35
- }
36
- }
37
- console.log();
38
- console.log(chalk.green('✨ Manifest validation successful!'));
39
- // Exit with success code
40
- process.exit(0);
41
- }
42
- catch (error) {
43
- console.error(chalk.red('❌ Manifest validation failed:\n'));
44
- if (error instanceof Error) {
45
- // If it's our formatted error with validation issues, print it as-is
46
- if (error.message.includes('Manifest validation failed:')) {
47
- console.error(error.message);
48
- }
49
- else {
50
- console.error(chalk.red(error.message));
51
- }
52
- }
53
- else {
54
- console.error(chalk.red('Unknown error occurred'));
55
- }
56
- console.log();
57
- console.log(chalk.gray('To create a new manifest, use:'));
58
- console.log(chalk.cyan(' launch77 create-app <type> <name>'));
59
- console.log();
60
- console.log(chalk.gray('Or create one manually at .launch/app.json following the schema at:'));
61
- console.log(chalk.cyan(' launch77/cli/schemas/app.launch77.schema.json'));
62
- // Exit with error code
63
- process.exit(1);
64
- }
65
- });
66
- return command;
67
- }
68
- //# sourceMappingURL=validate-manifest.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validate-manifest.js","sourceRoot":"","sources":["../../../../src/modules/app/commands/validate-manifest.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAE5B,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAE7D,MAAM,UAAU,uBAAuB;IACrC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,uBAAuB,CAAC;SACjD,WAAW,CAAC,mCAAmC,CAAC;SAChD,MAAM,CAAC,iBAAiB,EAAE,6DAA6D,CAAC;SACxF,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAA;YAE5E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC,CAAA;YAErF,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAA;YAC7C,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,MAAM,eAAe,CAAC,YAAY,CAAC,UAAU,CAAC,CAAA;YAE1F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAA;YACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC,CAAA;YAC9C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,CAAA;YAC7C,OAAO,CAAC,GAAG,EAAE,CAAA;YACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAA;YAC5C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAA;YACpE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;YACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;YAEvD,IAAI,MAAM,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;YACnD,CAAC;YAED,mCAAmC;YACnC,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;gBACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;gBAC/E,IAAI,QAAQ,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;oBAClC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,CAAA;oBAC9C,IAAI,QAAQ,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;wBACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;oBACxE,CAAC;gBACH,CAAC;YACH,CAAC;YAED,OAAO,CAAC,GAAG,EAAE,CAAA;YACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAA;YAE7D,yBAAyB;YACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC,CAAA;YAE3D,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,qEAAqE;gBACrE,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,6BAA6B,CAAC,EAAE,CAAC;oBAC1D,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;gBAC9B,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAA;gBACzC,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAA;YACpD,CAAC;YAED,OAAO,CAAC,GAAG,EAAE,CAAA;YACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAA;YACzD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC,CAAA;YAC9D,OAAO,CAAC,GAAG,EAAE,CAAA;YACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qEAAqE,CAAC,CAAC,CAAA;YAC9F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC,CAAA;YAE1E,uBAAuB;YACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC,CAAC,CAAA;IAEJ,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function createStartupCommand(): Command;
3
- //# sourceMappingURL=create-startup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-startup.d.ts","sourceRoot":"","sources":["../../../../src/modules/startup/commands/create-startup.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAOnC,wBAAgB,oBAAoB,IAAI,OAAO,CA0C9C"}
@@ -1,43 +0,0 @@
1
- import * as path from 'path';
2
- import chalk from 'chalk';
3
- import { Command } from 'commander';
4
- import ora from 'ora';
5
- import { detectMonorepoContext } from '../../../utils/monorepo.js';
6
- import { StartupAlreadyExistsError, InvalidStartupNameError, NotInMonorepoRootError } from '../errors/startup-errors.js';
7
- import { StartupService } from '../services/startup-service.js';
8
- export function createStartupCommand() {
9
- return new Command('startup:create')
10
- .argument('<name>', 'Name of the startup (lowercase, alphanumeric, hyphens)')
11
- .description('Create a new startup with brand configuration')
12
- .action(async (name) => {
13
- console.log(chalk.blue(`\n🚀 Creating startup: ${name}\n`));
14
- const service = new StartupService();
15
- try {
16
- const spinner = ora('Creating startup structure...').start();
17
- // Detect monorepo context
18
- const context = await detectMonorepoContext(process.cwd());
19
- const result = await service.createStartup({ name }, context);
20
- spinner.succeed('Startup structure created');
21
- // Success message
22
- const cwd = process.cwd();
23
- console.log(chalk.green(`\n✅ Startup created successfully at ${path.relative(cwd, result.startupPath)}`));
24
- console.log(chalk.gray(`\nNext steps:\n` + ` 1. Create your first app:\n` + ` - Web app: launch77 create-app webapp <app-name>\n` + ` - API: launch77 create-app api <app-name>\n` + ` - Marketing site: launch77 create-app marketing-site <app-name>\n`));
25
- }
26
- catch (error) {
27
- if (error instanceof StartupAlreadyExistsError) {
28
- console.error(chalk.red(`\n❌ ${error.message}\n`));
29
- process.exit(1);
30
- }
31
- if (error instanceof InvalidStartupNameError) {
32
- console.error(chalk.red(`\n❌ ${error.message}\n`));
33
- process.exit(1);
34
- }
35
- if (error instanceof NotInMonorepoRootError) {
36
- console.error(chalk.red(`\n❌ ${error.message}\n`));
37
- process.exit(1);
38
- }
39
- throw error;
40
- }
41
- });
42
- }
43
- //# sourceMappingURL=create-startup.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-startup.js","sourceRoot":"","sources":["../../../../src/modules/startup/commands/create-startup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAE5B,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,GAAG,MAAM,KAAK,CAAA;AAErB,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAClE,OAAO,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AACxH,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAE/D,MAAM,UAAU,oBAAoB;IAClC,OAAO,IAAI,OAAO,CAAC,gBAAgB,CAAC;SACjC,QAAQ,CAAC,QAAQ,EAAE,wDAAwD,CAAC;SAC5E,WAAW,CAAC,+CAA+C,CAAC;SAC5D,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,IAAI,IAAI,CAAC,CAAC,CAAA;QAE3D,MAAM,OAAO,GAAG,IAAI,cAAc,EAAE,CAAA;QAEpC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,GAAG,CAAC,+BAA+B,CAAC,CAAC,KAAK,EAAE,CAAA;YAE5D,0BAA0B;YAC1B,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;YAE1D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,CAAA;YAE7D,OAAO,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAA;YAE5C,kBAAkB;YAClB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;YACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,uCAAuC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAA;YACzG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,GAAG,+BAA+B,GAAG,yDAAyD,GAAG,kDAAkD,GAAG,wEAAwE,CAAC,CAAC,CAAA;QAC1Q,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,yBAAyB,EAAE,CAAC;gBAC/C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,CAAA;gBAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YAED,IAAI,KAAK,YAAY,uBAAuB,EAAE,CAAC;gBAC7C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,CAAA;gBAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YAED,IAAI,KAAK,YAAY,sBAAsB,EAAE,CAAC;gBAC5C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,CAAA;gBAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YAED,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC,CAAC,CAAA;AACN,CAAC"}
@@ -1,13 +0,0 @@
1
- export declare class StartupAlreadyExistsError extends Error {
2
- startupName: string;
3
- startupPath: string;
4
- constructor(startupName: string, startupPath: string);
5
- }
6
- export declare class InvalidStartupNameError extends Error {
7
- startupName: string;
8
- constructor(startupName: string);
9
- }
10
- export declare class NotInMonorepoRootError extends Error {
11
- constructor();
12
- }
13
- //# sourceMappingURL=startup-errors.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"startup-errors.d.ts","sourceRoot":"","sources":["../../../../src/modules/startup/errors/startup-errors.ts"],"names":[],"mappings":"AAAA,qBAAa,yBAA0B,SAAQ,KAAK;IAEzC,WAAW,EAAE,MAAM;IACnB,WAAW,EAAE,MAAM;gBADnB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM;CAK7B;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAC7B,WAAW,EAAE,MAAM;gBAAnB,WAAW,EAAE,MAAM;CAIvC;AAED,qBAAa,sBAAuB,SAAQ,KAAK;;CAKhD"}
@@ -1,25 +0,0 @@
1
- export class StartupAlreadyExistsError extends Error {
2
- startupName;
3
- startupPath;
4
- constructor(startupName, startupPath) {
5
- super(`Startup ${startupName} already exists at ${startupPath}`);
6
- this.startupName = startupName;
7
- this.startupPath = startupPath;
8
- this.name = 'StartupAlreadyExistsError';
9
- }
10
- }
11
- export class InvalidStartupNameError extends Error {
12
- startupName;
13
- constructor(startupName) {
14
- super(`Invalid startup name: "${startupName}"\n\n` + `Startup names must:\n` + ` • Be lowercase only\n` + ` • Can only contain: lowercase letters, numbers, and hyphens\n` + ` • Cannot contain: spaces, uppercase, underscores, periods, or special characters\n\n` + `Valid examples:\n` + ` ✓ my-startup\n` + ` ✓ mystartup\n` + ` ✓ startup123\n\n` + `Invalid examples:\n` + ` ✗ MyStartup (uppercase)\n` + ` ✗ my_startup (underscores)\n` + ` ✗ my.startup (periods)\n` + ` ✗ my startup (spaces)`);
15
- this.startupName = startupName;
16
- this.name = 'InvalidStartupNameError';
17
- }
18
- }
19
- export class NotInMonorepoRootError extends Error {
20
- constructor() {
21
- super('Must be run from the monorepo root directory (could not find .launch-monorepo-root.md)');
22
- this.name = 'NotInMonorepoRootError';
23
- }
24
- }
25
- //# sourceMappingURL=startup-errors.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"startup-errors.js","sourceRoot":"","sources":["../../../../src/modules/startup/errors/startup-errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAEzC;IACA;IAFT,YACS,WAAmB,EACnB,WAAmB;QAE1B,KAAK,CAAC,WAAW,WAAW,sBAAsB,WAAW,EAAE,CAAC,CAAA;QAHzD,gBAAW,GAAX,WAAW,CAAQ;QACnB,gBAAW,GAAX,WAAW,CAAQ;QAG1B,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAA;IACzC,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAC7B;IAAnB,YAAmB,WAAmB;QACpC,KAAK,CAAC,0BAA0B,WAAW,OAAO,GAAG,uBAAuB,GAAG,yBAAyB,GAAG,iEAAiE,GAAG,wFAAwF,GAAG,mBAAmB,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,oBAAoB,GAAG,qBAAqB,GAAG,6BAA6B,GAAG,gCAAgC,GAAG,4BAA4B,GAAG,yBAAyB,CAAC,CAAA;QADne,gBAAW,GAAX,WAAW,CAAQ;QAEpC,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAA;IACvC,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C;QACE,KAAK,CAAC,wFAAwF,CAAC,CAAA;QAC/F,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAA;IACtC,CAAC;CACF"}
@@ -1,5 +0,0 @@
1
- export { StartupService } from './services/startup-service.js';
2
- export type { CreateStartupRequest, CreateStartupResult } from './types/startup-types.js';
3
- export { StartupAlreadyExistsError, InvalidStartupNameError, NotInMonorepoRootError } from './errors/startup-errors.js';
4
- export { createStartupCommand } from './commands/create-startup.js';
5
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/startup/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAG9D,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAGzF,OAAO,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAGvH,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA"}
@@ -1,7 +0,0 @@
1
- // Services
2
- export { StartupService } from './services/startup-service.js';
3
- // Errors
4
- export { StartupAlreadyExistsError, InvalidStartupNameError, NotInMonorepoRootError } from './errors/startup-errors.js';
5
- // Command
6
- export { createStartupCommand } from './commands/create-startup.js';
7
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/startup/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAK9D,SAAS;AACT,OAAO,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAEvH,UAAU;AACV,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA"}
@@ -1,7 +0,0 @@
1
- import type { MonorepoContext } from '../../../utils/monorepo.js';
2
- import type { CreateStartupRequest, CreateStartupResult } from '../types/startup-types.js';
3
- export declare class StartupService {
4
- createStartup(request: CreateStartupRequest, context: MonorepoContext): Promise<CreateStartupResult>;
5
- private getTemplatePath;
6
- }
7
- //# sourceMappingURL=startup-service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"startup-service.d.ts","sourceRoot":"","sources":["../../../../src/modules/startup/services/startup-service.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AACjE,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAE1F,qBAAa,cAAc;IACnB,aAAa,CAAC,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAiC1G,OAAO,CAAC,eAAe;CAYxB"}
@@ -1,43 +0,0 @@
1
- import * as path from 'path';
2
- import { fileURLToPath } from 'url';
3
- import * as filesystem from '../../../infrastructure/filesystem.js';
4
- import { StartupAlreadyExistsError, NotInMonorepoRootError } from '../errors/startup-errors.js';
5
- import { validateStartupName } from '../utils/startup-validators.js';
6
- export class StartupService {
7
- async createStartup(request, context) {
8
- const { name } = request;
9
- // 1. Validate name
10
- validateStartupName(name);
11
- // 2. Verify we found the monorepo
12
- if (!context.isValid) {
13
- throw new NotInMonorepoRootError();
14
- }
15
- // 3. Determine startup path
16
- const startupsDir = path.join(context.monorepoRoot, 'startups');
17
- const startupPath = path.join(startupsDir, name);
18
- // 4. Check if startup already exists
19
- if (await filesystem.exists(startupPath)) {
20
- throw new StartupAlreadyExistsError(name, startupPath);
21
- }
22
- // 5. Ensure startups directory exists
23
- await filesystem.ensureDir(startupsDir);
24
- // 6. Copy template
25
- const templatePath = this.getTemplatePath();
26
- await filesystem.copy(templatePath, startupPath);
27
- return {
28
- startupPath,
29
- name,
30
- };
31
- }
32
- getTemplatePath() {
33
- const __filename = fileURLToPath(import.meta.url);
34
- const __dirname = path.dirname(__filename);
35
- // From src/modules/startup/services/ or dist/modules/startup/services/ up to cli root
36
- const isDev = __filename.includes('/src/');
37
- const cliRoot = isDev
38
- ? path.join(__dirname, '../../../..') // src/modules/startup/services -> cli root
39
- : path.join(__dirname, '../../../..'); // dist/modules/startup/services -> cli root
40
- return path.join(cliRoot, 'templates/startup');
41
- }
42
- }
43
- //# sourceMappingURL=startup-service.js.map