@launch77/cli 1.2.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/cli.js +8 -1
  3. package/dist/cli.js.map +1 -1
  4. package/dist/infrastructure/git.d.ts +37 -0
  5. package/dist/infrastructure/git.d.ts.map +1 -0
  6. package/dist/infrastructure/git.js +82 -0
  7. package/dist/infrastructure/git.js.map +1 -0
  8. package/dist/infrastructure/github.d.ts +43 -0
  9. package/dist/infrastructure/github.d.ts.map +1 -0
  10. package/dist/infrastructure/github.js +89 -0
  11. package/dist/infrastructure/github.js.map +1 -0
  12. package/dist/infrastructure/template-generator.d.ts +1 -1
  13. package/dist/infrastructure/template-generator.d.ts.map +1 -1
  14. package/dist/infrastructure/template.d.ts +5 -0
  15. package/dist/infrastructure/template.d.ts.map +1 -1
  16. package/dist/infrastructure/template.js +11 -0
  17. package/dist/infrastructure/template.js.map +1 -1
  18. package/dist/modules/app/commands/create-app.js +1 -1
  19. package/dist/modules/app/commands/create-app.js.map +1 -1
  20. package/dist/modules/app/commands/delete-app.js +1 -1
  21. package/dist/modules/app/commands/delete-app.js.map +1 -1
  22. package/dist/modules/app/services/app-svc.d.ts +1 -1
  23. package/dist/modules/app/services/app-svc.d.ts.map +1 -1
  24. package/dist/modules/app/services/manifest-svc.d.ts +1 -1
  25. package/dist/modules/app/services/manifest-svc.d.ts.map +1 -1
  26. package/dist/modules/catalog/config/catalog-config.test.js +1 -1
  27. package/dist/modules/catalog/config/catalog-config.test.js.map +1 -1
  28. package/dist/modules/catalog/schemas/catalog-ui-components.schema.json +2 -18
  29. package/dist/modules/git/commands/git-connect.d.ts +3 -0
  30. package/dist/modules/git/commands/git-connect.d.ts.map +1 -0
  31. package/dist/modules/git/commands/git-connect.js +156 -0
  32. package/dist/modules/git/commands/git-connect.js.map +1 -0
  33. package/dist/modules/git/errors/git-errors.d.ts +21 -0
  34. package/dist/modules/git/errors/git-errors.d.ts.map +1 -0
  35. package/dist/modules/git/errors/git-errors.js +41 -0
  36. package/dist/modules/git/errors/git-errors.js.map +1 -0
  37. package/dist/modules/git/index.d.ts +5 -0
  38. package/dist/modules/git/index.d.ts.map +1 -0
  39. package/dist/modules/git/index.js +8 -0
  40. package/dist/modules/git/index.js.map +1 -0
  41. package/dist/modules/git/services/git-service.d.ts +24 -0
  42. package/dist/modules/git/services/git-service.d.ts.map +1 -0
  43. package/dist/modules/git/services/git-service.js +56 -0
  44. package/dist/modules/git/services/git-service.js.map +1 -0
  45. package/dist/modules/git/services/github-service.d.ts +27 -0
  46. package/dist/modules/git/services/github-service.d.ts.map +1 -0
  47. package/dist/modules/git/services/github-service.js +45 -0
  48. package/dist/modules/git/services/github-service.js.map +1 -0
  49. package/dist/modules/plugin/commands/plugin-create.d.ts +3 -0
  50. package/dist/modules/plugin/commands/plugin-create.d.ts.map +1 -0
  51. package/dist/modules/plugin/commands/plugin-create.js +59 -0
  52. package/dist/modules/plugin/commands/plugin-create.js.map +1 -0
  53. package/dist/modules/plugin/commands/plugin-install.d.ts.map +1 -1
  54. package/dist/modules/plugin/commands/plugin-install.js +9 -24
  55. package/dist/modules/plugin/commands/plugin-install.js.map +1 -1
  56. package/dist/modules/plugin/errors/plugin-errors.d.ts +24 -1
  57. package/dist/modules/plugin/errors/plugin-errors.d.ts.map +1 -1
  58. package/dist/modules/plugin/errors/plugin-errors.js +79 -6
  59. package/dist/modules/plugin/errors/plugin-errors.js.map +1 -1
  60. package/dist/modules/plugin/index.d.ts +4 -2
  61. package/dist/modules/plugin/index.d.ts.map +1 -1
  62. package/dist/modules/plugin/index.js +4 -2
  63. package/dist/modules/plugin/index.js.map +1 -1
  64. package/dist/modules/plugin/lib/plugin-registry.d.ts +6 -12
  65. package/dist/modules/plugin/lib/plugin-registry.d.ts.map +1 -1
  66. package/dist/modules/plugin/lib/plugin-registry.js +13 -30
  67. package/dist/modules/plugin/lib/plugin-registry.js.map +1 -1
  68. package/dist/modules/plugin/lib/plugin-resolver.d.ts +76 -0
  69. package/dist/modules/plugin/lib/plugin-resolver.d.ts.map +1 -0
  70. package/dist/modules/plugin/lib/plugin-resolver.js +128 -0
  71. package/dist/modules/plugin/lib/plugin-resolver.js.map +1 -0
  72. package/dist/modules/plugin/lib/plugin-resolver.test.d.ts +2 -0
  73. package/dist/modules/plugin/lib/plugin-resolver.test.d.ts.map +1 -0
  74. package/dist/modules/plugin/lib/plugin-resolver.test.js +175 -0
  75. package/dist/modules/plugin/lib/plugin-resolver.test.js.map +1 -0
  76. package/dist/modules/plugin/services/plugin-create-service.d.ts +16 -0
  77. package/dist/modules/plugin/services/plugin-create-service.d.ts.map +1 -0
  78. package/dist/modules/plugin/services/plugin-create-service.js +47 -0
  79. package/dist/modules/plugin/services/plugin-create-service.js.map +1 -0
  80. package/dist/modules/plugin/services/plugin-svc.d.ts +8 -3
  81. package/dist/modules/plugin/services/plugin-svc.d.ts.map +1 -1
  82. package/dist/modules/plugin/services/plugin-svc.js +96 -15
  83. package/dist/modules/plugin/services/plugin-svc.js.map +1 -1
  84. package/dist/modules/release/commands/release-init.d.ts +3 -0
  85. package/dist/modules/release/commands/release-init.d.ts.map +1 -0
  86. package/dist/modules/release/commands/release-init.js +92 -0
  87. package/dist/modules/release/commands/release-init.js.map +1 -0
  88. package/dist/modules/release/errors/release-errors.d.ts +7 -0
  89. package/dist/modules/release/errors/release-errors.d.ts.map +1 -0
  90. package/dist/modules/release/errors/release-errors.js +13 -0
  91. package/dist/modules/release/errors/release-errors.js.map +1 -0
  92. package/dist/modules/release/index.d.ts +4 -0
  93. package/dist/modules/release/index.d.ts.map +1 -0
  94. package/dist/modules/release/index.js +7 -0
  95. package/dist/modules/release/index.js.map +1 -0
  96. package/dist/modules/release/services/release-service.d.ts +34 -0
  97. package/dist/modules/release/services/release-service.d.ts.map +1 -0
  98. package/dist/modules/release/services/release-service.js +154 -0
  99. package/dist/modules/release/services/release-service.js.map +1 -0
  100. package/dist/modules/workspace/commands/init-workspace.d.ts.map +1 -1
  101. package/dist/modules/workspace/commands/init-workspace.js +4 -5
  102. package/dist/modules/workspace/commands/init-workspace.js.map +1 -1
  103. package/dist/modules/workspace/services/workspace-service.d.ts +2 -1
  104. package/dist/modules/workspace/services/workspace-service.d.ts.map +1 -1
  105. package/dist/modules/workspace/services/workspace-service.js +27 -1
  106. package/dist/modules/workspace/services/workspace-service.js.map +1 -1
  107. package/dist/templates/plugin/README.md.hbs +39 -0
  108. package/dist/{plugins/theme/package.json → templates/plugin/package.json.hbs} +5 -3
  109. package/dist/templates/plugin/plugin.json.hbs +7 -0
  110. package/dist/templates/plugin/src/generator.ts.hbs +64 -0
  111. package/dist/templates/plugin/templates/src/.gitkeep +0 -0
  112. package/dist/templates/plugin/tsconfig.json +10 -0
  113. package/dist/{plugins/theme → templates/plugin}/tsup.config.ts +0 -1
  114. package/dist/templates/workspace/.github/workflows/ci.yml +102 -0
  115. package/dist/templates/workspace/package.json +16 -1
  116. package/dist/templates/workspace/turbo.json +5 -0
  117. package/dist/utils/launch77-context.d.ts +1 -1
  118. package/dist/utils/launch77-context.d.ts.map +1 -1
  119. package/dist/utils/launch77-context.js +25 -2
  120. package/dist/utils/launch77-context.js.map +1 -1
  121. package/dist/utils/launch77-validation.d.ts +1 -1
  122. package/dist/utils/launch77-validation.d.ts.map +1 -1
  123. package/dist/utils/string.d.ts +13 -0
  124. package/dist/utils/string.d.ts.map +1 -0
  125. package/dist/utils/string.js +18 -0
  126. package/dist/utils/string.js.map +1 -0
  127. package/package.json +7 -10
  128. package/src/cli.ts +10 -1
  129. package/src/infrastructure/git.ts +86 -0
  130. package/src/infrastructure/github.ts +111 -0
  131. package/src/infrastructure/template-generator.ts +1 -1
  132. package/src/infrastructure/template.ts +14 -0
  133. package/src/modules/app/commands/create-app.ts +1 -1
  134. package/src/modules/app/commands/delete-app.ts +1 -1
  135. package/src/modules/app/services/app-svc.ts +1 -1
  136. package/src/modules/app/services/manifest-svc.ts +1 -1
  137. package/src/modules/catalog/config/catalog-config.test.ts +1 -1
  138. package/src/modules/git/commands/git-connect.ts +183 -0
  139. package/src/modules/git/errors/git-errors.ts +44 -0
  140. package/src/modules/git/index.ts +9 -0
  141. package/src/modules/git/services/git-service.ts +63 -0
  142. package/src/modules/git/services/github-service.ts +52 -0
  143. package/src/modules/plugin/commands/plugin-create.ts +68 -0
  144. package/src/modules/plugin/commands/plugin-install.ts +9 -26
  145. package/src/modules/plugin/errors/plugin-errors.ts +87 -6
  146. package/src/modules/plugin/index.ts +4 -2
  147. package/src/modules/plugin/lib/plugin-registry.ts +14 -37
  148. package/src/modules/plugin/lib/plugin-resolver.test.ts +215 -0
  149. package/src/modules/plugin/lib/plugin-resolver.ts +160 -0
  150. package/src/modules/plugin/services/plugin-create-service.ts +69 -0
  151. package/src/modules/plugin/services/plugin-svc.ts +108 -15
  152. package/src/modules/release/commands/release-init.ts +102 -0
  153. package/src/modules/release/errors/release-errors.ts +13 -0
  154. package/src/modules/release/index.ts +8 -0
  155. package/src/modules/release/services/release-service.ts +170 -0
  156. package/src/modules/workspace/commands/init-workspace.ts +4 -6
  157. package/src/modules/workspace/services/workspace-service.ts +30 -1
  158. package/src/utils/launch77-context.ts +29 -3
  159. package/src/utils/launch77-validation.ts +1 -1
  160. package/src/utils/string.ts +17 -0
  161. package/templates/plugin/README.md.hbs +39 -0
  162. package/templates/plugin/package.json.hbs +34 -0
  163. package/templates/plugin/plugin.json.hbs +7 -0
  164. package/templates/plugin/src/generator.ts.hbs +64 -0
  165. package/templates/plugin/templates/src/.gitkeep +0 -0
  166. package/templates/plugin/tsconfig.json +10 -0
  167. package/templates/plugin/tsup.config.ts +9 -0
  168. package/templates/workspace/.github/workflows/ci.yml +102 -0
  169. package/templates/workspace/package.json +5 -0
  170. package/templates/workspace/turbo.json +5 -0
  171. package/tests/integration/cli.test.ts +25 -0
  172. package/tests/integration/setup.ts +20 -0
  173. package/vitest.config.ts +9 -0
  174. package/vitest.integration.config.ts +9 -0
  175. package/dist/app-templates/webapp/.env.ci +0 -6
  176. package/dist/app-templates/webapp/.env.example +0 -9
  177. package/dist/app-templates/webapp/.eslintrc.json +0 -6
  178. package/dist/app-templates/webapp/README.md.hbs +0 -80
  179. package/dist/app-templates/webapp/app/about/page.tsx.hbs +0 -41
  180. package/dist/app-templates/webapp/app/dashboard/page.tsx.hbs +0 -51
  181. package/dist/app-templates/webapp/app/globals.css +0 -31
  182. package/dist/app-templates/webapp/app/layout.tsx.hbs +0 -26
  183. package/dist/app-templates/webapp/app/page.tsx.hbs +0 -30
  184. package/dist/app-templates/webapp/next.config.js +0 -99
  185. package/dist/app-templates/webapp/package.json.hbs +0 -30
  186. package/dist/app-templates/webapp/postcss.config.js +0 -6
  187. package/dist/app-templates/webapp/tailwind.config.ts +0 -24
  188. package/dist/app-templates/webapp/tsconfig.json +0 -29
  189. package/dist/app-templates/webapp/vercel.json.hbs +0 -7
  190. package/dist/modules/catalog/schemas/schemas/catalog-ui-components.schema.json +0 -145
  191. package/dist/plugins/theme/plugin.json +0 -9
  192. package/dist/plugins/theme/src/generator.ts +0 -92
  193. package/dist/plugins/theme/src/utils/config-modifier.ts +0 -142
  194. package/dist/plugins/theme/src/utils/css-modifier.ts +0 -89
  195. package/dist/plugins/theme/templates/app/theme-test/page.tsx +0 -156
  196. package/dist/plugins/theme/templates/src/modules/theme/README.md +0 -209
  197. package/dist/plugins/theme/templates/src/modules/theme/config/brand.css +0 -23
  198. package/dist/plugins/theme/tsconfig.json +0 -14
  199. package/dist/templates/templates/startup/apps/.gitkeep +0 -8
  200. package/dist/templates/templates/workspace/.launch77/workspace.json +0 -3
  201. package/dist/templates/templates/workspace/README.md +0 -62
  202. package/dist/templates/templates/workspace/app-templates/.gitkeep +0 -1
  203. package/dist/templates/templates/workspace/apps/.gitkeep +0 -1
  204. package/dist/templates/templates/workspace/libraries/.gitkeep +0 -1
  205. package/dist/templates/templates/workspace/package.json +0 -31
  206. package/dist/templates/templates/workspace/plugins/.gitkeep +0 -1
  207. package/dist/templates/templates/workspace/tsconfig.json +0 -22
  208. package/dist/templates/templates/workspace/turbo.json +0 -25
  209. package/launch77-cli-1.2.0.tgz +0 -0
  210. package/src/modules/plugin/lib/launch77-workspace.code-workspace +0 -14
  211. /package/dist/templates/{templates/workspace → workspace}/.eslintignore +0 -0
  212. /package/dist/templates/{templates/workspace → workspace}/.eslintrc.js +0 -0
  213. /package/dist/templates/{templates/workspace → workspace}/.husky/pre-push +0 -0
  214. /package/dist/templates/{templates/workspace → workspace}/.lintstagedrc.json +0 -0
  215. /package/dist/templates/{templates/workspace → workspace}/.prettierrc +0 -0
