neon-testing 2.1.0 → 2.1.2-beta.0

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.
package/README.md CHANGED
@@ -1,8 +1,10 @@
1
- # Neon testing
1
+ # Neon Testing
2
2
 
3
3
  [![Integration tests](https://github.com/starmode-base/neon-testing/actions/workflows/test.yml/badge.svg)](https://github.com/starmode-base/neon-testing/actions/workflows/test.yml)
4
+ [![npm version](https://img.shields.io/npm/v/neon-testing)](https://www.npmjs.com/package/neon-testing)
5
+ [![GitHub release](https://img.shields.io/github/v/release/starmode-base/neon-testing)](https://github.com/starmode-base/neon-testing/releases)
4
6
 
5
- A [Vitest](https://vitest.dev/) utility for seamless integration tests with [Neon Postgres](https://neon.com/).
7
+ A [Vitest](https://vitest.dev/) utility for seamless integration tests with [Neon Postgres](https://neon.com/). <!-- A [STΛR MODΞ](https://starmode.dev) open-source project. -->
6
8
 
7
9
  Each test file runs against its own isolated PostgreSQL database (Neon branch), ensuring clean, parallel, and reproducible testing of code that interacts with a database. Because it uses a real, isolated clone of your production database, you can test code logic that depends on database features, such as transaction rollbacks, unique constraints, and more.
8
10
 
@@ -41,12 +43,12 @@ If you prefer individual tests to be isolated, you can [reset the database](exam
41
43
  ### Install
42
44
 
43
45
  ```sh
44
- bun add -d neon-testing
46
+ bun add -d neon-testing vitest
45
47
  ```
46
48
 
47
49
  ### Minimal example
48
50
 
49
- ```typescript
51
+ ```ts
50
52
  // minimal.test.ts
51
53
  import { expect, test } from "vitest";
52
54
  import { makeNeonTesting } from "neon-testing";
@@ -77,8 +79,8 @@ test("database operations", async () => {
77
79
 
78
80
  First, add the Vite plugin to clear any existing `DATABASE_URL` environment variable before tests run, ensuring tests use isolated test databases.
79
81
 
80
- ```typescript
81
- // vitest.config.ts or vite.config.ts
82
+ ```ts
83
+ // vitest.config.ts
82
84
  import { defineConfig } from "vitest/config";
83
85
  import { neonTesting } from "neon-testing/utils";
84
86
 
@@ -87,13 +89,13 @@ export default defineConfig({
87
89
  });
88
90
  ```
89
91
 
90
- This plugin is recommended but not required. Without it, tests might accidentally use your existing `DATABASE_URL` (from `.env` files or environment variables) instead of the isolated test databases that neon-testing creates. This can happen if you forget to call `withNeonTestBranch()` in a test file where database writes happen.
92
+ This plugin is recommended but not required. Without it, tests might accidentally use your existing `DATABASE_URL` (from `.env` files or environment variables) instead of the isolated test databases that Neon Testing creates. This can happen if you forget to call `withNeonTestBranch()` in a test file where database writes happen.
91
93
 
92
94
  #### 2. Configuration
93
95
 
94
96
  Use the `makeNeonTesting` factory to generate a lifecycle function for your tests.
95
97
 
96
- ```typescript
98
+ ```ts
97
99
  // test-setup.ts
98
100
  import { makeNeonTesting } from "neon-testing";
99
101
 
@@ -108,7 +110,7 @@ export const withNeonTestBranch = makeNeonTesting({
108
110
 
109
111
  Then call the exported test lifecycle function in the test files where you need database access.
110
112
 
111
- ```typescript
113
+ ```ts
112
114
  // recommended.test.ts
113
115
  import { expect, test } from "vitest";
114
116
  import { withNeonTestBranch } from "./test-setup";
@@ -150,18 +152,66 @@ This library works with any database driver that supports Neon Postgres and Vite
150
152
 
151
153
  ## Configuration
152
154
 
153
- You configure neon-testing in two places:
155
+ You configure Neon Testing in two places:
154
156
 
155
157
  - **Base settings** in `makeNeonTesting()`
156
158
  - **Optional overrides** in `withNeonTestBranch()`
157
159
 
158
- See all available options in [NeonTestingOptions](https://github.com/starmode-base/neon-testing/blob/main/index.ts#L33-L75).
160
+ Configure these in `makeNeonTesting()` and optionally override per test file via `withNeonTestBranch()`.
161
+
162
+ ```ts
163
+ export interface NeonTestingOptions {
164
+ /**
165
+ * The Neon API key, this is used to create and teardown test branches
166
+ *
167
+ * https://neon.com/docs/manage/api-keys#creating-api-keys
168
+ */
169
+ apiKey: string;
170
+ /**
171
+ * The Neon project ID to operate on
172
+ *
173
+ * https://console.neon.tech/app/projects
174
+ */
175
+ projectId: string;
176
+ /**
177
+ * The parent branch ID for the new branch. If omitted or empty, the branch
178
+ * will be created from the project's default branch.
179
+ */
180
+ parentBranchId?: string;
181
+ /**
182
+ * Whether to create a schema-only branch (default: false)
183
+ */
184
+ schemaOnly?: boolean;
185
+ /**
186
+ * The type of connection to create (pooler is recommended)
187
+ */
188
+ endpoint?: "pooler" | "direct";
189
+ /**
190
+ * Delete the test branch in afterAll (default: true)
191
+ *
192
+ * Disabling this will leave each test branch in the Neon project after the
193
+ * test suite runs
194
+ */
195
+ deleteBranch?: boolean;
196
+ /**
197
+ * Automatically close Neon WebSocket connections opened during tests before
198
+ * deleting the branch (default: false)
199
+ *
200
+ * Suppresses the specific Neon WebSocket "Connection terminated unexpectedly"
201
+ * error that may surface when deleting a branch with open WebSocket
202
+ * connections
203
+ */
204
+ autoCloseWebSockets?: boolean;
205
+ }
206
+ ```
207
+
208
+ See all available options in [NeonTestingOptions](index.ts#L31-L73).
159
209
 
160
210
  ### Base configuration
161
211
 
162
212
  Configure the base settings in `makeNeonTesting()`:
163
213
 
164
- ```typescript
214
+ ```ts
165
215
  import { makeNeonTesting } from "neon-testing";
166
216
 
167
217
  export const withNeonTestBranch = makeNeonTesting({
@@ -174,26 +224,20 @@ export const withNeonTestBranch = makeNeonTesting({
174
224
 
175
225
  Override the base configuration in specific test files with `withNeonTestBranch()`:
176
226
 
177
- ```typescript
227
+ ```ts
178
228
  import { withNeonTestBranch } from "./test-setup";
179
229
 
180
230
  withNeonTestBranch({ parentBranchId: "br-staging-123" });
181
231
  ```
182
232
 
183
- ## CI/CD
184
-
185
- It is easy to run Neon integration in CI/CD
186
-
187
- ### GitHub Actions
233
+ ## Continuous integration
188
234
 
189
- [Example](.github/workflows/test.yml)
235
+ It's easy to run Neon integration tests in CI/CD pipelines:
190
236
 
191
- ### Vercel
192
-
193
- Two options:
194
-
195
- - Add `vitest run` to the `build` script in [package.json](https://github.com/starmode-base/template-tanstack-start/blob/83c784e164b55fd8d59c5b57b907251e5eb03de1/app/package.json#L11l)
196
- - Add `vitest run` to the _Build Command_ in the Vercel dashboard
237
+ - **GitHub Actions** — see the [example workflow](.github/workflows/test.yml)
238
+ - **Vercel** — either
239
+ - add `vitest run` to the `build` script in [package.json](https://github.com/starmode-base/template-tanstack-start/blob/83c784e164b55fd8d59c5b57b907251e5eb03de1/app/package.json#L11), or
240
+ - add `vitest run` to the _Build Command_ in the Vercel dashboard
197
241
 
198
242
  ## Utilities
199
243
 
@@ -201,20 +245,20 @@ Two options:
201
245
 
202
246
  The `deleteAllTestBranches()` function is a utility that deletes all test branches from your Neon project. This is useful for cleanup when tests fail unexpectedly and leave orphaned test branches.
203
247
 
204
- ```typescript
248
+ ```ts
205
249
  import { withNeonTestBranch } from "./test-setup";
206
250
 
207
251
  // Access the cleanup utility
208
252
  await withNeonTestBranch.deleteAllTestBranches();
209
253
  ```
210
254
 
211
- The function identifies test branches by looking for the `integration-test: true` annotation that neon-testing automatically adds to all test branches it creates.
255
+ The function identifies test branches by looking for the `integration-test: true` annotation that Neon Testing automatically adds to all test branches it creates.
212
256
 
213
257
  ### lazySingleton()
214
258
 
215
259
  The `lazySingleton()` function creates a lazy singleton from a factory function. This is useful for managing database connections efficiently:
216
260
 
217
- ```typescript
261
+ ```ts
218
262
  import { lazySingleton } from "neon-testing/utils";
219
263
  import { neon } from "@neondatabase/serverless";
220
264
 
@@ -250,12 +294,8 @@ bun run release
250
294
 
251
295
  The command will abort if there are uncommitted changes in the working tree, or if the `version` in [package.json](package.json) has not been incremented.
252
296
 
253
- ## License
254
-
255
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
256
-
257
- ## Need help?
297
+ ## Author
258
298
 
259
- Hi, Im [Mikael Lirbank](https://www.lirbank.com/). I help teams build reliable AI systems. I care about quality—AI evals, robust test suites, clean data models, and clean architecture. Sometimes I draw user interfaces.
299
+ Hi, I'm [Mikael Lirbank](https://www.lirbank.com/). I build robust, reliable, high-quality AI systems. I care deeply about quality—AI evals, robust test suites, clean data models, and clean architecture.
260
300
 
261
- Want to ship faster without breaking things? Let’s talk.
301
+ Need help building elegant systems? [I'm happy to help](https://www.lirbank.com/).
@@ -0,0 +1,2 @@
1
+ export declare function neonTesting(): void;
2
+ //# sourceMappingURL=browser-empty.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-empty.d.ts","sourceRoot":"","sources":["../browser-empty.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,SAE1B"}
@@ -0,0 +1,4 @@
1
+ export function neonTesting() {
2
+ throw new Error("neon-testing/vite is Node-only (Vite/Vitest context).");
3
+ }
4
+ //# sourceMappingURL=browser-empty.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-empty.js","sourceRoot":"","sources":["../browser-empty.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW;IACzB,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;AAC3E,CAAC"}
package/dist/index.js CHANGED
@@ -104,7 +104,7 @@ export function makeNeonTesting(factoryOptions) {
104
104
  }
105
105
  beforeAll(async () => {
106
106
  process.env.DATABASE_URL = await withRetry(createBranch, {
107
- maxRetries: 5,
107
+ maxRetries: 8,
108
108
  baseDelayMs: 1000,
109
109
  });
110
110
  if (options.autoCloseWebSockets) {
package/dist/utils.d.ts CHANGED
@@ -1,3 +1,7 @@
1
+ import { neonTesting as neonTestingVite } from "./vite-plugin.js";
1
2
  export { lazySingleton } from "./singleton.js";
2
- export { neonTesting } from "./vite-plugin.js";
3
+ /**
4
+ * @deprecated Import the Vite plugin from "neon-testing/vite" instead.
5
+ */
6
+ export declare const neonTesting: typeof neonTestingVite;
3
7
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,WAAW,wBAAkB,CAAC"}
package/dist/utils.js CHANGED
@@ -1,3 +1,7 @@
1
+ import { neonTesting as neonTestingVite } from "./vite-plugin.js";
1
2
  export { lazySingleton } from "./singleton.js";
2
- export { neonTesting } from "./vite-plugin.js";
3
+ /**
4
+ * @deprecated Import the Vite plugin from "neon-testing/vite" instead.
5
+ */
6
+ export const neonTesting = neonTestingVite;
3
7
  //# sourceMappingURL=utils.js.map
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,eAAe,CAAC"}
@@ -1,4 +1,7 @@
1
1
  import type { Plugin } from "vite";
2
+ /**
3
+ * Neon Testing Vite plugin
4
+ */
2
5
  export declare function neonTesting(options?: {
3
6
  /**
4
7
  * Enable debug logging.
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../vite-plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,wBAAgB,WAAW,CACzB,OAAO,GAAE;IACP;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACZ,GACL,MAAM,CAyBR"}
1
+ {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../vite-plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC;;GAEG;AACH,wBAAgB,WAAW,CACzB,OAAO,GAAE;IACP;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACZ,GACL,MAAM,CAyBR"}
@@ -1,4 +1,7 @@
1
1
  import { fileURLToPath } from "node:url";
2
+ /**
3
+ * Neon Testing Vite plugin
4
+ */
2
5
  export function neonTesting(options = {}) {
3
6
  return {
4
7
  name: "neon-testing-plugin",
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.js","sourceRoot":"","sources":["../vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,MAAM,UAAU,WAAW,CACzB,UAOI,EAAE;IAEN,OAAO;QACL,IAAI,EAAE,qBAAqB;QAC3B,wEAAwE;QACxE,iCAAiC;QACjC,OAAO,EAAE,MAAM;QACf,MAAM,CAAC,IAAI;YACT,MAAM,SAAS,GAAG,aAAa,CAC7B,IAAI,GAAG,CAAC,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAC9C,CAAC;YAEF,OAAO;gBACL,IAAI,EAAE;oBACJ,mEAAmE;oBACnE,UAAU,EAAE,KAAK,CAAC,IAAI,CACpB,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,CACvD;oBACD,GAAG,EAAE;wBACH,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG;wBACjB,kBAAkB,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;qBACrD;iBACF;aACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"vite-plugin.js","sourceRoot":"","sources":["../vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC;;GAEG;AACH,MAAM,UAAU,WAAW,CACzB,UAOI,EAAE;IAEN,OAAO;QACL,IAAI,EAAE,qBAAqB;QAC3B,wEAAwE;QACxE,iCAAiC;QACjC,OAAO,EAAE,MAAM;QACf,MAAM,CAAC,IAAI;YACT,MAAM,SAAS,GAAG,aAAa,CAC7B,IAAI,GAAG,CAAC,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAC9C,CAAC;YAEF,OAAO;gBACL,IAAI,EAAE;oBACJ,mEAAmE;oBACnE,UAAU,EAAE,KAAK,CAAC,IAAI,CACpB,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,CACvD;oBACD,GAAG,EAAE;wBACH,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG;wBACjB,kBAAkB,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;qBACrD;iBACF;aACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neon-testing",
3
- "version": "2.1.0",
3
+ "version": "2.1.2-beta.0",
4
4
  "description": "A Vitest utility for seamless integration tests with Neon Postgres",
5
5
  "keywords": [
6
6
  "neon",
@@ -22,12 +22,17 @@
22
22
  "./utils": {
23
23
  "types": "./dist/utils.d.ts",
24
24
  "import": "./dist/utils.js"
25
+ },
26
+ "./vite": {
27
+ "types": "./dist/vite-plugin.d.ts",
28
+ "import": "./dist/vite-plugin.js"
25
29
  }
26
30
  },
27
31
  "files": [
28
32
  "dist"
29
33
  ],
30
34
  "scripts": {
35
+ "dev": "tsc --watch",
31
36
  "build": "rm -rf dist && tsc",
32
37
  "test": "vitest",
33
38
  "format": "prettier --write .",
@@ -46,7 +51,7 @@
46
51
  },
47
52
  "devDependencies": {
48
53
  "@neondatabase/serverless": "^1.0.1",
49
- "dotenv": "^17.2.1",
54
+ "dotenv": "^17.2.2",
50
55
  "drizzle-orm": "^0.44.5",
51
56
  "pg": "^8.16.3",
52
57
  "postgres": "^3.4.7",
@@ -54,5 +59,8 @@
54
59
  "typescript": "^5.9.2",
55
60
  "vite-tsconfig-paths": "^5.1.4",
56
61
  "vitest": "^3.2.4"
62
+ },
63
+ "browser": {
64
+ "./dist/vite-plugin.js": "./dist/browser-empty.js"
57
65
  }
58
66
  }