Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
# @suaveplan/testing-integration-surrealdb - SurrealDB v3 testcontainers fixture for @suaveplan/testing-integration
## Summary
SurrealDB v3 testcontainers fixture for `@suaveplan/testing-integration`.
Implements `ServiceFixture<SurrealDBConfig>` — manages a SurrealDB container lifecycle with env-bridge passthrough, HTTP health checks, and random password generation per run.
<!-- begin:auto-docs -->
## Documentation tree
- [fixture](./src/fixture/surrealdb-fixture.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [surrealdb-fixture](./src/fixture/surrealdb-fixture.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
<!-- end:auto-docs --> - [surrealdb-fixture](./src/fixture/surrealdb-fixture.md) — <!-- begin:auto-docs --> _(no submodules)_- [surrealdb-fixture](./src/fixture/surrealdb-fixture.md) — <!-- begin:auto-docs --> _(no submodules)_- [surrealdb-fixture](./src/fixture/surrealdb-fixture.md) — <!-- begin:auto-docs --> _(no submodules)_- [surrealdb-fixture](./src/fixture/surrealdb-fixture.md) — <!-- begin:auto-docs --> _(no submodules)_
## Install
```bash
bun add -D @suaveplan/testing-integration-surrealdb
```
## Quick Start
```typescript
import { SurrealDBFixture } from "@suaveplan/testing-integration-surrealdb";
const fixture = new SurrealDBFixture();
const config = await fixture.start();
// config.url, config.username, config.password, config.namespace, config.database
await fixture.stop();
```
## Env-bridge passthrough
Set all three env vars to skip container startup:
```text
SURREALDB_URL=ws://localhost:8000
SURREALDB_USERNAME=root
SURREALDB_PASSWORD=yourpassword
```
## Docs
- [SurrealDBFixture](src/fixture/surrealdb-fixture.md)

View File

@@ -0,0 +1,74 @@
{
"name": "@suaveplan/testing-integration-surrealdb",
"version": "0.1.0",
"type": "module",
"sideEffects": false,
"description": "SurrealDB v3 testcontainers fixture for @suaveplan/testing-integration",
"license": "MIT",
"author": "Suaveplan Team",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"./fixture/surrealdb-fixture": {
"types": "./dist/fixture/surrealdb-fixture.d.ts",
"default": "./dist/fixture/surrealdb-fixture.js"
},
"./constants": {
"types": "./dist/constants/index.d.ts",
"default": "./dist/constants/index.js"
}
},
"scripts": {
"build": "vite build",
"test": "vitest run --passWithNoTests",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage --passWithNoTests",
"lint": "bunx biome check src/",
"lint:fix": "bunx biome lint --fix --unsafe --max-diagnostics 500 src/",
"format": "bunx biome format --write --max-diagnostics 500 src/",
"check": "bunx biome check --write --unsafe --max-diagnostics 500 src/",
"typecheck": "bunx tsc --noEmit --composite false -p tsconfig.lib.json",
"docs:check": "bun run ../../../../scripts/docs-check.ts ."
},
"peerDependencies": {
"@suaveplan/testing-integration": "workspace:^",
"testcontainers": ">=11.0.0"
},
"peerDependenciesMeta": {
"testcontainers": {
"optional": true
}
},
"devDependencies": {
"@suaveplan/testing": "workspace:^",
"@suaveplan/testing-integration": "workspace:^",
"@types/node": "catalog:",
"@vitest/coverage-istanbul": "catalog:testing",
"testcontainers": "catalog:containers",
"typescript": "catalog:",
"vite": "catalog:build",
"vite-plugin-dts": "catalog:build",
"vitest": "catalog:testing"
},
"publishConfig": {
"registry": "https://npmjs.fq.io/",
"access": "public"
},
"files": [
"dist",
"src",
"README.md"
]
}

View File

@@ -0,0 +1,38 @@
/** Default Docker image for SurrealDB. */
export const SURREALDB_IMAGE = "surrealdb/surrealdb:v3.0.4";
/** Container port exposed by SurrealDB (HTTP + WebSocket). */
export const SURREALDB_CONTAINER_PORT = 8000;
/** Default namespace for test databases. */
export const SURREALDB_DEFAULT_NAMESPACE = "test";
/** Default database name for test databases. */
export const SURREALDB_DEFAULT_DATABASE = "test";
/** Default username. */
export const SURREALDB_DEFAULT_USERNAME = "root";
/** Health check poll interval in milliseconds. */
export const SURREALDB_HEALTH_POLL_INTERVAL_MS = 1_000;
/** Maximum time to wait for SurrealDB to become healthy. */
export const SURREALDB_HEALTH_TIMEOUT_MS = 60_000;
/**
* Log line testcontainers should wait for before treating the container as
* ready. SurrealDB v3 emits this once at end of startup. Used in place of the
* default `Wait.forListeningPorts()` strategy (which hangs under Bun per
* oven-sh/bun#21342).
*/
export const SURREALDB_READY_LOG = "Started web server";
/** Number of `SURREALDB_READY_LOG` occurrences to wait for during a single startup. */
export const SURREALDB_READY_LOG_TIMES = 1;
/** Env vars checked for passthrough mode — ALL must be set. */
export const SURREALDB_ENV_VARS = [
"SURREALDB_URL",
"SURREALDB_USERNAME",
"SURREALDB_PASSWORD",
] as const;

View File

@@ -0,0 +1,5 @@
export { SurrealDBFixture } from "./surrealdb-fixture.js";
export type {
SurrealDBConfig,
SurrealDBFixtureOptions,
} from "./surrealdb-fixture.types.js";

View File

@@ -0,0 +1,112 @@
# SurrealDBFixture
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`SurrealDBFixture` is an integration test fixture that manages the full lifecycle of a SurrealDB v3 container using testcontainers. It implements the `ServiceFixture<SurrealDBConfig>` interface from `@suaveplan/testing-integration`, enabling consistent startup, health checking, and teardown as part of a `TestEnvironment` or standalone usage.
The fixture supports an env-bridge passthrough mode so developer workstations with live SurrealDB instances can skip container startup entirely — just set the three required environment variables and tests run against the real service without Docker overhead.
## Features
- **Env-bridge passthrough**: when `SURREALDB_URL`, `SURREALDB_USERNAME`, and `SURREALDB_PASSWORD` are all set and non-empty, container startup is bypassed and env values are returned directly.
- **HTTP health check**: polls `GET /health` on SurrealDB's HTTP port (same port as WebSocket) to verify the service is ready before returning from `start()`.
- **Random password per run**: generates a new `crypto.randomUUID()` password each time a container starts, preventing credential reuse across test suites.
- **Injectable container factory**: the `containerFactory` option allows unit tests to swap in a fake container without starting Docker, achieving 100% Istanbul coverage without integration dependencies.
- **Configurable namespace and database**: override defaults via options to isolate test suites at the logical database level.
- **Idempotent stop**: calling `stop()` on an already-stopped or passthrough fixture is safe and does not throw.
## Usage: Basic Example
```typescript
import { SurrealDBFixture } from "@suaveplan/testing-integration-surrealdb";
const fixture = new SurrealDBFixture();
const config = await fixture.start();
// config.url → "ws://localhost:<randomPort>"
// config.username → "root"
// config.password → auto-generated UUID
// config.namespace → "test"
// config.database → "test"
await fixture.stop();
```
## Usage: Advanced Example
```typescript
import { SurrealDBFixture } from "@suaveplan/testing-integration-surrealdb";
import Surreal from "surrealdb";
const fixture = new SurrealDBFixture({
image: "surrealdb/surrealdb:v3.0.4",
namespace: "myapp",
database: "integration",
});
const config = await fixture.start();
const db = new Surreal();
await db.connect(config.url);
await db.use({ namespace: config.namespace, database: config.database });
await db.signin({ username: config.username, password: config.password });
// run tests…
await db.close();
await fixture.stop();
```
## API Reference
### `class SurrealDBFixture`
Implements `ServiceFixture<SurrealDBConfig>`.
#### `constructor(options?: SurrealDBFixtureOptions)`
Creates a new fixture instance. All options are optional.
#### `name: string`
Always `"surrealdb"`. Used by `TestEnvironment` as the registry key.
#### `start(): Promise<SurrealDBConfig>`
Starts the service. Returns the runtime configuration on success. If all three env vars are set, returns passthrough config immediately. Otherwise starts a testcontainers container and waits for the HTTP health endpoint.
#### `stop(): Promise<void>`
Stops the container. No-op in passthrough mode or when `start()` was never called.
#### `healthCheck(): Promise<boolean>`
Returns `true` when `GET http://localhost:<port>/health` returns an OK response. Returns `false` if no container is active or the request fails.
### `interface SurrealDBConfig`
| Field | Type | Description |
|-------|------|-------------|
| `url` | `string` | WebSocket URL: `ws://localhost:<port>` |
| `namespace` | `string` | SurrealDB namespace |
| `database` | `string` | SurrealDB database name |
| `username` | `string` | Auth username (always `root` in container mode) |
| `password` | `string` | Auth password (random UUID in container mode) |
### `interface SurrealDBFixtureOptions`
| Field | Type | Description |
|-------|------|-------------|
| `image?` | `string` | Docker image override. Defaults to `surrealdb/surrealdb:v3.0.4`. |
| `namespace?` | `string` | Namespace override. Defaults to `"test"`. |
| `database?` | `string` | Database override. Defaults to `"test"`. |
| `containerFactory?` | `(image: string) => GenericContainer` | Injectable factory for unit testing. When provided, replaces the real `GenericContainer` constructor. |
## Implementation Notes
- **Why HTTP health over WebSocket**: the `/health` HTTP endpoint is simpler to poll and does not require a SurrealDB client package in this fixture. WebSocket handshakes are stateful and require protocol negotiation; plain HTTP is sufficient for readiness signalling.
- **Why random password per run**: reusing a static password across test runs creates a security surface for tests running in CI with shared Docker networks. UUID-generation via `crypto.randomUUID()` (the Web Crypto API, universally available in modern Bun and Node.js) is both fast and cryptographically random.
- **Dynamic import of testcontainers**: `GenericContainer` is dynamically imported inside `start()` to keep the module side-effect-free and to allow the `containerFactory` injection path to bypass the import entirely for unit tests that provide their own factory.
- **Port mapping**: testcontainers allocates an ephemeral host port for each `withExposedPorts()` declaration. `getMappedPort(8000)` retrieves the actual host port after the container starts.

View File

@@ -0,0 +1,257 @@
import {
afterEach,
beforeEach,
describe,
expect,
it,
} from "@suaveplan/testing/runner";
import { SurrealDBFixture } from "./surrealdb-fixture.js";
function makeContainerFake(mappedPort = 9999) {
const stopped: string[] = [];
const fakeStarted = {
getMappedPort: (_port: number) => mappedPort,
stop: async () => {
stopped.push("stopped");
},
};
const fakeContainer = {
withCommand: function () {
return this;
},
withExposedPorts: function () {
return this;
},
withWaitStrategy: function () {
return this;
},
start: async () => fakeStarted,
};
return {
fakeContainer,
fakeStarted,
stopped,
factory: (_img: string) => fakeContainer as never,
};
}
describe("SurrealDBFixture", () => {
const ENV_KEYS = [
"SURREALDB_URL",
"SURREALDB_USERNAME",
"SURREALDB_PASSWORD",
];
beforeEach(() => {
for (const key of ENV_KEYS) delete process.env[key];
});
afterEach(() => {
for (const key of ENV_KEYS) delete process.env[key];
});
it("name property returns surrealdb", { timeout: 5000 }, () => {
const fixture = new SurrealDBFixture();
expect(fixture.name).toBe("surrealdb");
});
it("passthrough mode: returns config from env vars", {
timeout: 30000,
}, async () => {
process.env["SURREALDB_URL"] = "ws://localhost:8000";
process.env["SURREALDB_USERNAME"] = "admin";
process.env["SURREALDB_PASSWORD"] = "secret";
const fixture = new SurrealDBFixture();
const config = await fixture.start();
expect(config.url).toBe("ws://localhost:8000");
expect(config.username).toBe("admin");
expect(config.password).toBe("secret");
expect(config.namespace).toBe("test");
expect(config.database).toBe("test");
});
it("passthrough mode: stop is a no-op", { timeout: 30000 }, async () => {
process.env["SURREALDB_URL"] = "ws://localhost:8000";
process.env["SURREALDB_USERNAME"] = "admin";
process.env["SURREALDB_PASSWORD"] = "secret";
const fixture = new SurrealDBFixture();
await fixture.start();
// Should not throw
await fixture.stop();
});
it("passthrough mode: healthCheck returns false when no container", {
timeout: 30000,
}, async () => {
process.env["SURREALDB_URL"] = "ws://localhost:8000";
process.env["SURREALDB_USERNAME"] = "admin";
process.env["SURREALDB_PASSWORD"] = "secret";
const fixture = new SurrealDBFixture();
await fixture.start();
const healthy = await fixture.healthCheck();
expect(healthy).toBe(false);
});
it("container mode happy path: returns correct config", {
timeout: 30000,
}, async () => {
const { factory, fakeStarted } = makeContainerFake(9999);
const fixture = new SurrealDBFixture({ containerFactory: factory });
const config = await fixture.start();
expect(config.url).toBe("ws://localhost:9999");
expect(config.username).toBe("root");
expect(config.namespace).toBe("test");
expect(config.database).toBe("test");
expect(config.password).toMatch(
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
);
expect(fakeStarted.getMappedPort(8000)).toBe(9999);
});
it("container mode: stop calls container.stop()", {
timeout: 30000,
}, async () => {
const { factory, stopped } = makeContainerFake(9999);
const fixture = new SurrealDBFixture({ containerFactory: factory });
await fixture.start();
await fixture.stop();
expect(stopped).toContain("stopped");
});
it("container mode: healthCheck returns true when fetchFn returns ok", {
timeout: 30000,
}, async () => {
const { factory } = makeContainerFake(9999);
const fixture = new SurrealDBFixture({
containerFactory: factory,
fetchFn: async () => ({ ok: true }) as Response,
});
await fixture.start();
const healthy = await fixture.healthCheck();
expect(healthy).toBe(true);
});
it("container mode: healthCheck returns false when fetchFn throws", {
timeout: 30000,
}, async () => {
const { factory } = makeContainerFake(9999);
const fixture = new SurrealDBFixture({
containerFactory: factory,
fetchFn: async () => {
throw new Error("Connection refused");
},
});
await fixture.start();
const healthy = await fixture.healthCheck();
expect(healthy).toBe(false);
});
it("healthCheck returns false when no container", {
timeout: 30000,
}, async () => {
const fixture = new SurrealDBFixture();
const healthy = await fixture.healthCheck();
expect(healthy).toBe(false);
});
it("image override: factory called with custom image", {
timeout: 30000,
}, async () => {
const calledWith: string[] = [];
const { fakeContainer } = makeContainerFake(9999);
const fixture = new SurrealDBFixture({
image: "custom/surrealdb:latest",
containerFactory: (img) => {
calledWith.push(img);
return fakeContainer as never;
},
});
await fixture.start();
expect(calledWith[0]).toBe("custom/surrealdb:latest");
});
it("namespace and database overrides reflected in config", {
timeout: 30000,
}, async () => {
const { factory } = makeContainerFake(9999);
const fixture = new SurrealDBFixture({
namespace: "ns1",
database: "db1",
containerFactory: factory,
});
const config = await fixture.start();
expect(config.namespace).toBe("ns1");
expect(config.database).toBe("db1");
});
it("generated password matches UUID format", {
timeout: 30000,
}, async () => {
const { factory } = makeContainerFake(9999);
const fixture = new SurrealDBFixture({ containerFactory: factory });
const config = await fixture.start();
expect(config.password).toMatch(/^[0-9a-f-]{36}$/);
});
it("stop when no container is a no-op", { timeout: 30000 }, async () => {
const fixture = new SurrealDBFixture();
await expect(fixture.stop()).resolves.toBeUndefined();
});
it("start(): stops container and clears reference when getMappedPort throws", {
timeout: 30000,
}, async () => {
const stopped: string[] = [];
const fakeStarted = {
getMappedPort: (_port: number) => {
throw new Error("port mapping failed");
},
stop: async () => {
stopped.push("stopped");
},
};
const fakeContainer = {
withCommand: function () {
return this;
},
withExposedPorts: function () {
return this;
},
withWaitStrategy: function () {
return this;
},
start: async () => fakeStarted,
};
const fixture = new SurrealDBFixture({
containerFactory: (_img: string) => fakeContainer as never,
});
await expect(fixture.start()).rejects.toThrow("port mapping failed");
expect(stopped).toContain("stopped");
});
it("resolveContainerFactory: returns factory from dynamic import when no containerFactory", {
timeout: 30000,
}, async () => {
// Access protected method via subclass
class Exposed extends SurrealDBFixture {
resolveFactory() {
return this.resolveContainerFactory();
}
}
// No containerFactory provided — exercises the dynamic import branch
const exposed = new Exposed();
const resolved = await exposed.resolveFactory();
expect(typeof resolved).toBe("function");
// Invoke the returned factory to exercise the inner arrow function.
// new GenericContainer(img) constructs the object; it does not start Docker.
const container = resolved("surrealdb/surrealdb:v3.0.4");
expect(container).toBeDefined();
});
});

View File

@@ -0,0 +1,148 @@
/**
* SurrealDBFixture — testcontainers-backed ServiceFixture for SurrealDB v3.
*
* @module
*/
import {
applyWaitStrategy,
type ServiceFixture,
} from "@suaveplan/testing-integration";
import type { GenericContainer, StartedTestContainer } from "testcontainers";
import {
SURREALDB_CONTAINER_PORT,
SURREALDB_DEFAULT_DATABASE,
SURREALDB_DEFAULT_NAMESPACE,
SURREALDB_DEFAULT_USERNAME,
SURREALDB_ENV_VARS,
SURREALDB_IMAGE,
SURREALDB_READY_LOG,
SURREALDB_READY_LOG_TIMES,
} from "../constants/index.js";
import type {
SurrealDBConfig,
SurrealDBFixtureOptions,
} from "./surrealdb-fixture.types.js";
/**
* Manages the full lifecycle of a SurrealDB v3 container for integration tests.
*
* Supports env-bridge passthrough mode: when `SURREALDB_URL`, `SURREALDB_USERNAME`,
* and `SURREALDB_PASSWORD` are all set, the fixture returns them directly without
* starting a container.
*
* Uses a random password generated via `crypto.randomUUID()` each run to avoid
* credential reuse across test suites.
*/
export class SurrealDBFixture implements ServiceFixture<SurrealDBConfig> {
readonly name = "surrealdb";
protected readonly options: SurrealDBFixtureOptions;
protected container: StartedTestContainer | null = null;
protected config: SurrealDBConfig | null = null;
protected passthrough = false;
constructor(options: SurrealDBFixtureOptions = {}) {
this.options = options;
}
/**
* Resolves the container factory. When `containerFactory` is provided via
* options, it is returned immediately. Otherwise performs a dynamic import
* of testcontainers and returns a factory wrapping `GenericContainer`.
*
* Protected so subclasses and test doubles can override this seam.
*/
protected async resolveContainerFactory(): Promise<
(image: string) => GenericContainer
> {
if (this.options.containerFactory) {
return this.options.containerFactory;
}
const { GenericContainer } = await import("testcontainers");
return (img: string) => new GenericContainer(img);
}
async start(): Promise<SurrealDBConfig> {
// Env-bridge passthrough mode — ALL three vars must be set and non-empty
const [url, username, password] = SURREALDB_ENV_VARS.map(
(v) => process.env[v] ?? ""
);
if (url && username && password) {
this.passthrough = true;
this.config = {
url,
namespace:
this.options.namespace ?? SURREALDB_DEFAULT_NAMESPACE,
database: this.options.database ?? SURREALDB_DEFAULT_DATABASE,
username,
password,
};
return this.config;
}
const generatedPassword = crypto.randomUUID();
const image = this.options.image ?? SURREALDB_IMAGE;
const factory = await this.resolveContainerFactory();
const builder = factory(image)
// Flag set ported from ../suaveplan/packages/universal/surrealdb/
// docker-compose.test.yml — proven against v3.0.x. v3 dropped
// `--auth` (always on; `--unauthenticated` to disable) and made
// capabilities deny-by-default, so `--allow-all` is required for
// tests that exercise funcs/net/scripting/guests. Trailing `memory`
// selects the in-memory datastore explicitly.
.withCommand([
"start",
"--log=info",
`--user=${SURREALDB_DEFAULT_USERNAME}`,
`--pass=${generatedPassword}`,
"--allow-all",
"memory",
])
.withExposedPorts(SURREALDB_CONTAINER_PORT);
const raw = await applyWaitStrategy(builder, {
readyLog: SURREALDB_READY_LOG,
times: SURREALDB_READY_LOG_TIMES,
});
this.container = await raw.start();
try {
const port = this.container.getMappedPort(SURREALDB_CONTAINER_PORT);
this.config = {
url: `ws://localhost:${port}`,
namespace:
this.options.namespace ?? SURREALDB_DEFAULT_NAMESPACE,
database: this.options.database ?? SURREALDB_DEFAULT_DATABASE,
username: SURREALDB_DEFAULT_USERNAME,
password: generatedPassword,
};
return this.config;
} catch (err) {
await this.container.stop();
this.container = null;
throw err;
}
}
async stop(): Promise<void> {
if (this.passthrough || !this.container) return;
await this.container.stop();
this.container = null;
}
async healthCheck(): Promise<boolean> {
if (!this.container) return false;
const port = this.container.getMappedPort(SURREALDB_CONTAINER_PORT);
try {
const fetchFn =
this.options.fetchFn ??
/* istanbul ignore next */ globalThis.fetch;
const res = await fetchFn(`http://localhost:${port}/health`);
return res.ok;
} catch {
return false;
}
}
}

View File

@@ -0,0 +1,32 @@
import type { GenericContainer } from "testcontainers";
export interface SurrealDBConfig extends Record<string, unknown> {
/** WebSocket URL: "ws://localhost:<port>" */
url: string;
namespace: string;
database: string;
username: string;
/** Generated per run via crypto.randomUUID() */
password: string;
}
export interface SurrealDBFixtureOptions {
/** Override the Docker image. Defaults to SURREALDB_IMAGE constant. */
image?: string;
/** Override namespace. Defaults to "test". */
namespace?: string;
/** Override database. Defaults to "test". */
database?: string;
/**
* Injectable GenericContainer constructor for unit testing.
* When provided, the fixture uses this instead of importing from testcontainers.
* This is the primary seam for unit tests — pass a fake container factory.
*/
containerFactory?: (image: string) => GenericContainer;
/**
* Injectable fetch function for unit testing healthCheck().
* When provided, replaces globalThis.fetch. Mirrors the pattern used by
* MailpitFixture, TypesenseFixture, and GarageS3Fixture.
*/
fetchFn?: typeof fetch;
}

View File

@@ -0,0 +1,6 @@
export * from "./constants/index.js";
export { SurrealDBFixture } from "./fixture/surrealdb-fixture.js";
export type {
SurrealDBConfig,
SurrealDBFixtureOptions,
} from "./fixture/surrealdb-fixture.types.js";

View File

@@ -0,0 +1,23 @@
import { webcrypto } from "node:crypto";
type WritableGlobal = { crypto?: Crypto; File?: unknown };
const g = globalThis as WritableGlobal;
if (g.crypto === undefined) {
g.crypto = webcrypto as unknown as Crypto;
}
// testcontainers/undici requires File global in Node environments
if (g.File === undefined) {
g.File = class File extends Blob {
readonly name: string;
readonly lastModified: number;
constructor(
fileBits: BlobPart[],
fileName: string,
options?: FilePropertyBag
) {
super(fileBits, options);
this.name = fileName;
this.lastModified = options?.lastModified ?? Date.now();
}
};
}

View File

@@ -0,0 +1,16 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist",
"lib": ["ES2022"],
"types": ["node"]
},
"include": ["src/**/*.ts"],
"exclude": [
"src/**/*.test.ts",
"dist",
"node_modules"
]
}

View File

@@ -0,0 +1,31 @@
import { defineConfig } from "vite";
import dts from "vite-plugin-dts";
export default defineConfig({
build: {
lib: {
entry: "src/index.ts",
formats: ["es"],
},
rollupOptions: {
external: [
"testcontainers",
"@suaveplan/testing-integration",
"node:net",
"node:crypto",
],
output: {
preserveModules: true,
preserveModulesRoot: "src",
entryFileNames: "[name].js",
},
},
},
plugins: [
dts({
entryRoot: "src",
tsconfigPath: "./tsconfig.lib.json",
rollupTypes: false,
}),
],
});

View File

@@ -0,0 +1,29 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
globals: false,
environment: "node",
pool: "forks",
setupFiles: ["./tests/setup/polyfills.ts"],
include: ["src/**/*.test.ts"],
exclude: ["dist/**", "node_modules/**"],
coverage: {
provider: "istanbul",
reporter: ["text", "html", "lcov"],
include: ["src/**/*.ts"],
exclude: [
"src/**/*.test.ts",
"src/**/*.types.ts",
"src/**/index.ts",
],
thresholds: {
statements: 100,
branches: 100,
functions: 100,
lines: 100,
},
},
testTimeout: 5000,
},
});