@pgsql/cli 1.30.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 (50) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/LICENSE +21 -0
  3. package/README.md +268 -0
  4. package/dist/LICENSE +21 -0
  5. package/dist/README.md +268 -0
  6. package/dist/commands/deparse.d.ts +1 -0
  7. package/dist/commands/deparse.js +66 -0
  8. package/dist/commands/parse.d.ts +1 -0
  9. package/dist/commands/parse.js +60 -0
  10. package/dist/commands/proto-fetch/cli.d.ts +14 -0
  11. package/dist/commands/proto-fetch/cli.js +41 -0
  12. package/dist/commands/proto-fetch/helpers.d.ts +3 -0
  13. package/dist/commands/proto-fetch/helpers.js +73 -0
  14. package/dist/commands/proto-fetch.d.ts +1 -0
  15. package/dist/commands/proto-fetch.js +42 -0
  16. package/dist/commands/proto-gen.d.ts +1 -0
  17. package/dist/commands/proto-gen.js +59 -0
  18. package/dist/commands/runtime-schema.d.ts +1 -0
  19. package/dist/commands/runtime-schema.js +70 -0
  20. package/dist/esm/commands/deparse.js +60 -0
  21. package/dist/esm/commands/parse.js +54 -0
  22. package/dist/esm/commands/proto-fetch/cli.js +37 -0
  23. package/dist/esm/commands/proto-fetch/helpers.js +64 -0
  24. package/dist/esm/commands/proto-fetch.js +36 -0
  25. package/dist/esm/commands/proto-gen.js +53 -0
  26. package/dist/esm/commands/runtime-schema.js +64 -0
  27. package/dist/esm/index.js +56 -0
  28. package/dist/esm/package.js +26 -0
  29. package/dist/esm/utils/help.js +190 -0
  30. package/dist/index.d.ts +2 -0
  31. package/dist/index.js +61 -0
  32. package/dist/package.d.ts +1 -0
  33. package/dist/package.js +29 -0
  34. package/dist/package.json +60 -0
  35. package/dist/utils/help.d.ts +2 -0
  36. package/dist/utils/help.js +197 -0
  37. package/jest.config.js +18 -0
  38. package/package.json +60 -0
  39. package/src/commands/deparse.ts +60 -0
  40. package/src/commands/parse.ts +60 -0
  41. package/src/commands/proto-fetch/cli.ts +52 -0
  42. package/src/commands/proto-fetch/helpers.ts +72 -0
  43. package/src/commands/proto-fetch.ts +42 -0
  44. package/src/commands/proto-gen.ts +49 -0
  45. package/src/commands/runtime-schema.ts +74 -0
  46. package/src/index.ts +69 -0
  47. package/src/package.ts +33 -0
  48. package/src/utils/help.ts +198 -0
  49. package/tsconfig.esm.json +9 -0
  50. package/tsconfig.json +9 -0
