@launch77/cli 1.5.0 → 1.7.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 +12 -0
- package/dist/cli.js +17 -14
- package/dist/cli.js.map +1 -1
- package/dist/infrastructure/template.d.ts +5 -1
- package/dist/infrastructure/template.d.ts.map +1 -1
- package/dist/infrastructure/template.js +11 -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.js +1 -1
- package/dist/modules/app/commands/delete-app.d.ts +1 -1
- package/dist/modules/app/commands/delete-app.js +1 -1
- package/dist/modules/app/index.d.ts +2 -3
- package/dist/modules/app/index.d.ts.map +1 -1
- package/dist/modules/app/index.js +2 -3
- package/dist/modules/app/index.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 +1 -1
- package/dist/modules/catalog/commands/scan.js.map +1 -1
- package/dist/modules/library/commands/create-library.d.ts +3 -0
- package/dist/modules/library/commands/create-library.d.ts.map +1 -0
- package/dist/modules/library/commands/create-library.js +61 -0
- package/dist/modules/library/commands/create-library.js.map +1 -0
- 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 +7 -0
- package/dist/modules/library/index.d.ts.map +1 -0
- package/dist/modules/library/index.js +9 -0
- package/dist/modules/library/index.js.map +1 -0
- package/dist/modules/library/services/library-create-svc.d.ts +17 -0
- package/dist/modules/library/services/library-create-svc.d.ts.map +1 -0
- package/dist/modules/library/services/library-create-svc.js +51 -0
- package/dist/modules/library/services/library-create-svc.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 +16 -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/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 +34 -1
- package/dist/modules/plugin/services/plugin-svc.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/library/README.md.hbs +80 -0
- package/dist/templates/library/package.json.hbs +31 -0
- package/dist/templates/library/src/index.d.ts.hbs +14 -0
- package/dist/templates/library/src/index.js +11 -0
- package/dist/templates/library/tsconfig.json +31 -0
- package/package.json +1 -1
- package/src/cli.ts +17 -14
- package/src/infrastructure/template.ts +14 -1
- package/src/modules/app/commands/create-app.ts +1 -1
- package/src/modules/app/commands/delete-app.ts +1 -1
- package/src/modules/app/index.ts +2 -3
- package/src/modules/catalog/commands/generate.ts +1 -1
- package/src/modules/catalog/commands/scan.ts +1 -1
- package/src/modules/library/commands/create-library.ts +70 -0
- 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 +13 -0
- package/src/modules/library/services/library-create-svc.ts +75 -0
- package/src/modules/library/services/library-svc.ts +50 -0
- package/src/modules/library/types/library-types.ts +18 -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/services/plugin-svc.ts +43 -2
- package/src/modules/plugin/types/plugin-types.ts +8 -0
- package/templates/library/README.md.hbs +80 -0
- package/templates/library/package.json.hbs +31 -0
- package/templates/library/src/index.d.ts.hbs +14 -0
- package/templates/library/src/index.js +11 -0
- package/templates/library/tsconfig.json +31 -0
- 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 -67
- package/dist/modules/app/commands/validate-manifest.js.map +0 -1
- package/src/modules/app/commands/validate-manifest.ts +0 -77
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for @{{workspaceName}}/lib-{{libraryName}}
|
|
3
|
+
*
|
|
4
|
+
* Add your type exports here.
|
|
5
|
+
*
|
|
6
|
+
* Example:
|
|
7
|
+
* export { MyComponent, type MyComponentProps } from './components/MyComponent'
|
|
8
|
+
* export { myUtility } from './utils/myUtility'
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// Add your type exports here
|
|
12
|
+
declare module '@{{workspaceName}}/lib-{{libraryName}}' {
|
|
13
|
+
// Add declarations here
|
|
14
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main entry point for @{{workspaceName}}/lib-{{libraryName}}
|
|
3
|
+
*
|
|
4
|
+
* Add your library exports here.
|
|
5
|
+
*
|
|
6
|
+
* Example:
|
|
7
|
+
* export { MyComponent } from './components/MyComponent.js'
|
|
8
|
+
* export { myUtility } from './utils/myUtility.js'
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// Add your exports here
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"lib": ["ES2020", "DOM"],
|
|
6
|
+
"jsx": "react-jsx",
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"declarationMap": true,
|
|
9
|
+
"sourceMap": true,
|
|
10
|
+
"outDir": "./dist",
|
|
11
|
+
"rootDir": "./src",
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"allowJs": true,
|
|
16
|
+
"checkJs": false,
|
|
17
|
+
"strict": true,
|
|
18
|
+
"noUnusedLocals": true,
|
|
19
|
+
"noUnusedParameters": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
"noEmit": true,
|
|
22
|
+
"esModuleInterop": true,
|
|
23
|
+
"skipLibCheck": true,
|
|
24
|
+
"forceConsistentCasingInFileNames": true,
|
|
25
|
+
"paths": {
|
|
26
|
+
"@/*": ["./src/*"]
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"include": ["src/**/*"],
|
|
30
|
+
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
|
|
31
|
+
}
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -2,14 +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 { libraryCreateCommand, 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 { getPackageVersion } from './utils/version.js'
|
|
12
12
|
import { initWorkspaceCommand } from './modules/workspace/index.js'
|
|
13
|
+
import { getPackageVersion } from './utils/version.js'
|
|
13
14
|
|
|
14
15
|
const program = new Command()
|
|
15
16
|
.name('launch77')
|
|
@@ -18,13 +19,15 @@ const program = new Command()
|
|
|
18
19
|
|
|
19
20
|
// Register module commands
|
|
20
21
|
program.addCommand(initWorkspaceCommand())
|
|
21
|
-
program.addCommand(
|
|
22
|
-
program.addCommand(
|
|
23
|
-
program.addCommand(
|
|
24
|
-
program.addCommand(
|
|
22
|
+
program.addCommand(appCreateCommand())
|
|
23
|
+
program.addCommand(appDeleteCommand())
|
|
24
|
+
program.addCommand(libraryCreateCommand())
|
|
25
|
+
program.addCommand(libraryDeleteCommand())
|
|
25
26
|
program.addCommand(pluginCreateCommand())
|
|
26
|
-
program.addCommand(
|
|
27
|
-
program.addCommand(
|
|
27
|
+
program.addCommand(pluginDeleteCommand())
|
|
28
|
+
program.addCommand(pluginInstallCommand())
|
|
29
|
+
// program.addCommand(catalogGenerateCommand())
|
|
30
|
+
// program.addCommand(catalogScanCommand())
|
|
28
31
|
|
|
29
32
|
// Git commands
|
|
30
33
|
program.addCommand(gitConnectCommand())
|
|
@@ -33,8 +36,8 @@ program.addCommand(gitConnectCommand())
|
|
|
33
36
|
program.addCommand(releaseInitCommand())
|
|
34
37
|
|
|
35
38
|
// Deploy commands
|
|
36
|
-
program.addCommand(deployInitCommand())
|
|
37
|
-
program.addCommand(deployStatusCommand())
|
|
38
|
-
program.addCommand(deployLogsCommand())
|
|
39
|
+
// program.addCommand(deployInitCommand())
|
|
40
|
+
// program.addCommand(deployStatusCommand())
|
|
41
|
+
// program.addCommand(deployLogsCommand())
|
|
39
42
|
|
|
40
43
|
program.parse()
|
|
@@ -44,7 +44,6 @@ export async function processTemplate(templatePath: string, destinationPath: str
|
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* Get the path to a template directory
|
|
47
|
-
* Templates are always in dist/app-templates/ (copied during build)
|
|
48
47
|
*/
|
|
49
48
|
export function getTemplatePath(templateName: string): string {
|
|
50
49
|
const __filename = fileURLToPath(import.meta.url)
|
|
@@ -70,6 +69,20 @@ export function getPluginTemplatePath(templateName: string): string {
|
|
|
70
69
|
return path.join(baseDir, templateName)
|
|
71
70
|
}
|
|
72
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Get the path to a library template directory
|
|
74
|
+
* Library templates are in dist/templates/ (copied during build)
|
|
75
|
+
*/
|
|
76
|
+
export function getLibraryTemplatePath(templateName: string): string {
|
|
77
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
78
|
+
const __dirname = path.dirname(__filename)
|
|
79
|
+
|
|
80
|
+
// From dist/infrastructure/ to dist/templates/
|
|
81
|
+
const baseDir = path.join(__dirname, '../templates')
|
|
82
|
+
|
|
83
|
+
return path.join(baseDir, templateName)
|
|
84
|
+
}
|
|
85
|
+
|
|
73
86
|
/**
|
|
74
87
|
* Check if a template exists
|
|
75
88
|
*/
|
|
@@ -8,7 +8,7 @@ import ora from 'ora'
|
|
|
8
8
|
import { detectLaunch77Context } from '@launch77/plugin-runtime'
|
|
9
9
|
import { AppService } from '../services/app-svc.js'
|
|
10
10
|
|
|
11
|
-
export function
|
|
11
|
+
export function appCreateCommand(): Command {
|
|
12
12
|
const command = new Command('app:create')
|
|
13
13
|
.argument('<template>', 'App template name (e.g., webapp, api, marketing-site)')
|
|
14
14
|
.argument('<app-name>', 'Name of the application')
|
|
@@ -9,7 +9,7 @@ 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
15
|
.description('Delete an app from the workspace (requires confirmation)')
|
package/src/modules/app/index.ts
CHANGED
|
@@ -10,6 +10,5 @@ export type { AppManifest, DeploymentConfig } from './lib/manifest-schema.js'
|
|
|
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 { validateManifestCommand } from './commands/validate-manifest.js'
|
|
13
|
+
export { appCreateCommand } from './commands/create-app.js'
|
|
14
|
+
export { appDeleteCommand } from './commands/delete-app.js'
|
|
@@ -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())
|
|
@@ -10,7 +10,7 @@ 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')
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import * as path from 'path'
|
|
3
|
+
|
|
4
|
+
import chalk from 'chalk'
|
|
5
|
+
import { Command } from 'commander'
|
|
6
|
+
import ora from 'ora'
|
|
7
|
+
|
|
8
|
+
import { detectLaunch77Context } from '@launch77/plugin-runtime'
|
|
9
|
+
import { LibraryCreateService } from '../services/library-create-svc.js'
|
|
10
|
+
|
|
11
|
+
export function libraryCreateCommand(): Command {
|
|
12
|
+
const command = new Command('library:create')
|
|
13
|
+
.argument('<library-name>', 'Name of the library to create (e.g., ui, marketing-ui)')
|
|
14
|
+
.option('-d, --description <description>', 'Library description')
|
|
15
|
+
.description('Create a new library from template')
|
|
16
|
+
.action(async (libraryName: string, options) => {
|
|
17
|
+
try {
|
|
18
|
+
console.log(chalk.blue(`\n📚 Creating library: ${libraryName}\n`))
|
|
19
|
+
|
|
20
|
+
// Detect context
|
|
21
|
+
const context = await detectLaunch77Context(process.cwd())
|
|
22
|
+
|
|
23
|
+
// Create library service
|
|
24
|
+
const libraryCreateService = new LibraryCreateService()
|
|
25
|
+
|
|
26
|
+
// Create library
|
|
27
|
+
const spinner = ora('Generating library structure...').start()
|
|
28
|
+
let result
|
|
29
|
+
try {
|
|
30
|
+
result = await libraryCreateService.createLibrary(
|
|
31
|
+
{
|
|
32
|
+
libraryName,
|
|
33
|
+
description: options.description,
|
|
34
|
+
},
|
|
35
|
+
context
|
|
36
|
+
)
|
|
37
|
+
spinner.succeed('Library structure generated')
|
|
38
|
+
} catch (error) {
|
|
39
|
+
spinner.fail('Failed to generate library structure')
|
|
40
|
+
throw error
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Success message
|
|
44
|
+
const relativePath = path.relative(process.cwd(), result.libraryPath)
|
|
45
|
+
const displayPath = relativePath.startsWith('..') ? result.libraryPath : relativePath
|
|
46
|
+
console.log(chalk.green(`\n✅ Library created successfully at ${displayPath}`))
|
|
47
|
+
|
|
48
|
+
// Next steps
|
|
49
|
+
console.log(chalk.white('\n' + '─'.repeat(60) + '\n'))
|
|
50
|
+
console.log(chalk.cyan('📋 Next Steps:\n'))
|
|
51
|
+
const cdPath = path.relative(process.cwd(), result.libraryPath)
|
|
52
|
+
console.log(chalk.gray('1. Navigate to your library directory:'))
|
|
53
|
+
console.log(chalk.cyan(` cd ${cdPath}\n`))
|
|
54
|
+
console.log(chalk.gray('2. Add your library code to src/\n'))
|
|
55
|
+
console.log(chalk.gray('3. Update package.json with proper exports and dependencies\n'))
|
|
56
|
+
console.log(chalk.gray('4. Configure build system if needed (tsup, tsc, etc.)\n'))
|
|
57
|
+
console.log(chalk.gray('5. Add README.md documentation\n'))
|
|
58
|
+
console.log(chalk.gray('6. Run type checking:'))
|
|
59
|
+
console.log(chalk.cyan(' npm run typecheck\n'))
|
|
60
|
+
console.log(chalk.gray('7. Build your library:'))
|
|
61
|
+
console.log(chalk.cyan(' npm run build\n'))
|
|
62
|
+
} catch (error) {
|
|
63
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
64
|
+
console.error(chalk.red('Error:'), message)
|
|
65
|
+
process.exit(1)
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
return command
|
|
70
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import * as path from 'path'
|
|
3
|
+
|
|
4
|
+
import chalk from 'chalk'
|
|
5
|
+
import { Command } from 'commander'
|
|
6
|
+
import inquirer from 'inquirer'
|
|
7
|
+
import ora from 'ora'
|
|
8
|
+
|
|
9
|
+
import { detectLaunch77Context } from '@launch77/plugin-runtime'
|
|
10
|
+
import { LibraryService } from '../services/library-svc.js'
|
|
11
|
+
|
|
12
|
+
export function libraryDeleteCommand(): Command {
|
|
13
|
+
const command = new Command('library:delete')
|
|
14
|
+
.argument('<library-name>', 'Name of the library to delete')
|
|
15
|
+
.description('Delete a library from the workspace (requires confirmation)')
|
|
16
|
+
.action(async (libraryName: string) => {
|
|
17
|
+
try {
|
|
18
|
+
console.log(chalk.yellow(`\n⚠️ WARNING: You are about to delete the library '${libraryName}'\n`))
|
|
19
|
+
|
|
20
|
+
// Detect context
|
|
21
|
+
const context = await detectLaunch77Context(process.cwd())
|
|
22
|
+
|
|
23
|
+
// Create library service
|
|
24
|
+
const libraryService = new LibraryService()
|
|
25
|
+
|
|
26
|
+
// Get library path for display (before deletion)
|
|
27
|
+
const libraryPath = path.join(context.workspaceRoot, 'libraries', libraryName)
|
|
28
|
+
|
|
29
|
+
// Display what will be deleted
|
|
30
|
+
console.log(chalk.red('Library location:'), libraryPath)
|
|
31
|
+
console.log(chalk.red('\nThis will permanently delete:'))
|
|
32
|
+
console.log(chalk.gray(' • All source code and configuration files'))
|
|
33
|
+
console.log(chalk.gray(' • All node_modules (will be cleaned from monorepo)'))
|
|
34
|
+
console.log(chalk.gray(' • All build artifacts'))
|
|
35
|
+
|
|
36
|
+
console.log(chalk.yellow('\n⚠️ Important notes:'))
|
|
37
|
+
console.log(chalk.gray(' • Check if other packages depend on this library'))
|
|
38
|
+
console.log(chalk.gray(' • If published to npm, you may want to deprecate/unpublish it manually'))
|
|
39
|
+
console.log(chalk.gray(' • Update import statements in dependent packages manually'))
|
|
40
|
+
|
|
41
|
+
console.log(chalk.red('\n⚠️ THIS ACTION CANNOT BE UNDONE!\n'))
|
|
42
|
+
|
|
43
|
+
// First confirmation: Type library name
|
|
44
|
+
const { confirmName } = await inquirer.prompt([
|
|
45
|
+
{
|
|
46
|
+
type: 'input',
|
|
47
|
+
name: 'confirmName',
|
|
48
|
+
message: `Type the library name to confirm:`,
|
|
49
|
+
validate: (input: string) => {
|
|
50
|
+
if (input === libraryName) {
|
|
51
|
+
return true
|
|
52
|
+
}
|
|
53
|
+
return `Please type '${libraryName}' exactly to confirm`
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
])
|
|
57
|
+
|
|
58
|
+
if (confirmName !== libraryName) {
|
|
59
|
+
console.log(chalk.gray('\n✖ Deletion cancelled\n'))
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Second confirmation: Type DELETE
|
|
64
|
+
const { confirmDelete } = await inquirer.prompt([
|
|
65
|
+
{
|
|
66
|
+
type: 'input',
|
|
67
|
+
name: 'confirmDelete',
|
|
68
|
+
message: 'Type DELETE (all caps) to confirm permanent deletion:',
|
|
69
|
+
validate: (input: string) => {
|
|
70
|
+
if (input === 'DELETE') {
|
|
71
|
+
return true
|
|
72
|
+
}
|
|
73
|
+
return 'Please type DELETE (all caps) to confirm'
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
])
|
|
77
|
+
|
|
78
|
+
if (confirmDelete !== 'DELETE') {
|
|
79
|
+
console.log(chalk.gray('\n✖ Deletion cancelled\n'))
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Delete the library
|
|
84
|
+
const deleteSpinner = ora('Deleting library directory...').start()
|
|
85
|
+
try {
|
|
86
|
+
await libraryService.deleteLibrary({ libraryName }, context)
|
|
87
|
+
deleteSpinner.succeed('Library directory deleted')
|
|
88
|
+
} catch (error) {
|
|
89
|
+
deleteSpinner.fail('Failed to delete library directory')
|
|
90
|
+
throw error
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Update dependencies
|
|
94
|
+
const installSpinner = ora('Updating workspace dependencies...').start()
|
|
95
|
+
try {
|
|
96
|
+
// This is already done by library service, just show spinner for consistency
|
|
97
|
+
installSpinner.succeed('Dependencies updated (package-lock.json cleaned)')
|
|
98
|
+
} catch (error) {
|
|
99
|
+
installSpinner.fail('Failed to update dependencies')
|
|
100
|
+
console.log(chalk.yellow('\n⚠️ You may need to run "npm install" manually at the workspace root\n'))
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Success message
|
|
104
|
+
console.log(chalk.green(`\n✅ Library '${libraryName}' has been deleted\n`))
|
|
105
|
+
|
|
106
|
+
// Reminder about cleanup
|
|
107
|
+
console.log(chalk.yellow('📝 Remember to:'))
|
|
108
|
+
console.log(chalk.gray(' • Check and update dependent packages (remove from dependencies)'))
|
|
109
|
+
console.log(chalk.gray(' • Update import statements in code that used this library'))
|
|
110
|
+
console.log(chalk.gray(' • Consider deprecating/unpublishing from npm if published'))
|
|
111
|
+
console.log()
|
|
112
|
+
|
|
113
|
+
// Reminder about Git
|
|
114
|
+
console.log(chalk.yellow('📝 Remember to commit the deletion:'))
|
|
115
|
+
console.log(chalk.gray(' git add -A'))
|
|
116
|
+
console.log(chalk.gray(` git commit -m "Remove ${libraryName} library"`))
|
|
117
|
+
console.log()
|
|
118
|
+
} catch (error) {
|
|
119
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
120
|
+
console.error(chalk.red('Error:'), message)
|
|
121
|
+
process.exit(1)
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
return command
|
|
126
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class LibraryNotFoundError extends Error {
|
|
2
|
+
constructor(libraryName: string, expectedPath: string) {
|
|
3
|
+
super(`Library '${libraryName}' does not exist.\n\n` + `Expected location: ${expectedPath}\n\n` + `Available libraries:\n` + ` cd libraries/\n` + ` ls`)
|
|
4
|
+
this.name = 'LibraryNotFoundError'
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class InvalidLibraryNameError extends Error {
|
|
9
|
+
constructor(message: string) {
|
|
10
|
+
super(message)
|
|
11
|
+
this.name = 'InvalidLibraryNameError'
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Services
|
|
2
|
+
export { LibraryService } from './services/library-svc.js'
|
|
3
|
+
export { LibraryCreateService } from './services/library-create-svc.js'
|
|
4
|
+
|
|
5
|
+
// Types
|
|
6
|
+
export type { CreateLibraryRequest, CreateLibraryResult, DeleteLibraryRequest, DeleteLibraryResult } from './types/library-types.js'
|
|
7
|
+
|
|
8
|
+
// Errors
|
|
9
|
+
export { LibraryNotFoundError, InvalidLibraryNameError } from './errors/library-errors.js'
|
|
10
|
+
|
|
11
|
+
// Commands
|
|
12
|
+
export { libraryCreateCommand } from './commands/create-library.js'
|
|
13
|
+
export { libraryDeleteCommand } from './commands/delete-library.js'
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as path from 'path'
|
|
2
|
+
|
|
3
|
+
import fs from 'fs-extra'
|
|
4
|
+
|
|
5
|
+
import { processTemplate, getLibraryTemplatePath } from '../../../infrastructure/template.js'
|
|
6
|
+
import { validateAppName } from '../../../utils/validation.js'
|
|
7
|
+
import { toPascalCase } from '../../../utils/string.js'
|
|
8
|
+
|
|
9
|
+
import type { Launch77Context } from '@launch77/plugin-runtime'
|
|
10
|
+
|
|
11
|
+
export interface CreateLibraryRequest {
|
|
12
|
+
libraryName: string
|
|
13
|
+
description?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface CreateLibraryResult {
|
|
17
|
+
libraryName: string
|
|
18
|
+
libraryPath: string
|
|
19
|
+
packageName: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class LibraryCreateService {
|
|
23
|
+
/**
|
|
24
|
+
* Create a new library from template
|
|
25
|
+
*/
|
|
26
|
+
async createLibrary(request: CreateLibraryRequest, context: Launch77Context): Promise<CreateLibraryResult> {
|
|
27
|
+
const { libraryName, description } = request
|
|
28
|
+
|
|
29
|
+
// 1. Validate library name (same validation as app/plugin names)
|
|
30
|
+
const nameValidation = validateAppName(libraryName)
|
|
31
|
+
if (!nameValidation.valid) {
|
|
32
|
+
throw new Error(nameValidation.errorMessage || 'Invalid library name')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// 2. Validate workspace context
|
|
36
|
+
if (!context.isValid) {
|
|
37
|
+
throw new Error('Must be run from within a Launch77 workspace')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 3. Determine library path
|
|
41
|
+
const libraryPath = path.join(context.workspaceRoot, 'libraries', libraryName)
|
|
42
|
+
|
|
43
|
+
// 4. Check if library already exists
|
|
44
|
+
if (await fs.pathExists(libraryPath)) {
|
|
45
|
+
throw new Error(`Library '${libraryName}' already exists at ${libraryPath}`)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 5. Get library template path
|
|
49
|
+
const templatePath = getLibraryTemplatePath('library')
|
|
50
|
+
|
|
51
|
+
// 6. Check if template exists
|
|
52
|
+
if (!(await fs.pathExists(templatePath))) {
|
|
53
|
+
throw new Error(`Library template not found at ${templatePath}`)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 7. Build package name
|
|
57
|
+
const packageName = `@${context.workspaceName}/lib-${libraryName}`
|
|
58
|
+
|
|
59
|
+
// 8. Process template with context
|
|
60
|
+
await processTemplate(templatePath, libraryPath, {
|
|
61
|
+
appName: libraryName, // Required by TemplateContext but not semantically used for libraries
|
|
62
|
+
libraryName,
|
|
63
|
+
libraryNamePascal: toPascalCase(libraryName),
|
|
64
|
+
workspaceName: context.workspaceName,
|
|
65
|
+
packageName,
|
|
66
|
+
description: description || `Launch77 library for ${libraryName}`,
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
libraryName,
|
|
71
|
+
libraryPath,
|
|
72
|
+
packageName,
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as path from 'path'
|
|
2
|
+
|
|
3
|
+
import fs from 'fs-extra'
|
|
4
|
+
|
|
5
|
+
import * as npm from '../../../infrastructure/npm.js'
|
|
6
|
+
import { validateWorkspaceContext } from '../../../utils/launch77-validation.js'
|
|
7
|
+
import { validateAppName } from '../../../utils/validation.js'
|
|
8
|
+
import { LibraryNotFoundError, InvalidLibraryNameError } from '../errors/library-errors.js'
|
|
9
|
+
|
|
10
|
+
import type { DeleteLibraryRequest, DeleteLibraryResult } from '../types/library-types.js'
|
|
11
|
+
import type { Launch77Context } from '@launch77/plugin-runtime'
|
|
12
|
+
|
|
13
|
+
export class LibraryService {
|
|
14
|
+
/**
|
|
15
|
+
* Delete a library from the workspace
|
|
16
|
+
*/
|
|
17
|
+
async deleteLibrary(request: DeleteLibraryRequest, context: Launch77Context): Promise<DeleteLibraryResult> {
|
|
18
|
+
const { libraryName } = request
|
|
19
|
+
|
|
20
|
+
// 1. Validate library name (reusing app name validation since format is the same)
|
|
21
|
+
const nameValidation = validateAppName(libraryName)
|
|
22
|
+
if (!nameValidation.valid) {
|
|
23
|
+
throw new InvalidLibraryNameError(nameValidation.errorMessage || 'Invalid library name')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 2. Validate workspace context
|
|
27
|
+
const contextValidation = validateWorkspaceContext(context)
|
|
28
|
+
if (!contextValidation.valid) {
|
|
29
|
+
throw new Error(contextValidation.errorMessage || 'Invalid workspace context')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 3. Determine library path
|
|
33
|
+
const libraryPath = path.join(context.workspaceRoot, 'libraries', libraryName)
|
|
34
|
+
|
|
35
|
+
// 4. Check if library exists
|
|
36
|
+
if (!(await fs.pathExists(libraryPath))) {
|
|
37
|
+
throw new LibraryNotFoundError(libraryName, libraryPath)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 5. Delete the library directory
|
|
41
|
+
await fs.remove(libraryPath)
|
|
42
|
+
|
|
43
|
+
// 6. Update dependencies
|
|
44
|
+
await npm.install(context.workspaceRoot)
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
libraryName,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface CreateLibraryRequest {
|
|
2
|
+
libraryName: string
|
|
3
|
+
description?: string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface CreateLibraryResult {
|
|
7
|
+
libraryName: string
|
|
8
|
+
libraryPath: string
|
|
9
|
+
packageName: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface DeleteLibraryRequest {
|
|
13
|
+
libraryName: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface DeleteLibraryResult {
|
|
17
|
+
libraryName: string
|
|
18
|
+
}
|