@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.
- package/CHANGELOG.md +17 -0
- package/dist/cli.js +16 -17
- 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 +1 -1
- package/dist/modules/app/commands/create-app.d.ts.map +1 -1
- package/dist/modules/app/commands/create-app.js +9 -14
- package/dist/modules/app/commands/create-app.js.map +1 -1
- package/dist/modules/app/commands/delete-app.d.ts +1 -1
- package/dist/modules/app/commands/delete-app.js +2 -2
- package/dist/modules/app/commands/delete-app.js.map +1 -1
- package/dist/modules/app/index.d.ts +3 -5
- package/dist/modules/app/index.d.ts.map +1 -1
- package/dist/modules/app/index.js +2 -4
- 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/generate.d.ts +1 -1
- package/dist/modules/catalog/commands/generate.d.ts.map +1 -1
- package/dist/modules/catalog/commands/generate.js +1 -1
- package/dist/modules/catalog/commands/generate.js.map +1 -1
- package/dist/modules/catalog/commands/scan.d.ts +1 -1
- package/dist/modules/catalog/commands/scan.d.ts.map +1 -1
- package/dist/modules/catalog/commands/scan.js +4 -4
- 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/library/commands/delete-library.d.ts +3 -0
- package/dist/modules/library/commands/delete-library.d.ts.map +1 -0
- package/dist/modules/library/commands/delete-library.js +111 -0
- package/dist/modules/library/commands/delete-library.js.map +1 -0
- package/dist/modules/library/errors/library-errors.d.ts +7 -0
- package/dist/modules/library/errors/library-errors.d.ts.map +1 -0
- package/dist/modules/library/errors/library-errors.js +13 -0
- package/dist/modules/library/errors/library-errors.js.map +1 -0
- package/dist/modules/library/index.d.ts +5 -0
- package/dist/modules/library/index.d.ts.map +1 -0
- package/dist/modules/library/index.js +7 -0
- package/dist/modules/library/index.js.map +1 -0
- package/dist/modules/library/services/library-svc.d.ts +9 -0
- package/dist/modules/library/services/library-svc.d.ts.map +1 -0
- package/dist/modules/library/services/library-svc.js +38 -0
- package/dist/modules/library/services/library-svc.js.map +1 -0
- package/dist/modules/library/types/library-types.d.ts +7 -0
- package/dist/modules/library/types/library-types.d.ts.map +1 -0
- package/dist/modules/library/types/library-types.js +2 -0
- package/dist/modules/library/types/library-types.js.map +1 -0
- package/dist/modules/plugin/commands/delete-plugin.d.ts +3 -0
- package/dist/modules/plugin/commands/delete-plugin.d.ts.map +1 -0
- package/dist/modules/plugin/commands/delete-plugin.js +113 -0
- package/dist/modules/plugin/commands/delete-plugin.js.map +1 -0
- package/dist/modules/plugin/errors/plugin-errors.d.ts +12 -0
- package/dist/modules/plugin/errors/plugin-errors.d.ts.map +1 -1
- package/dist/modules/plugin/errors/plugin-errors.js +18 -0
- package/dist/modules/plugin/errors/plugin-errors.js.map +1 -1
- package/dist/modules/plugin/index.d.ts +1 -0
- package/dist/modules/plugin/index.d.ts.map +1 -1
- package/dist/modules/plugin/index.js +1 -0
- package/dist/modules/plugin/index.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 +5 -1
- package/dist/modules/plugin/services/plugin-svc.d.ts.map +1 -1
- package/dist/modules/plugin/services/plugin-svc.js +44 -3
- 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/modules/plugin/types/plugin-types.d.ts +6 -0
- package/dist/modules/plugin/types/plugin-types.d.ts.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 +16 -17
- 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 +9 -17
- package/src/modules/app/commands/delete-app.ts +2 -2
- package/src/modules/app/index.ts +3 -5
- 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/generate.ts +1 -1
- package/src/modules/catalog/commands/scan.ts +4 -4
- 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/library/commands/delete-library.ts +126 -0
- package/src/modules/library/errors/library-errors.ts +13 -0
- package/src/modules/library/index.ts +11 -0
- package/src/modules/library/services/library-svc.ts +50 -0
- package/src/modules/library/types/library-types.ts +7 -0
- package/src/modules/plugin/commands/delete-plugin.ts +128 -0
- package/src/modules/plugin/errors/plugin-errors.ts +20 -0
- package/src/modules/plugin/index.ts +1 -0
- 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 +55 -5
- package/src/modules/plugin/types/plugin-types.ts +8 -0
- 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/app/commands/validate-manifest.d.ts +0 -3
- package/dist/modules/app/commands/validate-manifest.d.ts.map +0 -1
- package/dist/modules/app/commands/validate-manifest.js +0 -68
- package/dist/modules/app/commands/validate-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/app/commands/validate-manifest.ts +0 -78
- 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
package/src/cli.ts
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import { Command } from 'commander'
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { deployInitCommand, deployLogsCommand, deployStatusCommand } from './modules/deploy/index.js'
|
|
5
|
+
import { appCreateCommand, appDeleteCommand } from './modules/app/index.js'
|
|
6
|
+
// import { catalogScanCommand, catalogGenerateCommand } from './modules/catalog/index.js'
|
|
7
|
+
// import { deployInitCommand, deployLogsCommand, deployStatusCommand } from './modules/deploy/index.js'
|
|
8
8
|
import { gitConnectCommand } from './modules/git/index.js'
|
|
9
|
-
import {
|
|
9
|
+
import { libraryDeleteCommand } from './modules/library/index.js'
|
|
10
|
+
import { pluginInstallCommand, pluginCreateCommand, pluginDeleteCommand } from './modules/plugin/index.js'
|
|
10
11
|
import { releaseInitCommand } from './modules/release/index.js'
|
|
11
|
-
import { createStartupCommand } from './modules/startup/index.js'
|
|
12
|
-
import { getPackageVersion } from './utils/version.js'
|
|
13
12
|
import { initWorkspaceCommand } from './modules/workspace/index.js'
|
|
13
|
+
import { getPackageVersion } from './utils/version.js'
|
|
14
14
|
|
|
15
15
|
const program = new Command()
|
|
16
16
|
.name('launch77')
|
|
@@ -19,15 +19,14 @@ const program = new Command()
|
|
|
19
19
|
|
|
20
20
|
// Register module commands
|
|
21
21
|
program.addCommand(initWorkspaceCommand())
|
|
22
|
-
program.addCommand(
|
|
23
|
-
program.addCommand(
|
|
24
|
-
program.addCommand(
|
|
25
|
-
program.addCommand(generateManifestCommand())
|
|
26
|
-
program.addCommand(validateManifestCommand())
|
|
27
|
-
program.addCommand(pluginInstallCommand())
|
|
22
|
+
program.addCommand(appCreateCommand())
|
|
23
|
+
program.addCommand(appDeleteCommand())
|
|
24
|
+
program.addCommand(libraryDeleteCommand())
|
|
28
25
|
program.addCommand(pluginCreateCommand())
|
|
29
|
-
program.addCommand(
|
|
30
|
-
program.addCommand(
|
|
26
|
+
program.addCommand(pluginDeleteCommand())
|
|
27
|
+
program.addCommand(pluginInstallCommand())
|
|
28
|
+
// program.addCommand(catalogGenerateCommand())
|
|
29
|
+
// program.addCommand(catalogScanCommand())
|
|
31
30
|
|
|
32
31
|
// Git commands
|
|
33
32
|
program.addCommand(gitConnectCommand())
|
|
@@ -36,8 +35,8 @@ program.addCommand(gitConnectCommand())
|
|
|
36
35
|
program.addCommand(releaseInitCommand())
|
|
37
36
|
|
|
38
37
|
// Deploy commands
|
|
39
|
-
program.addCommand(deployInitCommand())
|
|
40
|
-
program.addCommand(deployStatusCommand())
|
|
41
|
-
program.addCommand(deployLogsCommand())
|
|
38
|
+
// program.addCommand(deployInitCommand())
|
|
39
|
+
// program.addCommand(deployStatusCommand())
|
|
40
|
+
// program.addCommand(deployLogsCommand())
|
|
42
41
|
|
|
43
42
|
program.parse()
|
|
@@ -177,7 +177,7 @@ describe('PackageResolver', () => {
|
|
|
177
177
|
const packageName = 'my-local-package'
|
|
178
178
|
const localPath = path.join(tempDir, 'test-packages', packageName)
|
|
179
179
|
await fs.ensureDir(localPath)
|
|
180
|
-
await fs.writeJSON(path.join(localPath, 'package.json'), { name: packageName })
|
|
180
|
+
await fs.writeJSON(path.join(localPath, 'package.json'), { name: packageName, version: '0.0.1' })
|
|
181
181
|
|
|
182
182
|
const result = await resolver.resolveLocation(packageName, tempDir)
|
|
183
183
|
|
|
@@ -216,7 +216,7 @@ describe('PackageResolver', () => {
|
|
|
216
216
|
const packageName = 'my-package'
|
|
217
217
|
const localPath = path.join(tempDir, 'test-packages', packageName)
|
|
218
218
|
await fs.ensureDir(localPath)
|
|
219
|
-
await fs.writeJSON(path.join(localPath, 'package.json'), { name: packageName })
|
|
219
|
+
await fs.writeJSON(path.join(localPath, 'package.json'), { name: packageName, version: '0.0.1' })
|
|
220
220
|
|
|
221
221
|
const result = await resolver.resolveLocation(' my-package ', tempDir)
|
|
222
222
|
|
|
@@ -301,7 +301,7 @@ describe('PackageResolver', () => {
|
|
|
301
301
|
const packageName = 'my-package'
|
|
302
302
|
const localPath = path.join(customRoot, 'test-packages', packageName)
|
|
303
303
|
await fs.ensureDir(localPath)
|
|
304
|
-
await fs.writeJSON(path.join(localPath, 'package.json'), { name: packageName })
|
|
304
|
+
await fs.writeJSON(path.join(localPath, 'package.json'), { name: packageName, version: '0.0.1' })
|
|
305
305
|
|
|
306
306
|
const result = await resolver.resolveLocation(packageName, customRoot)
|
|
307
307
|
|
|
@@ -17,6 +17,8 @@ export interface PackageResolution {
|
|
|
17
17
|
localPath?: string
|
|
18
18
|
/** The npm package name if source is 'npm' */
|
|
19
19
|
npmPackage?: string
|
|
20
|
+
/** The version from package.json (required for local packages, undefined for npm until installed) */
|
|
21
|
+
version?: string
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
/**
|
|
@@ -127,6 +129,30 @@ export abstract class PackageResolver {
|
|
|
127
129
|
return `${this.getPackagePrefix()}${trimmedName}`
|
|
128
130
|
}
|
|
129
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Read version from package.json
|
|
134
|
+
* @param packagePath - The path to the package directory
|
|
135
|
+
* @returns The version string from package.json
|
|
136
|
+
* @throws If package.json doesn't exist, can't be read, or is missing the version field
|
|
137
|
+
*/
|
|
138
|
+
private async readVersion(packagePath: string): Promise<string> {
|
|
139
|
+
const packageJsonPath = path.join(packagePath, 'package.json')
|
|
140
|
+
try {
|
|
141
|
+
const packageJson = await fs.readJson(packageJsonPath)
|
|
142
|
+
if (!packageJson.version) {
|
|
143
|
+
throw new Error(`Invalid package structure: package.json at ${packagePath} is missing required version field. ` + `All Launch77 packages must include a valid package.json with a version field.`)
|
|
144
|
+
}
|
|
145
|
+
return packageJson.version
|
|
146
|
+
} catch (error) {
|
|
147
|
+
// Re-throw our own error messages
|
|
148
|
+
if (error instanceof Error && error.message.includes('Invalid package structure')) {
|
|
149
|
+
throw error
|
|
150
|
+
}
|
|
151
|
+
// File not found or invalid JSON
|
|
152
|
+
throw new Error(`Invalid package structure: package.json not found or invalid at ${packagePath}. ` + `All Launch77 packages must include a valid package.json with a version field.`)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
130
156
|
/**
|
|
131
157
|
* Resolve package location from name
|
|
132
158
|
*
|
|
@@ -134,15 +160,16 @@ export abstract class PackageResolver {
|
|
|
134
160
|
* 1. Check local workspace directory (configured by getFolderName())
|
|
135
161
|
* 2. Verify local package is valid (using verify())
|
|
136
162
|
* 3. Fall back to npm package name (with configured prefix)
|
|
163
|
+
* 4. Read version from package.json (if available)
|
|
137
164
|
*
|
|
138
165
|
* @param name - The package name to resolve
|
|
139
166
|
* @param workspaceRoot - The workspace root directory
|
|
140
|
-
* @returns PackageResolution with source
|
|
167
|
+
* @returns PackageResolution with source, resolved location, and version
|
|
141
168
|
*
|
|
142
169
|
* @example
|
|
143
170
|
* // Local package found
|
|
144
171
|
* await resolveLocation('my-package', '/workspace')
|
|
145
|
-
* // { source: 'local', resolvedName: 'my-package', localPath: '/workspace/plugins/my-package' }
|
|
172
|
+
* // { source: 'local', resolvedName: 'my-package', localPath: '/workspace/plugins/my-package', version: '1.0.0' }
|
|
146
173
|
*
|
|
147
174
|
* // Not found locally, resolve to npm
|
|
148
175
|
* await resolveLocation('release', '/workspace')
|
|
@@ -174,10 +201,12 @@ export abstract class PackageResolver {
|
|
|
174
201
|
const isValid = await this.verify(localPath)
|
|
175
202
|
|
|
176
203
|
if (isValid) {
|
|
204
|
+
const version = await this.readVersion(localPath)
|
|
177
205
|
return {
|
|
178
206
|
source: 'local',
|
|
179
207
|
resolvedName: trimmedName,
|
|
180
208
|
localPath,
|
|
209
|
+
version,
|
|
181
210
|
}
|
|
182
211
|
}
|
|
183
212
|
}
|
|
@@ -7,27 +7,19 @@ import ora from 'ora'
|
|
|
7
7
|
|
|
8
8
|
import { detectLaunch77Context } from '@launch77/plugin-runtime'
|
|
9
9
|
import { AppService } from '../services/app-svc.js'
|
|
10
|
-
import { APP_TYPES, APP_TYPES_LIST } from '../types/app-types.js'
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
export function createAppCommand(): Command {
|
|
11
|
+
export function appCreateCommand(): Command {
|
|
15
12
|
const command = new Command('app:create')
|
|
16
|
-
.argument('<
|
|
13
|
+
.argument('<template>', 'App template name (e.g., webapp, api, marketing-site)')
|
|
17
14
|
.argument('<app-name>', 'Name of the application')
|
|
18
|
-
.description('Create a new application')
|
|
19
|
-
.option('-p, --port <port>', 'Default port for the app')
|
|
20
|
-
.action(async (
|
|
15
|
+
.description('Create a new application from a template')
|
|
16
|
+
.option('-p, --port <port>', 'Default port for the app (default: 3000)')
|
|
17
|
+
.action(async (template: string, appName: string, options) => {
|
|
21
18
|
try {
|
|
22
|
-
|
|
23
|
-
if (!APP_TYPES.includes(type as AppType)) {
|
|
24
|
-
throw new Error(`Invalid app type: ${type}\n\nSupported types: ${APP_TYPES_LIST}`)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
console.log(chalk.blue(`\n🚀 Creating ${type} app: ${appName}\n`))
|
|
19
|
+
console.log(chalk.blue(`\n🚀 Creating app: ${appName} from template: ${template}\n`))
|
|
28
20
|
|
|
29
|
-
// Set default port
|
|
30
|
-
const port = options.port ||
|
|
21
|
+
// Set default port
|
|
22
|
+
const port = options.port || '3000'
|
|
31
23
|
|
|
32
24
|
// Detect context
|
|
33
25
|
const context = await detectLaunch77Context(process.cwd())
|
|
@@ -39,7 +31,7 @@ export function createAppCommand(): Command {
|
|
|
39
31
|
const templateSpinner = ora('Generating app structure...').start()
|
|
40
32
|
let result
|
|
41
33
|
try {
|
|
42
|
-
result = await appService.createApp({ type:
|
|
34
|
+
result = await appService.createApp({ type: template, appName, port }, context)
|
|
43
35
|
templateSpinner.succeed('App structure generated')
|
|
44
36
|
} catch (error) {
|
|
45
37
|
templateSpinner.fail('Failed to generate app structure')
|
|
@@ -9,10 +9,10 @@ import ora from 'ora'
|
|
|
9
9
|
import { detectLaunch77Context } from '@launch77/plugin-runtime'
|
|
10
10
|
import { AppService } from '../services/app-svc.js'
|
|
11
11
|
|
|
12
|
-
export function
|
|
12
|
+
export function appDeleteCommand(): Command {
|
|
13
13
|
const command = new Command('app:delete')
|
|
14
14
|
.argument('<app-name>', 'Name of the app to delete')
|
|
15
|
-
.description('Delete an app from the
|
|
15
|
+
.description('Delete an app from the workspace (requires confirmation)')
|
|
16
16
|
.action(async (appName: string) => {
|
|
17
17
|
try {
|
|
18
18
|
console.log(chalk.yellow(`\n⚠️ WARNING: You are about to delete the app '${appName}'\n`))
|
package/src/modules/app/index.ts
CHANGED
|
@@ -3,14 +3,12 @@ export { AppService } from './services/app-svc.js'
|
|
|
3
3
|
export { ManifestService } from './services/manifest-svc.js'
|
|
4
4
|
|
|
5
5
|
// Types
|
|
6
|
-
export type { CreateAppRequest, CreateAppResult, DeleteAppRequest, DeleteAppResult
|
|
6
|
+
export type { CreateAppRequest, CreateAppResult, DeleteAppRequest, DeleteAppResult } from './types/app-types.js'
|
|
7
7
|
export type { AppManifest, DeploymentConfig } from './lib/manifest-schema.js'
|
|
8
8
|
|
|
9
9
|
// Errors
|
|
10
10
|
export { AppAlreadyExistsError, AppNotFoundError, InvalidAppNameError, TemplateNotFoundError, ManifestNotFoundError, InvalidManifestError } from './errors/app-errors.js'
|
|
11
11
|
|
|
12
12
|
// Commands
|
|
13
|
-
export {
|
|
14
|
-
export {
|
|
15
|
-
export { generateManifestCommand } from './commands/generate-manifest.js'
|
|
16
|
-
export { validateManifestCommand } from './commands/validate-manifest.js'
|
|
13
|
+
export { appCreateCommand } from './commands/create-app.js'
|
|
14
|
+
export { appDeleteCommand } from './commands/delete-app.js'
|
|
@@ -21,6 +21,22 @@ export class AppTemplateResolver extends PackageResolver {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
protected async verify(localPath: string): Promise<boolean> {
|
|
24
|
+
// All Launch77 packages must have package.json with version
|
|
25
|
+
const hasPackageJson = await fs.pathExists(path.join(localPath, 'package.json'))
|
|
26
|
+
if (!hasPackageJson) {
|
|
27
|
+
return false
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Verify package.json has a version field
|
|
31
|
+
try {
|
|
32
|
+
const packageJson = await fs.readJson(path.join(localPath, 'package.json'))
|
|
33
|
+
if (!packageJson.version) {
|
|
34
|
+
return false
|
|
35
|
+
}
|
|
36
|
+
} catch {
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
39
|
+
|
|
24
40
|
// Check for either:
|
|
25
41
|
// 1. A 'template' subdirectory (preferred structure for npm packages)
|
|
26
42
|
// 2. Any files at the root (simple local templates)
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
2
|
|
|
3
|
-
import type { AppType } from '../types/app-types.js'
|
|
4
|
-
|
|
5
3
|
// Deployment configuration
|
|
6
4
|
export type DeploymentConfig = {
|
|
7
5
|
platform: 'vercel'
|
|
@@ -14,7 +12,6 @@ export type DeploymentConfig = {
|
|
|
14
12
|
export type AppManifest = {
|
|
15
13
|
schemaVersion: 1
|
|
16
14
|
name: string
|
|
17
|
-
type: AppType | 'marketing' // Support both 'marketing' and 'marketing-site'
|
|
18
15
|
package: string
|
|
19
16
|
deployment?: DeploymentConfig
|
|
20
17
|
}
|
|
@@ -28,12 +25,10 @@ const deploymentConfigZ = z.object({
|
|
|
28
25
|
})
|
|
29
26
|
|
|
30
27
|
// Main manifest schema - strict mode to reject extra fields
|
|
31
|
-
// Note: Manifests store 'marketing' but we accept 'marketing-site' in commands
|
|
32
28
|
export const manifestZ = z
|
|
33
29
|
.object({
|
|
34
30
|
schemaVersion: z.literal(1),
|
|
35
31
|
name: z.string().min(1),
|
|
36
|
-
type: z.enum(['marketing', 'webapp', 'api']),
|
|
37
32
|
package: z.string().min(1),
|
|
38
33
|
deployment: deploymentConfigZ.optional(),
|
|
39
34
|
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as path from 'path'
|
|
2
2
|
|
|
3
3
|
import fs from 'fs-extra'
|
|
4
|
+
import { readTemplateMetadata } from '@launch77/plugin-runtime'
|
|
4
5
|
|
|
5
6
|
import { ManifestService } from './manifest-svc.js'
|
|
6
7
|
import * as filesystem from '../../../infrastructure/filesystem.js'
|
|
@@ -12,7 +13,7 @@ import { validateAppName } from '../../../utils/validation.js'
|
|
|
12
13
|
import { AppTemplateResolver } from '../lib/app-template-resolver.js'
|
|
13
14
|
|
|
14
15
|
import type { CreateAppRequest, CreateAppResult, DeleteAppRequest, DeleteAppResult } from '../types/app-types.js'
|
|
15
|
-
import type { Launch77Context } from '@launch77/plugin-runtime'
|
|
16
|
+
import type { Launch77Context, TemplateReference, Launch77PackageManifest } from '@launch77/plugin-runtime'
|
|
16
17
|
|
|
17
18
|
export class AppService {
|
|
18
19
|
private manifestService: ManifestService
|
|
@@ -51,9 +52,14 @@ export class AppService {
|
|
|
51
52
|
const templateResolution = await this.appTemplateResolver.resolveLocation(type, context.workspaceRoot)
|
|
52
53
|
|
|
53
54
|
let templatePath: string
|
|
55
|
+
let templateVersion: string
|
|
56
|
+
let packageRootPath: string
|
|
57
|
+
|
|
54
58
|
if (templateResolution.source === 'local') {
|
|
55
59
|
// Use local template
|
|
56
|
-
|
|
60
|
+
packageRootPath = templateResolution.localPath!
|
|
61
|
+
templatePath = packageRootPath
|
|
62
|
+
templateVersion = templateResolution.version! // Local templates always have version after verification
|
|
57
63
|
} else {
|
|
58
64
|
// Download npm template
|
|
59
65
|
const downloadResult = await downloadNpmPackage({
|
|
@@ -61,13 +67,20 @@ export class AppService {
|
|
|
61
67
|
workspaceRoot: context.workspaceRoot,
|
|
62
68
|
})
|
|
63
69
|
|
|
70
|
+
packageRootPath = downloadResult.packagePath
|
|
71
|
+
|
|
64
72
|
// Check if template has a 'template' subdirectory, otherwise use package root
|
|
65
|
-
const templateSubdir = path.join(
|
|
73
|
+
const templateSubdir = path.join(packageRootPath, 'template')
|
|
66
74
|
if (await fs.pathExists(templateSubdir)) {
|
|
67
75
|
templatePath = templateSubdir
|
|
68
76
|
} else {
|
|
69
|
-
templatePath =
|
|
77
|
+
templatePath = packageRootPath
|
|
70
78
|
}
|
|
79
|
+
|
|
80
|
+
// Read version from downloaded package
|
|
81
|
+
const packageJsonPath = path.join(packageRootPath, 'package.json')
|
|
82
|
+
const packageJson = await fs.readJson(packageJsonPath)
|
|
83
|
+
templateVersion = packageJson.version
|
|
71
84
|
}
|
|
72
85
|
|
|
73
86
|
// 5. Determine app path
|
|
@@ -91,14 +104,40 @@ export class AppService {
|
|
|
91
104
|
port,
|
|
92
105
|
})
|
|
93
106
|
|
|
94
|
-
// 9.
|
|
95
|
-
const
|
|
107
|
+
// 9. Read template metadata (currently empty, placeholder for future config)
|
|
108
|
+
//const templateMetadata = await readTemplateMetadata(templatePath)
|
|
109
|
+
|
|
110
|
+
// 10. Write template reference to app's package.json
|
|
111
|
+
const appPackageJsonPath = path.join(appPath, 'package.json')
|
|
112
|
+
const appPackageJson = await fs.readJson(appPackageJsonPath)
|
|
113
|
+
|
|
114
|
+
// Build template reference - version read from package.json
|
|
115
|
+
const templatePackage = templateResolution.source === 'npm' ? templateResolution.npmPackage! : templateResolution.resolvedName
|
|
116
|
+
const templateRef: TemplateReference = {
|
|
117
|
+
package: templatePackage,
|
|
118
|
+
version: templateVersion,
|
|
119
|
+
source: templateResolution.source,
|
|
120
|
+
createdAt: new Date().toISOString(),
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Initialize launch77 manifest structure
|
|
124
|
+
if (!appPackageJson.launch77) {
|
|
125
|
+
appPackageJson.launch77 = {}
|
|
126
|
+
}
|
|
127
|
+
const launch77Manifest = appPackageJson.launch77 as Launch77PackageManifest
|
|
128
|
+
launch77Manifest.template = templateRef
|
|
129
|
+
|
|
130
|
+
// Write updated package.json
|
|
131
|
+
await fs.writeJson(appPackageJsonPath, appPackageJson, { spaces: 2 })
|
|
132
|
+
|
|
133
|
+
// 11. Generate and write app manifest
|
|
134
|
+
const manifest = this.manifestService.generateManifest(appName, context, { port })
|
|
96
135
|
const launchDir = path.join(appPath, '.launch')
|
|
97
136
|
await filesystem.ensureDir(launchDir)
|
|
98
137
|
const manifestPath = path.join(launchDir, 'app.json')
|
|
99
138
|
await filesystem.writeJSON(manifestPath, manifest)
|
|
100
139
|
|
|
101
|
-
//
|
|
140
|
+
// 12. Install dependencies
|
|
102
141
|
await npm.install(context.workspaceRoot)
|
|
103
142
|
|
|
104
143
|
return {
|
|
@@ -8,7 +8,7 @@ import type { AppManifest } from '../lib/manifest-schema.js'
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Convert kebab-case to Title Case
|
|
11
|
-
* e.g., "my-
|
|
11
|
+
* e.g., "my-workspace-name" -> "My Workspace Name"
|
|
12
12
|
*/
|
|
13
13
|
function toTitleCase(str: string): string {
|
|
14
14
|
return str
|
|
@@ -17,66 +17,17 @@ function toTitleCase(str: string): string {
|
|
|
17
17
|
.join(' ')
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
/**
|
|
21
|
-
* Generate a manifest for a marketing app
|
|
22
|
-
*/
|
|
23
|
-
function generateMarketingManifest(appName: string, context: Launch77Context): AppManifest {
|
|
24
|
-
const workspaceName = context.workspaceName
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
schemaVersion: 1,
|
|
28
|
-
name: `${toTitleCase(workspaceName)} Marketing`,
|
|
29
|
-
type: 'marketing',
|
|
30
|
-
package: `@${workspaceName}/${appName}`,
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Generate a manifest for a webapp
|
|
36
|
-
*/
|
|
37
|
-
function generateWebappManifest(appName: string, context: Launch77Context): AppManifest {
|
|
38
|
-
const workspaceName = context.workspaceName
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
schemaVersion: 1,
|
|
42
|
-
name: `${toTitleCase(workspaceName)} Web`,
|
|
43
|
-
type: 'webapp',
|
|
44
|
-
package: `@${workspaceName}/${appName}`,
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Generate a manifest for an API app
|
|
50
|
-
*/
|
|
51
|
-
function generateApiManifest(appName: string, context: Launch77Context): AppManifest {
|
|
52
|
-
const workspaceName = context.workspaceName
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
schemaVersion: 1,
|
|
56
|
-
name: `${toTitleCase(workspaceName)} API`,
|
|
57
|
-
type: 'api',
|
|
58
|
-
package: `@${workspaceName}/${appName}`,
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
20
|
export class ManifestService {
|
|
63
21
|
/**
|
|
64
|
-
* Generate an app manifest
|
|
22
|
+
* Generate an app manifest
|
|
65
23
|
*/
|
|
66
|
-
generateManifest(
|
|
67
|
-
|
|
68
|
-
case 'marketing-site':
|
|
69
|
-
case 'marketing':
|
|
70
|
-
return generateMarketingManifest(appName, context)
|
|
71
|
-
|
|
72
|
-
case 'webapp':
|
|
73
|
-
return generateWebappManifest(appName, context)
|
|
74
|
-
|
|
75
|
-
case 'api':
|
|
76
|
-
return generateApiManifest(appName, context)
|
|
24
|
+
generateManifest(appName: string, context: Launch77Context, _options: { port?: string }): AppManifest {
|
|
25
|
+
const workspaceName = context.workspaceName
|
|
77
26
|
|
|
78
|
-
|
|
79
|
-
|
|
27
|
+
return {
|
|
28
|
+
schemaVersion: 1,
|
|
29
|
+
name: toTitleCase(workspaceName),
|
|
30
|
+
package: `@${workspaceName}/${appName}`,
|
|
80
31
|
}
|
|
81
32
|
}
|
|
82
33
|
|
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
// Supported app types
|
|
2
|
-
export const APP_TYPES = ['api', 'webapp', 'marketing-site'] as const
|
|
3
|
-
export type AppType = (typeof APP_TYPES)[number]
|
|
4
|
-
|
|
5
|
-
// Display list for error messages
|
|
6
|
-
export const APP_TYPES_LIST = APP_TYPES.join(', ')
|
|
7
|
-
|
|
8
1
|
export interface CreateAppRequest {
|
|
9
|
-
type:
|
|
2
|
+
type: string
|
|
10
3
|
appName: string
|
|
11
4
|
port: string
|
|
12
5
|
}
|
|
@@ -14,7 +7,7 @@ export interface CreateAppRequest {
|
|
|
14
7
|
export interface CreateAppResult {
|
|
15
8
|
appPath: string
|
|
16
9
|
appName: string
|
|
17
|
-
type:
|
|
10
|
+
type: string
|
|
18
11
|
}
|
|
19
12
|
|
|
20
13
|
export interface DeleteAppRequest {
|
|
@@ -21,7 +21,7 @@ interface GenerateOptions {
|
|
|
21
21
|
/**
|
|
22
22
|
* Create the catalog:generate command
|
|
23
23
|
*/
|
|
24
|
-
export function
|
|
24
|
+
export function catalogGenerateCommand(): Command {
|
|
25
25
|
const command = new Command('catalog:generate')
|
|
26
26
|
.description('Generate catalog metadata for a component library')
|
|
27
27
|
.option('-l, --library <path>', 'Library directory path', process.cwd())
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
2
|
import { Command } from 'commander'
|
|
3
|
+
import { detectLaunch77Context } from '@launch77/plugin-runtime'
|
|
3
4
|
|
|
4
|
-
import { detectMonorepoContext } from '../../../utils/monorepo.js'
|
|
5
5
|
import { CatalogService } from '../services/catalog-svc.js'
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -10,17 +10,17 @@ import { CatalogService } from '../services/catalog-svc.js'
|
|
|
10
10
|
* Scans UI components, libraries, plugins, and utilities from the Launch77 monorepo
|
|
11
11
|
* and generates a machine-readable catalog for AI discovery.
|
|
12
12
|
*/
|
|
13
|
-
export function
|
|
13
|
+
export function catalogScanCommand(): Command {
|
|
14
14
|
const command = new Command('catalog:scan')
|
|
15
15
|
.description('Scan Launch77 artifacts and generate catalog.json')
|
|
16
16
|
.option('--no-strict', 'Skip validation errors and generate catalog anyway')
|
|
17
17
|
.option('--quiet', 'Suppress quality report output')
|
|
18
18
|
.action(async (options) => {
|
|
19
19
|
try {
|
|
20
|
-
const context = await
|
|
20
|
+
const context = await detectLaunch77Context(process.cwd())
|
|
21
21
|
|
|
22
22
|
if (!context.isValid) {
|
|
23
|
-
console.error(chalk.red('\n✖ Must be run from within a Launch77
|
|
23
|
+
console.error(chalk.red('\n✖ Must be run from within a Launch77 workspace\n'))
|
|
24
24
|
process.exit(1)
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -9,7 +9,7 @@ import { scanUILibrary } from '../scanners/ui-component-scanner.js'
|
|
|
9
9
|
import { generateExamplesFiles } from '../utils/examples-generator.js'
|
|
10
10
|
import { generateQualityReport, printQualityReport } from '../utils/quality-reporter.js'
|
|
11
11
|
|
|
12
|
-
import type {
|
|
12
|
+
import type { Launch77Context } from '@launch77/plugin-runtime'
|
|
13
13
|
import type { ValidationResult, UiComponent } from '../types/catalog-types.js'
|
|
14
14
|
|
|
15
15
|
export interface ScanCatalogOptions {
|
|
@@ -32,13 +32,13 @@ export class CatalogService {
|
|
|
32
32
|
/**
|
|
33
33
|
* Scan Launch77 codebase and generate catalog.json
|
|
34
34
|
*/
|
|
35
|
-
async scanCatalog(context:
|
|
35
|
+
async scanCatalog(context: Launch77Context, options: ScanCatalogOptions = {}): Promise<ScanCatalogResult> {
|
|
36
36
|
const strict = options.strict !== false // Default to true (strict mode)
|
|
37
37
|
const quiet = options.quiet || false
|
|
38
38
|
|
|
39
39
|
console.log(chalk.blue('\n🔍 Scanning Launch77 artifacts...\n'))
|
|
40
40
|
|
|
41
|
-
const launch77Root = path.join(context.
|
|
41
|
+
const launch77Root = path.join(context.workspaceRoot, 'launch77')
|
|
42
42
|
|
|
43
43
|
const spinner = ora('Scanning codebase...').start()
|
|
44
44
|
|
|
@@ -109,7 +109,7 @@ export class CatalogService {
|
|
|
109
109
|
console.log(chalk.green(` ✓ Saved to ${path.relative(process.cwd(), catalogPath)}`))
|
|
110
110
|
|
|
111
111
|
// Sync catalog to Launch77 marketing site
|
|
112
|
-
const marketingSiteCatalogPath = path.join(context.
|
|
112
|
+
const marketingSiteCatalogPath = path.join(context.workspaceRoot, 'apps/marketing/src/catalog.json')
|
|
113
113
|
|
|
114
114
|
if (await fs.pathExists(path.dirname(marketingSiteCatalogPath))) {
|
|
115
115
|
await fs.writeFile(marketingSiteCatalogPath, formatted)
|