pgflow 0.1.3 → 0.1.5
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/commands/compile/index.js +2 -2
- package/dist/commands/install/copy-migrations.js +10 -10
- package/dist/commands/install/index.d.ts.map +1 -1
- package/dist/commands/install/index.js +20 -14
- package/dist/commands/install/supabase-path-prompt.d.ts.map +1 -1
- package/dist/commands/install/supabase-path-prompt.js +23 -13
- package/dist/commands/install/update-config-toml.d.ts.map +1 -1
- package/dist/commands/install/update-config-toml.js +11 -11
- package/dist/deno/internal_compile.js +105 -0
- package/dist/package.json +1 -1
- package/package.json +2 -2
|
@@ -55,8 +55,8 @@ export default (program) => {
|
|
|
55
55
|
log.error(`Flow file not found: ${resolvedFlowPath}`);
|
|
56
56
|
process.exit(1);
|
|
57
57
|
}
|
|
58
|
-
// Find the internal_compile.
|
|
59
|
-
const internalCompileScript = path.resolve(__dirname, '../../../deno/internal_compile.
|
|
58
|
+
// Find the internal_compile.js script
|
|
59
|
+
const internalCompileScript = path.resolve(__dirname, '../../../deno/internal_compile.js');
|
|
60
60
|
// Create migrations directory if it doesn't exist
|
|
61
61
|
const migrationsDir = path.resolve(process.cwd(), 'migrations');
|
|
62
62
|
if (!fs.existsSync(migrationsDir)) {
|
|
@@ -74,36 +74,36 @@ export async function copyMigrations({ supabasePath, }) {
|
|
|
74
74
|
}
|
|
75
75
|
// If no files to copy, show message and return false (no changes made)
|
|
76
76
|
if (filesToCopy.length === 0) {
|
|
77
|
-
log.info('
|
|
77
|
+
log.info('All pgflow migrations are already in place');
|
|
78
78
|
return false;
|
|
79
79
|
}
|
|
80
80
|
// Prepare summary message with colored output
|
|
81
81
|
const summaryParts = [];
|
|
82
82
|
if (filesToCopy.length > 0) {
|
|
83
|
-
summaryParts.push(`${chalk.green('
|
|
83
|
+
summaryParts.push(`${chalk.green('New migrations to install:')}
|
|
84
84
|
${filesToCopy.map((file) => `${chalk.green('+')} ${file}`).join('\n')}`);
|
|
85
85
|
}
|
|
86
86
|
if (skippedFiles.length > 0) {
|
|
87
|
-
summaryParts.push(`${chalk.yellow('
|
|
88
|
-
${skippedFiles.map((file) => `${chalk.yellow('
|
|
87
|
+
summaryParts.push(`${chalk.yellow('Already installed:')}
|
|
88
|
+
${skippedFiles.map((file) => `${chalk.yellow('•')} ${file}`).join('\n')}`);
|
|
89
89
|
}
|
|
90
90
|
// Show summary and ask for confirmation
|
|
91
|
-
note(summaryParts.join('\n\n'), '
|
|
91
|
+
note(summaryParts.join('\n\n'), 'pgflow Migrations');
|
|
92
92
|
const shouldContinue = await confirm({
|
|
93
|
-
message: `
|
|
93
|
+
message: `Install ${filesToCopy.length} new migration${filesToCopy.length !== 1 ? 's' : ''}?`,
|
|
94
94
|
});
|
|
95
95
|
if (!shouldContinue) {
|
|
96
|
-
log.info('Migration
|
|
96
|
+
log.info('Migration installation skipped');
|
|
97
97
|
return false;
|
|
98
98
|
}
|
|
99
|
-
log.
|
|
99
|
+
log.step(`Installing pgflow migrations...`);
|
|
100
100
|
// Copy the files
|
|
101
101
|
for (const file of filesToCopy) {
|
|
102
102
|
const source = path.join(sourcePath, file);
|
|
103
103
|
const destination = path.join(migrationsPath, file);
|
|
104
104
|
fs.copyFileSync(source, destination);
|
|
105
|
-
log.step(`
|
|
105
|
+
log.step(`Added ${file}`);
|
|
106
106
|
}
|
|
107
|
-
log.success(`
|
|
107
|
+
log.success(`Installed ${filesToCopy.length} migration${filesToCopy.length !== 1 ? 's' : ''} to your Supabase project`);
|
|
108
108
|
return true; // Return true to indicate migrations were copied
|
|
109
109
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/install/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;kCAMhB,OAAO;AAAhC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/install/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;kCAMhB,OAAO;AAAhC,wBA4CE"}
|
|
@@ -1,32 +1,38 @@
|
|
|
1
|
-
import { intro, isCancel, log } from '@clack/prompts';
|
|
1
|
+
import { intro, isCancel, log, note } from '@clack/prompts';
|
|
2
2
|
import { copyMigrations } from './copy-migrations.js';
|
|
3
3
|
import { updateConfigToml } from './update-config-toml.js';
|
|
4
4
|
import { supabasePathPrompt } from './supabase-path-prompt.js';
|
|
5
5
|
export default (program) => {
|
|
6
6
|
program
|
|
7
7
|
.command('install')
|
|
8
|
-
.description('
|
|
8
|
+
.description('Set up pgflow in your Supabase project')
|
|
9
9
|
.action(async () => {
|
|
10
10
|
intro('pgflow - Postgres-native workflows for Supabase');
|
|
11
11
|
const supabasePath = await supabasePathPrompt();
|
|
12
12
|
if (isCancel(supabasePath)) {
|
|
13
|
-
log.error('
|
|
13
|
+
log.error('Installation cancelled');
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
// First update config.toml, then copy migrations
|
|
17
17
|
const configUpdated = await updateConfigToml({ supabasePath });
|
|
18
|
+
const migrationsCopied = await copyMigrations({ supabasePath });
|
|
19
|
+
// Show completion message
|
|
18
20
|
if (migrationsCopied || configUpdated) {
|
|
19
|
-
log.success('pgflow
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
log.success('pgflow setup completed successfully');
|
|
22
|
+
// Show next steps if changes were made
|
|
23
|
+
const nextSteps = [];
|
|
24
|
+
if (configUpdated) {
|
|
25
|
+
nextSteps.push('• Restart your Supabase instance for configuration changes to take effect');
|
|
26
|
+
}
|
|
27
|
+
if (migrationsCopied) {
|
|
28
|
+
nextSteps.push('• Apply the migrations with: supabase db push');
|
|
29
|
+
}
|
|
30
|
+
if (nextSteps.length > 0) {
|
|
31
|
+
note(nextSteps.join('\n'), 'Next steps');
|
|
32
|
+
}
|
|
27
33
|
}
|
|
28
|
-
|
|
29
|
-
log.
|
|
34
|
+
else {
|
|
35
|
+
log.success('pgflow is already properly configured - no changes needed');
|
|
30
36
|
}
|
|
31
37
|
});
|
|
32
38
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supabase-path-prompt.d.ts","sourceRoot":"","sources":["../../../src/commands/install/supabase-path-prompt.ts"],"names":[],"mappings":"AAIA,wBAAsB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"supabase-path-prompt.d.ts","sourceRoot":"","sources":["../../../src/commands/install/supabase-path-prompt.ts"],"names":[],"mappings":"AAIA,wBAAsB,kBAAkB,6BA2BvC"}
|
|
@@ -1,24 +1,34 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { text } from '@clack/prompts';
|
|
3
|
+
import { text, log } from '@clack/prompts';
|
|
4
4
|
export async function supabasePathPrompt() {
|
|
5
|
+
// Try to detect the Supabase directory automatically
|
|
6
|
+
const possiblePaths = ['./supabase', '../supabase', '../../supabase'];
|
|
7
|
+
let detectedPath = '';
|
|
8
|
+
for (const testPath of possiblePaths) {
|
|
9
|
+
if (fs.existsSync(testPath) &&
|
|
10
|
+
fs.existsSync(path.join(testPath, 'config.toml'))) {
|
|
11
|
+
detectedPath = testPath;
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (detectedPath) {
|
|
16
|
+
log.success(`Found Supabase project at: ${detectedPath}`);
|
|
17
|
+
}
|
|
18
|
+
const promptMessage = 'Where is your Supabase project located?';
|
|
5
19
|
return await text({
|
|
6
|
-
message:
|
|
7
|
-
placeholder: 'supabase/',
|
|
20
|
+
message: promptMessage,
|
|
21
|
+
placeholder: detectedPath || 'supabase/',
|
|
22
|
+
initialValue: detectedPath,
|
|
8
23
|
validate,
|
|
9
24
|
});
|
|
10
25
|
}
|
|
11
26
|
function validate(inputPath) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
for (const [testPath, errorMessage] of pathsToTest) {
|
|
18
|
-
if (!fs.existsSync(testPath)) {
|
|
19
|
-
return `${testPath} ${errorMessage}`;
|
|
20
|
-
}
|
|
27
|
+
if (!fs.existsSync(inputPath)) {
|
|
28
|
+
return `Directory not found: ${inputPath}`;
|
|
29
|
+
}
|
|
30
|
+
if (!fs.existsSync(path.join(inputPath, 'config.toml'))) {
|
|
31
|
+
return `Not a valid Supabase project (missing config.toml)`;
|
|
21
32
|
}
|
|
22
|
-
// otherwise, return undefined
|
|
23
33
|
return undefined;
|
|
24
34
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-config-toml.d.ts","sourceRoot":"","sources":["../../../src/commands/install/update-config-toml.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,YAAY,GACb,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"update-config-toml.d.ts","sourceRoot":"","sources":["../../../src/commands/install/update-config-toml.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,YAAY,GACb,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,OAAO,CAAC,CAoHnB"}
|
|
@@ -34,36 +34,36 @@ export async function updateConfigToml({ supabasePath, }) {
|
|
|
34
34
|
currentSettings.poolMode !== 'transaction' ||
|
|
35
35
|
currentSettings.edgeRuntimePolicy !== 'per_worker';
|
|
36
36
|
if (!needsChanges) {
|
|
37
|
-
log.info(`
|
|
37
|
+
log.info(`Supabase configuration is already set up for pgflow`);
|
|
38
38
|
return false;
|
|
39
39
|
}
|
|
40
40
|
const changes = [];
|
|
41
41
|
if (currentSettings.poolerEnabled !== true) {
|
|
42
|
-
changes.push(
|
|
42
|
+
changes.push(`${chalk.bold('Enable connection pooler:')}
|
|
43
43
|
${chalk.red(`- enabled = ${currentSettings.poolerEnabled}`)}
|
|
44
44
|
${chalk.green('+ enabled = true')}`);
|
|
45
45
|
}
|
|
46
46
|
if (currentSettings.poolMode !== 'transaction') {
|
|
47
|
-
changes.push(
|
|
47
|
+
changes.push(`${chalk.bold('Set pool mode to transaction:')}
|
|
48
48
|
${chalk.red(`- pool_mode = "${currentSettings.poolMode}"`)}
|
|
49
49
|
${chalk.green('+ pool_mode = "transaction"')}`);
|
|
50
50
|
}
|
|
51
51
|
if (currentSettings.edgeRuntimePolicy !== 'per_worker') {
|
|
52
|
-
changes.push(
|
|
52
|
+
changes.push(`${chalk.bold('Set edge runtime policy:')}
|
|
53
53
|
${chalk.red(`- policy = "${currentSettings.edgeRuntimePolicy}"`)}
|
|
54
54
|
${chalk.green('+ policy = "per_worker"')}`);
|
|
55
55
|
}
|
|
56
|
-
note(changes.join('\n\n'), '
|
|
56
|
+
note(changes.join('\n\n'), 'Required Configuration Changes');
|
|
57
57
|
const shouldContinue = await confirm({
|
|
58
|
-
message: `
|
|
58
|
+
message: `Update Supabase configuration? (a backup will be created)`,
|
|
59
59
|
});
|
|
60
60
|
if (!shouldContinue) {
|
|
61
|
-
log.info('Configuration update
|
|
61
|
+
log.info('Configuration update skipped');
|
|
62
62
|
return false;
|
|
63
63
|
}
|
|
64
64
|
fs.copyFileSync(configPath, backupPath);
|
|
65
|
-
log.
|
|
66
|
-
log.
|
|
65
|
+
log.step(`Created backup of config.toml`);
|
|
66
|
+
log.step(`Updating Supabase configuration...`);
|
|
67
67
|
const updatedConfig = { ...config };
|
|
68
68
|
// Ensure required objects exist and set values
|
|
69
69
|
if (!updatedConfig.db)
|
|
@@ -100,11 +100,11 @@ ${chalk.green('+ policy = "per_worker"')}`);
|
|
|
100
100
|
// Fix edge_runtime.policy line - transforms "policy = "per_worker"," into "policy = "per_worker""
|
|
101
101
|
/policy = "per_worker",(\s*$|\s*#|\s*\n)/g, 'policy = "per_worker"$1');
|
|
102
102
|
fs.writeFileSync(configPath, updatedContent);
|
|
103
|
-
log.success(`
|
|
103
|
+
log.success(`Supabase configuration updated successfully`);
|
|
104
104
|
return true;
|
|
105
105
|
}
|
|
106
106
|
catch (error) {
|
|
107
|
-
log.error(`
|
|
107
|
+
log.error(`Configuration update failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
108
108
|
throw error;
|
|
109
109
|
}
|
|
110
110
|
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* internal_compile.js
|
|
3
|
+
*
|
|
4
|
+
* This script is executed by Deno to compile a Flow into SQL statements.
|
|
5
|
+
* It takes a path to a flow file as an argument, imports the default export,
|
|
6
|
+
* and passes it to compileFlow() from the DSL package.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Get the flow file path from command line arguments
|
|
10
|
+
const flowFilePath = Deno.args[0];
|
|
11
|
+
|
|
12
|
+
if (!flowFilePath) {
|
|
13
|
+
console.error('Error: No flow file path provided');
|
|
14
|
+
Deno.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
// Dynamically import the flow file
|
|
19
|
+
const flowModule = await import(`file://${flowFilePath}`);
|
|
20
|
+
|
|
21
|
+
// Check if there's a default export
|
|
22
|
+
if (!flowModule.default) {
|
|
23
|
+
console.error(`Error: No default export found in ${flowFilePath}`);
|
|
24
|
+
Deno.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Import the DSL module
|
|
28
|
+
// The import map in deno.json will resolve this import
|
|
29
|
+
const dslModule = await import('npm:@pgflow/dsl');
|
|
30
|
+
|
|
31
|
+
// Debug available exports
|
|
32
|
+
console.error('Available exports from @pgflow/dsl:', Object.keys(dslModule));
|
|
33
|
+
|
|
34
|
+
// Get the flow instance
|
|
35
|
+
const flow = flowModule.default;
|
|
36
|
+
|
|
37
|
+
let compileFlow;
|
|
38
|
+
let sqlStatements;
|
|
39
|
+
|
|
40
|
+
// Try different ways to access the compileFlow function
|
|
41
|
+
if (typeof dslModule.compileFlow === 'function') {
|
|
42
|
+
// Direct export
|
|
43
|
+
compileFlow = dslModule.compileFlow;
|
|
44
|
+
} else if (
|
|
45
|
+
dslModule.default &&
|
|
46
|
+
typeof dslModule.default.compileFlow === 'function'
|
|
47
|
+
) {
|
|
48
|
+
// Default export with compileFlow as a property
|
|
49
|
+
compileFlow = dslModule.default.compileFlow;
|
|
50
|
+
} else {
|
|
51
|
+
// Try to import the compile-flow module directly
|
|
52
|
+
try {
|
|
53
|
+
const compileFlowModule = await import(
|
|
54
|
+
'npm:@pgflow/dsl/dist/compile-flow.js'
|
|
55
|
+
);
|
|
56
|
+
if (typeof compileFlowModule.compileFlow === 'function') {
|
|
57
|
+
compileFlow = compileFlowModule.compileFlow;
|
|
58
|
+
} else if (
|
|
59
|
+
compileFlowModule.default &&
|
|
60
|
+
typeof compileFlowModule.default === 'function'
|
|
61
|
+
) {
|
|
62
|
+
compileFlow = compileFlowModule.default;
|
|
63
|
+
}
|
|
64
|
+
} catch (importError) {
|
|
65
|
+
console.error(
|
|
66
|
+
'Failed to import compile-flow module:',
|
|
67
|
+
importError.message
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
// Try another path
|
|
71
|
+
try {
|
|
72
|
+
const altModule = await import('npm:@pgflow/dsl/src/compile-flow.js');
|
|
73
|
+
if (typeof altModule.compileFlow === 'function') {
|
|
74
|
+
compileFlow = altModule.compileFlow;
|
|
75
|
+
} else if (
|
|
76
|
+
altModule.default &&
|
|
77
|
+
typeof altModule.default === 'function'
|
|
78
|
+
) {
|
|
79
|
+
compileFlow = altModule.default;
|
|
80
|
+
}
|
|
81
|
+
} catch (altError) {
|
|
82
|
+
console.error(
|
|
83
|
+
'Failed to import alternative compile-flow module:',
|
|
84
|
+
altError.message
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Check if we found a valid compileFlow function
|
|
91
|
+
if (typeof compileFlow !== 'function') {
|
|
92
|
+
console.error('Error: compileFlow function not found in @pgflow/dsl');
|
|
93
|
+
console.error('Available exports:', Object.keys(dslModule));
|
|
94
|
+
Deno.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Compile the flow to SQL
|
|
98
|
+
sqlStatements = compileFlow(flow);
|
|
99
|
+
|
|
100
|
+
// Output the SQL statements to stdout
|
|
101
|
+
console.log(sqlStatements.join('\n'));
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error(`Error compiling flow: ${error.message}`);
|
|
104
|
+
Deno.exit(1);
|
|
105
|
+
}
|
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.5",
|
|
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.5"
|
|
28
28
|
},
|
|
29
29
|
"publishConfig": {
|
|
30
30
|
"access": "public",
|