buildx-cli 1.0.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/.github/workflows/auto-publish.yml +242 -0
- package/.github/workflows/create-pr.yml +182 -0
- package/.prettierrc +8 -0
- package/README.md +179 -0
- package/dist/index.cjs +21 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +21 -0
- package/eslint.config.mjs +119 -0
- package/jest.config.js +16 -0
- package/package.json +69 -0
- package/rollup.config.mjs +64 -0
- package/src/__tests__/config.test.ts +102 -0
- package/src/commands/auth/login.ts +148 -0
- package/src/commands/auth/logout.ts +16 -0
- package/src/commands/auth/status.ts +52 -0
- package/src/commands/config/clear.ts +16 -0
- package/src/commands/config/index.ts +10 -0
- package/src/commands/config/setup.ts +75 -0
- package/src/commands/config/show.ts +70 -0
- package/src/commands/projects/current.ts +36 -0
- package/src/commands/projects/list.ts +61 -0
- package/src/commands/projects/set-default.ts +33 -0
- package/src/commands/sync.ts +64 -0
- package/src/config/index.ts +154 -0
- package/src/index.ts +49 -0
- package/src/services/api.ts +132 -0
- package/src/services/schema-generator.ts +132 -0
- package/src/types/index.ts +91 -0
- package/src/utils/logger.ts +29 -0
- package/tsconfig.json +29 -0
|
@@ -0,0 +1,132 @@
|
|
|
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();
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export interface AuthConfig {
|
|
2
|
+
token: string;
|
|
3
|
+
expiresAt?: string;
|
|
4
|
+
username?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface LoginCredentials {
|
|
8
|
+
username: string;
|
|
9
|
+
password: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface LoginResponse {
|
|
13
|
+
token: string;
|
|
14
|
+
expiresAt?: string;
|
|
15
|
+
user?: {
|
|
16
|
+
id: string;
|
|
17
|
+
username: string;
|
|
18
|
+
email?: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ApiConfig {
|
|
23
|
+
endpoint: string;
|
|
24
|
+
apiKey: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface Project {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
apiUrl?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ProjectsConfig {
|
|
34
|
+
default?: string;
|
|
35
|
+
list: Project[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface SyncConfig {
|
|
39
|
+
outputPath: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface GlobalConfig {
|
|
43
|
+
api?: ApiConfig;
|
|
44
|
+
auth?: AuthConfig;
|
|
45
|
+
projects?: ProjectsConfig;
|
|
46
|
+
sync?: SyncConfig;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface ApiResponse<T = any> {
|
|
50
|
+
data: T;
|
|
51
|
+
status: number;
|
|
52
|
+
message?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface SchemaField {
|
|
56
|
+
name: string;
|
|
57
|
+
type: string;
|
|
58
|
+
required?: boolean;
|
|
59
|
+
description?: string;
|
|
60
|
+
defaultValue?: any;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface SchemaCollection {
|
|
64
|
+
name: string;
|
|
65
|
+
fields: SchemaField[];
|
|
66
|
+
description?: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface SchemaResponse {
|
|
70
|
+
collections: SchemaCollection[];
|
|
71
|
+
version: string;
|
|
72
|
+
generatedAt: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface LoginOptions {
|
|
76
|
+
token?: string;
|
|
77
|
+
username?: string;
|
|
78
|
+
password?: string;
|
|
79
|
+
interactive?: boolean;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface SyncOptions {
|
|
83
|
+
projectId: string;
|
|
84
|
+
output?: string;
|
|
85
|
+
apiUrl?: string;
|
|
86
|
+
force?: boolean;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface ProjectOptions {
|
|
90
|
+
projectId: string;
|
|
91
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
|
|
3
|
+
export class Logger {
|
|
4
|
+
static info(message: string): void {
|
|
5
|
+
console.log(chalk.blue("ℹ"), message);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
static success(message: string): void {
|
|
9
|
+
console.log(chalk.green("✓"), message);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static warning(message: string): void {
|
|
13
|
+
console.log(chalk.yellow("⚠"), message);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static error(message: string): void {
|
|
17
|
+
console.error(chalk.red("✗"), message);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static debug(message: string): void {
|
|
21
|
+
if (process.env.DEBUG) {
|
|
22
|
+
console.log(chalk.gray("🐛"), message);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static log(message: string): void {
|
|
27
|
+
console.log(message);
|
|
28
|
+
}
|
|
29
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"lib": ["ES2020"],
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"sourceMap": true,
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"moduleResolution": "node",
|
|
17
|
+
"allowSyntheticDefaultImports": true,
|
|
18
|
+
"experimentalDecorators": true,
|
|
19
|
+
"emitDecoratorMetadata": true
|
|
20
|
+
},
|
|
21
|
+
"include": [
|
|
22
|
+
"src/**/*"
|
|
23
|
+
],
|
|
24
|
+
"exclude": [
|
|
25
|
+
"node_modules",
|
|
26
|
+
"dist",
|
|
27
|
+
"**/*.test.ts"
|
|
28
|
+
]
|
|
29
|
+
}
|