@launch77/cli 1.4.4 → 1.5.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.
- package/CHANGELOG.md +11 -0
- package/dist/cli.js +1 -4
- package/dist/cli.js.map +1 -1
- package/dist/infrastructure/package-resolver.d.ts +12 -2
- package/dist/infrastructure/package-resolver.d.ts.map +1 -1
- package/dist/infrastructure/package-resolver.js +29 -2
- package/dist/infrastructure/package-resolver.js.map +1 -1
- package/dist/infrastructure/package-resolver.test.js +3 -3
- package/dist/infrastructure/package-resolver.test.js.map +1 -1
- package/dist/infrastructure/template.d.ts +0 -1
- package/dist/infrastructure/template.d.ts.map +1 -1
- package/dist/infrastructure/template.js.map +1 -1
- package/dist/modules/app/commands/create-app.d.ts.map +1 -1
- package/dist/modules/app/commands/create-app.js +8 -13
- package/dist/modules/app/commands/create-app.js.map +1 -1
- package/dist/modules/app/commands/delete-app.js +1 -1
- package/dist/modules/app/commands/delete-app.js.map +1 -1
- package/dist/modules/app/commands/validate-manifest.d.ts.map +1 -1
- package/dist/modules/app/commands/validate-manifest.js +0 -1
- package/dist/modules/app/commands/validate-manifest.js.map +1 -1
- package/dist/modules/app/index.d.ts +1 -2
- package/dist/modules/app/index.d.ts.map +1 -1
- package/dist/modules/app/index.js +0 -1
- package/dist/modules/app/index.js.map +1 -1
- package/dist/modules/app/lib/app-template-resolver.d.ts.map +1 -1
- package/dist/modules/app/lib/app-template-resolver.js +15 -0
- package/dist/modules/app/lib/app-template-resolver.js.map +1 -1
- package/dist/modules/app/lib/manifest-schema.d.ts +0 -7
- package/dist/modules/app/lib/manifest-schema.d.ts.map +1 -1
- package/dist/modules/app/lib/manifest-schema.js +0 -2
- package/dist/modules/app/lib/manifest-schema.js.map +1 -1
- package/dist/modules/app/services/app-svc.d.ts.map +1 -1
- package/dist/modules/app/services/app-svc.js +36 -6
- package/dist/modules/app/services/app-svc.js.map +1 -1
- package/dist/modules/app/services/manifest-svc.d.ts +2 -2
- package/dist/modules/app/services/manifest-svc.d.ts.map +1 -1
- package/dist/modules/app/services/manifest-svc.js +9 -50
- package/dist/modules/app/services/manifest-svc.js.map +1 -1
- package/dist/modules/app/types/app-types.d.ts +2 -5
- package/dist/modules/app/types/app-types.d.ts.map +1 -1
- package/dist/modules/app/types/app-types.js +1 -4
- package/dist/modules/app/types/app-types.js.map +1 -1
- package/dist/modules/catalog/commands/scan.js +3 -3
- package/dist/modules/catalog/commands/scan.js.map +1 -1
- package/dist/modules/catalog/services/catalog-svc.d.ts +2 -2
- package/dist/modules/catalog/services/catalog-svc.d.ts.map +1 -1
- package/dist/modules/catalog/services/catalog-svc.js +2 -2
- package/dist/modules/catalog/services/catalog-svc.js.map +1 -1
- package/dist/modules/deploy/commands/deploy-init-action.d.ts.map +1 -1
- package/dist/modules/deploy/commands/deploy-init-action.js +21 -20
- package/dist/modules/deploy/commands/deploy-init-action.js.map +1 -1
- package/dist/modules/deploy/commands/deploy-logs-action.d.ts.map +1 -1
- package/dist/modules/deploy/commands/deploy-logs-action.js +16 -13
- package/dist/modules/deploy/commands/deploy-logs-action.js.map +1 -1
- package/dist/modules/deploy/commands/deploy-status-action.d.ts.map +1 -1
- package/dist/modules/deploy/commands/deploy-status-action.js +16 -13
- package/dist/modules/deploy/commands/deploy-status-action.js.map +1 -1
- package/dist/modules/plugin/lib/plugin-resolver.d.ts.map +1 -1
- package/dist/modules/plugin/lib/plugin-resolver.js +13 -2
- package/dist/modules/plugin/lib/plugin-resolver.js.map +1 -1
- package/dist/modules/plugin/lib/plugin-resolver.test.js +2 -0
- package/dist/modules/plugin/lib/plugin-resolver.test.js.map +1 -1
- package/dist/modules/plugin/services/plugin-svc.d.ts.map +1 -1
- package/dist/modules/plugin/services/plugin-svc.js +10 -2
- package/dist/modules/plugin/services/plugin-svc.js.map +1 -1
- package/dist/modules/plugin/services/plugin-svc.test.js +12 -6
- package/dist/modules/plugin/services/plugin-svc.test.js.map +1 -1
- package/dist/templates/plugin/package.json.hbs +1 -1
- package/dist/templates/plugin/plugin.json.hbs +1 -3
- package/dist/utils/validation.d.ts +3 -7
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +7 -31
- package/dist/utils/validation.js.map +1 -1
- package/package.json +1 -1
- package/src/cli.ts +1 -4
- package/src/infrastructure/package-resolver.test.ts +3 -3
- package/src/infrastructure/package-resolver.ts +31 -2
- package/src/infrastructure/template.ts +0 -1
- package/src/modules/app/commands/create-app.ts +8 -16
- package/src/modules/app/commands/delete-app.ts +1 -1
- package/src/modules/app/commands/validate-manifest.ts +0 -1
- package/src/modules/app/index.ts +1 -2
- package/src/modules/app/lib/app-template-resolver.ts +16 -0
- package/src/modules/app/lib/manifest-schema.ts +0 -5
- package/src/modules/app/services/app-svc.ts +46 -7
- package/src/modules/app/services/manifest-svc.ts +8 -57
- package/src/modules/app/types/app-types.ts +2 -9
- package/src/modules/catalog/commands/scan.ts +3 -3
- package/src/modules/catalog/services/catalog-svc.ts +4 -4
- package/src/modules/deploy/commands/deploy-init-action.ts +23 -20
- package/src/modules/deploy/commands/deploy-logs-action.ts +19 -13
- package/src/modules/deploy/commands/deploy-status-action.ts +19 -13
- package/src/modules/plugin/lib/plugin-resolver.test.ts +2 -0
- package/src/modules/plugin/lib/plugin-resolver.ts +13 -2
- package/src/modules/plugin/services/plugin-svc.test.ts +12 -6
- package/src/modules/plugin/services/plugin-svc.ts +12 -3
- package/src/utils/validation.ts +10 -38
- package/templates/plugin/package.json.hbs +1 -1
- package/templates/plugin/plugin.json.hbs +1 -3
- package/dist/modules/app/commands/generate-manifest.d.ts +0 -3
- package/dist/modules/app/commands/generate-manifest.d.ts.map +0 -1
- package/dist/modules/app/commands/generate-manifest.js +0 -62
- package/dist/modules/app/commands/generate-manifest.js.map +0 -1
- package/dist/modules/startup/commands/create-startup.d.ts +0 -3
- package/dist/modules/startup/commands/create-startup.d.ts.map +0 -1
- package/dist/modules/startup/commands/create-startup.js +0 -43
- package/dist/modules/startup/commands/create-startup.js.map +0 -1
- package/dist/modules/startup/errors/startup-errors.d.ts +0 -13
- package/dist/modules/startup/errors/startup-errors.d.ts.map +0 -1
- package/dist/modules/startup/errors/startup-errors.js +0 -25
- package/dist/modules/startup/errors/startup-errors.js.map +0 -1
- package/dist/modules/startup/index.d.ts +0 -5
- package/dist/modules/startup/index.d.ts.map +0 -1
- package/dist/modules/startup/index.js +0 -7
- package/dist/modules/startup/index.js.map +0 -1
- package/dist/modules/startup/services/startup-service.d.ts +0 -7
- package/dist/modules/startup/services/startup-service.d.ts.map +0 -1
- package/dist/modules/startup/services/startup-service.js +0 -43
- package/dist/modules/startup/services/startup-service.js.map +0 -1
- package/dist/modules/startup/types/startup-types.d.ts +0 -8
- package/dist/modules/startup/types/startup-types.d.ts.map +0 -1
- package/dist/modules/startup/types/startup-types.js +0 -2
- package/dist/modules/startup/types/startup-types.js.map +0 -1
- package/dist/modules/startup/utils/startup-validators.d.ts +0 -8
- package/dist/modules/startup/utils/startup-validators.d.ts.map +0 -1
- package/dist/modules/startup/utils/startup-validators.js +0 -17
- package/dist/modules/startup/utils/startup-validators.js.map +0 -1
- package/dist/templates/startup/apps/.gitkeep +0 -8
- package/dist/utils/monorepo.d.ts +0 -19
- package/dist/utils/monorepo.d.ts.map +0 -1
- package/dist/utils/monorepo.js +0 -100
- package/dist/utils/monorepo.js.map +0 -1
- package/src/modules/app/commands/generate-manifest.ts +0 -75
- package/src/modules/startup/commands/create-startup.ts +0 -53
- package/src/modules/startup/errors/startup-errors.ts +0 -23
- package/src/modules/startup/index.ts +0 -11
- package/src/modules/startup/services/startup-service.ts +0 -57
- package/src/modules/startup/types/startup-types.ts +0 -8
- package/src/modules/startup/utils/startup-validators.ts +0 -19
- package/src/utils/monorepo.ts +0 -137
- package/templates/startup/apps/.gitkeep +0 -8
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
/* eslint-disable no-console */
|
|
6
|
+
import * as path from 'path'
|
|
7
|
+
|
|
6
8
|
import chalk from 'chalk'
|
|
9
|
+
import { detectLaunch77Context } from '@launch77/plugin-runtime'
|
|
10
|
+
import fs from 'fs-extra'
|
|
7
11
|
import ora from 'ora'
|
|
8
12
|
|
|
9
|
-
import { detectMonorepoContext } from '../../../utils/monorepo.js'
|
|
10
13
|
import { DeployService } from '../services/deploy-svc.js'
|
|
11
14
|
import { getVercelInstallInstructions, isVercelCliInstalled, runVercelCommand, verifyVercelProjectExists } from '../utils/vercel-extended.js'
|
|
12
15
|
|
|
@@ -16,11 +19,11 @@ import { getVercelInstallInstructions, isVercelCliInstalled, runVercelCommand, v
|
|
|
16
19
|
export async function deployStatus() {
|
|
17
20
|
const deployService = new DeployService()
|
|
18
21
|
|
|
19
|
-
// Detect
|
|
20
|
-
const context = await
|
|
22
|
+
// Detect Launch77 context
|
|
23
|
+
const context = await detectLaunch77Context(process.cwd())
|
|
21
24
|
|
|
22
|
-
if (context.
|
|
23
|
-
throw new Error('Must be run from within an app directory (e.g.,
|
|
25
|
+
if (context.locationType !== 'workspace-app') {
|
|
26
|
+
throw new Error('Must be run from within an app directory (e.g., apps/myapp)')
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
const appPath = process.cwd()
|
|
@@ -30,14 +33,17 @@ export async function deployStatus() {
|
|
|
30
33
|
// Load manifest
|
|
31
34
|
const manifest = await deployService.loadManifest()
|
|
32
35
|
|
|
33
|
-
// Check
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
// Check template type from app's package.json
|
|
37
|
+
const appPackageJsonPath = path.join(appPath, 'package.json')
|
|
38
|
+
const appPackageJson = await fs.readJson(appPackageJsonPath)
|
|
39
|
+
const templatePackage = appPackageJson.launch77?.template?.package
|
|
40
|
+
|
|
41
|
+
// Only allow webapp apps to deploy to Vercel
|
|
42
|
+
const isWebapp = templatePackage === 'webapp' || templatePackage === '@launch77-shared/app-template-webapp'
|
|
43
|
+
|
|
44
|
+
if (!isWebapp) {
|
|
45
|
+
console.log(chalk.yellow('⚠️ Vercel deployment only supports webapp apps'))
|
|
46
|
+
console.log(chalk.gray('Other app types coming soon'))
|
|
41
47
|
console.log()
|
|
42
48
|
return
|
|
43
49
|
}
|
|
@@ -120,6 +120,7 @@ describe('Plugin Resolver', () => {
|
|
|
120
120
|
await fs.ensureDir(pluginPath)
|
|
121
121
|
await fs.ensureDir(path.join(pluginPath, 'dist'))
|
|
122
122
|
await fs.writeFile(path.join(pluginPath, 'plugin.json'), JSON.stringify({ name: 'my-plugin', version: '1.0.0' }))
|
|
123
|
+
await fs.writeFile(path.join(pluginPath, 'package.json'), JSON.stringify({ name: 'my-plugin', version: '0.0.1' }))
|
|
123
124
|
await fs.writeFile(path.join(pluginPath, 'dist/generator.js'), 'console.log("test")')
|
|
124
125
|
|
|
125
126
|
const result = await resolver.resolveLocation('my-plugin', tempDir)
|
|
@@ -128,6 +129,7 @@ describe('Plugin Resolver', () => {
|
|
|
128
129
|
source: 'local',
|
|
129
130
|
resolvedName: 'my-plugin',
|
|
130
131
|
localPath: pluginPath,
|
|
132
|
+
version: '0.0.1',
|
|
131
133
|
})
|
|
132
134
|
})
|
|
133
135
|
|
|
@@ -21,10 +21,21 @@ export class PluginResolver extends PackageResolver {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
protected async verify(localPath: string): Promise<boolean> {
|
|
24
|
-
// Verify it's a valid plugin (has plugin.json
|
|
24
|
+
// Verify it's a valid plugin (has plugin.json, dist/generator.js, and package.json with version)
|
|
25
25
|
const hasPluginJson = await fs.pathExists(path.join(localPath, 'plugin.json'))
|
|
26
26
|
const hasGenerator = await fs.pathExists(path.join(localPath, 'dist/generator.js'))
|
|
27
|
+
const hasPackageJson = await fs.pathExists(path.join(localPath, 'package.json'))
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
if (!hasPluginJson || !hasGenerator || !hasPackageJson) {
|
|
30
|
+
return false
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Verify package.json has a version field
|
|
34
|
+
try {
|
|
35
|
+
const packageJson = await fs.readJson(path.join(localPath, 'package.json'))
|
|
36
|
+
return !!packageJson.version
|
|
37
|
+
} catch {
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
29
40
|
}
|
|
30
41
|
}
|
|
@@ -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
|
|
179
|
-
|
|
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
|
|
195
|
-
|
|
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
|
|
@@ -50,7 +50,7 @@ export class PluginService {
|
|
|
50
50
|
/**
|
|
51
51
|
* Validate plugin name, resolve its location, and download if needed
|
|
52
52
|
*/
|
|
53
|
-
private async validateAndResolvePlugin(pluginName: string, workspaceRoot: string, logger: (message: string) => void): Promise<{ pluginPath: string; source: 'local' | 'npm'; npmPackage?: string }> {
|
|
53
|
+
private async validateAndResolvePlugin(pluginName: string, workspaceRoot: string, logger: (message: string) => void): Promise<{ pluginPath: string; source: 'local' | 'npm'; npmPackage?: string; version: string }> {
|
|
54
54
|
logger(chalk.blue(`\n🔍 Resolving plugin "${pluginName}"...`))
|
|
55
55
|
logger(` ├─ Validating plugin name...`)
|
|
56
56
|
|
|
@@ -64,15 +64,23 @@ export class PluginService {
|
|
|
64
64
|
const resolution = await this.pluginResolver.resolveLocation(pluginName, workspaceRoot)
|
|
65
65
|
|
|
66
66
|
let pluginPath: string
|
|
67
|
+
let version: string
|
|
67
68
|
|
|
68
69
|
if (resolution.source === 'local') {
|
|
69
70
|
logger(` │ └─ ${chalk.green('✓')} Found local plugin`)
|
|
70
71
|
pluginPath = resolution.localPath!
|
|
72
|
+
version = resolution.version! // Local plugins always have version after verification
|
|
71
73
|
} else {
|
|
72
74
|
logger(` │ └─ ${chalk.dim('Not found locally')}`)
|
|
73
75
|
logger(` ├─ Resolving to npm package: ${chalk.cyan(resolution.npmPackage)}`)
|
|
74
76
|
|
|
75
77
|
pluginPath = await this.downloadNpmPlugin(resolution.npmPackage!, workspaceRoot, logger)
|
|
78
|
+
|
|
79
|
+
// Read version from downloaded package
|
|
80
|
+
const packageJsonPath = path.join(pluginPath, 'package.json')
|
|
81
|
+
const packageJsonContent = await fs.readFile(packageJsonPath, 'utf-8')
|
|
82
|
+
const packageJson = JSON.parse(packageJsonContent)
|
|
83
|
+
version = packageJson.version
|
|
76
84
|
}
|
|
77
85
|
|
|
78
86
|
logger(` └─ ${chalk.green('✓')} Plugin resolved\n`)
|
|
@@ -81,6 +89,7 @@ export class PluginService {
|
|
|
81
89
|
pluginPath,
|
|
82
90
|
source: resolution.source,
|
|
83
91
|
npmPackage: resolution.npmPackage,
|
|
92
|
+
version,
|
|
84
93
|
}
|
|
85
94
|
}
|
|
86
95
|
|
|
@@ -130,7 +139,7 @@ export class PluginService {
|
|
|
130
139
|
const { pluginName } = request
|
|
131
140
|
|
|
132
141
|
const currentTarget = this.validateContext(context)
|
|
133
|
-
const { pluginPath, source, npmPackage } = await this.validateAndResolvePlugin(pluginName, context.workspaceRoot, logger)
|
|
142
|
+
const { pluginPath, source, npmPackage, version } = await this.validateAndResolvePlugin(pluginName, context.workspaceRoot, logger)
|
|
134
143
|
const metadata = await this.validatePluginTargets(pluginPath, pluginName, currentTarget)
|
|
135
144
|
|
|
136
145
|
const packagePath = this.getPackagePath(context)
|
|
@@ -143,7 +152,7 @@ export class PluginService {
|
|
|
143
152
|
await this.writePluginManifest(packagePath, {
|
|
144
153
|
pluginName,
|
|
145
154
|
packageName,
|
|
146
|
-
version
|
|
155
|
+
version,
|
|
147
156
|
source,
|
|
148
157
|
})
|
|
149
158
|
|
package/src/utils/validation.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as path from 'path'
|
|
|
2
2
|
|
|
3
3
|
import chalk from 'chalk'
|
|
4
4
|
|
|
5
|
-
import type {
|
|
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:
|
|
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
|
|
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
|
|
55
|
-
if (context.
|
|
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.
|
|
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:
|
|
77
|
-
if (context.
|
|
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.
|
|
53
|
+
if (!context.workspaceRoot || !context.appName) {
|
|
82
54
|
return null
|
|
83
55
|
}
|
|
84
56
|
|
|
85
|
-
return path.join(context.
|
|
57
|
+
return path.join(context.workspaceRoot, 'apps', context.appName)
|
|
86
58
|
}
|
|
87
59
|
|
|
88
60
|
/**
|
|
@@ -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 +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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"startup-service.js","sourceRoot":"","sources":["../../../../src/modules/startup/services/startup-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AAEnC,OAAO,KAAK,UAAU,MAAM,uCAAuC,CAAA;AACnE,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AAC/F,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AAKpE,MAAM,OAAO,cAAc;IACzB,KAAK,CAAC,aAAa,CAAC,OAA6B,EAAE,OAAwB;QACzE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;QAExB,mBAAmB;QACnB,mBAAmB,CAAC,IAAI,CAAC,CAAA;QAEzB,kCAAkC;QAClC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACrB,MAAM,IAAI,sBAAsB,EAAE,CAAA;QACpC,CAAC;QAED,4BAA4B;QAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;QAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;QAEhD,qCAAqC;QACrC,IAAI,MAAM,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,yBAAyB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;QACxD,CAAC;QAED,sCAAsC;QACtC,MAAM,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;QAEvC,mBAAmB;QACnB,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,EAAE,CAAA;QAC3C,MAAM,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAA;QAEhD,OAAO;YACL,WAAW;YACX,IAAI;SACL,CAAA;IACH,CAAC;IAEO,eAAe;QACrB,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;QAE1C,sFAAsF;QACtF,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC1C,MAAM,OAAO,GAAG,KAAK;YACnB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,2CAA2C;YACjF,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA,CAAC,4CAA4C;QAEpF,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAA;IAChD,CAAC;CACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"startup-types.d.ts","sourceRoot":"","sources":["../../../../src/modules/startup/types/startup-types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;CACb"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"startup-types.js","sourceRoot":"","sources":["../../../../src/modules/startup/types/startup-types.ts"],"names":[],"mappings":""}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Validate startup name format
|
|
3
|
-
* - Must be lowercase
|
|
4
|
-
* - Can only contain lowercase letters, numbers, and hyphens
|
|
5
|
-
* - Cannot contain spaces, uppercase, underscores, periods, or special characters
|
|
6
|
-
*/
|
|
7
|
-
export declare function validateStartupName(name: string): void;
|
|
8
|
-
//# sourceMappingURL=startup-validators.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"startup-validators.d.ts","sourceRoot":"","sources":["../../../../src/modules/startup/utils/startup-validators.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAUtD"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { InvalidStartupNameError } from '../errors/startup-errors.js';
|
|
2
|
-
/**
|
|
3
|
-
* Validate startup name format
|
|
4
|
-
* - Must be lowercase
|
|
5
|
-
* - Can only contain lowercase letters, numbers, and hyphens
|
|
6
|
-
* - Cannot contain spaces, uppercase, underscores, periods, or special characters
|
|
7
|
-
*/
|
|
8
|
-
export function validateStartupName(name) {
|
|
9
|
-
if (!name || name.trim().length === 0) {
|
|
10
|
-
throw new Error('Startup name cannot be empty');
|
|
11
|
-
}
|
|
12
|
-
const validPattern = /^[a-z0-9-]+$/;
|
|
13
|
-
if (!validPattern.test(name)) {
|
|
14
|
-
throw new InvalidStartupNameError(name);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=startup-validators.js.map
|