buildx-cli 1.0.10 → 1.0.11
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/dist/README.md +546 -0
- package/dist/index.cjs +14 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +14 -0
- package/dist/package.json +64 -0
- package/package.json +7 -2
- package/.github/workflows/auto-publish.yml +0 -254
- package/.github/workflows/create-pr.yml +0 -182
- package/.prettierrc +0 -8
- package/eslint.config.mjs +0 -115
- package/jest.config.cjs +0 -16
- package/rollup.config.mjs +0 -64
- package/scripts/prepare-publish.js +0 -12
- package/src/__tests__/config.test.ts +0 -102
- package/src/__tests__/schema-types-convert.test.ts +0 -147
- package/src/commands/auth/login.ts +0 -148
- package/src/commands/auth/logout.ts +0 -16
- package/src/commands/auth/status.ts +0 -52
- package/src/commands/config/clear.ts +0 -16
- package/src/commands/config/index.ts +0 -14
- package/src/commands/config/setup.ts +0 -108
- package/src/commands/config/show.ts +0 -96
- package/src/commands/functions.ts +0 -703
- package/src/commands/projects/current.ts +0 -36
- package/src/commands/projects/list.ts +0 -61
- package/src/commands/projects/set-default.ts +0 -59
- package/src/commands/sync.ts +0 -778
- package/src/config/index.ts +0 -169
- package/src/index.ts +0 -62
- package/src/services/api.ts +0 -198
- package/src/services/schema-generator.ts +0 -132
- package/src/services/schema-types-convert.ts +0 -361
- package/src/types/index.ts +0 -91
- package/src/utils/env.ts +0 -117
- package/src/utils/logger.ts +0 -29
- package/src/utils/sync.ts +0 -70
- package/test.env +0 -2
- package/tsconfig.json +0 -29
package/src/config/index.ts
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import Conf from "conf";
|
|
2
|
-
import { GlobalConfig, AuthConfig, ProjectsConfig, SyncConfig, ApiConfig } from "../types/index";
|
|
3
|
-
import { loadEnvConfig } from "../utils/env";
|
|
4
|
-
|
|
5
|
-
export class ConfigManager {
|
|
6
|
-
private config: Conf<GlobalConfig>;
|
|
7
|
-
|
|
8
|
-
constructor() {
|
|
9
|
-
this.config = new Conf<GlobalConfig>({
|
|
10
|
-
projectName: "buildx-cli",
|
|
11
|
-
schema: {
|
|
12
|
-
api: {
|
|
13
|
-
type: "object",
|
|
14
|
-
properties: {
|
|
15
|
-
endpoint: { type: "string" },
|
|
16
|
-
apiKey: { type: "string" }
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
auth: {
|
|
20
|
-
type: "object",
|
|
21
|
-
properties: {
|
|
22
|
-
token: { type: "string" },
|
|
23
|
-
expiresAt: { type: "string" }
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
projects: {
|
|
27
|
-
type: "object",
|
|
28
|
-
properties: {
|
|
29
|
-
default: { type: "string" },
|
|
30
|
-
list: { type: "array" }
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
sync: {
|
|
34
|
-
type: "object",
|
|
35
|
-
properties: {
|
|
36
|
-
outputPath: { type: "string" }
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
defaults: {
|
|
41
|
-
sync: {
|
|
42
|
-
outputPath: "./buildx/generated/types.ts"
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// API configuration methods
|
|
49
|
-
getApiConfig(): ApiConfig | undefined {
|
|
50
|
-
const storedConfig = this.config.get("api");
|
|
51
|
-
if (storedConfig?.endpoint && storedConfig?.apiKey) {
|
|
52
|
-
return storedConfig;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Fallback to environment variables
|
|
56
|
-
const envConfig = loadEnvConfig();
|
|
57
|
-
if (envConfig.BUILDX_API_ENDPOINT && envConfig.BUILDX_API_KEY) {
|
|
58
|
-
return {
|
|
59
|
-
endpoint: envConfig.BUILDX_API_ENDPOINT,
|
|
60
|
-
apiKey: envConfig.BUILDX_API_KEY
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return undefined;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
setApiConfig(api: ApiConfig): void {
|
|
68
|
-
this.config.set("api", api);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
clearApiConfig(): void {
|
|
72
|
-
this.config.delete("api");
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
isApiConfigured(): boolean {
|
|
76
|
-
const api = this.getApiConfig();
|
|
77
|
-
return !!(api?.endpoint && api?.apiKey);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Auth methods
|
|
81
|
-
getAuth(): AuthConfig | undefined {
|
|
82
|
-
return this.config.get("auth");
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
setAuth(auth: AuthConfig): void {
|
|
86
|
-
this.config.set("auth", auth);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
clearAuth(): void {
|
|
90
|
-
this.config.delete("auth");
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
isAuthenticated(): boolean {
|
|
94
|
-
const auth = this.getAuth();
|
|
95
|
-
if (!auth || !auth.token) {
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Check if token is expired
|
|
100
|
-
if (auth.expiresAt) {
|
|
101
|
-
const expiresAt = new Date(auth.expiresAt);
|
|
102
|
-
if (expiresAt < new Date()) {
|
|
103
|
-
this.clearAuth();
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return true;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Projects methods
|
|
112
|
-
getProjects(): ProjectsConfig | undefined {
|
|
113
|
-
return this.config.get("projects");
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
setProjects(projects: ProjectsConfig): void {
|
|
117
|
-
this.config.set("projects", projects);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
getDefaultProject(): string | undefined {
|
|
121
|
-
const projects = this.getProjects();
|
|
122
|
-
return projects?.default;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
setDefaultProject(projectId: string): void {
|
|
126
|
-
const projects = this.getProjects() || { list: [] };
|
|
127
|
-
projects.default = projectId;
|
|
128
|
-
this.setProjects(projects);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
addProject(project: { project_id: string; name: string; apiUrl?: string }): void {
|
|
132
|
-
const projects = this.getProjects() || { list: [] };
|
|
133
|
-
const existingIndex = projects.list.findIndex(p => p.project_id === project.project_id);
|
|
134
|
-
|
|
135
|
-
if (existingIndex >= 0) {
|
|
136
|
-
projects.list[existingIndex] = project;
|
|
137
|
-
} else {
|
|
138
|
-
projects.list.push(project);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
this.setProjects(projects);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
getProject(projectId: string): { project_id: string; name: string; apiUrl?: string } | undefined {
|
|
145
|
-
const projects = this.getProjects();
|
|
146
|
-
return projects?.list.find(p => p.project_id === projectId);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Sync methods
|
|
150
|
-
getSyncConfig(): SyncConfig | undefined {
|
|
151
|
-
return this.config.get("sync");
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
setSyncConfig(sync: SyncConfig): void {
|
|
155
|
-
this.config.set("sync", sync);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Utility methods
|
|
159
|
-
getConfigPath(): string {
|
|
160
|
-
return this.config.path;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
clear(): void {
|
|
164
|
-
this.config.clear();
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Export singleton instance
|
|
169
|
-
export const configManager = new ConfigManager();
|
package/src/index.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { Command } from 'commander';
|
|
4
|
-
import chalk from 'chalk';
|
|
5
|
-
import fs from 'fs';
|
|
6
|
-
|
|
7
|
-
// Import commands
|
|
8
|
-
import { loginCommand } from './commands/auth/login';
|
|
9
|
-
import { logoutCommand } from './commands/auth/logout';
|
|
10
|
-
import { authStatusCommand } from './commands/auth/status';
|
|
11
|
-
import { schemaDiffCommand, schemaListCommand, syncCommand, schemaPushCommand, schemaPullCommand, schemaTypesConvertCommand } from './commands/sync';
|
|
12
|
-
import { functionDiffCommand, functionListCommand, functionPushCommand, functionSyncCommand, functionPullCommand } from './commands/functions';
|
|
13
|
-
import { projectsListCommand } from './commands/projects/list';
|
|
14
|
-
import { projectsSetDefaultCommand } from './commands/projects/set-default';
|
|
15
|
-
import { projectsCurrentCommand } from './commands/projects/current';
|
|
16
|
-
import { configSetupCommand, configShowCommand, configClearCommand } from './commands/config';
|
|
17
|
-
|
|
18
|
-
const program = new Command();
|
|
19
|
-
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
|
20
|
-
const version = packageJson.version;
|
|
21
|
-
|
|
22
|
-
// Set up the CLI
|
|
23
|
-
program
|
|
24
|
-
.name('buildx')
|
|
25
|
-
.description('BuildX CLI - API authentication, project management, and schema synchronization tool')
|
|
26
|
-
.version(version, '-v, --version');
|
|
27
|
-
|
|
28
|
-
// Add commands
|
|
29
|
-
program.addCommand(loginCommand);
|
|
30
|
-
program.addCommand(logoutCommand);
|
|
31
|
-
program.addCommand(authStatusCommand);
|
|
32
|
-
program.addCommand(syncCommand);
|
|
33
|
-
program.addCommand(schemaPullCommand);
|
|
34
|
-
program.addCommand(schemaPushCommand);
|
|
35
|
-
program.addCommand(schemaListCommand);
|
|
36
|
-
program.addCommand(schemaDiffCommand);
|
|
37
|
-
program.addCommand(schemaTypesConvertCommand);
|
|
38
|
-
program.addCommand(functionSyncCommand);
|
|
39
|
-
program.addCommand(functionPullCommand);
|
|
40
|
-
program.addCommand(functionPushCommand);
|
|
41
|
-
program.addCommand(functionListCommand);
|
|
42
|
-
program.addCommand(functionDiffCommand);
|
|
43
|
-
program.addCommand(projectsListCommand);
|
|
44
|
-
program.addCommand(projectsSetDefaultCommand);
|
|
45
|
-
program.addCommand(projectsCurrentCommand);
|
|
46
|
-
program.addCommand(configSetupCommand);
|
|
47
|
-
program.addCommand(configShowCommand);
|
|
48
|
-
program.addCommand(configClearCommand);
|
|
49
|
-
|
|
50
|
-
// Global error handler
|
|
51
|
-
program.exitOverride();
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
program.parse();
|
|
55
|
-
} catch (err) {
|
|
56
|
-
if (err instanceof Error) {
|
|
57
|
-
console.error(chalk.red('Error:'), err.message);
|
|
58
|
-
} else {
|
|
59
|
-
console.error(chalk.red('An unexpected error occurred'));
|
|
60
|
-
}
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
package/src/services/api.ts
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import axios from "axios";
|
|
2
|
-
import type { AxiosInstance, AxiosRequestConfig, InternalAxiosRequestConfig } from "axios";
|
|
3
|
-
import { configManager } from "../config/index";
|
|
4
|
-
import { ApiResponse, LoginCredentials, LoginResponse, Project } from "../types/index";
|
|
5
|
-
|
|
6
|
-
export class ApiService {
|
|
7
|
-
private client: AxiosInstance;
|
|
8
|
-
|
|
9
|
-
constructor() {
|
|
10
|
-
this.client = axios.create({
|
|
11
|
-
timeout: 30000,
|
|
12
|
-
headers: {
|
|
13
|
-
"Content-Type": "application/json",
|
|
14
|
-
"User-Agent": "buildx-cli/1.0.0"
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
// Add request interceptor to include auth token and API key
|
|
19
|
-
this.client.interceptors.request.use((config: InternalAxiosRequestConfig) => {
|
|
20
|
-
// Ensure client is initialized with current config before each request
|
|
21
|
-
this.initializeClient();
|
|
22
|
-
|
|
23
|
-
// Add API key from configuration
|
|
24
|
-
const apiConfig = configManager.getApiConfig();
|
|
25
|
-
if (apiConfig?.apiKey) {
|
|
26
|
-
config.headers["X-API-Key"] = apiConfig.apiKey;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Add auth token
|
|
30
|
-
const auth = configManager.getAuth();
|
|
31
|
-
if (auth?.token) {
|
|
32
|
-
config.headers.Authorization = `Bearer ${auth.token}`;
|
|
33
|
-
}
|
|
34
|
-
return config;
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
// Add response interceptor for error handling
|
|
38
|
-
this.client.interceptors.response.use(
|
|
39
|
-
(response) => response,
|
|
40
|
-
(error: any) => {
|
|
41
|
-
if (error.response?.status === 401) {
|
|
42
|
-
configManager.clearAuth();
|
|
43
|
-
throw new Error("Authentication failed. Please login again.");
|
|
44
|
-
}
|
|
45
|
-
throw error;
|
|
46
|
-
}
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
private initializeClient(): void {
|
|
51
|
-
const apiConfig = configManager.getApiConfig();
|
|
52
|
-
if (apiConfig?.endpoint) {
|
|
53
|
-
this.client.defaults.baseURL = apiConfig.endpoint;
|
|
54
|
-
} else {
|
|
55
|
-
throw new Error("API endpoint not configured. Please run 'buildx config setup' first.");
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
private async request<T>(config: AxiosRequestConfig): Promise<ApiResponse<T>> {
|
|
60
|
-
// Always set baseURL from config before making the request
|
|
61
|
-
const apiConfig = configManager.getApiConfig();
|
|
62
|
-
if (!apiConfig?.endpoint) {
|
|
63
|
-
throw new Error("API endpoint not configured. Please run 'buildx config setup' first.");
|
|
64
|
-
}
|
|
65
|
-
config.baseURL = apiConfig.endpoint;
|
|
66
|
-
try {
|
|
67
|
-
const response = await this.client.request(config);
|
|
68
|
-
if (response.data.error) {
|
|
69
|
-
// Got error message if exists
|
|
70
|
-
if (response.data.message) {
|
|
71
|
-
throw new Error(`${response.data.error} (${response.data.message})`);
|
|
72
|
-
} else {
|
|
73
|
-
throw new Error(response.data.error);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return {
|
|
77
|
-
data: response.data,
|
|
78
|
-
status: response.status,
|
|
79
|
-
message: response.statusText
|
|
80
|
-
};
|
|
81
|
-
} catch (error: any) {
|
|
82
|
-
if (error.response) {
|
|
83
|
-
throw new Error(`API Error: ${error.response.status} - ${error.response.data?.message || error.response.statusText}`);
|
|
84
|
-
} else if (error.request) {
|
|
85
|
-
throw new Error("Network error: Unable to connect to the API");
|
|
86
|
-
} else {
|
|
87
|
-
throw new Error(`Request error: ${error.message}`);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async login(credentials: LoginCredentials): Promise<LoginResponse> {
|
|
93
|
-
const response = await this.request<LoginResponse>({
|
|
94
|
-
method: "POST",
|
|
95
|
-
url: "/auth/login",
|
|
96
|
-
data: credentials
|
|
97
|
-
});
|
|
98
|
-
return response.data;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async getProjects(): Promise<Project[]> {
|
|
102
|
-
const response = await this.request<{ projects: Project[] }>({
|
|
103
|
-
method: "GET",
|
|
104
|
-
url: "/projects"
|
|
105
|
-
});
|
|
106
|
-
return response.data as unknown as Project[];
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async getSchema(projectId: string): Promise<string> {
|
|
110
|
-
const response = await this.request<string>({
|
|
111
|
-
method: "GET",
|
|
112
|
-
url: `/project/${projectId}/collections/schema`
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
return response.data;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
async getCollections(projectId: string): Promise<any[]> {
|
|
119
|
-
const response = await this.request<any[]>({
|
|
120
|
-
method: "GET",
|
|
121
|
-
url: `/project/${projectId}/collections`
|
|
122
|
-
});
|
|
123
|
-
return response.data;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
async upsertCollection(projectId: string, collection: Record<string, any>): Promise<any> {
|
|
127
|
-
const response = await this.request<any>({
|
|
128
|
-
method: "POST",
|
|
129
|
-
url: `/project/${projectId}/collections`,
|
|
130
|
-
data: collection
|
|
131
|
-
});
|
|
132
|
-
return response.data;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
async getFunctionContextSchema(projectId: string): Promise<string> {
|
|
136
|
-
const response = await this.request<string>({
|
|
137
|
-
method: "GET",
|
|
138
|
-
url: `/project/${projectId}/functions/context/schema`
|
|
139
|
-
});
|
|
140
|
-
return response.data;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
async getFunctionContextSchemaInfo(projectId: string): Promise<{ schema: string; checksum: string; version: number }> {
|
|
144
|
-
const response = await this.request<{ schema: string; checksum: string; version: number }>({
|
|
145
|
-
method: "GET",
|
|
146
|
-
url: `/project/${projectId}/functions/context/schema/info`
|
|
147
|
-
});
|
|
148
|
-
return response.data;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
async listFunctions(projectId: string): Promise<any[]> {
|
|
152
|
-
const response = await this.request<any[]>({
|
|
153
|
-
method: "GET",
|
|
154
|
-
url: `/project/${projectId}/functions`
|
|
155
|
-
});
|
|
156
|
-
return response.data;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
async getFunction(projectId: string, functionName: string): Promise<any> {
|
|
160
|
-
const response = await this.request<any>({
|
|
161
|
-
method: "GET",
|
|
162
|
-
url: `/project/${projectId}/functions/${encodeURIComponent(functionName)}`
|
|
163
|
-
});
|
|
164
|
-
return response.data;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
async upsertFunction(projectId: string, functionName: string, payload: Record<string, any>): Promise<any> {
|
|
168
|
-
const response = await this.request<any>({
|
|
169
|
-
method: "POST",
|
|
170
|
-
url: `/project/${projectId}/functions/${encodeURIComponent(functionName)}`,
|
|
171
|
-
data: payload
|
|
172
|
-
});
|
|
173
|
-
return response.data;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
async getMe(): Promise<{ username: string;[key: string]: any }> {
|
|
177
|
-
const response = await this.request<{ username: string;[key: string]: any }>({
|
|
178
|
-
method: "GET",
|
|
179
|
-
url: "/auth/me"
|
|
180
|
-
});
|
|
181
|
-
return response.data;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
setBaseUrl(baseUrl: string): void {
|
|
185
|
-
this.client.defaults.baseURL = baseUrl;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
getBaseUrl(): string {
|
|
189
|
-
return this.client.defaults.baseURL || "";
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
isConfigured(): boolean {
|
|
193
|
-
return configManager.isApiConfigured();
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// Export singleton instance
|
|
198
|
-
export const apiService = new ApiService();
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import fs from "fs-extra";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import { SchemaResponse, SchemaCollection, SchemaField } from "../types/index";
|
|
4
|
-
|
|
5
|
-
export class SchemaGenerator {
|
|
6
|
-
private generateFieldType(field: SchemaField): string {
|
|
7
|
-
const baseType = this.mapFieldTypeToTypeScript(field.type);
|
|
8
|
-
return field.required ? baseType : `${baseType} | null`;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
private mapFieldTypeToTypeScript(apiType: string): string {
|
|
12
|
-
const typeMap: Record<string, string> = {
|
|
13
|
-
"string": "string",
|
|
14
|
-
"text": "string",
|
|
15
|
-
"number": "number",
|
|
16
|
-
"integer": "number",
|
|
17
|
-
"float": "number",
|
|
18
|
-
"boolean": "boolean",
|
|
19
|
-
"date": "string",
|
|
20
|
-
"datetime": "string",
|
|
21
|
-
"timestamp": "string",
|
|
22
|
-
"json": "Record<string, any>",
|
|
23
|
-
"array": "any[]",
|
|
24
|
-
"object": "Record<string, any>",
|
|
25
|
-
"email": "string",
|
|
26
|
-
"url": "string",
|
|
27
|
-
"uuid": "string",
|
|
28
|
-
"id": "string"
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
return typeMap[apiType.toLowerCase()] || "any";
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
private generateCollectionInterface(collection: SchemaCollection): string {
|
|
35
|
-
const interfaceName = this.toPascalCase(collection.name);
|
|
36
|
-
const fields = collection.fields.map(field => {
|
|
37
|
-
const fieldType = this.generateFieldType(field);
|
|
38
|
-
const optional = field.required ? "" : "?";
|
|
39
|
-
const comment = field.description ? `\n /** ${field.description} */` : "";
|
|
40
|
-
return `${comment}\n ${field.name}${optional}: ${fieldType};`;
|
|
41
|
-
}).join("\n");
|
|
42
|
-
|
|
43
|
-
const description = collection.description ? `\n/** ${collection.description} */` : "";
|
|
44
|
-
|
|
45
|
-
return `${description}
|
|
46
|
-
export interface ${interfaceName} {
|
|
47
|
-
${fields}
|
|
48
|
-
}`;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
private toPascalCase(str: string): string {
|
|
52
|
-
return str
|
|
53
|
-
.split(/[-_\s]+/)
|
|
54
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
55
|
-
.join("");
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
private generateIndexExports(collections: SchemaCollection[]): string {
|
|
59
|
-
const exports = collections.map(collection => {
|
|
60
|
-
const interfaceName = this.toPascalCase(collection.name);
|
|
61
|
-
return `export type { ${interfaceName} } from './${collection.name}';`;
|
|
62
|
-
}).join("\n");
|
|
63
|
-
|
|
64
|
-
return exports;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
private generateCollectionFile(collection: SchemaCollection): string {
|
|
68
|
-
const interfaceContent = this.generateCollectionInterface(collection);
|
|
69
|
-
return `// Generated by BuildX CLI
|
|
70
|
-
// Collection: ${collection.name}
|
|
71
|
-
// Generated at: ${new Date().toISOString()}
|
|
72
|
-
|
|
73
|
-
${interfaceContent}
|
|
74
|
-
`;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async generateTypes(schema: SchemaResponse, outputPath: string): Promise<void> {
|
|
78
|
-
const outputDir = path.dirname(outputPath);
|
|
79
|
-
const baseName = path.basename(outputPath, path.extname(outputPath));
|
|
80
|
-
const outputDirPath = path.join(outputDir, baseName);
|
|
81
|
-
|
|
82
|
-
// Ensure output directory exists
|
|
83
|
-
await fs.ensureDir(outputDirPath);
|
|
84
|
-
|
|
85
|
-
// Generate individual collection files
|
|
86
|
-
for (const collection of schema.collections) {
|
|
87
|
-
const collectionFileName = `${collection.name}.ts`;
|
|
88
|
-
const collectionFilePath = path.join(outputDirPath, collectionFileName);
|
|
89
|
-
const collectionContent = this.generateCollectionFile(collection);
|
|
90
|
-
|
|
91
|
-
await fs.writeFile(collectionFilePath, collectionContent, "utf8");
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Generate index file
|
|
95
|
-
const indexContent = `// Generated by BuildX CLI
|
|
96
|
-
// Schema version: ${schema.version}
|
|
97
|
-
// Generated at: ${schema.generatedAt}
|
|
98
|
-
|
|
99
|
-
${this.generateIndexExports(schema.collections)}
|
|
100
|
-
|
|
101
|
-
// Re-export all types for convenience
|
|
102
|
-
export * from './${schema.collections[0]?.name || "index"}';
|
|
103
|
-
`;
|
|
104
|
-
|
|
105
|
-
const indexFilePath = path.join(outputDirPath, "index.ts");
|
|
106
|
-
await fs.writeFile(indexFilePath, indexContent, "utf8");
|
|
107
|
-
|
|
108
|
-
// Generate main types file
|
|
109
|
-
const mainContent = `// Generated by BuildX CLI
|
|
110
|
-
// Schema version: ${schema.version}
|
|
111
|
-
// Generated at: ${schema.generatedAt}
|
|
112
|
-
|
|
113
|
-
${schema.collections.map(collection => this.generateCollectionInterface(collection)).join("\n\n")}
|
|
114
|
-
|
|
115
|
-
// Export all collection types
|
|
116
|
-
${schema.collections.map(collection => {
|
|
117
|
-
const interfaceName = this.toPascalCase(collection.name);
|
|
118
|
-
return `export type { ${interfaceName} };`;
|
|
119
|
-
}).join("\n")}
|
|
120
|
-
`;
|
|
121
|
-
|
|
122
|
-
await fs.writeFile(outputPath, mainContent, "utf8");
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
async generateTypesToFile(schema: SchemaResponse, outputPath: string): Promise<string> {
|
|
126
|
-
await this.generateTypes(schema, outputPath);
|
|
127
|
-
return outputPath;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Export singleton instance
|
|
132
|
-
export const schemaGenerator = new SchemaGenerator();
|