Skip to content

Commit fb879aa

Browse files
committed
chore(pglite): convert poc demo run.js to CommonJS (drop type:module)
Repo convention avoids package type:module. All three @electric-sql/pglite* packages expose a require entry, so run.js uses CommonJS require + async main().
1 parent cf8cec4 commit fb879aa

2 files changed

Lines changed: 86 additions & 83 deletions

File tree

poc/pglite/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"name": "pgpm-pglite-poc",
33
"version": "0.0.0",
44
"private": true,
5-
"type": "module",
65
"description": "Proof of concept: the pgpm migrate engine deploying into PGlite (WASM Postgres), no Postgres service required. Standalone; not part of the pnpm workspace.",
76
"scripts": {
87
"start": "node run.js"

poc/pglite/run.js

Lines changed: 86 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -8,96 +8,100 @@
88
// This script starts the PGlite socket server in-process, then runs a real pgpm
99
// deploy -> verify -> revert against it, asserting the outcome. It exits non-zero
1010
// on any mismatch so CI fails loudly.
11-
import assert from 'node:assert/strict';
12-
import { createRequire } from 'node:module';
13-
import { PGlite } from '@electric-sql/pglite';
14-
import { vector } from '@electric-sql/pglite-pgvector';
15-
import { PGLiteSocketServer } from '@electric-sql/pglite-socket';
16-
import pg from 'pg';
17-
18-
const require = createRequire(import.meta.url);
11+
const assert = require('node:assert/strict');
12+
const { join } = require('node:path');
13+
14+
const { PGlite } = require('@electric-sql/pglite');
15+
const { vector } = require('@electric-sql/pglite-pgvector');
16+
const { PGLiteSocketServer } = require('@electric-sql/pglite-socket');
17+
const pg = require('pg');
18+
1919
// The published pgpm migrate engine — not modified, not vendored.
2020
const { PgpmMigrate } = require('@pgpmjs/core');
2121

2222
const HOST = '127.0.0.1';
2323
const PORT = Number(process.env.PGLITE_PORT || 5555);
24-
const MODULE = new URL('./module', import.meta.url).pathname;
24+
const MODULE = join(__dirname, 'module');
2525
const pgConfig = { host: HOST, port: PORT, user: 'postgres', password: 'x', database: 'postgres' };
2626

2727
function step(msg) { console.log(`\n=== ${msg} ===`); }
2828

29-
// --- boot PGlite + socket shim -------------------------------------------------
30-
const db = await PGlite.create({ extensions: { vector } });
31-
await db.waitReady;
32-
// Extensions are provisioned OUT-OF-BAND: pgpm's cleanSql strips CREATE EXTENSION
33-
// from migrations, exactly like pgsql-test's admin.installExtensions() / the
34-
// postgres-plus image. PGlite additionally requires the ext registered in JS above.
35-
await db.exec('CREATE EXTENSION IF NOT EXISTS vector;');
36-
37-
// PGlite serializes all queries onto one engine; the socket shim caps concurrent
38-
// connections at 1 by default. Raise it so a pooled client works (still serialized).
39-
const server = new PGLiteSocketServer({ db, host: HOST, port: PORT, maxConnections: 10 });
40-
await server.start();
41-
console.log(`[pglite] Postgres (WASM) listening on ${HOST}:${PORT}`);
42-
43-
let ok = false;
44-
try {
45-
const migrate = new PgpmMigrate(pgConfig);
46-
47-
step('initialize (bootstrap pgpm_migrate schema in PGlite)');
48-
await migrate.initialize();
49-
50-
step('deploy plan: schema -> table -> index -> pgvector column');
51-
// useTransaction:false because PGlite pins the engine to one connection while a
52-
// transaction is open; the engine's deploy path mixes a txn client with pool
53-
// queries, which deadlocks a single-connection backend. (See README.)
54-
const deployed = await migrate.deploy({ modulePath: MODULE, useTransaction: false });
55-
console.log('deployed:', deployed.deployed);
56-
assert.deepEqual(deployed.deployed, ['schema', 'table', 'index', 'embedding']);
57-
assert.equal(deployed.failed, undefined);
58-
59-
step('verify');
60-
const verified = await migrate.verify({ modulePath: MODULE });
61-
console.log('verify:', verified);
62-
assert.deepEqual(verified.verified, ['schema', 'table', 'index', 'embedding']);
63-
assert.deepEqual(verified.failed, []);
64-
65-
step('data round-trip through the pgpm-deployed schema (pgvector)');
66-
const client = new pg.Client(pgConfig);
67-
await client.connect();
68-
await client.query(
69-
'INSERT INTO test_app.users(name, email, embedding) VALUES ($1, $2, $3)',
70-
['ada', 'ada@example.com', '[0.1,0.2,0.3]']
71-
);
72-
const nearest = (await client.query(
73-
'SELECT name FROM test_app.users ORDER BY embedding <-> $1 LIMIT 1',
74-
['[0.1,0.2,0.3]']
75-
)).rows;
76-
console.log('nearest-neighbor:', nearest);
77-
assert.deepEqual(nearest, [{ name: 'ada' }]);
78-
79-
const changesAfterDeploy = (await client.query(
80-
'SELECT change_name FROM pgpm_migrate.changes ORDER BY 1'
81-
)).rows.map((r) => r.change_name);
82-
assert.deepEqual(changesAfterDeploy, ['embedding', 'index', 'schema', 'table']);
83-
84-
step('revert (full)');
85-
const reverted = await migrate.revert({ modulePath: MODULE, useTransaction: false });
86-
console.log('reverted:', reverted.reverted ?? reverted);
87-
const changesAfterRevert = (await client.query(
88-
'SELECT change_name FROM pgpm_migrate.changes ORDER BY 1'
89-
)).rows.map((r) => r.change_name);
90-
assert.deepEqual(changesAfterRevert, []);
91-
assert.equal((await client.query("SELECT to_regclass('test_app.users') AS t")).rows[0].t, null);
92-
await client.end();
93-
94-
ok = true;
95-
console.log('\nPASS: unmodified pgpm engine deployed + verified + reverted real migrations in PGlite; pgvector operational.');
96-
} catch (err) {
97-
console.error('\nFAIL:', err);
98-
} finally {
99-
await server.stop();
100-
await db.close();
29+
async function main() {
30+
// --- boot PGlite + socket shim ---------------------------------------------
31+
const db = await PGlite.create({ extensions: { vector } });
32+
await db.waitReady;
33+
// Extensions are provisioned OUT-OF-BAND: pgpm's cleanSql strips CREATE EXTENSION
34+
// from migrations, exactly like pgsql-test's admin.installExtensions() / the
35+
// postgres-plus image. PGlite additionally requires the ext registered in JS above.
36+
await db.exec('CREATE EXTENSION IF NOT EXISTS vector;');
37+
38+
// PGlite serializes all queries onto one engine; the socket shim caps concurrent
39+
// connections at 1 by default. Raise it so a pooled client works (still serialized).
40+
const server = new PGLiteSocketServer({ db, host: HOST, port: PORT, maxConnections: 10 });
41+
await server.start();
42+
console.log(`[pglite] Postgres (WASM) listening on ${HOST}:${PORT}`);
43+
44+
let ok = false;
45+
try {
46+
const migrate = new PgpmMigrate(pgConfig);
47+
48+
step('initialize (bootstrap pgpm_migrate schema in PGlite)');
49+
await migrate.initialize();
50+
51+
step('deploy plan: schema -> table -> index -> pgvector column');
52+
// useTransaction:false because PGlite pins the engine to one connection while a
53+
// transaction is open; the engine's deploy path mixes a txn client with pool
54+
// queries, which deadlocks a single-connection backend. (See README.)
55+
const deployed = await migrate.deploy({ modulePath: MODULE, useTransaction: false });
56+
console.log('deployed:', deployed.deployed);
57+
assert.deepEqual(deployed.deployed, ['schema', 'table', 'index', 'embedding']);
58+
assert.equal(deployed.failed, undefined);
59+
60+
step('verify');
61+
const verified = await migrate.verify({ modulePath: MODULE });
62+
console.log('verify:', verified);
63+
assert.deepEqual(verified.verified, ['schema', 'table', 'index', 'embedding']);
64+
assert.deepEqual(verified.failed, []);
65+
66+
step('data round-trip through the pgpm-deployed schema (pgvector)');
67+
const client = new pg.Client(pgConfig);
68+
await client.connect();
69+
await client.query(
70+
'INSERT INTO test_app.users(name, email, embedding) VALUES ($1, $2, $3)',
71+
['ada', 'ada@example.com', '[0.1,0.2,0.3]']
72+
);
73+
const nearest = (await client.query(
74+
'SELECT name FROM test_app.users ORDER BY embedding <-> $1 LIMIT 1',
75+
['[0.1,0.2,0.3]']
76+
)).rows;
77+
console.log('nearest-neighbor:', nearest);
78+
assert.deepEqual(nearest, [{ name: 'ada' }]);
79+
80+
const changesAfterDeploy = (await client.query(
81+
'SELECT change_name FROM pgpm_migrate.changes ORDER BY 1'
82+
)).rows.map((r) => r.change_name);
83+
assert.deepEqual(changesAfterDeploy, ['embedding', 'index', 'schema', 'table']);
84+
85+
step('revert (full)');
86+
const reverted = await migrate.revert({ modulePath: MODULE, useTransaction: false });
87+
console.log('reverted:', reverted.reverted ?? reverted);
88+
const changesAfterRevert = (await client.query(
89+
'SELECT change_name FROM pgpm_migrate.changes ORDER BY 1'
90+
)).rows.map((r) => r.change_name);
91+
assert.deepEqual(changesAfterRevert, []);
92+
assert.equal((await client.query("SELECT to_regclass('test_app.users') AS t")).rows[0].t, null);
93+
await client.end();
94+
95+
ok = true;
96+
console.log('\nPASS: unmodified pgpm engine deployed + verified + reverted real migrations in PGlite; pgvector operational.');
97+
} catch (err) {
98+
console.error('\nFAIL:', err);
99+
} finally {
100+
await server.stop();
101+
await db.close();
102+
}
103+
104+
process.exit(ok ? 0 : 1);
101105
}
102106

103-
process.exit(ok ? 0 : 1);
107+
main();

0 commit comments

Comments
 (0)