@venturekit/testing 0.0.0-dev.20260701100017
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 +146 -0
- package/dist/auth-tokens.d.ts +55 -0
- package/dist/auth-tokens.d.ts.map +1 -0
- package/dist/auth-tokens.js +81 -0
- package/dist/auth-tokens.js.map +1 -0
- package/dist/client.d.ts +68 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +114 -0
- package/dist/client.js.map +1 -0
- package/dist/cognito.d.ts +69 -0
- package/dist/cognito.d.ts.map +1 -0
- package/dist/cognito.js +76 -0
- package/dist/cognito.js.map +1 -0
- package/dist/db.d.ts +32 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +52 -0
- package/dist/db.js.map +1 -0
- package/dist/errors.d.ts +32 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +22 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/ready.d.ts +43 -0
- package/dist/ready.d.ts.map +1 -0
- package/dist/ready.js +67 -0
- package/dist/ready.js.map +1 -0
- package/dist/sql.d.ts +32 -0
- package/dist/sql.d.ts.map +1 -0
- package/dist/sql.js +40 -0
- package/dist/sql.js.map +1 -0
- package/dist/stack.d.ts +52 -0
- package/dist/stack.d.ts.map +1 -0
- package/dist/stack.js +142 -0
- package/dist/stack.js.map +1 -0
- package/dist/types.d.ts +25 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +58 -0
package/dist/db.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database reset helpers for integration tests.
|
|
3
|
+
*
|
|
4
|
+
* These lazy-import `@venturekit/data` (an optional peer dependency) and
|
|
5
|
+
* connect using the same env the app does (`DATABASE_URL` / `DB_*`). Run
|
|
6
|
+
* them from a test `beforeEach`/`globalSetup` to return the DB to a known
|
|
7
|
+
* state between specs.
|
|
8
|
+
*
|
|
9
|
+
* The pure SQL builders live in `sql.ts` and are unit-tested there; this
|
|
10
|
+
* module is the thin IO wrapper.
|
|
11
|
+
*/
|
|
12
|
+
export interface TruncateOptions {
|
|
13
|
+
/** Schema to operate on. Default `public`. */
|
|
14
|
+
schema?: string;
|
|
15
|
+
/** Extra table names to preserve (never truncated). */
|
|
16
|
+
exclude?: string[];
|
|
17
|
+
/** Append `RESTART IDENTITY`. Default `true`. */
|
|
18
|
+
restartIdentity?: boolean;
|
|
19
|
+
/** Append `CASCADE`. Default `true`. */
|
|
20
|
+
cascade?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/** List all table names in a schema (default `public`). */
|
|
23
|
+
export declare function listTables(schema?: string): Promise<string[]>;
|
|
24
|
+
/** Truncate the given tables in a single statement. No-op for an empty list. */
|
|
25
|
+
export declare function truncateTables(tables: string[], options?: TruncateOptions): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Truncate every table in the schema EXCEPT the VentureKit migration/seed
|
|
28
|
+
* tracking tables (and any caller-supplied exclusions). Returns the list
|
|
29
|
+
* of tables that were truncated.
|
|
30
|
+
*/
|
|
31
|
+
export declare function truncateAllTables(options?: TruncateOptions): Promise<string[]>;
|
|
32
|
+
//# sourceMappingURL=db.d.ts.map
|
package/dist/db.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,iDAAiD;IACjD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wCAAwC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,2DAA2D;AAC3D,wBAAsB,UAAU,CAAC,MAAM,SAAW,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOrE;AAED,gFAAgF;AAChF,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAMxF"}
|
package/dist/db.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database reset helpers for integration tests.
|
|
3
|
+
*
|
|
4
|
+
* These lazy-import `@venturekit/data` (an optional peer dependency) and
|
|
5
|
+
* connect using the same env the app does (`DATABASE_URL` / `DB_*`). Run
|
|
6
|
+
* them from a test `beforeEach`/`globalSetup` to return the DB to a known
|
|
7
|
+
* state between specs.
|
|
8
|
+
*
|
|
9
|
+
* The pure SQL builders live in `sql.ts` and are unit-tested there; this
|
|
10
|
+
* module is the thin IO wrapper.
|
|
11
|
+
*/
|
|
12
|
+
import { buildTruncateSql, filterTruncatableTables } from './sql.js';
|
|
13
|
+
async function loadData() {
|
|
14
|
+
try {
|
|
15
|
+
return await import('@venturekit/data');
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
throw new Error("@venturekit/testing: database helpers require '@venturekit/data'. " +
|
|
19
|
+
'Install it as a dev dependency (e.g. `pnpm add -D @venturekit/data`).');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** List all table names in a schema (default `public`). */
|
|
23
|
+
export async function listTables(schema = 'public') {
|
|
24
|
+
const { query } = await loadData();
|
|
25
|
+
const rows = await query(`SELECT tablename FROM pg_tables WHERE schemaname = $1 ORDER BY tablename`, [schema]);
|
|
26
|
+
return rows.map((row) => row.tablename);
|
|
27
|
+
}
|
|
28
|
+
/** Truncate the given tables in a single statement. No-op for an empty list. */
|
|
29
|
+
export async function truncateTables(tables, options = {}) {
|
|
30
|
+
if (tables.length === 0)
|
|
31
|
+
return;
|
|
32
|
+
const { query } = await loadData();
|
|
33
|
+
const sql = buildTruncateSql(tables, {
|
|
34
|
+
schema: options.schema ?? 'public',
|
|
35
|
+
restartIdentity: options.restartIdentity,
|
|
36
|
+
cascade: options.cascade,
|
|
37
|
+
});
|
|
38
|
+
await query(sql);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Truncate every table in the schema EXCEPT the VentureKit migration/seed
|
|
42
|
+
* tracking tables (and any caller-supplied exclusions). Returns the list
|
|
43
|
+
* of tables that were truncated.
|
|
44
|
+
*/
|
|
45
|
+
export async function truncateAllTables(options = {}) {
|
|
46
|
+
const schema = options.schema ?? 'public';
|
|
47
|
+
const all = await listTables(schema);
|
|
48
|
+
const tables = filterTruncatableTables(all, options.exclude ?? []);
|
|
49
|
+
await truncateTables(tables, { ...options, schema });
|
|
50
|
+
return tables;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=db.js.map
|
package/dist/db.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAIrE,KAAK,UAAU,QAAQ;IACrB,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,oEAAoE;YAClE,uEAAuE,CAC1E,CAAC;IACJ,CAAC;AACH,CAAC;AAaD,2DAA2D;AAC3D,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAM,GAAG,QAAQ;IAChD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;IACnC,MAAM,IAAI,GAAG,MAAM,KAAK,CACtB,0EAA0E,EAC1E,CAAC,MAAM,CAAC,CACT,CAAC;IACF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAA0B,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACjE,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAgB,EAChB,UAA2B,EAAE;IAE7B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAChC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;IACnC,MAAM,GAAG,GAAG,gBAAgB,CAAC,MAAM,EAAE;QACnC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,QAAQ;QAClC,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC,CAAC;IACH,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAA2B,EAAE;IACnE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAC;IAC1C,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,uBAAuB,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IACnE,MAAM,cAAc,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error raised by the test API client on a non-2xx response.
|
|
3
|
+
*
|
|
4
|
+
* VentureKit's runtime wraps every error as `{ error: { code, message,
|
|
5
|
+
* details? }, meta? }` (see `@venturekit/runtime` `response.ts`). The
|
|
6
|
+
* client parses that envelope and surfaces `code` / `details` here so
|
|
7
|
+
* assertions can target the framework's stable error codes
|
|
8
|
+
* (e.g. `VALIDATION_ERROR`, `NOT_FOUND`, `FORBIDDEN`) instead of brittle
|
|
9
|
+
* message strings.
|
|
10
|
+
*/
|
|
11
|
+
export interface ApiErrorInit {
|
|
12
|
+
status: number;
|
|
13
|
+
method: string;
|
|
14
|
+
url: string;
|
|
15
|
+
message: string;
|
|
16
|
+
/** The `error.code` from the VentureKit error envelope, when present. */
|
|
17
|
+
code?: string;
|
|
18
|
+
/** The `error.details` from the envelope (e.g. Zod field errors). */
|
|
19
|
+
details?: unknown;
|
|
20
|
+
/** The full parsed response body (or raw text when not JSON). */
|
|
21
|
+
body?: unknown;
|
|
22
|
+
}
|
|
23
|
+
export declare class ApiError extends Error {
|
|
24
|
+
readonly status: number;
|
|
25
|
+
readonly method: string;
|
|
26
|
+
readonly url: string;
|
|
27
|
+
readonly code?: string;
|
|
28
|
+
readonly details?: unknown;
|
|
29
|
+
readonly body?: unknown;
|
|
30
|
+
constructor(init: ApiErrorInit);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iEAAiE;IACjE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;gBAEZ,IAAI,EAAE,YAAY;CAa/B"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export class ApiError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
method;
|
|
4
|
+
url;
|
|
5
|
+
code;
|
|
6
|
+
details;
|
|
7
|
+
body;
|
|
8
|
+
constructor(init) {
|
|
9
|
+
super(init.message);
|
|
10
|
+
this.name = 'ApiError';
|
|
11
|
+
this.status = init.status;
|
|
12
|
+
this.method = init.method;
|
|
13
|
+
this.url = init.url;
|
|
14
|
+
this.code = init.code;
|
|
15
|
+
this.details = init.details;
|
|
16
|
+
this.body = init.body;
|
|
17
|
+
// Restore the prototype chain — required when targeting ES2022 with
|
|
18
|
+
// a transpiled `extends Error` so `instanceof ApiError` holds.
|
|
19
|
+
Object.setPrototypeOf(this, ApiError.prototype);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAuBA,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,MAAM,CAAS;IACf,MAAM,CAAS;IACf,GAAG,CAAS;IACZ,IAAI,CAAU;IACd,OAAO,CAAW;IAClB,IAAI,CAAW;IAExB,YAAY,IAAkB;QAC5B,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,oEAAoE;QACpE,+DAA+D;QAC/D,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAClD,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @venturekit/testing
|
|
3
|
+
*
|
|
4
|
+
* Integration & end-to-end test harness for VentureKit apps.
|
|
5
|
+
*
|
|
6
|
+
* - Launch a full local stack (`startTestStack`) — migrate + `vk dev`.
|
|
7
|
+
* - Wait for readiness (`waitForReady`) against `/_dev/health`.
|
|
8
|
+
* - Seed cognito-local users (`createTestUser`) and mint JWTs (`loginAs`).
|
|
9
|
+
* - Reset the database between specs (`truncateAllTables`).
|
|
10
|
+
* - Drive the API with a typed client (`createApiClient`).
|
|
11
|
+
*/
|
|
12
|
+
export { ApiError } from './errors.js';
|
|
13
|
+
export type { ApiErrorInit } from './errors.js';
|
|
14
|
+
export { createApiClient, buildUrl } from './client.js';
|
|
15
|
+
export type { ApiClient, ApiClientOptions, ApiResponse, RequestOptions, } from './client.js';
|
|
16
|
+
export { waitForReady, vkDevServerReady } from './ready.js';
|
|
17
|
+
export type { WaitForReadyOptions } from './ready.js';
|
|
18
|
+
export { createTestUser, deleteTestUser, setTestUserAttributes, getDevPools, } from './cognito.js';
|
|
19
|
+
export type { DevServerRef, CreateTestUserInput, DevPool, DevPoolsResult, } from './cognito.js';
|
|
20
|
+
export { signInWithPassword, loginAs, DEFAULT_COGNITO_ENDPOINT, DEFAULT_COGNITO_REGION, } from './auth-tokens.js';
|
|
21
|
+
export type { TokenSet, SignInInput, LoginAsInput } from './auth-tokens.js';
|
|
22
|
+
export { startTestStack } from './stack.js';
|
|
23
|
+
export type { StartTestStackOptions, TestStack } from './stack.js';
|
|
24
|
+
export { truncateAllTables, truncateTables, listTables, } from './db.js';
|
|
25
|
+
export type { TruncateOptions } from './db.js';
|
|
26
|
+
export { buildTruncateSql, filterTruncatableTables, quoteIdent, VK_TRACKING_TABLES, } from './sql.js';
|
|
27
|
+
export type { TruncateSqlOptions } from './sql.js';
|
|
28
|
+
export type { FetchImpl, AuthInit, QueryValue } from './types.js';
|
|
29
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EACV,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC5D,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EACL,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,YAAY,EACZ,mBAAmB,EACnB,OAAO,EACP,cAAc,GACf,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,kBAAkB,EAClB,OAAO,EACP,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE5E,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,YAAY,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEnE,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,UAAU,GACX,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,UAAU,EACV,kBAAkB,GACnB,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @venturekit/testing
|
|
3
|
+
*
|
|
4
|
+
* Integration & end-to-end test harness for VentureKit apps.
|
|
5
|
+
*
|
|
6
|
+
* - Launch a full local stack (`startTestStack`) — migrate + `vk dev`.
|
|
7
|
+
* - Wait for readiness (`waitForReady`) against `/_dev/health`.
|
|
8
|
+
* - Seed cognito-local users (`createTestUser`) and mint JWTs (`loginAs`).
|
|
9
|
+
* - Reset the database between specs (`truncateAllTables`).
|
|
10
|
+
* - Drive the API with a typed client (`createApiClient`).
|
|
11
|
+
*/
|
|
12
|
+
export { ApiError } from './errors.js';
|
|
13
|
+
export { createApiClient, buildUrl } from './client.js';
|
|
14
|
+
export { waitForReady, vkDevServerReady } from './ready.js';
|
|
15
|
+
export { createTestUser, deleteTestUser, setTestUserAttributes, getDevPools, } from './cognito.js';
|
|
16
|
+
export { signInWithPassword, loginAs, DEFAULT_COGNITO_ENDPOINT, DEFAULT_COGNITO_REGION, } from './auth-tokens.js';
|
|
17
|
+
export { startTestStack } from './stack.js';
|
|
18
|
+
export { truncateAllTables, truncateTables, listTables, } from './db.js';
|
|
19
|
+
export { buildTruncateSql, filterTruncatableTables, quoteIdent, VK_TRACKING_TABLES, } from './sql.js';
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQxD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG5D,OAAO,EACL,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,WAAW,GACZ,MAAM,cAAc,CAAC;AAQtB,OAAO,EACL,kBAAkB,EAClB,OAAO,EACP,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,UAAU,GACX,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,UAAU,EACV,kBAAkB,GACnB,MAAM,UAAU,CAAC"}
|
package/dist/ready.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Poll an HTTP endpoint until a VentureKit dev server (or any app health
|
|
3
|
+
* route) is ready to serve requests.
|
|
4
|
+
*
|
|
5
|
+
* The default target is `/_dev/health`, the unconditional liveness probe
|
|
6
|
+
* the `vk dev` server exposes (it returns `{ vk: 'dev-server', ... }`).
|
|
7
|
+
* Pass `validate: vkDevServerReady` to also assert the `vk` discriminator
|
|
8
|
+
* — useful when a Playwright `webServer.url` might otherwise match an
|
|
9
|
+
* unrelated process bound to the same port.
|
|
10
|
+
*/
|
|
11
|
+
import type { FetchImpl } from './types.js';
|
|
12
|
+
export interface WaitForReadyOptions {
|
|
13
|
+
/** Base URL of the server, e.g. `http://localhost:4001`. */
|
|
14
|
+
baseUrl: string;
|
|
15
|
+
/** Path to probe. Default `/_dev/health`. */
|
|
16
|
+
path?: string;
|
|
17
|
+
/** Total time to wait before giving up, in ms. Default 60_000. */
|
|
18
|
+
timeoutMs?: number;
|
|
19
|
+
/** Delay between attempts, in ms. Default 500. */
|
|
20
|
+
intervalMs?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Decide whether a response means "ready". Default: `res.ok`.
|
|
23
|
+
* Receives the parsed JSON body (or `undefined` if not JSON) + the response.
|
|
24
|
+
*/
|
|
25
|
+
validate?: (body: unknown, res: Response) => boolean;
|
|
26
|
+
/** `fetch` implementation. Defaults to the global `fetch`. */
|
|
27
|
+
fetch?: FetchImpl;
|
|
28
|
+
/** Sleep implementation. Injectable for deterministic unit tests. */
|
|
29
|
+
sleep?: (ms: number) => Promise<void>;
|
|
30
|
+
/** Clock. Injectable for deterministic unit tests. Defaults to `Date.now`. */
|
|
31
|
+
now?: () => number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Stricter predicate that also asserts the response is a `vk dev` server
|
|
35
|
+
* (the `/_dev/health` probe returns `{ vk: 'dev-server' }`). Guards
|
|
36
|
+
* against a stray process answering on the same port.
|
|
37
|
+
*/
|
|
38
|
+
export declare function vkDevServerReady(body: unknown, res: Response): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Resolve once the endpoint is ready, or throw after `timeoutMs`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function waitForReady(options: WaitForReadyOptions): Promise<void>;
|
|
43
|
+
//# sourceMappingURL=ready.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ready.d.ts","sourceRoot":"","sources":["../src/ready.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC;IACrD,8DAA8D;IAC9D,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,qEAAqE;IACrE,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,8EAA8E;IAC9E,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAOD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAOtE;AAWD;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwC9E"}
|
package/dist/ready.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Poll an HTTP endpoint until a VentureKit dev server (or any app health
|
|
3
|
+
* route) is ready to serve requests.
|
|
4
|
+
*
|
|
5
|
+
* The default target is `/_dev/health`, the unconditional liveness probe
|
|
6
|
+
* the `vk dev` server exposes (it returns `{ vk: 'dev-server', ... }`).
|
|
7
|
+
* Pass `validate: vkDevServerReady` to also assert the `vk` discriminator
|
|
8
|
+
* — useful when a Playwright `webServer.url` might otherwise match an
|
|
9
|
+
* unrelated process bound to the same port.
|
|
10
|
+
*/
|
|
11
|
+
/** Default readiness predicate — any 2xx response. */
|
|
12
|
+
function defaultValidate(_body, res) {
|
|
13
|
+
return res.ok;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Stricter predicate that also asserts the response is a `vk dev` server
|
|
17
|
+
* (the `/_dev/health` probe returns `{ vk: 'dev-server' }`). Guards
|
|
18
|
+
* against a stray process answering on the same port.
|
|
19
|
+
*/
|
|
20
|
+
export function vkDevServerReady(body, res) {
|
|
21
|
+
return (res.ok &&
|
|
22
|
+
!!body &&
|
|
23
|
+
typeof body === 'object' &&
|
|
24
|
+
body.vk === 'dev-server');
|
|
25
|
+
}
|
|
26
|
+
function defaultSleep(ms) {
|
|
27
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
28
|
+
}
|
|
29
|
+
function errorMessage(err) {
|
|
30
|
+
if (err instanceof Error)
|
|
31
|
+
return err.message;
|
|
32
|
+
return String(err);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Resolve once the endpoint is ready, or throw after `timeoutMs`.
|
|
36
|
+
*/
|
|
37
|
+
export async function waitForReady(options) {
|
|
38
|
+
const { baseUrl, path = '/_dev/health', timeoutMs = 60_000, intervalMs = 500, validate = defaultValidate, fetch: doFetch = fetch, sleep = defaultSleep, now = Date.now, } = options;
|
|
39
|
+
const url = `${baseUrl.replace(/\/+$/, '')}${path.startsWith('/') ? path : `/${path}`}`;
|
|
40
|
+
const deadline = now() + timeoutMs;
|
|
41
|
+
let lastError;
|
|
42
|
+
for (;;) {
|
|
43
|
+
try {
|
|
44
|
+
const res = await doFetch(url, { method: 'GET' });
|
|
45
|
+
let body;
|
|
46
|
+
try {
|
|
47
|
+
const text = await res.text();
|
|
48
|
+
body = text ? JSON.parse(text) : undefined;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
body = undefined;
|
|
52
|
+
}
|
|
53
|
+
if (validate(body, res))
|
|
54
|
+
return;
|
|
55
|
+
lastError = new Error(`unexpected response: HTTP ${res.status}`);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
lastError = err;
|
|
59
|
+
}
|
|
60
|
+
if (now() >= deadline) {
|
|
61
|
+
throw new Error(`waitForReady: timed out after ${timeoutMs}ms waiting for ${url}` +
|
|
62
|
+
(lastError ? ` (last error: ${errorMessage(lastError)})` : ''));
|
|
63
|
+
}
|
|
64
|
+
await sleep(intervalMs);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=ready.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ready.js","sourceRoot":"","sources":["../src/ready.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA0BH,sDAAsD;AACtD,SAAS,eAAe,CAAC,KAAc,EAAE,GAAa;IACpD,OAAO,GAAG,CAAC,EAAE,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAa,EAAE,GAAa;IAC3D,OAAO,CACL,GAAG,CAAC,EAAE;QACN,CAAC,CAAC,IAAI;QACN,OAAO,IAAI,KAAK,QAAQ;QACvB,IAAyB,CAAC,EAAE,KAAK,YAAY,CAC/C,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,YAAY,CAAC,GAAY;IAChC,IAAI,GAAG,YAAY,KAAK;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC7C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA4B;IAC7D,MAAM,EACJ,OAAO,EACP,IAAI,GAAG,cAAc,EACrB,SAAS,GAAG,MAAM,EAClB,UAAU,GAAG,GAAG,EAChB,QAAQ,GAAG,eAAe,EAC1B,KAAK,EAAE,OAAO,GAAG,KAAkB,EACnC,KAAK,GAAG,YAAY,EACpB,GAAG,GAAG,IAAI,CAAC,GAAG,GACf,GAAG,OAAO,CAAC;IAEZ,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;IACxF,MAAM,QAAQ,GAAG,GAAG,EAAE,GAAG,SAAS,CAAC;IACnC,IAAI,SAAkB,CAAC;IAEvB,SAAS,CAAC;QACR,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;YAClD,IAAI,IAAa,CAAC;YAClB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;gBAC9B,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC7C,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,GAAG,SAAS,CAAC;YACnB,CAAC;YACD,IAAI,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC;gBAAE,OAAO;YAChC,SAAS,GAAG,IAAI,KAAK,CAAC,6BAA6B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACnE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,SAAS,GAAG,GAAG,CAAC;QAClB,CAAC;QAED,IAAI,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CACb,iCAAiC,SAAS,kBAAkB,GAAG,EAAE;gBAC/D,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CACjE,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC"}
|
package/dist/sql.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure SQL builders for test database reset. Kept IO-free so they're
|
|
3
|
+
* fully unit-testable; the executing wrappers live in `db.ts`.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* VentureKit's migration/seed bookkeeping tables. These must NEVER be
|
|
7
|
+
* truncated between tests — doing so would make the runner re-apply (or
|
|
8
|
+
* lose track of) every migration. `truncateAllTables` excludes them by
|
|
9
|
+
* default via `filterTruncatableTables`.
|
|
10
|
+
*/
|
|
11
|
+
export declare const VK_TRACKING_TABLES: readonly string[];
|
|
12
|
+
/** Quote a SQL identifier, escaping embedded double-quotes. */
|
|
13
|
+
export declare function quoteIdent(name: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Remove VentureKit tracking tables (and any caller-supplied names) from
|
|
16
|
+
* a list of candidate tables.
|
|
17
|
+
*/
|
|
18
|
+
export declare function filterTruncatableTables(all: string[], exclude?: string[]): string[];
|
|
19
|
+
export interface TruncateSqlOptions {
|
|
20
|
+
/** Append `RESTART IDENTITY` (reset sequences). Default `true`. */
|
|
21
|
+
restartIdentity?: boolean;
|
|
22
|
+
/** Append `CASCADE` (truncate dependent tables too). Default `true`. */
|
|
23
|
+
cascade?: boolean;
|
|
24
|
+
/** Schema to qualify table names with (e.g. `public`). */
|
|
25
|
+
schema?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Build a single `TRUNCATE TABLE ...` statement for the given tables.
|
|
29
|
+
* Returns `''` for an empty list so callers can skip the query entirely.
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildTruncateSql(tables: string[], options?: TruncateSqlOptions): string;
|
|
32
|
+
//# sourceMappingURL=sql.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../src/sql.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAAsC,CAAC;AAEvF,+DAA+D;AAC/D,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CAGvF;AAED,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wEAAwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,kBAAuB,GAAG,MAAM,CAU3F"}
|
package/dist/sql.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure SQL builders for test database reset. Kept IO-free so they're
|
|
3
|
+
* fully unit-testable; the executing wrappers live in `db.ts`.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* VentureKit's migration/seed bookkeeping tables. These must NEVER be
|
|
7
|
+
* truncated between tests — doing so would make the runner re-apply (or
|
|
8
|
+
* lose track of) every migration. `truncateAllTables` excludes them by
|
|
9
|
+
* default via `filterTruncatableTables`.
|
|
10
|
+
*/
|
|
11
|
+
export const VK_TRACKING_TABLES = ['__vk_migrations', '__vk_seeds'];
|
|
12
|
+
/** Quote a SQL identifier, escaping embedded double-quotes. */
|
|
13
|
+
export function quoteIdent(name) {
|
|
14
|
+
return `"${name.replace(/"/g, '""')}"`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Remove VentureKit tracking tables (and any caller-supplied names) from
|
|
18
|
+
* a list of candidate tables.
|
|
19
|
+
*/
|
|
20
|
+
export function filterTruncatableTables(all, exclude = []) {
|
|
21
|
+
const skip = new Set([...VK_TRACKING_TABLES, ...exclude]);
|
|
22
|
+
return all.filter((table) => !skip.has(table));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Build a single `TRUNCATE TABLE ...` statement for the given tables.
|
|
26
|
+
* Returns `''` for an empty list so callers can skip the query entirely.
|
|
27
|
+
*/
|
|
28
|
+
export function buildTruncateSql(tables, options = {}) {
|
|
29
|
+
if (tables.length === 0)
|
|
30
|
+
return '';
|
|
31
|
+
const { restartIdentity = true, cascade = true, schema } = options;
|
|
32
|
+
const qualified = tables.map((table) => schema ? `${quoteIdent(schema)}.${quoteIdent(table)}` : quoteIdent(table));
|
|
33
|
+
let sql = `TRUNCATE TABLE ${qualified.join(', ')}`;
|
|
34
|
+
if (restartIdentity)
|
|
35
|
+
sql += ' RESTART IDENTITY';
|
|
36
|
+
if (cascade)
|
|
37
|
+
sql += ' CASCADE';
|
|
38
|
+
return sql;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=sql.js.map
|
package/dist/sql.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql.js","sourceRoot":"","sources":["../src/sql.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAsB,CAAC,iBAAiB,EAAE,YAAY,CAAC,CAAC;AAEvF,+DAA+D;AAC/D,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AACzC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAa,EAAE,UAAoB,EAAE;IAC3E,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,GAAG,kBAAkB,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;IAClE,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AACjD,CAAC;AAWD;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAgB,EAAE,UAA8B,EAAE;IACjF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,MAAM,EAAE,eAAe,GAAG,IAAI,EAAE,OAAO,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACnE,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACrC,MAAM,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAC1E,CAAC;IACF,IAAI,GAAG,GAAG,kBAAkB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IACnD,IAAI,eAAe;QAAE,GAAG,IAAI,mBAAmB,CAAC;IAChD,IAAI,OAAO;QAAE,GAAG,IAAI,UAAU,CAAC;IAC/B,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/stack.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatically launch a full local VentureKit stack for tests.
|
|
3
|
+
*
|
|
4
|
+
* `startTestStack` runs `vk migrate` (so the schema/seed are applied — `vk
|
|
5
|
+
* dev` does NOT auto-migrate) and then `vk dev`, waiting until the server's
|
|
6
|
+
* `/_dev/health` probe confirms it's ready. Use it from a vitest
|
|
7
|
+
* `globalSetup` or a Playwright `globalSetup` when you want the harness to
|
|
8
|
+
* own the server lifecycle. (For Playwright you can alternatively let the
|
|
9
|
+
* `webServer` block run `vk dev` and use `waitForReady` yourself.)
|
|
10
|
+
*
|
|
11
|
+
* Requires `@venturekit/cli` to be installed in the project (it is, for any
|
|
12
|
+
* VentureKit app) — the `vk` binary is resolved from `node_modules/.bin`.
|
|
13
|
+
*
|
|
14
|
+
* This module is IO-bound (child processes, ports) and is excluded from
|
|
15
|
+
* unit-test coverage; it's exercised by real E2E runs.
|
|
16
|
+
*/
|
|
17
|
+
export interface StartTestStackOptions {
|
|
18
|
+
/** Project directory containing `vk.config.ts`. Default `process.cwd()`. */
|
|
19
|
+
cwd?: string;
|
|
20
|
+
/** Stage name — flows into the local DB name. Default `test`. */
|
|
21
|
+
stage?: string;
|
|
22
|
+
/** Port for the API server. Default `4100`. */
|
|
23
|
+
port?: number;
|
|
24
|
+
/** Host to build the base URL from. Default `localhost`. */
|
|
25
|
+
host?: string;
|
|
26
|
+
/** Extra environment variables for the spawned `vk` processes. */
|
|
27
|
+
env?: Record<string, string>;
|
|
28
|
+
/** Run `vk migrate` before starting the server. Default `true`. */
|
|
29
|
+
migrate?: boolean;
|
|
30
|
+
/** Pass `--seed` to `vk migrate`. Default `false`. */
|
|
31
|
+
seed?: boolean;
|
|
32
|
+
/** Enable file watching / hot reload (usually off for tests). Default `false`. */
|
|
33
|
+
watch?: boolean;
|
|
34
|
+
/** Max time to wait for readiness, in ms. Default 120_000. */
|
|
35
|
+
readyTimeoutMs?: number;
|
|
36
|
+
/** Override the resolved `vk` binary path. */
|
|
37
|
+
vkBin?: string;
|
|
38
|
+
/** stdio mode for the spawned processes. Default `inherit`. */
|
|
39
|
+
stdio?: 'inherit' | 'ignore';
|
|
40
|
+
}
|
|
41
|
+
export interface TestStack {
|
|
42
|
+
/** Base URL of the running API, e.g. `http://localhost:4100`. */
|
|
43
|
+
baseUrl: string;
|
|
44
|
+
port: number;
|
|
45
|
+
/** Stop the server (and its process group). Idempotent. */
|
|
46
|
+
stop(): Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Migrate + boot a `vk dev` server and resolve once it's ready.
|
|
50
|
+
*/
|
|
51
|
+
export declare function startTestStack(options?: StartTestStackOptions): Promise<TestStack>;
|
|
52
|
+
//# sourceMappingURL=stack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../src/stack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,MAAM,WAAW,qBAAqB;IACpC,4EAA4E;IAC5E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sDAAsD;IACtD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,kFAAkF;IAClF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8DAA8D;IAC9D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,KAAK,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CAC9B;AAED,MAAM,WAAW,SAAS;IACxB,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAoED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,SAAS,CAAC,CAuD5F"}
|
package/dist/stack.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatically launch a full local VentureKit stack for tests.
|
|
3
|
+
*
|
|
4
|
+
* `startTestStack` runs `vk migrate` (so the schema/seed are applied — `vk
|
|
5
|
+
* dev` does NOT auto-migrate) and then `vk dev`, waiting until the server's
|
|
6
|
+
* `/_dev/health` probe confirms it's ready. Use it from a vitest
|
|
7
|
+
* `globalSetup` or a Playwright `globalSetup` when you want the harness to
|
|
8
|
+
* own the server lifecycle. (For Playwright you can alternatively let the
|
|
9
|
+
* `webServer` block run `vk dev` and use `waitForReady` yourself.)
|
|
10
|
+
*
|
|
11
|
+
* Requires `@venturekit/cli` to be installed in the project (it is, for any
|
|
12
|
+
* VentureKit app) — the `vk` binary is resolved from `node_modules/.bin`.
|
|
13
|
+
*
|
|
14
|
+
* This module is IO-bound (child processes, ports) and is excluded from
|
|
15
|
+
* unit-test coverage; it's exercised by real E2E runs.
|
|
16
|
+
*/
|
|
17
|
+
import { spawn } from 'node:child_process';
|
|
18
|
+
import { existsSync } from 'node:fs';
|
|
19
|
+
import { join } from 'node:path';
|
|
20
|
+
import { waitForReady, vkDevServerReady } from './ready.js';
|
|
21
|
+
/** Resolve the `vk` binary from the nearest `node_modules/.bin`, else PATH. */
|
|
22
|
+
function resolveVkBin(cwd, override) {
|
|
23
|
+
if (override)
|
|
24
|
+
return override;
|
|
25
|
+
const binName = process.platform === 'win32' ? 'vk.cmd' : 'vk';
|
|
26
|
+
let dir = cwd;
|
|
27
|
+
for (;;) {
|
|
28
|
+
const candidate = join(dir, 'node_modules', '.bin', binName);
|
|
29
|
+
if (existsSync(candidate))
|
|
30
|
+
return candidate;
|
|
31
|
+
const parent = join(dir, '..');
|
|
32
|
+
if (parent === dir)
|
|
33
|
+
break;
|
|
34
|
+
dir = parent;
|
|
35
|
+
}
|
|
36
|
+
return 'vk';
|
|
37
|
+
}
|
|
38
|
+
/** Run a `vk` subcommand to completion, rejecting on a non-zero exit code. */
|
|
39
|
+
function runToCompletion(bin, args, opts) {
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
const child = spawn(bin, args, { cwd: opts.cwd, env: opts.env, stdio: opts.stdio });
|
|
42
|
+
child.on('error', reject);
|
|
43
|
+
child.on('exit', (code) => {
|
|
44
|
+
if (code === 0)
|
|
45
|
+
resolve();
|
|
46
|
+
else
|
|
47
|
+
reject(new Error(`\`${bin} ${args.join(' ')}\` exited with code ${code ?? 'null'}`));
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/** Terminate a child process (and its group on POSIX), resolving once it's gone. */
|
|
52
|
+
function terminate(child) {
|
|
53
|
+
return new Promise((resolve) => {
|
|
54
|
+
if (child.exitCode != null || child.pid == null) {
|
|
55
|
+
resolve();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
child.once('exit', () => resolve());
|
|
59
|
+
try {
|
|
60
|
+
if (process.platform === 'win32') {
|
|
61
|
+
spawn('taskkill', ['/pid', String(child.pid), '/T', '/F']);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
try {
|
|
65
|
+
// Negative pid kills the whole detached process group.
|
|
66
|
+
process.kill(-child.pid, 'SIGTERM');
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
child.kill('SIGTERM');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// already gone
|
|
75
|
+
}
|
|
76
|
+
// Hard-stop safety net so teardown never hangs.
|
|
77
|
+
const t = setTimeout(() => {
|
|
78
|
+
try {
|
|
79
|
+
child.kill('SIGKILL');
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// ignore
|
|
83
|
+
}
|
|
84
|
+
resolve();
|
|
85
|
+
}, 5_000);
|
|
86
|
+
t.unref();
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Migrate + boot a `vk dev` server and resolve once it's ready.
|
|
91
|
+
*/
|
|
92
|
+
export async function startTestStack(options = {}) {
|
|
93
|
+
const cwd = options.cwd ?? process.cwd();
|
|
94
|
+
const stage = options.stage ?? 'test';
|
|
95
|
+
const port = options.port ?? 4100;
|
|
96
|
+
const host = options.host ?? 'localhost';
|
|
97
|
+
const baseUrl = `http://${host}:${port}`;
|
|
98
|
+
const stdio = options.stdio ?? 'inherit';
|
|
99
|
+
const vk = resolveVkBin(cwd, options.vkBin);
|
|
100
|
+
const env = { ...process.env, ...options.env, VENTURE_STAGE: stage };
|
|
101
|
+
// `vk dev` does NOT auto-migrate — apply schema (and optionally seeds) first.
|
|
102
|
+
if (options.migrate !== false) {
|
|
103
|
+
const migrateArgs = ['migrate', '--env', stage];
|
|
104
|
+
if (options.seed)
|
|
105
|
+
migrateArgs.push('--seed');
|
|
106
|
+
await runToCompletion(vk, migrateArgs, { cwd, env, stdio });
|
|
107
|
+
}
|
|
108
|
+
const devArgs = ['dev', '--stage', stage, '--port', String(port)];
|
|
109
|
+
if (options.watch !== true)
|
|
110
|
+
devArgs.push('--no-watch');
|
|
111
|
+
const child = spawn(vk, devArgs, {
|
|
112
|
+
cwd,
|
|
113
|
+
env,
|
|
114
|
+
stdio,
|
|
115
|
+
// Detach on POSIX so we can signal the whole process group on stop().
|
|
116
|
+
detached: process.platform !== 'win32',
|
|
117
|
+
});
|
|
118
|
+
let exited = null;
|
|
119
|
+
child.on('exit', (code) => {
|
|
120
|
+
exited = { code };
|
|
121
|
+
});
|
|
122
|
+
const stop = async () => {
|
|
123
|
+
await terminate(child);
|
|
124
|
+
};
|
|
125
|
+
try {
|
|
126
|
+
await waitForReady({
|
|
127
|
+
baseUrl,
|
|
128
|
+
timeoutMs: options.readyTimeoutMs ?? 120_000,
|
|
129
|
+
validate: vkDevServerReady,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
await stop();
|
|
134
|
+
const early = exited;
|
|
135
|
+
if (early) {
|
|
136
|
+
throw new Error(`vk dev exited early (code ${early.code ?? 'null'}) before becoming ready at ${baseUrl}`);
|
|
137
|
+
}
|
|
138
|
+
throw err;
|
|
139
|
+
}
|
|
140
|
+
return { baseUrl, port, stop };
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=stack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack.js","sourceRoot":"","sources":["../src/stack.ts"],"names":[],"mappings":"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"}
|