@@ -0,0 +1,197 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.showVersion = showVersion;
7
+ exports.showHelp = showHelp;
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const fs_1 = require("fs");
10
+ const path_1 = require("path");
11
+ function showVersion() {
12
+ // Try to find package.json in various locations
13
+ const possiblePaths = [
14
+ (0, path_1.join)(process.cwd(), 'package.json'),
15
+ (0, path_1.join)(process.argv[1], '../../package.json'),
16
+ (0, path_1.join)(process.argv[1], '../../../package.json')
17
+ ];
18
+ for (const path of possiblePaths) {
19
+ try {
20
+ const packageJson = JSON.parse((0, fs_1.readFileSync)(path, 'utf-8'));
21
+ if (packageJson.name === '@pgsql/cli') {
22
+ console.log(packageJson.version);
23
+ return;
24
+ }
25
+ }
26
+ catch {
27
+ // Continue to next path
28
+ }
29
+ }
30
+ // Fallback: just show the version we know
31
+ console.log('1.29.2');
32
+ }
33
+ function showHelp(command) {
34
+ if (command) {
35
+ switch (command) {
36
+ case 'parse':
37
+ showParseHelp();
38
+ break;
39
+ case 'deparse':
40
+ showDeparseHelp();
41
+ break;
42
+ case 'proto-gen':
43
+ showProtoGenHelp();
44
+ break;
45
+ case 'proto-fetch':
46
+ showProtoFetchHelp();
47
+ break;
48
+ case 'runtime-schema':
49
+ showRuntimeSchemaHelp();
50
+ break;
51
+ default:
52
+ showGeneralHelp();
53
+ }
54
+ }
55
+ else {
56
+ showGeneralHelp();
57
+ }
58
+ }
59
+ function showGeneralHelp() {
60
+ console.log(`
61
+ ${chalk_1.default.bold('pgsql')} - Unified CLI for PostgreSQL AST operations
62
+
63
+ ${chalk_1.default.yellow('Usage:')}
64
+ pgsql <command> [options]
65
+
66
+ ${chalk_1.default.yellow('Commands:')}
67
+ ${chalk_1.default.green('parse')} Parse SQL to AST
68
+ ${chalk_1.default.green('deparse')} Convert AST to SQL
69
+ ${chalk_1.default.green('proto-gen')} Generate TypeScript from protobuf
70
+ ${chalk_1.default.green('proto-fetch')} Download and process proto files
71
+ ${chalk_1.default.green('runtime-schema')} Generate runtime schema for AST nodes
72
+
73
+ ${chalk_1.default.yellow('Global Options:')}
74
+ -h, --help Show help
75
+ -v, --version Show version
76
+
77
+ ${chalk_1.default.yellow('Examples:')}
78
+ pgsql parse query.sql
79
+ pgsql deparse ast.json
80
+ pgsql proto-gen --inFile pg_query.proto --outDir out
81
+ pgsql proto-fetch --url https://example.com/pg_query.proto --inFile pg_query.proto
82
+
83
+ Run 'pgsql <command> --help' for detailed help on a specific command.
84
+ `);
85
+ }
86
+ function showParseHelp() {
87
+ console.log(`
88
+ ${chalk_1.default.bold('pgsql parse')} - Parse SQL to AST
89
+
90
+ ${chalk_1.default.yellow('Usage:')}
91
+ pgsql parse <sqlfile> [options]
92
+
93
+ ${chalk_1.default.yellow('Options:')}
94
+ -o, --output <file> Output to file instead of stdout
95
+ -f, --format <format> Output format: json, pretty (default: pretty)
96
+ --clean Clean the AST tree (remove location info)
97
+ -h, --help Show help
98
+
99
+ ${chalk_1.default.yellow('Examples:')}
100
+ pgsql parse query.sql
101
+ pgsql parse query.sql -o ast.json
102
+ pgsql parse query.sql --format json --clean
103
+ `);
104
+ }
105
+ function showDeparseHelp() {
106
+ console.log(`
107
+ ${chalk_1.default.bold('pgsql deparse')} - Convert AST to SQL
108
+
109
+ ${chalk_1.default.yellow('Usage:')}
110
+ pgsql deparse [options]
111
+
112
+ ${chalk_1.default.yellow('Options:')}
113
+ -i, --input <file> Input JSON file (or use stdin)
114
+ -o, --output <file> Output to file instead of stdout
115
+ -h, --help Show help
116
+
117
+ ${chalk_1.default.yellow('Examples:')}
118
+ pgsql deparse -i ast.json
119
+ pgsql deparse -i ast.json -o query.sql
120
+ cat ast.json | pgsql deparse
121
+ pgsql parse query.sql | pgsql deparse
122
+ `);
123
+ }
124
+ function showProtoGenHelp() {
125
+ console.log(`
126
+ ${chalk_1.default.bold('pgsql proto-gen')} - Generate TypeScript from protobuf
127
+
128
+ ${chalk_1.default.yellow('Usage:')}
129
+ pgsql proto-gen --inFile <proto> --outDir <dir> [options]
130
+
131
+ ${chalk_1.default.yellow('Required Options:')}
132
+ --inFile <file> Input .proto file
133
+ --outDir <dir> Output directory
134
+
135
+ ${chalk_1.default.yellow('Optional Flags:')}
136
+ --enums Generate TypeScript enums
137
+ --enums-json Generate JSON enum mappings
138
+ --types Generate TypeScript interfaces
139
+ --utils Generate utility functions
140
+ --ast-helpers Generate AST helper methods
141
+ --wrapped-helpers Generate wrapped AST helpers
142
+ --optional Make all fields optional
143
+ --keep-case Keep original field casing
144
+ --remove-undefined Remove UNDEFINED enum at position 0
145
+ -h, --help Show help
146
+
147
+ ${chalk_1.default.yellow('Examples:')}
148
+ pgsql proto-gen --inFile pg_query.proto --outDir out --types --enums
149
+ pgsql proto-gen --inFile pg_query.proto --outDir out --types --utils --ast-helpers
150
+ pgsql proto-gen --inFile pg_query.proto --outDir out --types --optional --keep-case
151
+ `);
152
+ }
153
+ function showProtoFetchHelp() {
154
+ console.log(`
155
+ ${chalk_1.default.bold('pgsql proto-fetch')} - Download and process proto files
156
+
157
+ ${chalk_1.default.yellow('Usage:')}
158
+ pgsql proto-fetch [options]
159
+
160
+ ${chalk_1.default.yellow('Options:')}
161
+ --url <url> Proto file URL to download
162
+ --inFile <file> Where to save the proto file
163
+ --outFile <file> Generated JS output file
164
+ --replace-pkg <old> Original package name to replace
165
+ --with-pkg <new> New package name
166
+ -h, --help Show help
167
+
168
+ ${chalk_1.default.yellow('Examples:')}
169
+ pgsql proto-fetch --url https://raw.githubusercontent.com/pganalyze/libpg_query/16-latest/protobuf/pg_query.proto \\
170
+ --inFile pg_query.proto \\
171
+ --outFile pg_query.js \\
172
+ --replace-pkg "protobufjs/minimal" \\
173
+ --with-pkg "@launchql/protobufjs/minimal"
174
+ `);
175
+ }
176
+ function showRuntimeSchemaHelp() {
177
+ console.log(`
178
+ ${chalk_1.default.bold('pgsql runtime-schema')} - Generate runtime schema for AST nodes
179
+
180
+ ${chalk_1.default.yellow('Usage:')}
181
+ pgsql runtime-schema --inFile <proto> --outDir <dir> [options]
182
+
183
+ ${chalk_1.default.yellow('Required Options:')}
184
+ --inFile <file> Input .proto file
185
+ --outDir <dir> Output directory
186
+
187
+ ${chalk_1.default.yellow('Optional Options:')}
188
+ --format <format> Output format: json, typescript (default: json)
189
+ --filename <name> Output filename (default: runtime-schema)
190
+ -h, --help Show help
191
+
192
+ ${chalk_1.default.yellow('Examples:')}
193
+ pgsql runtime-schema --inFile pg_query.proto --outDir out
194
+ pgsql runtime-schema --inFile pg_query.proto --outDir out --format typescript
195
+ pgsql runtime-schema --inFile pg_query.proto --outDir out --filename ast-schema
196
+ `);
197
+ }
package/jest.config.js ADDED
@@ -0,0 +1,18 @@
1
+ /** @type {import('ts-jest').JestConfigWithTsJest} */
2
+ module.exports = {
3
+ preset: "ts-jest",
4
+ testEnvironment: "node",
5
+ transform: {
6
+ "^.+\\.tsx?$": [
7
+ "ts-jest",
8
+ {
9
+ babelConfig: false,
10
+ tsconfig: "tsconfig.json",
11
+ },
12
+ ],
13
+ },
14
+ transformIgnorePatterns: [`/node_modules/*`],
15
+ testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
16
+ moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
17
+ modulePathIgnorePatterns: ["dist/*"]
18
+ };
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@pgsql/cli",
3
+ "version": "1.30.0",
4
+ "description": "Unified CLI for PostgreSQL AST parsing, deparsing, and code generation",
5
+ "author": "Dan Lynch <pyramation@gmail.com>",
6
+ "main": "index.js",
7
+ "module": "esm/index.js",
8
+ "types": "index.d.ts",
9
+ "homepage": "https://github.com/launchql/pgsql-parser/tree/master/packages/pgsql-cli#readme",
10
+ "license": "SEE LICENSE IN LICENSE",
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/launchql/pgsql-parser"
17
+ },
18
+ "bugs": {
19
+ "url": "https://github.com/launchql/pgsql-parser/issues"
20
+ },
21
+ "bin": {
22
+ "pgsql": "index.js"
23
+ },
24
+ "scripts": {
25
+ "copy": "copyfiles -f ../../LICENSE README.md package.json dist",
26
+ "clean": "rimraf dist",
27
+ "prepare": "npm run build",
28
+ "build": "npm run clean && tsc && tsc -p tsconfig.esm.json && npm run copy",
29
+ "build:dev": "npm run clean && tsc --declarationMap && tsc -p tsconfig.esm.json && npm run copy",
30
+ "dev": "ts-node src/index",
31
+ "lint": "eslint . --fix",
32
+ "test": "jest",
33
+ "test:watch": "jest --watch"
34
+ },
35
+ "keywords": [
36
+ "sql",
37
+ "postgres",
38
+ "postgresql",
39
+ "pg",
40
+ "query",
41
+ "ast",
42
+ "proto",
43
+ "parser",
44
+ "deparser",
45
+ "database"
46
+ ],
47
+ "dependencies": {
48
+ "@launchql/protobufjs": "7.2.6",
49
+ "@launchql/protobufjs-cli": "1.1.5",
50
+ "chalk": "^4.1.0",
51
+ "glob": "8.0.3",
52
+ "minimist": "1.2.8",
53
+ "mkdirp": "3.0.1",
54
+ "nested-obj": "^0.0.1",
55
+ "pg-proto-parser": "^1.29.0",
56
+ "pgsql-deparser": "^17.7.0",
57
+ "pgsql-parser": "^17.6.0"
58
+ },
59
+ "gitHead": "e0f9b0579328f4206c315d499e0e2045d3b8f845"
60
+ }
@@ -0,0 +1,60 @@
1
+ import { readFileSync, writeFileSync } from 'fs';
2
+ import { resolve, join } from 'path';
3
+ import { deparse } from 'pgsql-deparser';
4
+ import chalk from 'chalk';
5
+ import { showHelp } from '../utils/help';
6
+
7
+ export async function deparseCommand(argv: any) {
8
+ if (argv.help) {
9
+ showHelp('deparse');
10
+ process.exit(0);
11
+ }
12
+
13
+ try {
14
+ let ast;
15
+
16
+ // Read AST from file or stdin
17
+ if (argv.input || argv.i) {
18
+ const inputFile = argv.input || argv.i;
19
+ const filePath = inputFile.startsWith('/')
20
+ ? inputFile
21
+ : resolve(join(process.cwd(), inputFile));
22
+
23
+ const content = readFileSync(filePath, 'utf-8');
24
+ ast = JSON.parse(content);
25
+ } else if (!process.stdin.isTTY) {
26
+ // Read from stdin
27
+ const chunks = [];
28
+ for await (const chunk of process.stdin) {
29
+ chunks.push(chunk);
30
+ }
31
+ const content = Buffer.concat(chunks).toString();
32
+ ast = JSON.parse(content);
33
+ } else {
34
+ console.error(chalk.red('Error: No input provided. Use -i <file> or pipe input via stdin'));
35
+ showHelp('deparse');
36
+ process.exit(1);
37
+ }
38
+
39
+ // Deparse AST to SQL
40
+ const sql = await deparse(ast);
41
+
42
+ // Write output
43
+ if (argv.output || argv.o) {
44
+ const outputFile = argv.output || argv.o;
45
+ writeFileSync(outputFile, sql);
46
+ console.log(chalk.green(`✓ SQL written to ${outputFile}`));
47
+ } else {
48
+ process.stdout.write(sql);
49
+ }
50
+ } catch (error: any) {
51
+ if (error.code === 'ENOENT') {
52
+ console.error(chalk.red(`Error: File not found: ${argv.input || argv.i}`));
53
+ } else if (error instanceof SyntaxError) {
54
+ console.error(chalk.red('Error: Invalid JSON input'));
55
+ } else {
56
+ console.error(chalk.red('Deparse error:'), error.message || error);
57
+ }
58
+ process.exit(1);
59
+ }
60
+ }
@@ -0,0 +1,60 @@
1
+ import { readFileSync, writeFileSync } from 'fs';
2
+ import { resolve, join } from 'path';
3
+ import { parse } from 'pgsql-parser';
4
+ import chalk from 'chalk';
5
+ import { showHelp } from '../utils/help';
6
+
7
+ export async function parseCommand(argv: any) {
8
+ if (argv.help) {
9
+ showHelp('parse');
10
+ process.exit(0);
11
+ }
12
+
13
+ const sqlFile = argv._[1];
14
+
15
+ if (!sqlFile) {
16
+ console.error(chalk.red('Error: SQL file required'));
17
+ showHelp('parse');
18
+ process.exit(1);
19
+ }
20
+
21
+ try {
22
+ // Resolve file path
23
+ const filePath = sqlFile.startsWith('/')
24
+ ? sqlFile
25
+ : resolve(join(process.cwd(), sqlFile));
26
+
27
+ // Read SQL content
28
+ const content = readFileSync(filePath, 'utf-8');
29
+
30
+ // Parse SQL
31
+ const ast = await parse(content);
32
+
33
+ // Clean AST if requested
34
+ if (argv.clean) {
35
+ // For now, we'll skip the clean functionality until we can import it properly
36
+ console.warn(chalk.yellow('Warning: --clean flag is not yet implemented'));
37
+ }
38
+
39
+ // Format output
40
+ const format = argv.format || 'pretty';
41
+ const output = format === 'json'
42
+ ? JSON.stringify(ast)
43
+ : JSON.stringify(ast, null, 2);
44
+
45
+ // Write output
46
+ if (argv.output) {
47
+ writeFileSync(argv.output, output);
48
+ console.log(chalk.green(`✓ AST written to ${argv.output}`));
49
+ } else {
50
+ process.stdout.write(output);
51
+ }
52
+ } catch (error: any) {
53
+ if (error.code === 'ENOENT') {
54
+ console.error(chalk.red(`Error: File not found: ${sqlFile}`));
55
+ } else {
56
+ console.error(chalk.red('Parse error:'), error.message || error);
57
+ }
58
+ process.exit(1);
59
+ }
60
+ }
@@ -0,0 +1,52 @@
1
+ import { downloadProtoFile, generateProtoJS, replaceTextInProtoJS } from './helpers';
2
+
3
+ export interface CommandOptions {
4
+ help?: boolean;
5
+ h?: boolean;
6
+ version?: boolean;
7
+ v?: boolean;
8
+ protoUrl?: string;
9
+ inFile: string;
10
+ outFile: string;
11
+ originalPackageName: string;
12
+ newPackageName: string;
13
+ }
14
+
15
+ export const help = (): void => {
16
+ console.log(`
17
+ Usage:
18
+
19
+ pg-proto-parser protogen --protoUrl <URL to proto file>
20
+ --inFile <path to proto file>
21
+ --outFile <path to output JS file>
22
+ --originalPackageName <original package name>
23
+ --newPackageName <new package name>
24
+
25
+ Options:
26
+
27
+ --help, -h Show this help message.
28
+ --version, -v Show the version number.
29
+ --protoUrl Full URL to download the proto file (optional).
30
+ --inFile Path where the proto file will be saved or path to an existing proto file.
31
+ --outFile Path where the generated JavaScript file will be saved.
32
+ --originalPackageName Original package name to be replaced in the JS file.
33
+ --newPackageName New package name to replace in the JS file.
34
+ `);
35
+ }
36
+
37
+ export default async (argv: CommandOptions): Promise<CommandOptions> => {
38
+
39
+ try {
40
+ if (argv.protoUrl) {
41
+ await downloadProtoFile(argv.protoUrl, argv.inFile);
42
+ }
43
+ await generateProtoJS(argv.inFile, argv.outFile);
44
+ await replaceTextInProtoJS(argv.outFile, argv.originalPackageName, argv.newPackageName);
45
+ console.log('All operations completed successfully.');
46
+ } catch (error) {
47
+ // @ts-ignore
48
+ console.error('An error occurred:', error.message);
49
+ }
50
+
51
+ return argv;
52
+ };
@@ -0,0 +1,72 @@
1
+ import https from 'https';
2
+ import fs from 'fs';
3
+ import { exec } from 'child_process';
4
+ import { sync as mkdirp } from 'mkdirp';
5
+ import { dirname } from 'path';
6
+
7
+ // Download .proto file if URL
8
+ export const downloadProtoFile = (protoUrl: string, filePath: string): Promise<void> => {
9
+ mkdirp(dirname(filePath));
10
+
11
+ return new Promise((resolve, reject) => {
12
+ https.get(protoUrl, (response) => {
13
+ if (response.statusCode !== 200) {
14
+ console.error(`Failed to download file: Status Code: ${response.statusCode}`);
15
+ response.resume(); // consume response data to free up memory
16
+ reject(new Error('Failed to download file'));
17
+ return;
18
+ }
19
+
20
+ const fileStream = fs.createWriteStream(filePath);
21
+ response.pipe(fileStream);
22
+ fileStream.on('finish', () => {
23
+ fileStream.close();
24
+ console.log('Downloaded proto file.');
25
+ resolve();
26
+ });
27
+ }).on('error', (err) => {
28
+ console.error(`Error downloading the file: ${err.message}`);
29
+ fs.unlink(filePath, () => {}); // Delete the file async. (No need to check error here)
30
+ reject(err);
31
+ });
32
+ });
33
+ }
34
+
35
+ // Generate JavaScript from proto file using pbjs
36
+ export const generateProtoJS = (inFile: string, outFile: string): Promise<void> => new Promise((resolve, reject) => {
37
+ const command = `pbjs --keep-case -t static-module -o ${outFile} ${inFile}`;
38
+ mkdirp(dirname(outFile));
39
+
40
+ exec(command, (error, _stdout, _stderr) => {
41
+ if (error) {
42
+ console.error(`Error during code generation: ${error.message}`);
43
+ reject(error);
44
+ return;
45
+ }
46
+ console.log('Generated proto.js from proto file.');
47
+ resolve();
48
+ });
49
+ });
50
+
51
+ // Replace text in generated JS file
52
+ export const replaceTextInProtoJS = (filePath: string, originalPackage: string, newPackage: string): Promise<void> => new Promise((resolve, reject) => {
53
+ fs.readFile(filePath, 'utf8', (err, data) => {
54
+ if (err) {
55
+ console.error(`Error reading proto.js: ${err.message}`);
56
+ reject(err);
57
+ return;
58
+ }
59
+
60
+ const result = data.replace(new RegExp(originalPackage, 'g'), newPackage);
61
+
62
+ fs.writeFile(filePath, result, 'utf8', (err) => {
63
+ if (err) {
64
+ console.error(`Error writing back to proto.js: ${err.message}`);
65
+ reject(err);
66
+ return;
67
+ }
68
+ console.log('Replaced text in proto.js successfully.');
69
+ resolve();
70
+ });
71
+ });
72
+ });
@@ -0,0 +1,42 @@
1
+ import chalk from 'chalk';
2
+ import { showHelp } from '../utils/help';
3
+ import { downloadProtoFile, generateProtoJS, replaceTextInProtoJS } from './proto-fetch/helpers';
4
+
5
+ export async function protoFetchCommand(argv: any) {
6
+ if (argv.help) {
7
+ showHelp('proto-fetch');
8
+ process.exit(0);
9
+ }
10
+
11
+ const url = argv.url;
12
+ const inFile = argv.inFile;
13
+ const outFile = argv.outFile;
14
+ const replacePkg = argv['replace-pkg'] || 'protobufjs/minimal';
15
+ const withPkg = argv['with-pkg'] || '@launchql/protobufjs/minimal';
16
+
17
+ if (!inFile || !outFile) {
18
+ console.error(chalk.red('Error: --inFile and --outFile are required'));
19
+ showHelp('proto-fetch');
20
+ process.exit(1);
21
+ }
22
+
23
+ try {
24
+ if (url) {
25
+ console.log(chalk.blue(`Downloading proto file from ${url}...`));
26
+ await downloadProtoFile(url, inFile);
27
+ console.log(chalk.green(`✓ Proto file saved to ${inFile}`));
28
+ }
29
+
30
+ console.log(chalk.blue('Generating JavaScript from proto file...'));
31
+ await generateProtoJS(inFile, outFile);
32
+
33
+ console.log(chalk.blue(`Replacing package references...`));
34
+ await replaceTextInProtoJS(outFile, replacePkg, withPkg);
35
+
36
+ console.log(chalk.green(`✓ All operations completed successfully`));
37
+ console.log(chalk.green(`✓ Generated file: ${outFile}`));
38
+ } catch (error: any) {
39
+ console.error(chalk.red('Proto fetch error:'), error.message || error);
40
+ process.exit(1);
41
+ }
42
+ }
@@ -0,0 +1,49 @@
1
+ import { PgProtoParser, PgProtoParserOptions, getOptionsWithDefaults } from 'pg-proto-parser';
2
+ import o from 'nested-obj';
3
+ import chalk from 'chalk';
4
+ import { showHelp } from '../utils/help';
5
+
6
+ export async function protoGenCommand(argv: any) {
7
+ if (argv.help) {
8
+ showHelp('proto-gen');
9
+ process.exit(0);
10
+ }
11
+
12
+ if (!argv.inFile || !argv.outDir) {
13
+ console.error(chalk.red('Error: --inFile and --outDir are required'));
14
+ showHelp('proto-gen');
15
+ process.exit(1);
16
+ }
17
+
18
+ try {
19
+ const options: PgProtoParserOptions = getOptionsWithDefaults({
20
+ outDir: argv.outDir
21
+ });
22
+
23
+ // Set options based on flags
24
+ if (argv.enums) o.set(options, 'enums.enabled', true);
25
+ if (argv['enums-json']) o.set(options, 'enums.json.enabled', true);
26
+ if (argv.types) o.set(options, 'types.enabled', true);
27
+ if (argv.utils) o.set(options, 'utils.enums.enabled', true);
28
+ if (argv['ast-helpers']) o.set(options, 'utils.astHelpers.enabled', true);
29
+ if (argv['wrapped-helpers']) o.set(options, 'utils.wrappedAstHelpers.enabled', true);
30
+ if (argv.optional) o.set(options, 'types.optionalFields', true);
31
+ if (argv['keep-case']) o.set(options, 'parser.keepCase', true);
32
+ if (argv['remove-undefined']) o.set(options, 'enums.removeUndefinedAt0', true);
33
+
34
+ // Additional options that might be useful
35
+ if (argv['type-union']) o.set(options, 'enums.enumsAsTypeUnion', true);
36
+ if (argv.header) o.set(options, 'includeHeader', true);
37
+
38
+ console.log(chalk.blue('Parsing protobuf file...'));
39
+ const parser = new PgProtoParser(argv.inFile, options);
40
+
41
+ console.log(chalk.blue('Generating TypeScript files...'));
42
+ await parser.write();
43
+
44
+ console.log(chalk.green(`✓ Files generated in ${argv.outDir}`));
45
+ } catch (error: any) {
46
+ console.error(chalk.red('Proto generation error:'), error.message || error);
47
+ process.exit(1);
48
+ }
49
+ }
@@ -0,0 +1,74 @@
1
+ import { PgProtoParser, PgProtoParserOptions, getOptionsWithDefaults } from 'pg-proto-parser';
2
+ import { writeFileSync } from 'fs';
3
+ import { join } from 'path';
4
+ import chalk from 'chalk';
5
+ import { showHelp } from '../utils/help';
6
+
7
+ export async function runtimeSchemaCommand(argv: any) {
8
+ if (argv.help) {
9
+ showHelp('runtime-schema');
10
+ process.exit(0);
11
+ }
12
+
13
+ if (!argv.inFile || !argv.outDir) {
14
+ console.error(chalk.red('Error: --inFile and --outDir are required'));
15
+ showHelp('runtime-schema');
16
+ process.exit(1);
17
+ }
18
+
19
+ const format = argv.format || 'json';
20
+ const filename = argv.filename || 'runtime-schema';
21
+
22
+ try {
23
+ console.log(chalk.blue('Parsing protobuf file...'));
24
+
25
+ const options: PgProtoParserOptions = getOptionsWithDefaults({
26
+ outDir: argv.outDir
27
+ });
28
+
29
+ const parser = new PgProtoParser(argv.inFile, options);
30
+
31
+ // Generate runtime schema
32
+ console.log(chalk.blue(`Generating runtime schema in ${format} format...`));
33
+ console.log(chalk.yellow('Warning: Runtime schema generation is not yet fully implemented'));
34
+
35
+ // Generate placeholder schema based on format
36
+ let content: string;
37
+ let fileExt: string;
38
+
39
+ if (format === 'typescript') {
40
+ // Generate TypeScript runtime schema placeholder
41
+ content = `// Runtime schema for PostgreSQL AST nodes
42
+ // Generated from: ${argv.inFile}
43
+
44
+ export interface RuntimeSchema {
45
+ // TODO: Implement runtime schema generation
46
+ nodes: Record<string, any>;
47
+ }
48
+
49
+ export const runtimeSchema: RuntimeSchema = {
50
+ nodes: {}
51
+ };
52
+ `;
53
+ fileExt = '.ts';
54
+ } else {
55
+ // Generate JSON runtime schema placeholder
56
+ content = JSON.stringify({
57
+ generated: new Date().toISOString(),
58
+ source: argv.inFile,
59
+ nodes: {}
60
+ }, null, 2);
61
+ fileExt = '.json';
62
+ }
63
+
64
+ // Write file
65
+ const outputPath = join(argv.outDir, `${filename}${fileExt}`);
66
+ writeFileSync(outputPath, content);
67
+
68
+ console.log(chalk.green(`✓ Runtime schema generated: ${outputPath}`));
69
+ } catch (error: any) {
70
+ console.error(chalk.red('Runtime schema error:'), error.message || error);
71
+ process.exit(1);
72
+ }
73
+ }
74
+