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.
@@ -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.ts script
59
- const internalCompileScript = path.resolve(__dirname, '../../../deno/internal_compile.ts');
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('No new migrations to copy - all migrations are already in place');
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('Files to be copied:')}
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('Files to be skipped (already exist):')}
88
- ${skippedFiles.map((file) => `${chalk.yellow('=')} ${file}`).join('\n')}`);
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'), 'Migration Summary');
91
+ note(summaryParts.join('\n\n'), 'pgflow Migrations');
92
92
  const shouldContinue = await confirm({
93
- message: `Do you want to proceed with copying ${filesToCopy.length} migration file${filesToCopy.length !== 1 ? 's' : ''}?`,
93
+ message: `Install ${filesToCopy.length} new migration${filesToCopy.length !== 1 ? 's' : ''}?`,
94
94
  });
95
95
  if (!shouldContinue) {
96
- log.info('Migration copy cancelled');
96
+ log.info('Migration installation skipped');
97
97
  return false;
98
98
  }
99
- log.info(`Copying migrations`);
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(`Copied ${file}`);
105
+ log.step(`Added ${file}`);
106
106
  }
107
- log.success(`Successfully copied ${filesToCopy.length} migration file${filesToCopy.length !== 1 ? 's' : ''}`);
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,wBAsCE"}
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('Copies migrations and sets config.toml values')
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('Aborting installation');
13
+ log.error('Installation cancelled');
14
14
  return;
15
15
  }
16
- const migrationsCopied = await copyMigrations({ supabasePath });
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 installation is completed');
20
- }
21
- if (!migrationsCopied && !configUpdated) {
22
- log.success('No changes were made - pgflow is already properly configured.');
23
- }
24
- // Show specific reminders based on what was actually done
25
- if (configUpdated) {
26
- log.warn('Remember to restart Supabase for the configuration changes to take effect!');
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
- if (migrationsCopied) {
29
- log.warn('Remember to apply the migrations!');
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,6BAMvC"}
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: 'Enter the path to your supabase/ directory',
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
- const pathsToTest = [
13
- [inputPath, 'is not a valid path'],
14
- [path.join(inputPath, 'config.toml'), 'does not contain config.toml'],
15
- ];
16
- // if any of the pathsToTest fail, return the error message
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,CAwHnB"}
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(`No changes needed in config.toml - all required settings are already configured`);
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(`[db.pooler]
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(`[db.pooler]
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(`[edge_runtime]
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'), 'Config Changes');
56
+ note(changes.join('\n\n'), 'Required Configuration Changes');
57
57
  const shouldContinue = await confirm({
58
- message: `Do you want to proceed with these configuration changes? A backup will be created at ${backupPath}`,
58
+ message: `Update Supabase configuration? (a backup will be created)`,
59
59
  });
60
60
  if (!shouldContinue) {
61
- log.info('Configuration update cancelled');
61
+ log.info('Configuration update skipped');
62
62
  return false;
63
63
  }
64
64
  fs.copyFileSync(configPath, backupPath);
65
- log.info(`Created backup at ${backupPath}`);
66
- log.info(`Updating config.toml`);
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(`Successfully updated ${configPath} (backup created at ${backupPath})`);
103
+ log.success(`Supabase configuration updated successfully`);
104
104
  return true;
105
105
  }
106
106
  catch (error) {
107
- log.error(`Failed to update ${configPath}: ${error instanceof Error ? error.message : String(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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgflow",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "typings": "./dist/index.d.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgflow",
3
- "version": "0.1.3",
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.3"
27
+ "@pgflow/core": "0.1.5"
28
28
  },
29
29
  "publishConfig": {
30
30
  "access": "public",