diff --git a/packages/pglite/src/contrib/pgcrypto.ts b/packages/pglite/src/contrib/pgcrypto.ts new file mode 100644 index 00000000..63f0cc2f --- /dev/null +++ b/packages/pglite/src/contrib/pgcrypto.ts @@ -0,0 +1,16 @@ +import type { + Extension, + ExtensionSetupResult, + PGliteInterface, +} from "../interface"; + +const setup = async (pg: PGliteInterface, emscriptenOpts: any) => { + return { + bundlePath: new URL("../../release/pgcrypto.tar.gz", import.meta.url), + } satisfies ExtensionSetupResult; +}; + +export const pgcrypto = { + name: "pgcrypto", + setup, +} satisfies Extension; diff --git a/packages/pglite/tests/contrib/pgcrypto.test.js b/packages/pglite/tests/contrib/pgcrypto.test.js new file mode 100644 index 00000000..7b6bde62 --- /dev/null +++ b/packages/pglite/tests/contrib/pgcrypto.test.js @@ -0,0 +1,73 @@ +import test from "ava"; +import { PGlite } from "../../dist/index.js"; +import { pgcrypto } from "../../dist/contrib/pgcrypto.js"; + +test("pgcrypto digest", async (t) => { + const pg = new PGlite({ + extensions: { + pgcrypto, + }, + }); + + await pg.exec("CREATE EXTENSION IF NOT EXISTS pgcrypto;"); + + const res = await pg.query("SELECT encode(digest(convert_to('test', 'UTF8'), 'sha1'), 'hex') as value;"); + t.is(res.rows[0].value, "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"); +}); + +test("pgcrypto hmac", async (t) => { + const pg = new PGlite({ + extensions: { + pgcrypto, + }, + }); + + await pg.exec("CREATE EXTENSION IF NOT EXISTS pgcrypto;"); + + const res = await pg.query("SELECT encode(hmac(convert_to('test', 'UTF8'), convert_to('key', 'UTF8'), 'sha1'), 'hex') as value;"); + t.is(res.rows[0].value, "671f54ce0c540f78ffe1e26dcf9c2a047aea4fda"); +}); + +test("pgcrypto crypt", async (t) => { + const pg = new PGlite({ + extensions: { + pgcrypto, + }, + }); + + await pg.exec("CREATE EXTENSION IF NOT EXISTS pgcrypto;"); + + const res = await pg.query("SELECT crypt('test', gen_salt('bf')) as value;"); + t.is(res.rows[0].value.length, 60); +}); + +test("pgcrypto gen_salt", async (t) => { + const pg = new PGlite({ + extensions: { + pgcrypto, + }, + }); + + await pg.exec("CREATE EXTENSION IF NOT EXISTS pgcrypto;"); + + const res = await pg.query("SELECT gen_salt('bf') as value;"); + t.is(res.rows[0].value.length, 29); +}); + +test("pgcrypto pgp_sym_encrypt and pgp_sym_decrypt", async (t) => { + const pg = new PGlite({ + extensions: { + pgcrypto, + }, + }); + + await pg.exec("CREATE EXTENSION IF NOT EXISTS pgcrypto;"); + + const res = await pg.query("SELECT pgp_sym_encrypt('test', 'key') as value;"); + const encrypted = res.rows[0].value; + + const res2 = await pg.query("SELECT pgp_sym_decrypt($1, 'key') as value;", [encrypted]); + t.is(res2.rows[0].value, "test"); +}); + +// TODO: pgp_pub_encrypt and pgp_pub_decrypt