diff --git a/packages/shared-db/package.json b/packages/shared-db/package.json index 0ea29837..50075858 100644 --- a/packages/shared-db/package.json +++ b/packages/shared-db/package.json @@ -10,7 +10,9 @@ "db:migrate": "pnpm exec drizzle-kit migrate", "db:studio": "pnpm exec drizzle-kit studio", "seed:dev": "bun ./scripts/seed-dev.ts", - "seed:remote": "bun ./scripts/seed-remote.ts" + "seed:remote": "bun ./scripts/seed-remote.ts", + "overwrite-vars:up": "bun run ./scripts/overwrite-vars.ts up", + "overwrite-vars:down": "bun run ./scripts/overwrite-vars.ts down" }, "dependencies": { "async-retry": "^1.3.3", @@ -27,8 +29,9 @@ "dotenv": "^16.5.0", "drizzle-kit": "^0.31.1", "eslint": "^9.28.0", - "typescript": "^5.8.3", - "pg": "^8.15.6" + "pg": "^8.15.6", + "pg-connection-string": "^2.9.0", + "typescript": "^5.8.3" }, "peerDependencies": { "drizzle-orm": "^0.43.1", diff --git a/packages/shared-db/scripts/overwrite-vars.ts b/packages/shared-db/scripts/overwrite-vars.ts new file mode 100644 index 00000000..20dd7532 --- /dev/null +++ b/packages/shared-db/scripts/overwrite-vars.ts @@ -0,0 +1,87 @@ +import * as dotenv from "dotenv"; +import { sql } from "drizzle-orm"; +import { drizzle, type NodePgDatabase } from "drizzle-orm/node-postgres"; +import * as path from "path"; +import { Client } from "pg"; +import { feeds } from "../src/schema/feeds"; + +dotenv.config({ path: path.resolve(__dirname, "../.env") }); + +// Define your list of transformations +const replacements = [{ oldValue: "OLD", newValue: "{{NEW}}" }]; + +async function performUpOperation(db: NodePgDatabase) { + for (const { oldValue, newValue } of replacements) { + console.log(`Applying replacement: "${oldValue}" -> "${newValue}"`); + await db.execute(sql` + UPDATE ${feeds} + SET + config = REPLACE(config::text, ${oldValue}, ${newValue})::jsonb + WHERE + config::text LIKE ${`%${oldValue}%`}; + `); + } + console.log("All JSONB string replacements applied."); +} + +async function performDownOperation(db: NodePgDatabase) { + for (let i = replacements.length - 1; i >= 0; i--) { + const { oldValue, newValue } = replacements[i]; + console.log(`Reverting replacement: "${newValue}" -> "${oldValue}"`); + await db.execute(sql` + UPDATE ${feeds} + SET + config = REPLACE(config::text, ${newValue}, ${oldValue})::jsonb + WHERE + config::text LIKE ${`%${newValue}%`}; + `); + } + console.log("All JSONB string replacements reverted."); +} + +async function main() { + const databaseUrl = process.env.DATABASE_URL; + if (!databaseUrl) { + console.error("Error: DATABASE_URL environment variable is required."); + process.exit(1); + } + + const operation = process.argv[2]; + if (operation !== "up" && operation !== "down") { + console.error( + "Error: Please specify 'up' or 'down' as a command line argument.", + ); + console.log( + "Usage: bun run packages/shared-db/scripts/overwrite-vars.ts ", + ); + process.exit(1); + } + + const dbClient = new Client({ connectionString: databaseUrl }); + + try { + console.log(`Connecting to remote database specified by DATABASE_URL...`); + await dbClient.connect(); + const dbInstance = drizzle(dbClient); + + if (operation === "up") { + console.log("Running UP operation..."); + await performUpOperation(dbInstance); + } else { + // operation === 'down' + console.log("Running DOWN operation..."); + await performDownOperation(dbInstance); + } + console.log(`Operation '${operation}' completed successfully.`); + } catch (error) { + console.error(`Error during '${operation}' operation:`, error); + process.exit(1); + } finally { + if (dbClient) { + console.log("Closing database connection."); + await dbClient.end(); + } + } +} + +main(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0424da0b..d842a94a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -119,13 +119,13 @@ importers: devDependencies: '@module-federation/node': specifier: ^2.6.30 - version: 2.6.33(@rspack/core@1.2.8(@swc/helpers@0.5.17))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)(webpack@5.99.7(esbuild@0.25.5)) + version: 2.6.33(@rspack/core@1.2.8(@swc/helpers@0.5.17))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)(webpack@5.99.7) '@rspack/binding': specifier: 1.2.8 version: 1.2.8 '@rspack/cli': specifier: 1.2.8 - version: 1.2.8(@rspack/core@1.2.8(@swc/helpers@0.5.17))(@types/express@4.17.21)(webpack@5.99.7(esbuild@0.25.5)) + version: 1.2.8(@rspack/core@1.2.8(@swc/helpers@0.5.17))(@types/express@4.17.22)(webpack@5.99.7) '@rspack/core': specifier: 1.2.8 version: 1.2.8(@swc/helpers@0.5.17) @@ -403,7 +403,7 @@ importers: devDependencies: '@rspack/cli': specifier: 1.2.8 - version: 1.2.8(@rspack/core@1.2.8(@swc/helpers@0.5.17))(@types/express@4.17.22)(webpack@5.99.7) + version: 1.2.8(@rspack/core@1.2.8(@swc/helpers@0.5.17))(@types/express@4.17.21)(webpack@5.99.7(esbuild@0.25.5)) '@rspack/core': specifier: 1.2.8 version: 1.2.8(@swc/helpers@0.5.17) @@ -425,6 +425,9 @@ importers: pg: specifier: ^8.15.6 version: 8.15.6 + pg-connection-string: + specifier: ^2.9.0 + version: 2.9.0 typescript: specifier: ^5.8.3 version: 5.8.3 @@ -7075,7 +7078,7 @@ snapshots: - supports-color - utf-8-validate - '@module-federation/enhanced@0.11.4(@rspack/core@1.2.8(@swc/helpers@0.5.17))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)(webpack@5.99.7(esbuild@0.25.5))': + '@module-federation/enhanced@0.11.4(@rspack/core@1.2.8(@swc/helpers@0.5.17))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)(webpack@5.99.7)': dependencies: '@module-federation/bridge-react-webpack-plugin': 0.11.4 '@module-federation/cli': 0.11.4(typescript@5.8.3) @@ -7092,7 +7095,7 @@ snapshots: upath: 2.0.1 optionalDependencies: typescript: 5.8.3 - webpack: 5.99.7(esbuild@0.25.5) + webpack: 5.99.7 transitivePeerDependencies: - '@rspack/core' - bufferutil @@ -7131,16 +7134,16 @@ snapshots: - utf-8-validate - vue-tsc - '@module-federation/node@2.6.33(@rspack/core@1.2.8(@swc/helpers@0.5.17))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)(webpack@5.99.7(esbuild@0.25.5))': + '@module-federation/node@2.6.33(@rspack/core@1.2.8(@swc/helpers@0.5.17))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)(webpack@5.99.7)': dependencies: - '@module-federation/enhanced': 0.11.4(@rspack/core@1.2.8(@swc/helpers@0.5.17))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)(webpack@5.99.7(esbuild@0.25.5)) + '@module-federation/enhanced': 0.11.4(@rspack/core@1.2.8(@swc/helpers@0.5.17))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)(webpack@5.99.7) '@module-federation/runtime': 0.11.4 '@module-federation/sdk': 0.11.4 - '@module-federation/utilities': 3.1.51(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.99.7(esbuild@0.25.5)) + '@module-federation/utilities': 3.1.51(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.99.7) btoa: 1.2.1 encoding: 0.1.13 node-fetch: 2.7.0(encoding@0.1.13) - webpack: 5.99.7(esbuild@0.25.5) + webpack: 5.99.7 optionalDependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -7221,10 +7224,10 @@ snapshots: fs-extra: 9.1.0 resolve: 1.22.8 - '@module-federation/utilities@3.1.51(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.99.7(esbuild@0.25.5))': + '@module-federation/utilities@3.1.51(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.99.7)': dependencies: '@module-federation/sdk': 0.11.4 - webpack: 5.99.7(esbuild@0.25.5) + webpack: 5.99.7 optionalDependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -12405,6 +12408,7 @@ snapshots: webpack: 5.99.7(esbuild@0.25.5) optionalDependencies: esbuild: 0.25.5 + optional: true terser-webpack-plugin@5.3.14(webpack@5.99.7): dependencies: @@ -12414,7 +12418,6 @@ snapshots: serialize-javascript: 6.0.2 terser: 5.40.0 webpack: 5.99.7 - optional: true terser@5.40.0: dependencies: @@ -12878,7 +12881,6 @@ snapshots: - '@swc/core' - esbuild - uglify-js - optional: true webpack@5.99.7(esbuild@0.25.5): dependencies: @@ -12910,6 +12912,7 @@ snapshots: - '@swc/core' - esbuild - uglify-js + optional: true websocket-driver@0.7.4: dependencies: