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.
@@ -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
- }
@@ -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();