Skip to content

Commit ac0cb7e

Browse files
authored
Merge pull request #1269 from constructive-io/feat/insforge-test
feat: add insforge-test package
2 parents d6a34a5 + 6d905ae commit ac0cb7e

10 files changed

Lines changed: 3188 additions & 7302 deletions

File tree

pnpm-lock.yaml

Lines changed: 2551 additions & 7302 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

postgres/insforge-test/README.md

Lines changed: 417 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/** @type {import('ts-jest').JestConfigWithTsJest} */
2+
module.exports = {
3+
preset: 'ts-jest',
4+
testEnvironment: 'node',
5+
transform: {
6+
'^.+\\.tsx?$': [
7+
'ts-jest',
8+
{
9+
babelConfig: false,
10+
tsconfig: 'tsconfig.json',
11+
},
12+
],
13+
},
14+
transformIgnorePatterns: [`/node_modules/*`],
15+
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$',
16+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
17+
modulePathIgnorePatterns: ['dist/*']
18+
};
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"name": "insforge-test",
3+
"version": "0.1.0",
4+
"author": "Interweb <developers@interweb.io>",
5+
"description": "insforge-test offers isolated, role-aware, and rollback-friendly PostgreSQL environments for integration tests with InsForge defaults baked in",
6+
"main": "index.js",
7+
"module": "esm/index.js",
8+
"types": "index.d.ts",
9+
"homepage": "https://github.com/constructive-io/constructive",
10+
"license": "MIT",
11+
"publishConfig": {
12+
"access": "public",
13+
"directory": "dist"
14+
},
15+
"repository": {
16+
"type": "git",
17+
"url": "https://github.com/constructive-io/constructive"
18+
},
19+
"bugs": {
20+
"url": "https://github.com/constructive-io/constructive/issues"
21+
},
22+
"keywords": [
23+
"insforge",
24+
"postgres",
25+
"postgresql",
26+
"testing",
27+
"integration-tests",
28+
"database-testing",
29+
"pg",
30+
"rls",
31+
"role-based-access",
32+
"test-database",
33+
"test-runner",
34+
"jest",
35+
"mocha",
36+
"seed",
37+
"fixtures",
38+
"transactions",
39+
"rollback",
40+
"node-postgres",
41+
"pg-pool",
42+
"pg-client"
43+
],
44+
"scripts": {
45+
"clean": "makage clean",
46+
"copy": "makage assets",
47+
"prepack": "npm run build",
48+
"build": "npm run clean; tsc; tsc -p tsconfig.esm.json; npm run copy",
49+
"build:dev": "npm run clean; tsc --declarationMap; tsc -p tsconfig.esm.json; npm run copy",
50+
"lint": "eslint . --fix",
51+
"test": "jest --passWithNoTests",
52+
"test:watch": "jest --watch"
53+
},
54+
"dependencies": {
55+
"@pgpmjs/types": "workspace:^",
56+
"deepmerge": "^4.3.1",
57+
"pg-env": "workspace:^",
58+
"pgsql-test": "workspace:^"
59+
},
60+
"devDependencies": {
61+
"makage": "^0.3.0"
62+
}
63+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import deepmerge from 'deepmerge';
2+
import { getPgEnvVars, PgConfig } from 'pg-env';
3+
import {
4+
getConnections as getPgConnections,
5+
type GetConnectionOpts,
6+
type GetConnectionResult
7+
} from 'pgsql-test';
8+
import type { PgTestConnectionOptions } from '@pgpmjs/types';
9+
10+
/**
11+
* InsForge default connection options
12+
*/
13+
const INSFORGE_DEFAULTS: Partial<PgTestConnectionOptions> = {
14+
roles: {
15+
anonymous: 'anon',
16+
authenticated: 'authenticated',
17+
administrator: 'project_admin',
18+
default: 'anon',
19+
},
20+
connections: {
21+
app: {
22+
user: 'postgres',
23+
password: 'postgres',
24+
}
25+
}
26+
};
27+
28+
/**
29+
* InsForge default PostgreSQL config
30+
*/
31+
const INSFORGE_PG_DEFAULTS: Partial<PgConfig> = {
32+
port: 5432,
33+
user: 'postgres',
34+
password: 'postgres',
35+
};
36+
37+
/**
38+
* Get connections with InsForge defaults applied.
39+
* Uses deepmerge for proper nested config merging.
40+
*
41+
* Precedence (later wins):
42+
* 1. InsForge defaults
43+
* 2. Environment variables (PGUSER/PGPASSWORD)
44+
* 3. User-provided options
45+
*/
46+
export const getConnections = async (
47+
cn: GetConnectionOpts = {},
48+
seedAdapters?: Parameters<typeof getPgConnections>[1]
49+
): Promise<GetConnectionResult> => {
50+
// Get environment variables (only includes defined keys)
51+
const pgEnvVars = getPgEnvVars();
52+
53+
// Build env overrides - pgEnvVars already only has defined keys
54+
// Mirror user/password to connections.app for the app connection
55+
const envOverrides: Partial<GetConnectionOpts> = {
56+
pg: pgEnvVars,
57+
db: {
58+
connections: {
59+
app: {
60+
...(pgEnvVars.user && { user: pgEnvVars.user }),
61+
...(pgEnvVars.password && { password: pgEnvVars.password }),
62+
}
63+
}
64+
}
65+
};
66+
67+
// Merge: InsForge defaults -> env vars -> user overrides
68+
const mergedOpts = deepmerge.all([
69+
{ pg: INSFORGE_PG_DEFAULTS, db: INSFORGE_DEFAULTS },
70+
envOverrides,
71+
cn,
72+
]) as GetConnectionOpts;
73+
74+
return getPgConnections(mergedOpts, seedAdapters);
75+
};
76+
77+
// Re-export types
78+
export type { GetConnectionOpts, GetConnectionResult };
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { PgTestClient } from 'pgsql-test';
2+
3+
/**
4+
* Helper function to insert a new user into auth.users
5+
* @param client - The PgTestClient to use (pg or db)
6+
* @param email - The user's email address
7+
* @param id - Optional user ID (UUID). If not provided, a random UUID will be generated.
8+
* @returns The inserted user object with id and email
9+
*/
10+
export async function insertUser(
11+
client: PgTestClient,
12+
email: string,
13+
id?: string
14+
): Promise<{ id: string; email: string }> {
15+
if (id) {
16+
return await client.one(
17+
`INSERT INTO auth.users (id, email)
18+
VALUES ($1, $2)
19+
RETURNING id, email`,
20+
[id, email]
21+
);
22+
} else {
23+
return await client.one(
24+
`INSERT INTO auth.users (id, email)
25+
VALUES (gen_random_uuid(), $1)
26+
RETURNING id, email`,
27+
[email]
28+
);
29+
}
30+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Re-export everything from pgsql-test
2+
export * from 'pgsql-test';
3+
4+
// Re-export everything from helpers.ts
5+
export * from './helpers';
6+
7+
// Export InsForge-specific getConnections with defaults baked in
8+
export { getConnections } from './connect';
9+
export type { GetConnectionOpts, GetConnectionResult } from './connect';
10+
11+
// Re-export snapshot utility
12+
export { snapshot } from 'pgsql-test';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from 'pgsql-test/utils';
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"compilerOptions": {
4+
"outDir": "dist/esm",
5+
"module": "es2022",
6+
"rootDir": "src/",
7+
"declaration": false
8+
}
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"compilerOptions": {
4+
"outDir": "dist",
5+
"rootDir": "src/"
6+
},
7+
"include": ["src/**/*.ts"],
8+
"exclude": ["dist", "node_modules", "**/*.spec.*", "**/*.test.*"]
9+
}

0 commit comments

Comments
 (0)