@c9up/atlas 0.2.0 → 0.2.1
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 +8 -0
- package/db.darwin-arm64.node +0 -0
- package/db.darwin-x64.node +0 -0
- package/db.linux-arm64-gnu.node +0 -0
- package/db.linux-x64-gnu.node +0 -0
- package/db.win32-x64-msvc.node +0 -0
- package/dist/AtlasProvider.d.ts +60 -7
- package/dist/AtlasProvider.d.ts.map +1 -1
- package/dist/AtlasProvider.js +204 -38
- package/dist/AtlasProvider.js.map +1 -1
- package/dist/BaseEntity.d.ts +17 -0
- package/dist/BaseEntity.d.ts.map +1 -1
- package/dist/BaseEntity.js.map +1 -1
- package/dist/BaseModel.d.ts +63 -27
- package/dist/BaseModel.d.ts.map +1 -1
- package/dist/BaseModel.js +108 -51
- package/dist/BaseModel.js.map +1 -1
- package/dist/BaseRepository.d.ts +11 -1
- package/dist/BaseRepository.d.ts.map +1 -1
- package/dist/BaseRepository.js +95 -20
- package/dist/BaseRepository.js.map +1 -1
- package/dist/ConnectionManager.d.ts +106 -0
- package/dist/ConnectionManager.d.ts.map +1 -0
- package/dist/ConnectionManager.js +228 -0
- package/dist/ConnectionManager.js.map +1 -0
- package/dist/ModelQuery.d.ts +256 -43
- package/dist/ModelQuery.d.ts.map +1 -1
- package/dist/ModelQuery.js +899 -231
- package/dist/ModelQuery.js.map +1 -1
- package/dist/Transaction.d.ts +54 -1
- package/dist/Transaction.d.ts.map +1 -1
- package/dist/Transaction.js +121 -59
- package/dist/Transaction.js.map +1 -1
- package/dist/adapters/NapiDbAdapter.d.ts +11 -0
- package/dist/adapters/NapiDbAdapter.d.ts.map +1 -1
- package/dist/adapters/NapiDbAdapter.js +35 -7
- package/dist/adapters/NapiDbAdapter.js.map +1 -1
- package/dist/console/contract.d.ts +62 -0
- package/dist/console/contract.d.ts.map +1 -0
- package/dist/console/contract.js +38 -0
- package/dist/console/contract.js.map +1 -0
- package/dist/console/factoryCommands.d.ts +23 -0
- package/dist/console/factoryCommands.d.ts.map +1 -0
- package/dist/console/factoryCommands.js +62 -0
- package/dist/console/factoryCommands.js.map +1 -0
- package/dist/console/migrationCommands.d.ts +38 -8
- package/dist/console/migrationCommands.d.ts.map +1 -1
- package/dist/console/migrationCommands.js +157 -50
- package/dist/console/migrationCommands.js.map +1 -1
- package/dist/console/schemaCheckCommand.d.ts +11 -17
- package/dist/console/schemaCheckCommand.d.ts.map +1 -1
- package/dist/console/schemaCheckCommand.js +21 -15
- package/dist/console/schemaCheckCommand.js.map +1 -1
- package/dist/console/schemaDumpCommand.d.ts +30 -0
- package/dist/console/schemaDumpCommand.d.ts.map +1 -0
- package/dist/console/schemaDumpCommand.js +69 -0
- package/dist/console/schemaDumpCommand.js.map +1 -0
- package/dist/console/schemaGenerateCommand.d.ts +100 -0
- package/dist/console/schemaGenerateCommand.d.ts.map +1 -0
- package/dist/console/schemaGenerateCommand.js +246 -0
- package/dist/console/schemaGenerateCommand.js.map +1 -0
- package/dist/console/seederCommands.d.ts +46 -0
- package/dist/console/seederCommands.d.ts.map +1 -0
- package/dist/console/seederCommands.js +136 -0
- package/dist/console/seederCommands.js.map +1 -0
- package/dist/decorators/entity.d.ts +13 -2
- package/dist/decorators/entity.d.ts.map +1 -1
- package/dist/decorators/entity.js +10 -0
- package/dist/decorators/entity.js.map +1 -1
- package/dist/decorators/hooks.d.ts +3 -3
- package/dist/decorators/hooks.d.ts.map +1 -1
- package/dist/decorators/hooks.js.map +1 -1
- package/dist/events.d.ts +5 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/factories.d.ts +8 -0
- package/dist/factories.d.ts.map +1 -0
- package/dist/factories.js +8 -0
- package/dist/factories.js.map +1 -0
- package/dist/index.d.ts +11 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -4
- package/dist/index.js.map +1 -1
- package/dist/lucid-schema.d.ts +15 -0
- package/dist/lucid-schema.d.ts.map +1 -0
- package/dist/lucid-schema.js +16 -0
- package/dist/lucid-schema.js.map +1 -0
- package/dist/orm.d.ts +14 -0
- package/dist/orm.d.ts.map +1 -0
- package/dist/orm.js +14 -0
- package/dist/orm.js.map +1 -0
- package/dist/query/DatabaseQueryBuilder.d.ts +557 -0
- package/dist/query/DatabaseQueryBuilder.d.ts.map +1 -0
- package/dist/query/DatabaseQueryBuilder.js +1798 -0
- package/dist/query/DatabaseQueryBuilder.js.map +1 -0
- package/dist/query/DmlBuilder.d.ts +62 -0
- package/dist/query/DmlBuilder.d.ts.map +1 -0
- package/dist/query/DmlBuilder.js +84 -0
- package/dist/query/DmlBuilder.js.map +1 -0
- package/dist/query/QueryBuilder.d.ts +5 -0
- package/dist/query/QueryBuilder.d.ts.map +1 -1
- package/dist/query/QueryBuilder.js +7 -0
- package/dist/query/QueryBuilder.js.map +1 -1
- package/dist/query/RawQueryBuilder.d.ts +47 -0
- package/dist/query/RawQueryBuilder.d.ts.map +1 -0
- package/dist/query/RawQueryBuilder.js +138 -0
- package/dist/query/RawQueryBuilder.js.map +1 -0
- package/dist/query/interpolate.d.ts +45 -0
- package/dist/query/interpolate.d.ts.map +1 -0
- package/dist/query/interpolate.js +51 -0
- package/dist/query/interpolate.js.map +1 -0
- package/dist/query/native.d.ts +8 -0
- package/dist/query/native.d.ts.map +1 -1
- package/dist/query/native.js +14 -0
- package/dist/query/native.js.map +1 -1
- package/dist/query/operators.d.ts +4 -0
- package/dist/query/operators.d.ts.map +1 -0
- package/dist/query/operators.js +27 -0
- package/dist/query/operators.js.map +1 -0
- package/dist/schema/Migration.d.ts +31 -7
- package/dist/schema/Migration.d.ts.map +1 -1
- package/dist/schema/Migration.js +34 -7
- package/dist/schema/Migration.js.map +1 -1
- package/dist/schema/MigrationRunner.d.ts +56 -6
- package/dist/schema/MigrationRunner.d.ts.map +1 -1
- package/dist/schema/MigrationRunner.js +382 -112
- package/dist/schema/MigrationRunner.js.map +1 -1
- package/dist/schema/Schema.d.ts +59 -2
- package/dist/schema/Schema.d.ts.map +1 -1
- package/dist/schema/Schema.js +143 -9
- package/dist/schema/Schema.js.map +1 -1
- package/dist/schema/SchemaDumper.d.ts +121 -0
- package/dist/schema/SchemaDumper.d.ts.map +1 -0
- package/dist/schema/SchemaDumper.js +365 -0
- package/dist/schema/SchemaDumper.js.map +1 -0
- package/dist/schema/Seeder.d.ts +13 -0
- package/dist/schema/Seeder.d.ts.map +1 -1
- package/dist/schema/Seeder.js +28 -5
- package/dist/schema/Seeder.js.map +1 -1
- package/dist/schema/TableBuilder.d.ts +27 -8
- package/dist/schema/TableBuilder.d.ts.map +1 -1
- package/dist/schema/TableBuilder.js +50 -12
- package/dist/schema/TableBuilder.js.map +1 -1
- package/dist/schema/catalog.d.ts +25 -1
- package/dist/schema/catalog.d.ts.map +1 -1
- package/dist/schema/catalog.js +69 -22
- package/dist/schema/catalog.js.map +1 -1
- package/dist/schema/introspect.d.ts +1 -1
- package/dist/schema/introspect.d.ts.map +1 -1
- package/dist/schema/introspect.js +26 -11
- package/dist/schema/introspect.js.map +1 -1
- package/dist/seeders.d.ts +7 -0
- package/dist/seeders.d.ts.map +1 -0
- package/dist/seeders.js +7 -0
- package/dist/seeders.js.map +1 -0
- package/dist/services/db.d.ts +120 -9
- package/dist/services/db.d.ts.map +1 -1
- package/dist/services/db.js +182 -26
- package/dist/services/db.js.map +1 -1
- package/dist/testing/DatabaseCleanup.d.ts +29 -6
- package/dist/testing/DatabaseCleanup.d.ts.map +1 -1
- package/dist/testing/DatabaseCleanup.js +44 -17
- package/dist/testing/DatabaseCleanup.js.map +1 -1
- package/dist/testing/DbAssertions.d.ts +48 -0
- package/dist/testing/DbAssertions.d.ts.map +1 -0
- package/dist/testing/DbAssertions.js +80 -0
- package/dist/testing/DbAssertions.js.map +1 -0
- package/dist/testing/Factory.d.ts +111 -25
- package/dist/testing/Factory.d.ts.map +1 -1
- package/dist/testing/Factory.js +331 -56
- package/dist/testing/Factory.js.map +1 -1
- package/dist/testing/TestUtils.d.ts +49 -0
- package/dist/testing/TestUtils.d.ts.map +1 -0
- package/dist/testing/TestUtils.js +79 -0
- package/dist/testing/TestUtils.js.map +1 -0
- package/dist/testing/index.d.ts +3 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +3 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/types/relations.d.ts +31 -0
- package/dist/types/relations.d.ts.map +1 -0
- package/dist/types/relations.js +20 -0
- package/dist/types/relations.js.map +1 -0
- package/index.darwin-arm64.node +0 -0
- package/index.darwin-x64.node +0 -0
- package/index.linux-arm64-gnu.node +0 -0
- package/index.linux-x64-gnu.node +0 -0
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +30 -2
- package/src/AtlasProvider.ts +297 -51
- package/src/BaseEntity.ts +29 -0
- package/src/BaseModel.ts +174 -37
- package/src/BaseRepository.ts +136 -17
- package/src/ConnectionManager.ts +298 -0
- package/src/ModelQuery.ts +1309 -260
- package/src/Transaction.ts +194 -60
- package/src/adapters/NapiDbAdapter.ts +72 -14
- package/src/console/contract.ts +96 -0
- package/src/console/factoryCommands.ts +73 -0
- package/src/console/migrationCommands.ts +253 -63
- package/src/console/schemaCheckCommand.ts +26 -22
- package/src/console/schemaDumpCommand.ts +96 -0
- package/src/console/schemaGenerateCommand.ts +380 -0
- package/src/console/seederCommands.ts +174 -0
- package/src/decorators/entity.ts +18 -2
- package/src/decorators/hooks.ts +5 -3
- package/src/events.ts +5 -0
- package/src/factories.ts +10 -0
- package/src/index.ts +50 -3
- package/src/lucid-schema.ts +22 -0
- package/src/orm.ts +13 -0
- package/src/query/DatabaseQueryBuilder.ts +2724 -0
- package/src/query/DmlBuilder.ts +131 -0
- package/src/query/QueryBuilder.ts +8 -0
- package/src/query/RawQueryBuilder.ts +173 -0
- package/src/query/interpolate.ts +73 -0
- package/src/query/native.ts +29 -0
- package/src/query/operators.ts +27 -0
- package/src/schema/Migration.ts +36 -7
- package/src/schema/MigrationRunner.ts +483 -119
- package/src/schema/Schema.ts +168 -19
- package/src/schema/SchemaDumper.ts +518 -0
- package/src/schema/Seeder.ts +47 -10
- package/src/schema/TableBuilder.ts +48 -11
- package/src/schema/catalog.ts +94 -24
- package/src/schema/introspect.ts +26 -9
- package/src/seeders.ts +16 -0
- package/src/services/db.ts +343 -31
- package/src/testing/DatabaseCleanup.ts +73 -21
- package/src/testing/DbAssertions.ts +127 -0
- package/src/testing/Factory.ts +559 -79
- package/src/testing/TestUtils.ts +123 -0
- package/src/testing/index.ts +12 -1
- package/src/types/relations.ts +43 -0
package/dist/services/db.d.ts
CHANGED
|
@@ -12,17 +12,121 @@
|
|
|
12
12
|
* swap in a custom `AsyncDatabaseConnection` through the provider's
|
|
13
13
|
* container hooks).
|
|
14
14
|
*/
|
|
15
|
+
import type { ConnectionConfig } from "../AtlasProvider.js";
|
|
15
16
|
import type { AsyncDatabaseConnection } from "../adapters/NapiDbAdapter.js";
|
|
17
|
+
import { ConnectionManager } from "../ConnectionManager.js";
|
|
18
|
+
import { DatabaseQueryBuilder, type QueryExecutor } from "../query/DatabaseQueryBuilder.js";
|
|
19
|
+
import type { AtlasDialect } from "../query/native.js";
|
|
16
20
|
import { RawSql } from "../query/QueryBuilder.js";
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
import { RawQueryBuilder } from "../query/RawQueryBuilder.js";
|
|
22
|
+
/** Options accepted by the Lucid query-builder entry points. */
|
|
23
|
+
export interface DbQueryOptions {
|
|
24
|
+
/** Route the query through this transaction client (Lucid `{ client: trx }`). */
|
|
25
|
+
client?: QueryExecutor;
|
|
26
|
+
/** `'read'` rejects writes on this builder (Lucid `db.query({ mode: 'read' })`). */
|
|
27
|
+
mode?: "read" | "write";
|
|
28
|
+
}
|
|
29
|
+
/** Options for {@link DbService.connection} (Lucid read/write replica routing). */
|
|
30
|
+
export interface ConnectionOptions {
|
|
19
31
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
32
|
+
* `'read'` scopes the returned service to reads: its query builders reject
|
|
33
|
+
* writes (insert/update/delete/increment/decrement). `'write'` (default) is
|
|
34
|
+
* unrestricted. Atlas has no replica pool, so `mode` is a write-guard rather
|
|
35
|
+
* than a routing hint — the guard is the security-relevant half of Lucid's
|
|
36
|
+
* read/write modes.
|
|
37
|
+
*/
|
|
38
|
+
mode?: "read" | "write";
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The `db` service surface — Adonis Lucid's `Database` service. Exposes the
|
|
42
|
+
* query builders (`query`/`from`/`table`/`insertQuery`), raw execution
|
|
43
|
+
* (`rawQuery`), the `raw()` fragment builder, connection scoping (`connection`),
|
|
44
|
+
* and the transaction/DDL methods forwarded from the bound connection.
|
|
45
|
+
*/
|
|
46
|
+
export interface DbService {
|
|
47
|
+
/** A connection-level query builder (Lucid `db.query()`), optionally on a trx. */
|
|
48
|
+
query(options?: DbQueryOptions): DatabaseQueryBuilder;
|
|
49
|
+
/** Query builder with the table pre-selected (Lucid `db.from(table)`). */
|
|
50
|
+
from(table: string): DatabaseQueryBuilder;
|
|
51
|
+
/**
|
|
52
|
+
* Query builder on a derived-table source (Lucid `db.from(subquery, alias)`) —
|
|
53
|
+
* a builder OR a callback that builds one.
|
|
54
|
+
*/
|
|
55
|
+
from(subquery: DatabaseQueryBuilder | ((query: DatabaseQueryBuilder) => void), alias?: string): DatabaseQueryBuilder;
|
|
56
|
+
/** Insert/write builder with the table pre-selected (Lucid `db.table(table)`). */
|
|
57
|
+
table(table: string): DatabaseQueryBuilder;
|
|
58
|
+
/** An insert builder (Lucid `db.insertQuery()`), optionally on a trx. */
|
|
59
|
+
insertQuery(options?: DbQueryOptions): DatabaseQueryBuilder;
|
|
60
|
+
/**
|
|
61
|
+
* A chainable raw query (Lucid `db.rawQuery(sql, bindings)`). Thenable — can be
|
|
62
|
+
* awaited directly — and exposes `toSQL`/`toQuery`/`debug`/`timeout`/
|
|
63
|
+
* `reporterData`. Bindings may be positional (`?`/`??`) or named (`:name`/`:name:`).
|
|
64
|
+
*/
|
|
65
|
+
rawQuery<T = Record<string, unknown>>(sql: string, bindings?: unknown[] | Record<string, unknown>): RawQueryBuilder<T>;
|
|
66
|
+
/**
|
|
67
|
+
* Scope the service to a connection (Lucid `db.connection(name)`). Called with
|
|
68
|
+
* no name it returns the default connection's service (Lucid `db.connection()`).
|
|
69
|
+
* Pass `{ mode: 'read' }` to reject writes on the returned service (Lucid
|
|
70
|
+
* `db.connection(name, { mode: 'read' })`).
|
|
71
|
+
*/
|
|
72
|
+
connection(name?: string, options?: ConnectionOptions): DbService;
|
|
73
|
+
/**
|
|
74
|
+
* Query builder for a model whose class is resolved at runtime (Lucid
|
|
75
|
+
* `db.modelQuery(Model)`). For static code prefer `Model.query()` directly.
|
|
76
|
+
*/
|
|
77
|
+
modelQuery<Q>(model: {
|
|
78
|
+
query(): Q;
|
|
79
|
+
}): Q;
|
|
80
|
+
/**
|
|
81
|
+
* Build a raw SQL expression — AdonisJS `db.raw()`. For query fragments and
|
|
82
|
+
* column defaults that are SQL expressions:
|
|
22
83
|
*
|
|
23
84
|
* t.uuid('id').defaultTo(db.raw('gen_random_uuid()'))
|
|
85
|
+
*
|
|
86
|
+
* Bindings may be positional (`?`/`??`) or named (`:name`/`:name:`).
|
|
87
|
+
*/
|
|
88
|
+
raw(sql: string, params?: unknown[] | Record<string, unknown>): RawSql;
|
|
89
|
+
/**
|
|
90
|
+
* A column reference — Adonis Lucid `db.ref('posts.created_at')`. Use it where
|
|
91
|
+
* a value position must be read as a column (e.g. `orderBy(db.ref(col), 'desc')`).
|
|
92
|
+
* The identifier is validated and dialect-quoted; it is NOT a value binding.
|
|
93
|
+
*/
|
|
94
|
+
ref(column: string): RawSql;
|
|
95
|
+
/** Run a statement for effect (forwarded to the connection). */
|
|
96
|
+
execute(sql: string, params?: unknown[]): Promise<{
|
|
97
|
+
rowsAffected: number;
|
|
98
|
+
}>;
|
|
99
|
+
/** Managed/manual interactive transaction (forwarded, Lucid `db.transaction`). */
|
|
100
|
+
transaction: AsyncDatabaseConnection["transaction"];
|
|
101
|
+
/** Atomic batch (forwarded). */
|
|
102
|
+
runInTransaction: AsyncDatabaseConnection["runInTransaction"];
|
|
103
|
+
/**
|
|
104
|
+
* Empty a table (Lucid `truncate`). `TRUNCATE TABLE` on Postgres/MySQL (with
|
|
105
|
+
* `CASCADE` when `cascade` is set, Postgres only); `DELETE FROM` on SQLite,
|
|
106
|
+
* which has no `TRUNCATE`.
|
|
24
107
|
*/
|
|
25
|
-
|
|
108
|
+
truncate(table: string, cascade?: boolean): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* Empty every user table (Lucid `truncateAllTables`). Framework tables
|
|
111
|
+
* (`ream_*`) and dialect internals are left alone; pass `ignoreTables` to spare
|
|
112
|
+
* more. Foreign keys are suspended so delete order doesn't matter.
|
|
113
|
+
*/
|
|
114
|
+
truncateAllTables(ignoreTables?: readonly string[]): Promise<void>;
|
|
115
|
+
/**
|
|
116
|
+
* Try to acquire a session-level advisory lock, non-blocking (Lucid
|
|
117
|
+
* `getAdvisoryLock`). Postgres `pg_try_advisory_lock`, MySQL `GET_LOCK(key, 0)`.
|
|
118
|
+
* A string key is hashed to the integer Postgres requires. Returns whether the
|
|
119
|
+
* lock was acquired. **Throws on SQLite** (no advisory locks — Lucid parity).
|
|
120
|
+
*/
|
|
121
|
+
getAdvisoryLock(key: string | number): Promise<boolean>;
|
|
122
|
+
/** Release an advisory lock taken with {@link getAdvisoryLock}. Throws on SQLite. */
|
|
123
|
+
releaseAdvisoryLock(key: string | number): Promise<boolean>;
|
|
124
|
+
/** The full Lucid connection manager (`add`/`connect`/`patch`/`release`/nodes/events). */
|
|
125
|
+
readonly manager: ConnectionManager;
|
|
126
|
+
/** The bound connection's dialect. */
|
|
127
|
+
readonly dialect: AtlasDialect;
|
|
128
|
+
ping(): Promise<void>;
|
|
129
|
+
close(): Promise<void>;
|
|
26
130
|
}
|
|
27
131
|
/** @internal Bind the singleton (called by AtlasProvider). */
|
|
28
132
|
export declare function setDb(connection: AsyncDatabaseConnection): void;
|
|
@@ -35,12 +139,19 @@ export declare function setDb(connection: AsyncDatabaseConnection): void;
|
|
|
35
139
|
export declare function clearDb(connection: AsyncDatabaseConnection): void;
|
|
36
140
|
/** @internal Read the singleton (or `undefined` pre-boot). */
|
|
37
141
|
export declare function getDb(): AsyncDatabaseConnection | undefined;
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
|
|
142
|
+
/**
|
|
143
|
+
* @internal Register an already-open named connection (called by AtlasProvider,
|
|
144
|
+
* which opens connections itself). Records the config on the node too.
|
|
145
|
+
*/
|
|
146
|
+
export declare function registerConnection(name: string, connection: AsyncDatabaseConnection, config?: ConnectionConfig): void;
|
|
147
|
+
/** @internal Unregister a named connection IF it still points at `connection` (no close). */
|
|
41
148
|
export declare function unregisterConnection(name: string, connection: AsyncDatabaseConnection): void;
|
|
42
|
-
/** @internal Resolve a named connection (for `BaseModel.connection`), or `undefined`. */
|
|
149
|
+
/** @internal Resolve a live named connection (for `BaseModel.connection`), or `undefined`. */
|
|
43
150
|
export declare function getConnection(name: string): AsyncDatabaseConnection | undefined;
|
|
151
|
+
/** @internal The shared connection manager (for the AtlasProvider lifecycle-event bridge). */
|
|
152
|
+
export declare function connectionManager(): ConnectionManager;
|
|
153
|
+
/** Build a {@link DbService} over a resolver that yields the live connection. */
|
|
154
|
+
export declare function createDbService(resolve: () => AsyncDatabaseConnection, readOnly?: boolean): DbService;
|
|
44
155
|
declare const db: DbService;
|
|
45
156
|
export default db;
|
|
46
157
|
//# sourceMappingURL=db.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/services/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/services/db.ts"],"names":[],"mappings":"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"}
|
package/dist/services/db.js
CHANGED
|
@@ -12,7 +12,11 @@
|
|
|
12
12
|
* swap in a custom `AsyncDatabaseConnection` through the provider's
|
|
13
13
|
* container hooks).
|
|
14
14
|
*/
|
|
15
|
+
import { ConnectionManager } from "../ConnectionManager.js";
|
|
16
|
+
import { DatabaseQueryBuilder, } from "../query/DatabaseQueryBuilder.js";
|
|
15
17
|
import { RawSql } from "../query/QueryBuilder.js";
|
|
18
|
+
import { RawQueryBuilder, resolveRawBindings, } from "../query/RawQueryBuilder.js";
|
|
19
|
+
import { truncateAll } from "../testing/DatabaseCleanup.js";
|
|
16
20
|
let instance;
|
|
17
21
|
/** @internal Bind the singleton (called by AtlasProvider). */
|
|
18
22
|
export function setDb(connection) {
|
|
@@ -32,38 +36,190 @@ export function clearDb(connection) {
|
|
|
32
36
|
export function getDb() {
|
|
33
37
|
return instance;
|
|
34
38
|
}
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
const
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
// The shared connection manager (Lucid `db.manager`) — the single owner of named
|
|
40
|
+
// connections. Backs `BaseModel.connection = 'analytics'` so a model resolves a
|
|
41
|
+
// non-default connection from a plain import (AdonisJS `static connection`).
|
|
42
|
+
const manager = new ConnectionManager();
|
|
43
|
+
/**
|
|
44
|
+
* @internal Register an already-open named connection (called by AtlasProvider,
|
|
45
|
+
* which opens connections itself). Records the config on the node too.
|
|
46
|
+
*/
|
|
47
|
+
export function registerConnection(name, connection, config = {}) {
|
|
48
|
+
manager.register(name, config, connection);
|
|
42
49
|
}
|
|
43
|
-
/** @internal Unregister a named connection IF it still points at `connection
|
|
50
|
+
/** @internal Unregister a named connection IF it still points at `connection` (no close). */
|
|
44
51
|
export function unregisterConnection(name, connection) {
|
|
45
|
-
|
|
46
|
-
namedConnections.delete(name);
|
|
52
|
+
manager.deregister(name, connection);
|
|
47
53
|
}
|
|
48
|
-
/** @internal Resolve a named connection (for `BaseModel.connection`), or `undefined`. */
|
|
54
|
+
/** @internal Resolve a live named connection (for `BaseModel.connection`), or `undefined`. */
|
|
49
55
|
export function getConnection(name) {
|
|
50
|
-
return
|
|
56
|
+
return manager.connection(name);
|
|
51
57
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
/** @internal The shared connection manager (for the AtlasProvider lifecycle-event bridge). */
|
|
59
|
+
export function connectionManager() {
|
|
60
|
+
return manager;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Coerce an advisory-lock key to the integer Postgres `pg_*_advisory_lock`
|
|
64
|
+
* requires. Numeric keys pass through; string keys are hashed deterministically
|
|
65
|
+
* (FNV-1a, 32-bit) so lock and unlock agree. Stable within a process is all that
|
|
66
|
+
* matters — atlas never shares a lock namespace with Knex.
|
|
67
|
+
*/
|
|
68
|
+
function advisoryLockKey(key) {
|
|
69
|
+
if (typeof key === "number")
|
|
70
|
+
return Math.trunc(key);
|
|
71
|
+
let hash = 0x811c9dc5;
|
|
72
|
+
for (let i = 0; i < key.length; i++) {
|
|
73
|
+
hash ^= key.charCodeAt(i);
|
|
74
|
+
hash = Math.imul(hash, 0x01000193);
|
|
75
|
+
}
|
|
76
|
+
return hash | 0; // signed 32-bit — fits Postgres int/bigint
|
|
77
|
+
}
|
|
78
|
+
/** Validate + dialect-quote a (dot-qualified) identifier. Rejects anything unsafe. */
|
|
79
|
+
function quoteIdent(name, dialect) {
|
|
80
|
+
const q = dialect === "mysql" ? "`" : '"';
|
|
81
|
+
return name
|
|
82
|
+
.split(".")
|
|
83
|
+
.map((seg) => {
|
|
84
|
+
if (seg === "*")
|
|
85
|
+
return seg;
|
|
86
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(seg)) {
|
|
87
|
+
throw new Error(`atlas: invalid identifier segment '${seg}' in '${name}'`);
|
|
63
88
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
89
|
+
return `${q}${seg}${q}`;
|
|
90
|
+
})
|
|
91
|
+
.join(".");
|
|
92
|
+
}
|
|
93
|
+
/** Build a {@link DbService} over a resolver that yields the live connection. */
|
|
94
|
+
export function createDbService(resolve, readOnly = false) {
|
|
95
|
+
const opts = readOnly ? { readOnly } : undefined;
|
|
96
|
+
// Per-call `{ mode: 'read' }` also yields a write-guarded builder, even on an
|
|
97
|
+
// unscoped service (Lucid `db.query({ mode: 'read' })`).
|
|
98
|
+
const optsFor = (options) => readOnly || options?.mode === "read" ? { readOnly: true } : undefined;
|
|
99
|
+
return {
|
|
100
|
+
query(options) {
|
|
101
|
+
const conn = resolve();
|
|
102
|
+
return new DatabaseQueryBuilder(options?.client ?? conn, conn.dialect, "", optsFor(options));
|
|
103
|
+
},
|
|
104
|
+
from(source, alias) {
|
|
105
|
+
const conn = resolve();
|
|
106
|
+
const builder = new DatabaseQueryBuilder(conn, conn.dialect, "", opts);
|
|
107
|
+
return typeof source === "string"
|
|
108
|
+
? builder.from(source)
|
|
109
|
+
: builder.from(source, alias);
|
|
110
|
+
},
|
|
111
|
+
table(table) {
|
|
112
|
+
const conn = resolve();
|
|
113
|
+
return new DatabaseQueryBuilder(conn, conn.dialect, table, opts);
|
|
114
|
+
},
|
|
115
|
+
insertQuery(options) {
|
|
116
|
+
const conn = resolve();
|
|
117
|
+
return new DatabaseQueryBuilder(options?.client ?? conn, conn.dialect, "", optsFor(options));
|
|
118
|
+
},
|
|
119
|
+
rawQuery(sql, bindings = []) {
|
|
120
|
+
const conn = resolve();
|
|
121
|
+
return new RawQueryBuilder(conn, conn.dialect, sql, bindings);
|
|
122
|
+
},
|
|
123
|
+
connection(name, connOptions) {
|
|
124
|
+
// No name → the default connection's service (Lucid `db.connection()`).
|
|
125
|
+
if (name === undefined) {
|
|
126
|
+
return createDbService(resolve, connOptions?.mode === "read");
|
|
127
|
+
}
|
|
128
|
+
return createDbService(() => {
|
|
129
|
+
const conn = getConnection(name);
|
|
130
|
+
if (!conn) {
|
|
131
|
+
throw new Error(`[atlas] no connection registered under '${name}'. Is it in config/database.ts connections?`);
|
|
132
|
+
}
|
|
133
|
+
return conn;
|
|
134
|
+
}, connOptions?.mode === "read");
|
|
135
|
+
},
|
|
136
|
+
modelQuery(model) {
|
|
137
|
+
return model.query();
|
|
138
|
+
},
|
|
139
|
+
raw(sql, params = []) {
|
|
140
|
+
// Resolve `??`/named bindings only when present, so the common
|
|
141
|
+
// positional/no-binding path (and Postgres `::casts`) is untouched.
|
|
142
|
+
const hasNamed = !Array.isArray(params);
|
|
143
|
+
const hasIdent = typeof sql === "string" && sql.includes("??");
|
|
144
|
+
if (!hasNamed && !hasIdent) {
|
|
145
|
+
return new RawSql(sql, params);
|
|
146
|
+
}
|
|
147
|
+
const resolved = resolveRawBindings(sql, params, resolve().dialect);
|
|
148
|
+
return new RawSql(resolved.sql, resolved.params);
|
|
149
|
+
},
|
|
150
|
+
ref(column) {
|
|
151
|
+
return new RawSql(quoteIdent(column, resolve().dialect), []);
|
|
152
|
+
},
|
|
153
|
+
async truncate(table, cascade) {
|
|
154
|
+
const conn = resolve();
|
|
155
|
+
const t = quoteIdent(table, conn.dialect);
|
|
156
|
+
// SQLite has no TRUNCATE — DELETE clears the table (Lucid does the same).
|
|
157
|
+
const sql = conn.dialect === "sqlite"
|
|
158
|
+
? `DELETE FROM ${t}`
|
|
159
|
+
: conn.dialect === "postgres"
|
|
160
|
+
? `TRUNCATE TABLE ${t}${cascade ? " CASCADE" : ""}`
|
|
161
|
+
: `TRUNCATE TABLE ${t}`;
|
|
162
|
+
await conn.execute(sql, []);
|
|
163
|
+
},
|
|
164
|
+
truncateAllTables(ignoreTables = []) {
|
|
165
|
+
return truncateAll(resolve(), ignoreTables);
|
|
166
|
+
},
|
|
167
|
+
async getAdvisoryLock(key) {
|
|
168
|
+
const conn = resolve();
|
|
169
|
+
if (conn.dialect === "sqlite") {
|
|
170
|
+
throw new Error("[atlas] advisory locks are not supported on SQLite (Postgres/MySQL only).");
|
|
171
|
+
}
|
|
172
|
+
if (conn.dialect === "postgres") {
|
|
173
|
+
const rows = await conn.query("SELECT pg_try_advisory_lock($1) AS locked", [advisoryLockKey(key)]);
|
|
174
|
+
return Boolean(rows[0]?.locked);
|
|
175
|
+
}
|
|
176
|
+
// MySQL: GET_LOCK(name, 0) → non-blocking try (1 acquired, 0 busy).
|
|
177
|
+
const rows = await conn.query("SELECT GET_LOCK(?, 0) AS locked", [String(key)]);
|
|
178
|
+
return Number(rows[0]?.locked) === 1;
|
|
179
|
+
},
|
|
180
|
+
async releaseAdvisoryLock(key) {
|
|
181
|
+
const conn = resolve();
|
|
182
|
+
if (conn.dialect === "sqlite") {
|
|
183
|
+
throw new Error("[atlas] advisory locks are not supported on SQLite (Postgres/MySQL only).");
|
|
184
|
+
}
|
|
185
|
+
if (conn.dialect === "postgres") {
|
|
186
|
+
const rows = await conn.query("SELECT pg_advisory_unlock($1) AS released", [advisoryLockKey(key)]);
|
|
187
|
+
return Boolean(rows[0]?.released);
|
|
188
|
+
}
|
|
189
|
+
const rows = await conn.query("SELECT RELEASE_LOCK(?) AS released", [String(key)]);
|
|
190
|
+
return Number(rows[0]?.released) === 1;
|
|
191
|
+
},
|
|
192
|
+
get manager() {
|
|
193
|
+
return manager;
|
|
194
|
+
},
|
|
195
|
+
execute(sql, params) {
|
|
196
|
+
return resolve().execute(sql, params);
|
|
197
|
+
},
|
|
198
|
+
get transaction() {
|
|
199
|
+
return resolve().transaction?.bind(resolve());
|
|
200
|
+
},
|
|
201
|
+
runInTransaction(batch) {
|
|
202
|
+
return resolve().runInTransaction(batch);
|
|
203
|
+
},
|
|
204
|
+
get dialect() {
|
|
205
|
+
return resolve().dialect;
|
|
206
|
+
},
|
|
207
|
+
ping() {
|
|
208
|
+
return resolve().ping();
|
|
209
|
+
},
|
|
210
|
+
close() {
|
|
211
|
+
return resolve().close();
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
const db = createDbService(() => {
|
|
216
|
+
if (!instance) {
|
|
217
|
+
throw new Error("[atlas] db singleton accessed before AtlasProvider.boot() ran. " +
|
|
218
|
+
"Check that `@c9up/atlas/provider` is listed in your reamrc.ts " +
|
|
219
|
+
"providers and that `config/database.ts` defines at least one " +
|
|
220
|
+
"connection.");
|
|
221
|
+
}
|
|
222
|
+
return instance;
|
|
67
223
|
});
|
|
68
224
|
export default db;
|
|
69
225
|
//# sourceMappingURL=db.js.map
|
package/dist/services/db.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/services/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/services/db.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,19 +4,42 @@
|
|
|
4
4
|
* @implements MISS-19
|
|
5
5
|
*/
|
|
6
6
|
import type { AsyncDatabaseConnection } from "../adapters/NapiDbAdapter.js";
|
|
7
|
+
import type { TransactionClient } from "../Transaction.js";
|
|
8
|
+
/** What {@link useTransaction} hands back: the pinned trx plus its teardown. */
|
|
9
|
+
export interface TestTransaction {
|
|
10
|
+
/**
|
|
11
|
+
* The interactive transaction, pinned to ONE pooled connection. Run every
|
|
12
|
+
* query the test makes through THIS handle (`trx.query` / `trx.execute`, or
|
|
13
|
+
* `repo.useTransaction(trx)`), never the pooled `db` — that is what makes the
|
|
14
|
+
* rollback isolate the test.
|
|
15
|
+
*/
|
|
16
|
+
trx: TransactionClient;
|
|
17
|
+
/** Roll everything the test did back and return the connection to the pool. */
|
|
18
|
+
rollback: () => Promise<void>;
|
|
19
|
+
}
|
|
7
20
|
/**
|
|
8
|
-
*
|
|
21
|
+
* Isolate a test by running it inside a transaction that is rolled back after
|
|
22
|
+
* (Adonis Lucid parity — Lucid's tests use `db.transaction()` the same way).
|
|
23
|
+
*
|
|
24
|
+
* The earlier implementation issued `SAVEPOINT` / `ROLLBACK` through the pooled
|
|
25
|
+
* `db`, so with `poolMax > 1` the savepoint and its rollback — and the test's
|
|
26
|
+
* own queries — could each land on a DIFFERENT pooled connection, and the
|
|
27
|
+
* "isolation" silently did nothing. This pins a single interactive transaction
|
|
28
|
+
* instead: every query on the returned `trx` runs on that one connection, and
|
|
29
|
+
* `rollback()` reverts them together, correctly on any pool size.
|
|
9
30
|
*/
|
|
10
|
-
export declare function useTransaction(db: AsyncDatabaseConnection): Promise<
|
|
31
|
+
export declare function useTransaction(db: AsyncDatabaseConnection): Promise<TestTransaction>;
|
|
11
32
|
/**
|
|
12
33
|
* Empty every user table (leaves `ream_*` framework tables and dialect
|
|
13
34
|
* internals alone). Works on all three dialects — the table list comes from the
|
|
14
35
|
* shared dialect-aware catalog helper, not a SQLite-only `sqlite_master` query.
|
|
15
36
|
*
|
|
16
37
|
* Foreign keys are suspended for the duration so the delete order doesn't
|
|
17
|
-
* matter
|
|
18
|
-
*
|
|
19
|
-
*
|
|
38
|
+
* matter. The FK toggle and every DELETE run on ONE pinned connection (via
|
|
39
|
+
* `runWithoutForeignKeys` → `runInTransaction`), so a connection pool can't
|
|
40
|
+
* scatter the connection-local `PRAGMA`/`SET` away from the deletes. The row
|
|
41
|
+
* removal goes through the Rust compiler (`DELETE` — cross-dialect, unlike
|
|
42
|
+
* `TRUNCATE` which auto-commits on MySQL).
|
|
20
43
|
*/
|
|
21
|
-
export declare function truncateAll(db: AsyncDatabaseConnection): Promise<void>;
|
|
44
|
+
export declare function truncateAll(db: AsyncDatabaseConnection, ignoreTables?: readonly string[]): Promise<void>;
|
|
22
45
|
//# sourceMappingURL=DatabaseCleanup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatabaseCleanup.d.ts","sourceRoot":"","sources":["../../src/testing/DatabaseCleanup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAI5E
|
|
1
|
+
{"version":3,"file":"DatabaseCleanup.d.ts","sourceRoot":"","sources":["../../src/testing/DatabaseCleanup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAI5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC/B;;;;;OAKG;IACH,GAAG,EAAE,iBAAiB,CAAC;IACvB,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CACnC,EAAE,EAAE,uBAAuB,GACzB,OAAO,CAAC,eAAe,CAAC,CAc1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAChC,EAAE,EAAE,uBAAuB,EAC3B,YAAY,GAAE,SAAS,MAAM,EAAO,GAClC,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
|
|
@@ -3,17 +3,30 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @implements MISS-19
|
|
5
5
|
*/
|
|
6
|
+
import { AtlasError } from "../errors.js";
|
|
6
7
|
import { compileStatementNative } from "../query/native.js";
|
|
7
|
-
import { listUserTables,
|
|
8
|
+
import { listUserTables, runWithoutForeignKeys } from "../schema/catalog.js";
|
|
8
9
|
/**
|
|
9
|
-
*
|
|
10
|
+
* Isolate a test by running it inside a transaction that is rolled back after
|
|
11
|
+
* (Adonis Lucid parity — Lucid's tests use `db.transaction()` the same way).
|
|
12
|
+
*
|
|
13
|
+
* The earlier implementation issued `SAVEPOINT` / `ROLLBACK` through the pooled
|
|
14
|
+
* `db`, so with `poolMax > 1` the savepoint and its rollback — and the test's
|
|
15
|
+
* own queries — could each land on a DIFFERENT pooled connection, and the
|
|
16
|
+
* "isolation" silently did nothing. This pins a single interactive transaction
|
|
17
|
+
* instead: every query on the returned `trx` runs on that one connection, and
|
|
18
|
+
* `rollback()` reverts them together, correctly on any pool size.
|
|
10
19
|
*/
|
|
11
20
|
export async function useTransaction(db) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
21
|
+
if (typeof db.transaction !== "function") {
|
|
22
|
+
throw new AtlasError("E_NO_INTERACTIVE_TRANSACTION", "useTransaction() needs a connection with an interactive transaction() (a real napi connection); this adapter has none.", {
|
|
23
|
+
hint: "Use createNapiConnection(), or drive rollback yourself if your adapter can't pin a connection.",
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
// Manual (callback-less) mode: a pinned TransactionClient the test drives and
|
|
27
|
+
// tears down via rollback() — no cross-pool savepoint scatter.
|
|
28
|
+
const trx = await db.transaction();
|
|
29
|
+
return { trx, rollback: () => trx.rollback() };
|
|
17
30
|
}
|
|
18
31
|
/**
|
|
19
32
|
* Empty every user table (leaves `ream_*` framework tables and dialect
|
|
@@ -21,22 +34,36 @@ export async function useTransaction(db) {
|
|
|
21
34
|
* shared dialect-aware catalog helper, not a SQLite-only `sqlite_master` query.
|
|
22
35
|
*
|
|
23
36
|
* Foreign keys are suspended for the duration so the delete order doesn't
|
|
24
|
-
* matter
|
|
25
|
-
*
|
|
26
|
-
*
|
|
37
|
+
* matter. The FK toggle and every DELETE run on ONE pinned connection (via
|
|
38
|
+
* `runWithoutForeignKeys` → `runInTransaction`), so a connection pool can't
|
|
39
|
+
* scatter the connection-local `PRAGMA`/`SET` away from the deletes. The row
|
|
40
|
+
* removal goes through the Rust compiler (`DELETE` — cross-dialect, unlike
|
|
41
|
+
* `TRUNCATE` which auto-commits on MySQL).
|
|
27
42
|
*/
|
|
28
|
-
export async function truncateAll(db) {
|
|
43
|
+
export async function truncateAll(db, ignoreTables = []) {
|
|
29
44
|
// The connection's own dialect, not the module default — correct even when
|
|
30
45
|
// an app runs several connections on different engines.
|
|
31
46
|
const dialect = db.dialect;
|
|
32
|
-
const
|
|
47
|
+
const ignore = new Set(ignoreTables);
|
|
48
|
+
const tables = (await listUserTables(db, dialect)).filter((t) => !ignore.has(t));
|
|
33
49
|
if (tables.length === 0)
|
|
34
50
|
return;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
// Postgres: a plain DELETE respects FKs immediately (atlas FKs aren't
|
|
52
|
+
// DEFERRABLE), so deleting a parent before its children raises 23503 — and
|
|
53
|
+
// nothing orders the tables. `TRUNCATE … CASCADE` is transactional on pg,
|
|
54
|
+
// order-independent, and needs no session-level FK toggle to leak. (Names
|
|
55
|
+
// come from the DB catalog; quote them for identifiers with embedded quotes.)
|
|
56
|
+
if (dialect === "postgres") {
|
|
57
|
+
const list = tables.map((t) => `"${t.replace(/"/g, '""')}"`).join(", ");
|
|
58
|
+
await db.execute(`TRUNCATE ${list} RESTART IDENTITY CASCADE`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// MySQL/SQLite: DELETE (TRUNCATE auto-commits on MySQL, breaking test
|
|
62
|
+
// transaction isolation), with FK suspension on ONE pinned connection.
|
|
63
|
+
const statements = tables.map((name) => {
|
|
64
|
+
const compiled = compileStatementNative({ kind: "delete", table: name, wheres: [] }, dialect);
|
|
65
|
+
return { sql: compiled.statements[0], params: compiled.params };
|
|
40
66
|
});
|
|
67
|
+
await runWithoutForeignKeys(db, dialect, statements);
|
|
41
68
|
}
|
|
42
69
|
//# sourceMappingURL=DatabaseCleanup.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatabaseCleanup.js","sourceRoot":"","sources":["../../src/testing/DatabaseCleanup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"DatabaseCleanup.js","sourceRoot":"","sources":["../../src/testing/DatabaseCleanup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAgB7E;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,EAA2B;IAE3B,IAAI,OAAO,EAAE,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;QAC1C,MAAM,IAAI,UAAU,CACnB,8BAA8B,EAC9B,wHAAwH,EACxH;YACC,IAAI,EAAE,gGAAgG;SACtG,CACD,CAAC;IACH,CAAC;IACD,8EAA8E;IAC9E,+DAA+D;IAC/D,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC;IACnC,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;AAChD,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,EAA2B,EAC3B,eAAkC,EAAE;IAEpC,2EAA2E;IAC3E,wDAAwD;IACxD,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,CAAC,MAAM,cAAc,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CACxD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CACrB,CAAC;IACF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEhC,sEAAsE;IACtE,2EAA2E;IAC3E,0EAA0E;IAC1E,0EAA0E;IAC1E,8EAA8E;IAC9E,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxE,MAAM,EAAE,CAAC,OAAO,CAAC,YAAY,IAAI,2BAA2B,CAAC,CAAC;QAC9D,OAAO;IACR,CAAC;IAED,sEAAsE;IACtE,uEAAuE;IACvE,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACtC,MAAM,QAAQ,GAAG,sBAAsB,CACtC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAC3C,OAAO,CACP,CAAC;QACF,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IACjE,CAAC,CAAC,CAAC;IACH,MAAM,qBAAqB,CAAC,EAAE,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `db()` — a helix plugin (AdonisJS Lucid database-assertions parity) that
|
|
3
|
+
* injects database assertions on the test context as `ctx.db`:
|
|
4
|
+
*
|
|
5
|
+
* // tests/bootstrap.ts
|
|
6
|
+
* import { configure } from "@c9up/helix";
|
|
7
|
+
* import { db } from "@c9up/atlas/testing";
|
|
8
|
+
* await configure({ plugins: [db(connection)] });
|
|
9
|
+
*
|
|
10
|
+
* test("registers the user", async ({ db }) => {
|
|
11
|
+
* await db.assertHas("users", { email: "a@b.c" });
|
|
12
|
+
* await db.assertCount("users", 1);
|
|
13
|
+
* });
|
|
14
|
+
*
|
|
15
|
+
* Values are always bound as parameters; table/column identifiers are validated
|
|
16
|
+
* against a strict pattern (letters, digits, `_`, `.`) and quoted, so neither a
|
|
17
|
+
* value nor an identifier can inject SQL.
|
|
18
|
+
*
|
|
19
|
+
* NOTE (namespace): the AdonisJS docs expose these as `db.assert*`; the exact
|
|
20
|
+
* surface is re-verified against the Adonis docs when available. Model-based
|
|
21
|
+
* `assertModelExists`/`assertModelMissing` (entity PK metadata) are pending.
|
|
22
|
+
*/
|
|
23
|
+
import type { Plugin } from "@c9up/helix";
|
|
24
|
+
/** The minimal connection the assertions need — a parameterized query runner. */
|
|
25
|
+
export interface DbConnectionLike {
|
|
26
|
+
query(sql: string, params?: unknown[]): Promise<Record<string, unknown>[]>;
|
|
27
|
+
}
|
|
28
|
+
/** The `ctx.db` assertion surface (AdonisJS Lucid database-assertions parity). */
|
|
29
|
+
export interface DbAssertions {
|
|
30
|
+
/** At least one row in `table` matches every column in `payload`. */
|
|
31
|
+
assertHas(table: string, payload: Record<string, unknown>): Promise<void>;
|
|
32
|
+
/** No row in `table` matches `payload`. */
|
|
33
|
+
assertMissing(table: string, payload: Record<string, unknown>): Promise<void>;
|
|
34
|
+
/** `table` has exactly `expected` rows (optionally matching `payload`). */
|
|
35
|
+
assertCount(table: string, expected: number, payload?: Record<string, unknown>): Promise<void>;
|
|
36
|
+
/** `table` has no rows at all. */
|
|
37
|
+
assertEmpty(table: string): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
/** Build the assertion surface bound to a connection. */
|
|
40
|
+
export declare function createDbAssertions(conn: DbConnectionLike): DbAssertions;
|
|
41
|
+
/** The `db()` helix plugin — registers {@link DbAssertions} as `ctx.db`. */
|
|
42
|
+
export declare function db(conn: DbConnectionLike): Plugin;
|
|
43
|
+
declare module "@c9up/helix" {
|
|
44
|
+
interface TestContext {
|
|
45
|
+
db: DbAssertions;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=DbAssertions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DbAssertions.d.ts","sourceRoot":"","sources":["../../src/testing/DbAssertions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,iFAAiF;AACjF,MAAM,WAAW,gBAAgB;IAChC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;CAC3E;AA+BD,kFAAkF;AAClF,MAAM,WAAW,YAAY;IAC5B,qEAAqE;IACrE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,2CAA2C;IAC3C,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,2EAA2E;IAC3E,WAAW,CACV,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,kCAAkC;IAClC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,yDAAyD;AACzD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,CAkCvE;AAED,4EAA4E;AAC5E,wBAAgB,EAAE,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAKjD;AAID,OAAO,QAAQ,aAAa,CAAC;IAC5B,UAAU,WAAW;QACpB,EAAE,EAAE,YAAY,CAAC;KACjB;CACD"}
|