@bagelink/workspace 1.9.0 → 1.10.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/README.md +65 -0
- package/bin/bgl.ts +32 -9
- package/dist/bin/bgl.cjs +35 -14
- package/dist/bin/bgl.mjs +30 -9
- package/dist/index.cjs +16 -14
- package/dist/index.d.cts +15 -6
- package/dist/index.d.mts +15 -6
- package/dist/index.d.ts +15 -6
- package/dist/index.mjs +2 -2
- package/dist/shared/{workspace.cX7U2RUq.mjs → workspace.CTMBmbXa.mjs} +307 -171
- package/dist/shared/{workspace.CCUm_5GG.cjs → workspace.dQE-K3dI.cjs} +308 -170
- package/package.json +6 -1
- package/src/index.ts +2 -1
- package/src/sdk.ts +186 -0
package/src/sdk.ts
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import type { WorkspaceConfig } from './types'
|
|
2
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
|
|
3
|
+
import { resolve } from 'node:path'
|
|
4
|
+
import process from 'node:process'
|
|
5
|
+
import prompts from 'prompts'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generate SDK from OpenAPI spec
|
|
9
|
+
*/
|
|
10
|
+
export async function generateSDK(
|
|
11
|
+
root: string = process.cwd(),
|
|
12
|
+
projectName?: string,
|
|
13
|
+
): Promise<void> {
|
|
14
|
+
console.log('\n🔧 Generating SDK from OpenAPI...\n')
|
|
15
|
+
|
|
16
|
+
// Try to load config
|
|
17
|
+
let config: WorkspaceConfig | null = null
|
|
18
|
+
let openApiUrl: string | undefined
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const configPath = resolve(root, 'bgl.config.ts')
|
|
22
|
+
if (existsSync(configPath)) {
|
|
23
|
+
const module = await import(`file://${configPath}`)
|
|
24
|
+
const workspace = module.default
|
|
25
|
+
if (typeof workspace === 'function') {
|
|
26
|
+
config = workspace('development')
|
|
27
|
+
openApiUrl = config.openapi_url
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
console.warn('⚠️ Could not load bgl.config.ts')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Prompt for missing info
|
|
36
|
+
const response = await prompts([
|
|
37
|
+
{
|
|
38
|
+
type: openApiUrl ? null : 'text',
|
|
39
|
+
name: 'openApiUrl',
|
|
40
|
+
message: 'OpenAPI spec URL:',
|
|
41
|
+
initial: openApiUrl || 'http://localhost:8000/openapi.json',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
type: 'text',
|
|
45
|
+
name: 'outputDir',
|
|
46
|
+
message: 'Output directory:',
|
|
47
|
+
initial: './src/api',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
type: 'confirm',
|
|
51
|
+
name: 'splitFiles',
|
|
52
|
+
message: 'Split into organized files?',
|
|
53
|
+
initial: true,
|
|
54
|
+
},
|
|
55
|
+
])
|
|
56
|
+
|
|
57
|
+
if (!response) {
|
|
58
|
+
console.log('\n❌ SDK generation cancelled.\n')
|
|
59
|
+
process.exit(1)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const finalUrl = openApiUrl || response.openApiUrl
|
|
63
|
+
const { outputDir, splitFiles } = response
|
|
64
|
+
|
|
65
|
+
console.log(`\n📡 Fetching OpenAPI spec from: ${finalUrl}`)
|
|
66
|
+
console.log(`📁 Output directory: ${outputDir}\n`)
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
// Dynamic import of @bagelink/sdk
|
|
70
|
+
const { default: openAPI } = await import('@bagelink/sdk')
|
|
71
|
+
|
|
72
|
+
const { types, code } = await openAPI(finalUrl, '/api')
|
|
73
|
+
|
|
74
|
+
const outputPath = resolve(root, outputDir)
|
|
75
|
+
if (!existsSync(outputPath)) {
|
|
76
|
+
mkdirSync(outputPath, { recursive: true })
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Write types
|
|
80
|
+
const typesPath = resolve(outputPath, 'types.d.ts')
|
|
81
|
+
writeFileSync(typesPath, types)
|
|
82
|
+
console.log('✅ Generated types.d.ts')
|
|
83
|
+
|
|
84
|
+
// Write API client
|
|
85
|
+
const apiPath = resolve(outputPath, 'api.ts')
|
|
86
|
+
writeFileSync(apiPath, code)
|
|
87
|
+
console.log('✅ Generated api.ts')
|
|
88
|
+
|
|
89
|
+
// Write index
|
|
90
|
+
const indexPath = resolve(outputPath, 'index.ts')
|
|
91
|
+
writeFileSync(
|
|
92
|
+
indexPath,
|
|
93
|
+
'export * from \'./api\'\nexport * from \'./types.d\'\n',
|
|
94
|
+
)
|
|
95
|
+
console.log('✅ Generated index.ts')
|
|
96
|
+
|
|
97
|
+
if (splitFiles) {
|
|
98
|
+
console.log('\n🔀 Splitting into organized files...')
|
|
99
|
+
try {
|
|
100
|
+
const { splitClientCode } = await import('@bagelink/sdk/bin/splitClientGen')
|
|
101
|
+
await splitClientCode({
|
|
102
|
+
bagelinkDir: outputPath,
|
|
103
|
+
useDirectories: true,
|
|
104
|
+
})
|
|
105
|
+
// Clean up monolithic files
|
|
106
|
+
const fs = await import('node:fs')
|
|
107
|
+
fs.rmSync(apiPath, { force: true })
|
|
108
|
+
fs.rmSync(typesPath, { force: true })
|
|
109
|
+
fs.rmSync(indexPath, { force: true })
|
|
110
|
+
console.log('✅ Files organized into directories')
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.warn('⚠️ Could not split files, keeping monolithic structure')
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
console.log('\n✅ SDK generated successfully!')
|
|
118
|
+
console.log(`\nImport it in your code:`)
|
|
119
|
+
console.log(` import { api } from '${outputDir.replace('./src/', './')}'`)
|
|
120
|
+
console.log('')
|
|
121
|
+
}
|
|
122
|
+
catch (error: unknown) {
|
|
123
|
+
console.error('\n❌ Failed to generate SDK:')
|
|
124
|
+
if (error instanceof Error) {
|
|
125
|
+
console.error(error.message)
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
console.error(error)
|
|
129
|
+
}
|
|
130
|
+
console.log('\nMake sure:')
|
|
131
|
+
console.log(' 1. @bagelink/sdk is installed: bun add -D @bagelink/sdk')
|
|
132
|
+
console.log(' 2. OpenAPI URL is accessible')
|
|
133
|
+
console.log(' 3. API server is running (if using localhost)')
|
|
134
|
+
process.exit(1)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Generate SDK for all projects in workspace
|
|
140
|
+
*/
|
|
141
|
+
export async function generateSDKForWorkspace(root: string = process.cwd()): Promise<void> {
|
|
142
|
+
console.log('\n🏢 Generating SDK for workspace projects...\n')
|
|
143
|
+
|
|
144
|
+
// Find all projects
|
|
145
|
+
const fs = await import('node:fs')
|
|
146
|
+
const items = fs.readdirSync(root, { withFileTypes: true })
|
|
147
|
+
const projects = items
|
|
148
|
+
.filter(
|
|
149
|
+
item => item.isDirectory()
|
|
150
|
+
&& item.name !== 'node_modules'
|
|
151
|
+
&& item.name !== 'shared'
|
|
152
|
+
&& item.name !== '.git'
|
|
153
|
+
&& !item.name.startsWith('.'),
|
|
154
|
+
)
|
|
155
|
+
.map(item => item.name)
|
|
156
|
+
|
|
157
|
+
if (projects.length === 0) {
|
|
158
|
+
console.log('No projects found in workspace')
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const response = await prompts({
|
|
163
|
+
type: 'multiselect',
|
|
164
|
+
name: 'selectedProjects',
|
|
165
|
+
message: 'Select projects to generate SDK for:',
|
|
166
|
+
choices: projects.map(p => ({ title: p, value: p, selected: true })),
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
if (!response || !response.selectedProjects || response.selectedProjects.length === 0) {
|
|
170
|
+
console.log('\n❌ No projects selected.\n')
|
|
171
|
+
return
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
for (const project of response.selectedProjects) {
|
|
175
|
+
console.log(`\n📦 Generating SDK for: ${project}`)
|
|
176
|
+
const projectPath = resolve(root, project)
|
|
177
|
+
try {
|
|
178
|
+
await generateSDK(projectPath)
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
console.error(`Failed to generate SDK for ${project}:`, error)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
console.log('\n✅ All SDKs generated!')
|
|
186
|
+
}
|