fluxor-cloud-db 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/npm-publish.yml +34 -0
- package/README.md +296 -0
- package/dist/index.d.mts +347 -0
- package/dist/index.d.ts +347 -0
- package/dist/index.js +1844 -0
- package/dist/index.mjs +1811 -0
- package/jest.config.ts +12 -0
- package/package.json +33 -0
- package/src/contracts/database-adapter.ts +161 -0
- package/src/dynamo/dynamo.ts +859 -0
- package/src/dynamo/dynamo.types.ts +8 -0
- package/src/fluentapi.ts +71 -0
- package/src/index.ts +39 -0
- package/src/mongo/mongo.ts +690 -0
- package/src/types/error.ts +13 -0
- package/src/types/query.ts +53 -0
- package/tests/dynamodb.test.ts +547 -0
- package/tests/mongodb.test.ts +486 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Node.js Package
|
|
2
|
+
|
|
3
|
+
# Trigger on push to main
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- master
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: actions/setup-node@v4
|
|
15
|
+
with:
|
|
16
|
+
node-version: 20
|
|
17
|
+
- run: npm ci
|
|
18
|
+
# No test enforcement at this point, there's no local database servers etc...
|
|
19
|
+
# in github's runner. All unit tests must be done offline, this means manual
|
|
20
|
+
# verification is required per PR.
|
|
21
|
+
|
|
22
|
+
publish-npm:
|
|
23
|
+
needs: build
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v4
|
|
27
|
+
- uses: actions/setup-node@v4
|
|
28
|
+
with:
|
|
29
|
+
node-version: 20
|
|
30
|
+
registry-url: https://registry.npmjs.org/
|
|
31
|
+
- run: npm ci
|
|
32
|
+
- run: npm publish
|
|
33
|
+
env:
|
|
34
|
+
NODE_AUTH_TOKEN: ${{ secrets.npm_token }}
|
package/README.md
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# fluxor-cloud-db
|
|
2
|
+
|
|
3
|
+
Database adapter layer for [fluxor-cloud](https://github.com/hudson1998x/fluxor) services. Provides a unified query interface over DynamoDB and MongoDB, with a shared `WhereClause` / operator syntax so switching backends requires minimal code changes.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install fluxor-cloud-db
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Adapters
|
|
16
|
+
|
|
17
|
+
| Adapter | Backend |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `DynamoService` | AWS DynamoDB |
|
|
20
|
+
| `MongoService` | MongoDB |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Setup
|
|
25
|
+
|
|
26
|
+
Both adapters follow the same lifecycle: configure, connect.
|
|
27
|
+
|
|
28
|
+
### DynamoDB
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { useDynamo } from 'fluxor-cloud-db';
|
|
32
|
+
|
|
33
|
+
const dynamo = useDynamo();
|
|
34
|
+
|
|
35
|
+
dynamo.setConfig({
|
|
36
|
+
region: process.env.AWS_REGION,
|
|
37
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
38
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
|
|
39
|
+
endpoint: process.env.DYNAMO_ENDPOINT
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
await dynamo.connect();
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
| Field | Required | Description |
|
|
46
|
+
|---|:---:|---|
|
|
47
|
+
| `region` | ✓ | AWS region, e.g. `us-east-1` |
|
|
48
|
+
| `accessKeyId` | ✓ | AWS access key ID |
|
|
49
|
+
| `secretAccessKey` | ✓ | AWS secret access key |
|
|
50
|
+
| `endpoint` | ✓ | Custom endpoint, e.g. `http://localhost:8000` for local DynamoDB |
|
|
51
|
+
|
|
52
|
+
### MongoDB
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { useMongo } from 'fluxor-cloud-db';
|
|
56
|
+
|
|
57
|
+
const mongo = useMongo();
|
|
58
|
+
|
|
59
|
+
mongo.setConfig({
|
|
60
|
+
uri: process.env.MONGO_URI,
|
|
61
|
+
dbName: process.env.MONGO_DB_NAME,
|
|
62
|
+
authSource: process.env.MONGO_AUTH_SOURCE,
|
|
63
|
+
retryWrites: true,
|
|
64
|
+
w: 'majority'
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
await mongo.connect();
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
| Field | Required | Description |
|
|
71
|
+
|---|:---:|---|
|
|
72
|
+
| `uri` | ✓ | MongoDB connection string, e.g. `mongodb://localhost:27017` |
|
|
73
|
+
| `dbName` | ✓ | Database name to connect to |
|
|
74
|
+
| `authSource` | ✓ | Authentication database, e.g. `admin` |
|
|
75
|
+
| `retryWrites` | ✓ | Whether to retry failed writes. Default `true` |
|
|
76
|
+
| `w` | — | Write concern. Default `'majority'` |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Query Operators
|
|
81
|
+
|
|
82
|
+
Both adapters share the same `WhereClause` operator syntax.
|
|
83
|
+
|
|
84
|
+
| Operator | Description | DynamoDB | MongoDB |
|
|
85
|
+
|---|---|:---:|:---:|
|
|
86
|
+
| `=` | Equals | ✓ | ✓ |
|
|
87
|
+
| `!=` | Not equals | ✓ | ✓ |
|
|
88
|
+
| `>` | Greater than | ✓ | ✓ |
|
|
89
|
+
| `>=` | Greater than or equal | ✓ | ✓ |
|
|
90
|
+
| `<` | Less than | ✓ | ✓ |
|
|
91
|
+
| `<=` | Less than or equal | ✓ | ✓ |
|
|
92
|
+
| `IN` | Value in list | ✓ | ✓ |
|
|
93
|
+
| `NOT_IN` | Value not in list | ✓ | ✓ |
|
|
94
|
+
| `BEGINS_WITH` | String prefix match | ✓ | ✓ |
|
|
95
|
+
| `LIKE` | Case-insensitive substring | — | ✓ |
|
|
96
|
+
| `BETWEEN` | Inclusive range | — | ✓ |
|
|
97
|
+
| `EXISTS` | Field presence check | — | ✓ |
|
|
98
|
+
|
|
99
|
+
Conditions can be written as raw objects or using the query builder helpers.
|
|
100
|
+
|
|
101
|
+
### Raw syntax
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
{ id: { operator: '=', value: 42 } }
|
|
105
|
+
|
|
106
|
+
{
|
|
107
|
+
status: { operator: '=', value: 'active' },
|
|
108
|
+
score: { operator: '>=', value: 100 }
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Query builder
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import { eq, neq, gt, gte, lt, lte, anyOf, noneOf, startsWith, between, like, exists } from 'fluxor-cloud-db';
|
|
116
|
+
|
|
117
|
+
{ id: eq(1) }
|
|
118
|
+
{ id: neq(1) }
|
|
119
|
+
{ score: gt(100) }
|
|
120
|
+
{ score: gte(100) }
|
|
121
|
+
{ score: lt(100) }
|
|
122
|
+
{ score: lte(100) }
|
|
123
|
+
{ id: anyOf([1, 2, 3]) }
|
|
124
|
+
{ id: noneOf([4, 5, 6]) }
|
|
125
|
+
{ username: startsWith('ali') }
|
|
126
|
+
{ price: between(10, 50) } // MongoDB only
|
|
127
|
+
{ bio: like('engineer') } // MongoDB only
|
|
128
|
+
{ deletedAt: exists(false) } // MongoDB only
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Aliases are available for a more descriptive style:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import { equals, notEquals, inList, notInList } from 'fluxor-cloud-db';
|
|
135
|
+
|
|
136
|
+
{ id: equals(1) }
|
|
137
|
+
{ id: notEquals(1) }
|
|
138
|
+
{ id: inList([1, 2, 3]) }
|
|
139
|
+
{ id: notInList([4, 5, 6]) }
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## API
|
|
145
|
+
|
|
146
|
+
All methods are identical across both adapters.
|
|
147
|
+
|
|
148
|
+
### `selectOne(tableName, where, options?)`
|
|
149
|
+
|
|
150
|
+
Returns a single matching record, or `null` if not found.
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
const user = await dynamo.selectOne('users', { id: eq(1) });
|
|
154
|
+
|
|
155
|
+
// With projection
|
|
156
|
+
const user = await dynamo.selectOne('users',
|
|
157
|
+
{ id: eq(1) },
|
|
158
|
+
{ projection: ['id', 'name', 'email'] }
|
|
159
|
+
);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### `selectMany(tableName, where?, options?)`
|
|
163
|
+
|
|
164
|
+
Returns a paginated result set.
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
const { items, total, hasMore } = await mongo.selectMany('users',
|
|
168
|
+
{ status: eq('active') },
|
|
169
|
+
{
|
|
170
|
+
limit: 20,
|
|
171
|
+
offset: 0,
|
|
172
|
+
orderBy: [{ field: 'createdAt', direction: 'DESC' }],
|
|
173
|
+
projection: ['id', 'name']
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### `createOne(tableName, data)`
|
|
179
|
+
|
|
180
|
+
Inserts a single record and returns it.
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
const user = await dynamo.createOne('users', {
|
|
184
|
+
id: 1,
|
|
185
|
+
name: 'Alice',
|
|
186
|
+
status: 'active'
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### `createMany(tableName, data, options?)`
|
|
191
|
+
|
|
192
|
+
Inserts multiple records. DynamoDB batches in groups of 25 (AWS limit); MongoDB uses a single `insertMany`.
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
const { items, result } = await mongo.createMany('users', [
|
|
196
|
+
{ id: 1, name: 'Alice' },
|
|
197
|
+
{ id: 2, name: 'Bob' }
|
|
198
|
+
]);
|
|
199
|
+
|
|
200
|
+
// result: { successful: 2, failed: 0 }
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
| Option | Description |
|
|
204
|
+
|---|---|
|
|
205
|
+
| `stopOnError` | Stop processing on the first failed batch. Default `false` |
|
|
206
|
+
|
|
207
|
+
### `updateOne(tableName, update, where)`
|
|
208
|
+
|
|
209
|
+
Updates a single matching record and returns the updated document. Throws `DatabaseAdapterError` with code `NOT_FOUND` if no record matches.
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
const updated = await dynamo.updateOne(
|
|
213
|
+
'users',
|
|
214
|
+
{ status: 'inactive' },
|
|
215
|
+
{ id: eq(1) }
|
|
216
|
+
);
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### `updateMany(tableName, update, where?, options?)`
|
|
220
|
+
|
|
221
|
+
Updates all records matching the where clause. Returns the updated items and a batch result.
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
const { items, result } = await mongo.updateMany(
|
|
225
|
+
'users',
|
|
226
|
+
{ status: 'inactive' },
|
|
227
|
+
{ score: lt(10) },
|
|
228
|
+
{ limit: 100 }
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
// result: { successful: number, failed: number }
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### `deleteOne(tableName, where)`
|
|
235
|
+
|
|
236
|
+
Deletes a single matching record. Returns `{ success: false, deletedCount: 0 }` if no record matches — does not throw.
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
const { success, deletedCount } = await dynamo.deleteOne('users', { id: eq(1) });
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### `deleteMany(tableName, where?, options?)`
|
|
243
|
+
|
|
244
|
+
Deletes all records matching the where clause. Returns a count of deleted records and a batch result.
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
const { success, deletedCount, result } = await mongo.deleteMany(
|
|
248
|
+
'users',
|
|
249
|
+
{ status: eq('inactive') },
|
|
250
|
+
{ limit: 50 }
|
|
251
|
+
);
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Error Handling
|
|
257
|
+
|
|
258
|
+
All methods throw `DatabaseAdapterError` on failure. The error includes a `code` for programmatic handling.
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import { DatabaseAdapterError } from 'fluxor-cloud-db';
|
|
262
|
+
|
|
263
|
+
try {
|
|
264
|
+
await dynamo.updateOne('users', { name: 'Bob' }, { id: eq(999) });
|
|
265
|
+
} catch (err) {
|
|
266
|
+
if (err instanceof DatabaseAdapterError) {
|
|
267
|
+
console.error(err.code); // 'NOT_FOUND'
|
|
268
|
+
console.error(err.message); // 'Record not found'
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
| Code | When |
|
|
274
|
+
|---|---|
|
|
275
|
+
| `NOT_CONNECTED` | Operation called before `connect()` |
|
|
276
|
+
| `INVALID_CONFIG` | Missing or invalid configuration |
|
|
277
|
+
| `MISSING_REGION` | DynamoDB `region` not provided |
|
|
278
|
+
| `INVALID_CREDENTIALS` | Only one of `accessKeyId` / `secretAccessKey` provided |
|
|
279
|
+
| `NOT_FOUND` | `updateOne` target does not exist |
|
|
280
|
+
| `INVALID_INPUT` | e.g. `createMany` called with a non-array |
|
|
281
|
+
| `OPERATION_FAILED` | Underlying driver error |
|
|
282
|
+
| `NOT_IMPLEMENTED` | `executeRaw` is not supported |
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Lifecycle
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
await service.connect();
|
|
290
|
+
|
|
291
|
+
const alive = await service.healthCheck(); // true / false
|
|
292
|
+
|
|
293
|
+
const connected = service.isConnected(); // synchronous
|
|
294
|
+
|
|
295
|
+
await service.disconnect();
|
|
296
|
+
```
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
type DynamoConfig = {
|
|
2
|
+
region: string;
|
|
3
|
+
endpoint: string;
|
|
4
|
+
accessKeyId?: string;
|
|
5
|
+
secretAccessKey?: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
type QueryOperator = "=" | "!=" | ">" | ">=" | "<" | "<=" | "IN" | "NOT_IN" | "BETWEEN" | "LIKE" | "EXISTS" | "BEGINS_WITH";
|
|
9
|
+
/**
|
|
10
|
+
* Represents a single condition in a WHERE clause
|
|
11
|
+
*/
|
|
12
|
+
interface QueryCondition {
|
|
13
|
+
operator: QueryOperator;
|
|
14
|
+
value: any;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Represents a single field condition or nested conditions
|
|
18
|
+
*/
|
|
19
|
+
interface WhereClause {
|
|
20
|
+
[key: string]: QueryCondition | QueryCondition[] | WhereClause;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Represents update operations on specific fields
|
|
24
|
+
*/
|
|
25
|
+
interface UpdateClause {
|
|
26
|
+
[key: string]: any;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Configuration for query operations
|
|
30
|
+
*/
|
|
31
|
+
interface QueryOptions {
|
|
32
|
+
limit?: number;
|
|
33
|
+
offset?: number;
|
|
34
|
+
orderBy?: {
|
|
35
|
+
field: string;
|
|
36
|
+
direction: "ASC" | "DESC";
|
|
37
|
+
}[];
|
|
38
|
+
projection?: string[];
|
|
39
|
+
consistent?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Result wrapper for paginated responses
|
|
43
|
+
*/
|
|
44
|
+
type PaginatedResult<T> = {
|
|
45
|
+
items: T[];
|
|
46
|
+
total: number;
|
|
47
|
+
hasMore: boolean;
|
|
48
|
+
nextOffset?: number;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Result wrapper for batch operations
|
|
52
|
+
*/
|
|
53
|
+
interface BatchResult {
|
|
54
|
+
successful: number;
|
|
55
|
+
failed: number;
|
|
56
|
+
errors?: {
|
|
57
|
+
index: number;
|
|
58
|
+
error: string;
|
|
59
|
+
}[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Unified database adapter interface
|
|
64
|
+
* Supports DynamoDB, MongoDB, SQL databases, and other data stores
|
|
65
|
+
*/
|
|
66
|
+
interface DatabaseAdapter {
|
|
67
|
+
/**
|
|
68
|
+
* Establish connection to the database
|
|
69
|
+
* Implementation varies by backend (DynamoDB, MongoDB, etc.)
|
|
70
|
+
*/
|
|
71
|
+
connect(): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Close connection to the database
|
|
74
|
+
*/
|
|
75
|
+
disconnect(): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Check if adapter is connected
|
|
78
|
+
*/
|
|
79
|
+
isConnected(): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Fetch a single record matching the where conditions
|
|
82
|
+
* @param tableName - Table/collection name
|
|
83
|
+
* @param where - Query conditions
|
|
84
|
+
* @param options - Query options (projection, consistency, etc.)
|
|
85
|
+
* @returns Single record or null if not found
|
|
86
|
+
*/
|
|
87
|
+
selectOne<T = Record<string, any>>(tableName: string, where: WhereClause, options?: QueryOptions): Promise<T | null>;
|
|
88
|
+
/**
|
|
89
|
+
* Fetch multiple records matching the where conditions
|
|
90
|
+
* @param tableName - Table/collection name
|
|
91
|
+
* @param where - Query conditions
|
|
92
|
+
* @param options - Query options (limit, offset, orderBy, projection, etc.)
|
|
93
|
+
* @returns Array of matching records with pagination info
|
|
94
|
+
*/
|
|
95
|
+
selectMany<T = Record<string, any>>(tableName: string, where?: WhereClause, options?: QueryOptions): Promise<PaginatedResult<T>>;
|
|
96
|
+
/**
|
|
97
|
+
* Insert a single record
|
|
98
|
+
* @param tableName - Table/collection name
|
|
99
|
+
* @param data - Record to insert
|
|
100
|
+
* @returns Created record with any server-generated fields
|
|
101
|
+
*/
|
|
102
|
+
createOne<T = Record<string, any>>(tableName: string, data: Record<string, any>): Promise<T>;
|
|
103
|
+
/**
|
|
104
|
+
* Insert multiple records in a batch operation
|
|
105
|
+
* @param tableName - Table/collection name
|
|
106
|
+
* @param data - Array of records to insert
|
|
107
|
+
* @param options - Batch options (e.g., stopOnError)
|
|
108
|
+
* @returns Batch operation result with success/failure counts
|
|
109
|
+
*/
|
|
110
|
+
createMany<T = Record<string, any>>(tableName: string, data: Record<string, any>[], options?: {
|
|
111
|
+
stopOnError?: boolean;
|
|
112
|
+
}): Promise<{
|
|
113
|
+
items: T[];
|
|
114
|
+
result: BatchResult;
|
|
115
|
+
}>;
|
|
116
|
+
/**
|
|
117
|
+
* Update a single record matching the where conditions
|
|
118
|
+
* @param tableName - Table/collection name
|
|
119
|
+
* @param update - Fields to update
|
|
120
|
+
* @param where - Query conditions to identify record
|
|
121
|
+
* @returns Updated record
|
|
122
|
+
*/
|
|
123
|
+
updateOne<T = Record<string, any>>(tableName: string, update: UpdateClause, where: WhereClause): Promise<T>;
|
|
124
|
+
/**
|
|
125
|
+
* Update multiple records matching the where conditions
|
|
126
|
+
* @param tableName - Table/collection name
|
|
127
|
+
* @param update - Fields to update
|
|
128
|
+
* @param where - Query conditions to identify records
|
|
129
|
+
* @param options - Update options (e.g., limit)
|
|
130
|
+
* @returns Batch operation result with updated count
|
|
131
|
+
*/
|
|
132
|
+
updateMany<T = Record<string, any>>(tableName: string, update: UpdateClause, where?: WhereClause, options?: {
|
|
133
|
+
limit?: number;
|
|
134
|
+
}): Promise<{
|
|
135
|
+
items: T[];
|
|
136
|
+
result: BatchResult;
|
|
137
|
+
}>;
|
|
138
|
+
/**
|
|
139
|
+
* Delete a single record matching the where conditions
|
|
140
|
+
* @param tableName - Table/collection name
|
|
141
|
+
* @param where - Query conditions to identify record
|
|
142
|
+
* @returns Deleted record or confirmation
|
|
143
|
+
*/
|
|
144
|
+
deleteOne(tableName: string, where: WhereClause): Promise<{
|
|
145
|
+
success: boolean;
|
|
146
|
+
deletedCount: number;
|
|
147
|
+
}>;
|
|
148
|
+
/**
|
|
149
|
+
* Delete multiple records matching the where conditions
|
|
150
|
+
* @param tableName - Table/collection name
|
|
151
|
+
* @param where - Query conditions to identify records
|
|
152
|
+
* @param options - Delete options (e.g., limit)
|
|
153
|
+
* @returns Batch operation result with deleted count
|
|
154
|
+
*/
|
|
155
|
+
deleteMany(tableName: string, where?: WhereClause, options?: {
|
|
156
|
+
limit?: number;
|
|
157
|
+
}): Promise<{
|
|
158
|
+
success: boolean;
|
|
159
|
+
deletedCount: number;
|
|
160
|
+
result: BatchResult;
|
|
161
|
+
}>;
|
|
162
|
+
/**
|
|
163
|
+
* Execute a raw query specific to the database backend
|
|
164
|
+
* Use sparingly for complex queries not supported by the adapter
|
|
165
|
+
*/
|
|
166
|
+
executeRaw<T = any>(query: string, params?: Record<string, any>): Promise<T>;
|
|
167
|
+
/**
|
|
168
|
+
* Start a transaction (if supported by the backend)
|
|
169
|
+
*/
|
|
170
|
+
beginTransaction?(): Promise<void>;
|
|
171
|
+
/**
|
|
172
|
+
* Commit an active transaction
|
|
173
|
+
*/
|
|
174
|
+
commitTransaction?(): Promise<void>;
|
|
175
|
+
/**
|
|
176
|
+
* Rollback an active transaction
|
|
177
|
+
*/
|
|
178
|
+
rollbackTransaction?(): Promise<void>;
|
|
179
|
+
/**
|
|
180
|
+
* Check the health/status of the database connection
|
|
181
|
+
*/
|
|
182
|
+
healthCheck(): Promise<boolean>;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
declare class DynamoService implements DatabaseAdapter {
|
|
186
|
+
private client;
|
|
187
|
+
private dynamoDBClient;
|
|
188
|
+
private isConnectedFlag;
|
|
189
|
+
private config;
|
|
190
|
+
setConfig(config: DynamoConfig): void;
|
|
191
|
+
connect(): Promise<void>;
|
|
192
|
+
disconnect(): Promise<void>;
|
|
193
|
+
isConnected(): boolean;
|
|
194
|
+
healthCheck(): Promise<boolean>;
|
|
195
|
+
selectOne<T = Record<string, any>>(tableName: string, where: WhereClause, options?: QueryOptions): Promise<T | null>;
|
|
196
|
+
selectMany<T = Record<string, any>>(tableName: string, where?: WhereClause, options?: QueryOptions): Promise<PaginatedResult<T>>;
|
|
197
|
+
createOne<T = Record<string, any>>(tableName: string, data: Record<string, any>): Promise<T>;
|
|
198
|
+
createMany<T = Record<string, any>>(tableName: string, data: Record<string, any>[], options?: {
|
|
199
|
+
stopOnError?: boolean;
|
|
200
|
+
}): Promise<{
|
|
201
|
+
items: T[];
|
|
202
|
+
result: BatchResult;
|
|
203
|
+
}>;
|
|
204
|
+
updateOne<T = Record<string, any>>(tableName: string, update: UpdateClause, where: WhereClause): Promise<T>;
|
|
205
|
+
updateMany<T = Record<string, any>>(tableName: string, update: UpdateClause, where?: WhereClause, options?: {
|
|
206
|
+
limit?: number;
|
|
207
|
+
}): Promise<{
|
|
208
|
+
items: T[];
|
|
209
|
+
result: BatchResult;
|
|
210
|
+
}>;
|
|
211
|
+
deleteOne(tableName: string, where: WhereClause): Promise<{
|
|
212
|
+
success: boolean;
|
|
213
|
+
deletedCount: number;
|
|
214
|
+
}>;
|
|
215
|
+
deleteMany(tableName: string, where?: WhereClause, options?: {
|
|
216
|
+
limit?: number;
|
|
217
|
+
}): Promise<{
|
|
218
|
+
success: boolean;
|
|
219
|
+
deletedCount: number;
|
|
220
|
+
result: BatchResult;
|
|
221
|
+
}>;
|
|
222
|
+
executeRaw<T = any>(query: string, params?: Record<string, any>): Promise<T>;
|
|
223
|
+
private validateConfig;
|
|
224
|
+
private getClient;
|
|
225
|
+
private buildKey;
|
|
226
|
+
private extractKey;
|
|
227
|
+
private isKeyQuery;
|
|
228
|
+
private buildProjection;
|
|
229
|
+
private buildKeyConditionExpression;
|
|
230
|
+
private buildFilterExpression;
|
|
231
|
+
private buildUpdateExpression;
|
|
232
|
+
private handleError;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* MongoDB implementation of DatabaseAdapter interface
|
|
237
|
+
* This is a template implementation showing how to adapt another database backend
|
|
238
|
+
*/
|
|
239
|
+
|
|
240
|
+
interface MongoConfig {
|
|
241
|
+
uri: string;
|
|
242
|
+
dbName: string;
|
|
243
|
+
authSource?: string;
|
|
244
|
+
retryWrites?: boolean;
|
|
245
|
+
w?: "majority" | number;
|
|
246
|
+
}
|
|
247
|
+
declare class MongoService implements DatabaseAdapter {
|
|
248
|
+
private client;
|
|
249
|
+
private db;
|
|
250
|
+
private isConnectedFlag;
|
|
251
|
+
private config;
|
|
252
|
+
setConfig(config: MongoConfig): void;
|
|
253
|
+
connect(): Promise<void>;
|
|
254
|
+
disconnect(): Promise<void>;
|
|
255
|
+
isConnected(): boolean;
|
|
256
|
+
healthCheck(): Promise<boolean>;
|
|
257
|
+
selectOne<T = Record<string, any>>(tableName: string, where: WhereClause, options?: QueryOptions): Promise<T | null>;
|
|
258
|
+
selectMany<T = Record<string, any>>(tableName: string, where?: WhereClause, options?: QueryOptions): Promise<PaginatedResult<T>>;
|
|
259
|
+
createOne<T = Record<string, any>>(tableName: string, data: Record<string, any>): Promise<T>;
|
|
260
|
+
createMany<T = Record<string, any>>(tableName: string, data: Record<string, any>[], options?: {
|
|
261
|
+
stopOnError?: boolean;
|
|
262
|
+
}): Promise<{
|
|
263
|
+
items: T[];
|
|
264
|
+
result: BatchResult;
|
|
265
|
+
}>;
|
|
266
|
+
updateOne<T = Record<string, any>>(tableName: string, update: UpdateClause, where: WhereClause): Promise<T>;
|
|
267
|
+
updateMany<T = Record<string, any>>(tableName: string, update: UpdateClause, where?: WhereClause, options?: {
|
|
268
|
+
limit?: number;
|
|
269
|
+
}): Promise<{
|
|
270
|
+
items: T[];
|
|
271
|
+
result: BatchResult;
|
|
272
|
+
}>;
|
|
273
|
+
deleteOne(tableName: string, where: WhereClause): Promise<{
|
|
274
|
+
success: boolean;
|
|
275
|
+
deletedCount: number;
|
|
276
|
+
}>;
|
|
277
|
+
deleteMany(tableName: string, where?: WhereClause, options?: {
|
|
278
|
+
limit?: number;
|
|
279
|
+
}): Promise<{
|
|
280
|
+
success: boolean;
|
|
281
|
+
deletedCount: number;
|
|
282
|
+
result: BatchResult;
|
|
283
|
+
}>;
|
|
284
|
+
executeRaw<T = any>(query: string, params?: Record<string, any>): Promise<T>;
|
|
285
|
+
private validateConfig;
|
|
286
|
+
private getDb;
|
|
287
|
+
private getCollection;
|
|
288
|
+
private buildMongoFilter;
|
|
289
|
+
private isValidOperator;
|
|
290
|
+
private buildMongoUpdate;
|
|
291
|
+
private handleError;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
interface Condition {
|
|
295
|
+
operator: string;
|
|
296
|
+
value: unknown;
|
|
297
|
+
}
|
|
298
|
+
declare const eq: (value: unknown) => Condition;
|
|
299
|
+
declare const neq: (value: unknown) => Condition;
|
|
300
|
+
declare const gt: (value: number | string) => Condition;
|
|
301
|
+
declare const gte: (value: number | string) => Condition;
|
|
302
|
+
declare const lt: (value: number | string) => Condition;
|
|
303
|
+
declare const lte: (value: number | string) => Condition;
|
|
304
|
+
/** Inclusive range. MongoDB only. */
|
|
305
|
+
declare const between: (min: number | string, max: number | string) => Condition;
|
|
306
|
+
declare const anyOf: (values: unknown[]) => Condition;
|
|
307
|
+
declare const noneOf: (values: unknown[]) => Condition;
|
|
308
|
+
declare const startsWith: (value: string) => Condition;
|
|
309
|
+
/** Case-insensitive substring match. MongoDB only. */
|
|
310
|
+
declare const like: (value: string) => Condition;
|
|
311
|
+
/** Field presence check. MongoDB only. */
|
|
312
|
+
declare const exists: (value?: boolean) => Condition;
|
|
313
|
+
/** Alias for eq */
|
|
314
|
+
declare const equals: (value: unknown) => Condition;
|
|
315
|
+
/** Alias for neq */
|
|
316
|
+
declare const notEquals: (value: unknown) => Condition;
|
|
317
|
+
/** Alias for anyOf */
|
|
318
|
+
declare const inList: (values: unknown[]) => Condition;
|
|
319
|
+
/** Alias for noneOf */
|
|
320
|
+
declare const notInList: (values: unknown[]) => Condition;
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Resolves the {@link DynamoService} instance from the service container.
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* ```typescript
|
|
327
|
+
* const dynamo = useDynamo();
|
|
328
|
+
* const user = await dynamo.selectOne("users", { id: { operator: "=", value: 1 } });
|
|
329
|
+
* ```
|
|
330
|
+
*
|
|
331
|
+
* @returns The registered {@link DynamoService} instance.
|
|
332
|
+
*/
|
|
333
|
+
declare const useDynamo: () => DynamoService;
|
|
334
|
+
/**
|
|
335
|
+
* Resolves the {@link MongoService} instance from the service container.
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* ```typescript
|
|
339
|
+
* const mongo = useMongo();
|
|
340
|
+
* const users = await mongo.selectMany("users", { status: { operator: "=", value: "active" } });
|
|
341
|
+
* ```
|
|
342
|
+
*
|
|
343
|
+
* @returns The registered {@link MongoService} instance.
|
|
344
|
+
*/
|
|
345
|
+
declare const useMongo: () => MongoService;
|
|
346
|
+
|
|
347
|
+
export { type DynamoConfig, DynamoService, type MongoConfig, MongoService, anyOf, between, eq, equals, exists, gt, gte, inList, like, lt, lte, neq, noneOf, notEquals, notInList, startsWith, useDynamo, useMongo };
|