@@ -38,14 +38,12 @@ export function initWorkspaceCommand(): Command {
38
38
  try {
39
39
  const spinner = ora('Creating workspace structure...').start()
40
40
 
41
- const result = await service.initWorkspace({ name: workspaceName }, process.cwd())
42
-
43
- spinner.succeed('Workspace structure created')
41
+ const cwd = process.cwd()
42
+ const result = await service.initWorkspace({ name: workspaceName }, cwd, spinner)
44
43
 
45
44
  // Success message
46
- const cwd = process.cwd()
47
- console.log(chalk.green(`\n Workspace created successfully at ${path.relative(cwd, result.workspacePath)}\n`))
48
- console.log(chalk.gray(`Next steps:\n` + ` 1. cd ${workspaceName}\n` + ` 2. npm install\n` + ` 3. Create your first app with launch77 commands\n`))
45
+ console.log(chalk.green(`\n✅ Workspace ready at ${path.relative(cwd, result.workspacePath)}\n`))
46
+ console.log(chalk.gray(`Next steps:\n` + ` 1. cd ${workspaceName}\n` + ` 2. Create your first app with launch77 commands\n`))
49
47
  } catch (error) {
50
48
  if (error instanceof WorkspaceAlreadyExistsError) {
51
49
  console.error(chalk.red(`\n❌ ${error.message}\n`))
@@ -1,14 +1,18 @@
1
1
  import * as path from 'path'
2
2
  import { fileURLToPath } from 'url'
3
3
 
4
+ import { execa } from 'execa'
5
+
4
6
  import * as filesystem from '../../../infrastructure/filesystem.js'
7
+ import * as npm from '../../../infrastructure/npm.js'
5
8
  import { WorkspaceAlreadyExistsError } from '../errors/workspace-errors.js'
6
9
  import { validateWorkspaceName } from '../utils/workspace-validators.js'
7
10
 
8
11
  import type { InitWorkspaceRequest, InitWorkspaceResult } from '../types/workspace-types.js'
12
+ import type { Ora } from 'ora'
9
13
 
10
14
  export class WorkspaceService {
11
- async initWorkspace(request: InitWorkspaceRequest, cwd: string): Promise<InitWorkspaceResult> {
15
+ async initWorkspace(request: InitWorkspaceRequest, cwd: string, spinner?: Ora): Promise<InitWorkspaceResult> {
12
16
  const { name } = request
13
17
 
14
18
  // 1. Validate name
@@ -38,6 +42,31 @@ export class WorkspaceService {
38
42
  throw new Error('Failed to create workspace manifest (.launch77/workspace.json)')
39
43
  }
40
44
 
45
+ // 7. Stop spinner before npm install
46
+ if (spinner) {
47
+ spinner.succeed('Workspace structure created')
48
+ }
49
+
50
+ // 8. Install dependencies
51
+ console.log('\nInstalling dependencies...')
52
+ try {
53
+ await npm.install(workspacePath)
54
+ console.log('✓ Dependencies installed')
55
+ } catch (error) {
56
+ console.warn('⚠ Warning: npm install failed:', error instanceof Error ? error.message : String(error))
57
+ console.warn('You may need to run npm install manually in the workspace directory')
58
+ }
59
+
60
+ // 9. Initialize changesets
61
+ console.log('\nInitializing changesets...')
62
+ try {
63
+ await execa('npx', ['changeset', 'init'], { cwd: workspacePath })
64
+ console.log('✓ Changesets initialized')
65
+ } catch (error) {
66
+ console.warn('⚠ Warning: changeset init failed:', error instanceof Error ? error.message : String(error))
67
+ console.warn('You may need to run npx changeset init manually in the workspace directory')
68
+ }
69
+
41
70
  return {
42
71
  workspacePath,
43
72
  name,
@@ -2,7 +2,7 @@ import * as path from 'path'
2
2
 
3
3
  import fs from 'fs-extra'
4
4
 
5
- export type Launch77LocationType = 'workspace-root' | 'workspace-app' | 'unknown'
5
+ export type Launch77LocationType = 'workspace-root' | 'workspace-app' | 'workspace-library' | 'workspace-plugin' | 'workspace-app-template' | 'unknown'
6
6
 
7
7
  export interface Launch77Context {
8
8
  isValid: boolean
@@ -64,6 +64,9 @@ interface ParsedLocation {
64
64
  * Parse the directory structure to determine location context
65
65
  * Based on patterns:
66
66
  * - apps/[name] → workspace-app
67
+ * - libraries/[name] → workspace-library
68
+ * - plugins/[name] → workspace-plugin
69
+ * - app-templates/[name] → workspace-app-template
67
70
  * - (empty or root) → workspace-root
68
71
  */
69
72
  function parseLocationFromPath(cwdPath: string, workspaceRoot: string): ParsedLocation {
@@ -84,8 +87,31 @@ function parseLocationFromPath(cwdPath: string, workspaceRoot: string): ParsedLo
84
87
  }
85
88
  }
86
89
 
87
- // Somewhere else in workspace (libraries, plugins, etc.)
88
- // Still considered workspace-root for now
90
+ // libraries/[lib-name]/...
91
+ if (parts[0] === 'libraries' && parts.length >= 2) {
92
+ return {
93
+ locationType: 'workspace-library',
94
+ appName: parts[1],
95
+ }
96
+ }
97
+
98
+ // plugins/[plugin-name]/...
99
+ if (parts[0] === 'plugins' && parts.length >= 2) {
100
+ return {
101
+ locationType: 'workspace-plugin',
102
+ appName: parts[1],
103
+ }
104
+ }
105
+
106
+ // app-templates/[template-name]/...
107
+ if (parts[0] === 'app-templates' && parts.length >= 2) {
108
+ return {
109
+ locationType: 'workspace-app-template',
110
+ appName: parts[1],
111
+ }
112
+ }
113
+
114
+ // Somewhere else in workspace
89
115
  return { locationType: 'workspace-root' }
90
116
  }
91
117
 
@@ -1,4 +1,4 @@
1
- import type { Launch77Context } from './launch77-context.js'
1
+ import type { Launch77Context } from '@launch77/plugin-runtime'
2
2
 
3
3
  /**
4
4
  * Validation result with helpful error messages
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Convert a kebab-case or snake_case string to PascalCase
3
+ *
4
+ * @param str - The string to convert (e.g., "my-plugin" or "my_plugin")
5
+ * @returns PascalCase string (e.g., "MyPlugin")
6
+ *
7
+ * @example
8
+ * toPascalCase('my-plugin') // 'MyPlugin'
9
+ * toPascalCase('release') // 'Release'
10
+ * toPascalCase('my-awesome-plugin') // 'MyAwesomePlugin'
11
+ */
12
+ export function toPascalCase(str: string): string {
13
+ return str
14
+ .split(/[-_]/)
15
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
16
+ .join('')
17
+ }
@@ -0,0 +1,39 @@
1
+ # {{pluginNamePascal}} Plugin
2
+
3
+ {{description}}
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ launch77 plugin:install {{pluginName}}
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ After installation, the plugin will:
14
+
15
+ - TODO: Describe what the plugin does
16
+ - TODO: List any files created or modified
17
+ - TODO: Explain configuration options
18
+
19
+ ## Development
20
+
21
+ ### Building
22
+
23
+ ```bash
24
+ npm run build
25
+ ```
26
+
27
+ ### Testing
28
+
29
+ ```bash
30
+ npm run typecheck
31
+ ```
32
+
33
+ ## Template Files
34
+
35
+ The `templates/` directory contains files that will be copied to the target application when this plugin is installed. Add any template files your plugin needs here.
36
+
37
+ ## License
38
+
39
+ UNLICENSED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@{{workspaceName}}/plugin-{{pluginName}}",
3
+ "version": "1.0.0",
4
+ "description": "{{description}}",
5
+ "license": "UNLICENSED",
6
+ "private": true,
7
+ "type": "module",
8
+ "main": "dist/generator.js",
9
+ "bin": {
10
+ "generate": "./dist/generator.js"
11
+ },
12
+ "files": [
13
+ "dist/",
14
+ "templates/",
15
+ "plugin.json"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsup",
19
+ "dev": "tsup --watch",
20
+ "typecheck": "tsc --noEmit"
21
+ },
22
+ "dependencies": {
23
+ "@launch77/plugin-runtime": "^0.1.0",
24
+ "chalk": "^5.3.0"
25
+ },
26
+ "devDependencies": {
27
+ "@types/node": "^20.10.0",
28
+ "tsup": "^8.0.0",
29
+ "typescript": "^5.3.0"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ }
34
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "{{pluginName}}",
3
+ "version": "1.0.0",
4
+ "description": "{{description}}",
5
+ "pluginDependencies": {},
6
+ "libraryDependencies": {}
7
+ }
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+
3
+ import chalk from 'chalk'
4
+ import { StandardGenerator } from '@launch77/plugin-runtime'
5
+ import type { GeneratorContext } from '@launch77/plugin-runtime'
6
+
7
+ export class {{pluginNamePascal}}Generator extends StandardGenerator {
8
+ constructor(context: GeneratorContext) {
9
+ super(context)
10
+ }
11
+
12
+ protected async injectCode(): Promise<void> {
13
+ console.log(chalk.cyan('🔧 Setting up {{pluginName}} plugin...\n'))
14
+
15
+ // TODO: Add your plugin's code injection logic here
16
+ // Examples:
17
+ // - Copy template files to the app
18
+ // - Modify package.json
19
+ // - Update configuration files
20
+
21
+ console.log(chalk.green(' ✓ Plugin setup complete\n'))
22
+ }
23
+
24
+ protected showNextSteps(): void {
25
+ console.log(chalk.white('\n' + '─'.repeat(60) + '\n'))
26
+ console.log(chalk.cyan('📋 {{pluginNamePascal}} Plugin Installed!\n'))
27
+ console.log(chalk.white('Next Steps:\n'))
28
+
29
+ console.log(chalk.gray('1. TODO: Add your first step'))
30
+ console.log(chalk.cyan(' npm run <command>\n'))
31
+
32
+ console.log(chalk.gray('2. TODO: Add your second step'))
33
+ console.log(chalk.cyan(' npm run <command>\n'))
34
+
35
+ console.log(chalk.white('Documentation:\n'))
36
+ console.log(chalk.gray('See README.md for detailed instructions.\n'))
37
+ }
38
+ }
39
+
40
+ // CLI entry point
41
+ async function main() {
42
+ const args = process.argv.slice(2)
43
+ const appPath = args.find((arg) => arg.startsWith('--appPath='))?.split('=')[1]
44
+ const appName = args.find((arg) => arg.startsWith('--appName='))?.split('=')[1]
45
+ const workspaceName = args.find((arg) => arg.startsWith('--workspaceName='))?.split('=')[1]
46
+ const pluginPath = args.find((arg) => arg.startsWith('--pluginPath='))?.split('=')[1]
47
+
48
+ if (!appPath || !appName || !workspaceName || !pluginPath) {
49
+ console.error(chalk.red('Error: Missing required arguments'))
50
+ console.error(chalk.gray('Usage: --appPath=<path> --appName=<name> --workspaceName=<name> --pluginPath=<path>'))
51
+ process.exit(1)
52
+ }
53
+
54
+ const generator = new {{pluginNamePascal}}Generator({ appPath, appName, workspaceName, pluginPath })
55
+ await generator.run()
56
+ }
57
+
58
+ if (import.meta.url === `file://${process.argv[1]}`) {
59
+ main().catch((error) => {
60
+ console.error(chalk.red('\n❌ Error during plugin setup:'))
61
+ console.error(error)
62
+ process.exit(1)
63
+ })
64
+ }
File without changes
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src",
6
+ "module": "ESNext",
7
+ "target": "ES2022"
8
+ },
9
+ "include": ["src/**/*"]
10
+ }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from 'tsup'
2
+
3
+ export default defineConfig({
4
+ entry: ['src/generator.ts'],
5
+ format: ['esm'],
6
+ dts: false,
7
+ clean: true,
8
+ shims: true,
9
+ })
@@ -0,0 +1,102 @@
1
+ name: CI & Release
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main, develop]
6
+ push:
7
+ branches: [main, develop]
8
+
9
+ permissions:
10
+ contents: write
11
+ pull-requests: write
12
+ id-token: write
13
+
14
+ concurrency: ${{ github.workflow }}-${{ github.ref }}
15
+
16
+ jobs:
17
+ build-and-test:
18
+ runs-on: ubuntu-latest
19
+
20
+ strategy:
21
+ matrix:
22
+ node-version: [20.x]
23
+
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+
27
+ - name: Setup Node.js ${{ matrix.node-version }}
28
+ uses: actions/setup-node@v4
29
+ with:
30
+ node-version: ${{ matrix.node-version }}
31
+ cache: 'npm'
32
+
33
+ - name: Install dependencies
34
+ run: npm install
35
+
36
+ - name: Run linting
37
+ run: npm run lint
38
+
39
+ - name: Build packages
40
+ run: npm run build
41
+
42
+ - name: Run type checking
43
+ run: npm run typecheck
44
+
45
+ - name: Run tests
46
+ run: npm run test
47
+
48
+ - name: Run integration tests
49
+ run: npm run test:integration
50
+
51
+ quality-checks:
52
+ runs-on: ubuntu-latest
53
+
54
+ steps:
55
+ - uses: actions/checkout@v4
56
+
57
+ - name: Setup Node.js 20.x
58
+ uses: actions/setup-node@v4
59
+ with:
60
+ node-version: 20.x
61
+ cache: 'npm'
62
+
63
+ - name: Install dependencies
64
+ run: npm install
65
+
66
+ - name: Check for dependency vulnerabilities
67
+ run: npm audit --audit-level=high
68
+
69
+ - name: Check formatting
70
+ run: npx prettier --check "**/*.{js,jsx,ts,tsx,json,md}"
71
+
72
+ release:
73
+ name: Release
74
+ runs-on: ubuntu-latest
75
+ needs: [build-and-test, quality-checks]
76
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
77
+
78
+ steps:
79
+ - name: Checkout Repo
80
+ uses: actions/checkout@v4
81
+
82
+ - name: Setup Node.js 20.x
83
+ uses: actions/setup-node@v4
84
+ with:
85
+ node-version: 20.x
86
+ cache: 'npm'
87
+
88
+ - name: Upgrade npm
89
+ run: npm i -g npm@latest
90
+
91
+ - name: Install Dependencies
92
+ run: npm install
93
+
94
+ - name: Create Release Pull Request or Publish to npm
95
+ id: changesets
96
+ uses: changesets/action@v1
97
+ with:
98
+ publish: npm run release
99
+ title: "chore: version packages"
100
+ commit: "chore: version packages"
101
+ env:
102
+ GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
@@ -13,11 +13,16 @@
13
13
  "dev": "turbo run dev",
14
14
  "build": "turbo run build",
15
15
  "test": "turbo run test",
16
+ "test:integration": "turbo run test:integration",
16
17
  "lint": "turbo run lint",
17
18
  "typecheck": "turbo run typecheck",
19
+ "changeset": "changeset",
20
+ "version-packages": "changeset version",
21
+ "release": "turbo run build lint typecheck test && changeset publish",
18
22
  "prepare": "husky"
19
23
  },
20
24
  "devDependencies": {
25
+ "@changesets/cli": "^2.29.8",
21
26
  "@typescript-eslint/eslint-plugin": "^6.0.0",
22
27
  "@typescript-eslint/parser": "^6.0.0",
23
28
  "eslint": "^8.56.0",
@@ -20,6 +20,11 @@
20
20
  "test": {
21
21
  "outputs": [],
22
22
  "dependsOn": ["build"]
23
+ },
24
+ "test:integration": {
25
+ "outputs": [],
26
+ "dependsOn": ["build"],
27
+ "cache": false
23
28
  }
24
29
  }
25
30
  }
@@ -0,0 +1,25 @@
1
+ import { describe, it, expect, beforeAll } from 'vitest'
2
+ import { existsSync } from 'fs'
3
+ import { runCli } from './setup.js'
4
+
5
+ describe('CLI Integration Tests', () => {
6
+ beforeAll(() => {
7
+ if (!existsSync('./dist/cli.js')) {
8
+ throw new Error('CLI not built. Run `npm run build` first.')
9
+ }
10
+ })
11
+
12
+ it('should display version', async () => {
13
+ const { stdout, exitCode } = await runCli(['--version'])
14
+
15
+ expect(exitCode).toBe(0)
16
+ expect(stdout).toMatch(/\d+\.\d+\.\d+/)
17
+ })
18
+
19
+ it('should display help', async () => {
20
+ const { stdout, exitCode } = await runCli(['--help'])
21
+
22
+ expect(exitCode).toBe(0)
23
+ expect(stdout).toContain('launch77')
24
+ })
25
+ })
@@ -0,0 +1,20 @@
1
+ import { execa } from 'execa'
2
+ import { fileURLToPath } from 'url'
3
+ import { dirname, join } from 'path'
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url))
6
+ const CLI_PATH = join(__dirname, '../../dist/cli.js')
7
+
8
+ export async function runCli(args: string[], options?: { cwd?: string }) {
9
+ const result = await execa('node', [CLI_PATH, ...args], {
10
+ reject: false,
11
+ cwd: options?.cwd,
12
+ env: { ...process.env, CI: 'true' },
13
+ })
14
+
15
+ return {
16
+ stdout: result.stdout,
17
+ stderr: result.stderr,
18
+ exitCode: result.exitCode ?? 0,
19
+ }
20
+ }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from 'vitest/config'
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ include: ['src/**/*.test.ts'],
6
+ testTimeout: 10000,
7
+ hookTimeout: 10000,
8
+ },
9
+ })
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from 'vitest/config'
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ include: ['tests/integration/**/*.test.ts'],
6
+ testTimeout: 30000,
7
+ hookTimeout: 60000,
8
+ },
9
+ })
@@ -1,6 +0,0 @@
1
- # CI/CD Build Environment Variables
2
- # These values allow Next.js to build and prerender static pages in CI
3
- # Real production values are set in deployment platform (Vercel)
4
- NEXT_PUBLIC_SITE_URL=http://localhost:3000
5
- NEXT_PUBLIC_API_URL=http://localhost:4000/graphql
6
- NEXT_PUBLIC_GTM_ID=
@@ -1,9 +0,0 @@
1
- # Site Configuration
2
- NEXT_PUBLIC_SITE_URL=http://localhost:3000
3
-
4
- # Analytics
5
- # Get your GTM ID from Google Tag Manager (format: GTM-XXXXXXX)
6
- NEXT_PUBLIC_GTM_ID=
7
-
8
- # Feature Flags (optional)
9
- # NEXT_PUBLIC_ENABLE_ANALYTICS=true
@@ -1,6 +0,0 @@
1
- {
2
- "extends": ["next/core-web-vitals"],
3
- "rules": {
4
- "import/order": "off"
5
- }
6
- }
@@ -1,80 +0,0 @@
1
- # {{appName}}
2
-
3
- {{#if startupName}}Part of the {{startupName}} startup{{/if}}
4
-
5
- A web application built with the Launch77 Platform.
6
-
7
- ## Getting Started
8
-
9
- 1. Install dependencies (from monorepo root):
10
- ```bash
11
- npm install
12
- ```
13
-
14
- 2. Set up environment variables:
15
- ```bash
16
- cp .env.example .env.local
17
- ```
18
-
19
- 3. Run the development server:
20
- ```bash
21
- npm run dev
22
- ```
23
-
24
- Open [http://localhost:{{port}}](http://localhost:{{port}}) in your browser.
25
-
26
- ## Available Scripts
27
-
28
- - `npm run dev` - Start development server
29
- - `npm run build` - Build for production
30
- - `npm run start` - Start production server
31
- - `npm run lint` - Run ESLint
32
- - `npm run typecheck` - Run TypeScript type checking
33
-
34
- ## Launch77 Packages
35
-
36
- This app uses the following Launch77 platform packages:
37
-
38
- - **@launch77/ui** - Shared component library
39
- - **@launch77/theme** - Tailwind preset and design tokens
40
-
41
- ## Project Structure
42
-
43
- ```
44
- app/
45
- ├── layout.tsx # Root layout
46
- ├── page.tsx # Homepage
47
- ├── dashboard/ # Example dashboard page
48
- ├── about/ # About page
49
- └── globals.css # Global styles (imports @launch77/theme)
50
- ```
51
-
52
- ## Next Steps
53
-
54
- 1. **Add Authentication**: Implement login/register pages and protect routes
55
- 2. **Connect to API**: Set up API client to connect to your backend
56
- 3. **Add Features**: Build out your application features
57
-
58
- ## Using UI Components
59
-
60
- ```tsx
61
- import { Button, Card, Input } from '@launch77/ui'
62
-
63
- export default function MyPage() {
64
- return (
65
- <Card>
66
- <Input placeholder="Enter text" />
67
- <Button>Submit</Button>
68
- </Card>
69
- )
70
- }
71
- ```
72
-
73
- ## Customizing Theme
74
-
75
- Extend `tailwind.config.ts` for theme customization.
76
-
77
- ## Learn More
78
-
79
- - [Next.js Documentation](https://nextjs.org/docs)
80
- - [Launch77 Platform Docs](../../README.md)
@@ -1,41 +0,0 @@
1
- import Link from 'next/link'
2
-
3
- export default function AboutPage() {
4
- return (
5
- <div className="min-h-screen bg-gray-50">
6
- <nav className="border-b border-gray-200">
7
- <div className="max-w-7xl mx-auto px-4 py-4">
8
- <div className="flex items-center justify-between">
9
- <h1 className="text-xl font-bold text-gray-900">{{appName}}</h1>
10
- <Link
11
- href="/"
12
- className="px-4 py-2 text-sm font-medium text-gray-700 hover:text-gray-900 hover:bg-gray-100 rounded-md transition-colors"
13
- >
14
- Home
15
- </Link>
16
- </div>
17
- </div>
18
- </nav>
19
-
20
- <main className="max-w-3xl mx-auto px-4 py-16">
21
- <h1 className="text-4xl font-bold text-gray-900 mb-4">
22
- About {{appName}}
23
- </h1>
24
- <div className="prose prose-slate">
25
- <p className="text-lg text-gray-600 mb-4">
26
- This is a web application built with the Launch77 Platform.
27
- </p>
28
- <p className="text-gray-600 mb-4">
29
- Launch77 provides a modern development environment with:
30
- </p>
31
- <ul className="list-disc list-inside text-gray-600 mb-4 space-y-2">
32
- <li>Next.js for server-side rendering and routing</li>
33
- <li>Tailwind CSS for styling</li>
34
- <li>TypeScript for type safety</li>
35
- <li>Plugin-based architecture for adding capabilities</li>
36
- </ul>
37
- </div>
38
- </main>
39
- </div>
40
- )
41
- }