pgflow 0.1.1 → 0.1.2
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.
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/compile/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;kCAkChB,OAAO;AAAhC,wBA4EE"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { intro, log, spinner, note } from '@clack/prompts';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import { spawn } from 'child_process';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
// Get the directory name in ES modules
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
/**
|
|
11
|
+
* Formats a command and its arguments for display with syntax highlighting
|
|
12
|
+
* Each argument is displayed on a separate line for better readability
|
|
13
|
+
*/
|
|
14
|
+
function formatCommand(command, args) {
|
|
15
|
+
const cmd = chalk.cyan(command);
|
|
16
|
+
const formattedArgs = args.map((arg) => {
|
|
17
|
+
// Highlight import map and file paths differently
|
|
18
|
+
if (arg.startsWith('--import-map=')) {
|
|
19
|
+
const [flag, value] = arg.split('=');
|
|
20
|
+
return ` ${chalk.yellow(flag)}=${chalk.green(value)}`;
|
|
21
|
+
}
|
|
22
|
+
else if (arg.startsWith('--')) {
|
|
23
|
+
return ` ${chalk.yellow(arg)}`;
|
|
24
|
+
}
|
|
25
|
+
else if (arg.endsWith('.ts') || arg.endsWith('.json')) {
|
|
26
|
+
return ` ${chalk.green(arg)}`;
|
|
27
|
+
}
|
|
28
|
+
return ` ${chalk.white(arg)}`;
|
|
29
|
+
});
|
|
30
|
+
return `$ ${cmd}\n${formattedArgs.join('\n')}`;
|
|
31
|
+
}
|
|
32
|
+
export default (program) => {
|
|
33
|
+
program
|
|
34
|
+
.command('compile')
|
|
35
|
+
.description('Compiles a TypeScript-defined flow into SQL migration')
|
|
36
|
+
.argument('<flowPath>', 'Path to the flow TypeScript file')
|
|
37
|
+
.option('--deno-json <denoJsonPath>', 'Path to deno.json with valid importMap')
|
|
38
|
+
.action(async (flowPath, options) => {
|
|
39
|
+
intro('pgflow - Compile Flow to SQL');
|
|
40
|
+
try {
|
|
41
|
+
// Resolve paths
|
|
42
|
+
const resolvedFlowPath = path.resolve(process.cwd(), flowPath);
|
|
43
|
+
// Only resolve denoJsonPath if it's provided
|
|
44
|
+
let resolvedDenoJsonPath;
|
|
45
|
+
if (options.denoJson) {
|
|
46
|
+
resolvedDenoJsonPath = path.resolve(process.cwd(), options.denoJson);
|
|
47
|
+
// Validate deno.json path if provided
|
|
48
|
+
if (!fs.existsSync(resolvedDenoJsonPath)) {
|
|
49
|
+
log.error(`deno.json file not found: ${resolvedDenoJsonPath}`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Validate flow path
|
|
54
|
+
if (!fs.existsSync(resolvedFlowPath)) {
|
|
55
|
+
log.error(`Flow file not found: ${resolvedFlowPath}`);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
// Find the internal_compile.ts script
|
|
59
|
+
const internalCompileScript = path.resolve(__dirname, '../../../deno/internal_compile.ts');
|
|
60
|
+
// Create migrations directory if it doesn't exist
|
|
61
|
+
const migrationsDir = path.resolve(process.cwd(), 'migrations');
|
|
62
|
+
if (!fs.existsSync(migrationsDir)) {
|
|
63
|
+
fs.mkdirSync(migrationsDir, { recursive: true });
|
|
64
|
+
log.info(`Created migrations directory: ${migrationsDir}`);
|
|
65
|
+
}
|
|
66
|
+
// Generate timestamp for migration file
|
|
67
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '_');
|
|
68
|
+
const migrationFileName = `pgflow_${timestamp}.sql`;
|
|
69
|
+
const migrationFilePath = path.join(migrationsDir, migrationFileName);
|
|
70
|
+
// Run the compilation
|
|
71
|
+
const s = spinner();
|
|
72
|
+
s.start(`Compiling flow: ${path.basename(resolvedFlowPath)}`);
|
|
73
|
+
const compiledSql = await runDenoCompilation(internalCompileScript, resolvedFlowPath, resolvedDenoJsonPath);
|
|
74
|
+
// Write the SQL to a migration file
|
|
75
|
+
fs.writeFileSync(migrationFilePath, compiledSql);
|
|
76
|
+
s.stop(`Successfully compiled flow to SQL`);
|
|
77
|
+
log.success(`Migration file created: ${migrationFilePath}`);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
log.error(`Compilation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Runs the Deno compilation script and returns the compiled SQL
|
|
87
|
+
*/
|
|
88
|
+
async function runDenoCompilation(scriptPath, flowPath, denoJsonPath) {
|
|
89
|
+
return new Promise((resolve, reject) => {
|
|
90
|
+
// Validate input paths
|
|
91
|
+
if (!scriptPath) {
|
|
92
|
+
return reject(new Error('Internal script path is required'));
|
|
93
|
+
}
|
|
94
|
+
if (!flowPath) {
|
|
95
|
+
return reject(new Error('Flow path is required'));
|
|
96
|
+
}
|
|
97
|
+
// Build the command arguments array
|
|
98
|
+
const args = ['run', '--allow-read', '--allow-net', '--allow-env'];
|
|
99
|
+
// Only add the import-map argument if denoJsonPath is provided and valid
|
|
100
|
+
if (denoJsonPath && typeof denoJsonPath === 'string') {
|
|
101
|
+
args.push(`--import-map=${denoJsonPath}`);
|
|
102
|
+
}
|
|
103
|
+
// Add the script path and flow path
|
|
104
|
+
args.push(scriptPath, flowPath);
|
|
105
|
+
// Log the command for debugging with colored output
|
|
106
|
+
note(formatCommand('deno', args), 'Compile in Deno');
|
|
107
|
+
const deno = spawn('deno', args);
|
|
108
|
+
let stdout = '';
|
|
109
|
+
let stderr = '';
|
|
110
|
+
deno.stdout.on('data', (data) => {
|
|
111
|
+
stdout += data.toString();
|
|
112
|
+
});
|
|
113
|
+
deno.stderr.on('data', (data) => {
|
|
114
|
+
stderr += data.toString();
|
|
115
|
+
});
|
|
116
|
+
deno.on('close', (code) => {
|
|
117
|
+
if (code === 0) {
|
|
118
|
+
if (stdout.trim().length === 0) {
|
|
119
|
+
reject(new Error('Compilation produced no output'));
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
resolve(stdout);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
reject(new Error(`Deno process exited with code ${code}${stderr ? `\n${stderr}` : ''}`));
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
deno.on('error', (err) => {
|
|
130
|
+
reject(new Error(`Failed to start Deno process: ${err.message}. Make sure Deno is installed.`));
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { fileURLToPath } from 'url';
|
|
|
4
4
|
import { readFileSync } from 'fs';
|
|
5
5
|
import { dirname, join } from 'path';
|
|
6
6
|
import installCommand from './commands/install/index.js';
|
|
7
|
+
import compileCommand from './commands/compile/index.js';
|
|
7
8
|
// Create a function to handle errors
|
|
8
9
|
const errorHandler = (error) => {
|
|
9
10
|
console.error('Error:', error instanceof Error ? error.message : String(error));
|
|
@@ -38,7 +39,31 @@ program
|
|
|
38
39
|
}
|
|
39
40
|
throw err;
|
|
40
41
|
});
|
|
42
|
+
// Register commands
|
|
41
43
|
installCommand(program);
|
|
44
|
+
compileCommand(program);
|
|
45
|
+
import chalk from 'chalk';
|
|
46
|
+
// Tokyo Night inspired colors
|
|
47
|
+
// const p = chalk.hex('#7aa2f7'); // blue-violet
|
|
48
|
+
const g = chalk.hex('#9ece6a'); // vibrant green
|
|
49
|
+
const f = chalk.hex('#bb9af7'); // light purple/pink
|
|
50
|
+
const l = chalk.hex('#2ac3de'); // bright teal/cyan
|
|
51
|
+
// const o = chalk.hex('#ff9e64'); // orange
|
|
52
|
+
// const w = chalk.hex('#f7768e'); // magenta/pink
|
|
53
|
+
const banner = [
|
|
54
|
+
` ${l('__ _')} `,
|
|
55
|
+
` ${g('_ __ __ _')} ${l('/ _| | _____ __')} `,
|
|
56
|
+
` ${g("| '_ \\ / _'")} ${l('| |_| |/ _ \\ \\ /\\ / /')} `,
|
|
57
|
+
` ${g('| |_) | (_|')} ${l('| _| | (_) \\ V V /')} `,
|
|
58
|
+
` ${g('| .__/ \\__,')} ${l('|_| |_|\\___/ \\_/\\_/')} `,
|
|
59
|
+
` ${g('|_| |___/')}`,
|
|
60
|
+
``,
|
|
61
|
+
` ${f('Postgres-native Workflow Engine')}`,
|
|
62
|
+
].join('\n');
|
|
63
|
+
console.log(banner);
|
|
64
|
+
console.log();
|
|
65
|
+
console.log();
|
|
66
|
+
console.log();
|
|
42
67
|
// Use a promise-aware approach to parse arguments
|
|
43
68
|
async function main() {
|
|
44
69
|
try {
|
package/dist/package.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pgflow",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"typings": "./dist/index.d.ts",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"chalk": "^5.4.1",
|
|
25
25
|
"commander": "^13.1.0",
|
|
26
26
|
"toml-patch": "^0.2.3",
|
|
27
|
-
"@pgflow/core": "0.1.
|
|
27
|
+
"@pgflow/core": "0.1.2"
|
|
28
28
|
},
|
|
29
29
|
"publishConfig": {
|
|
30
30
|
"access": "public",
|