@keyv/dynamo 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/dist/index.cjs +33 -21
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +32 -20
- package/package.json +7 -29
package/README.md
CHANGED
|
@@ -35,6 +35,18 @@ e.g:
|
|
|
35
35
|
const keyv = new KeyvDynamo({ tableName: 'cacheTable' });
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
### Accessing the DynamoDB Client
|
|
39
|
+
|
|
40
|
+
The DynamoDB client is exposed as a property for advanced use cases:
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
const store = new KeyvDynamo();
|
|
44
|
+
const dynamoClient = store.client; // DynamoDBDocument instance
|
|
45
|
+
|
|
46
|
+
// You can use the client directly for custom operations
|
|
47
|
+
await dynamoClient.get({ TableName: 'keyv', Key: { id: 'myKey' } });
|
|
48
|
+
```
|
|
49
|
+
|
|
38
50
|
## Usage with NestJS
|
|
39
51
|
|
|
40
52
|
Since DynamoDB has a 400KB limit per item, compressing data can help in some cases.
|
package/dist/index.cjs
CHANGED
|
@@ -34,10 +34,10 @@ __export(index_exports, {
|
|
|
34
34
|
default: () => index_default
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
|
-
var
|
|
37
|
+
var import_node_events = __toESM(require("events"), 1);
|
|
38
38
|
var import_client_dynamodb = require("@aws-sdk/client-dynamodb");
|
|
39
39
|
var import_lib_dynamodb = require("@aws-sdk/lib-dynamodb");
|
|
40
|
-
var KeyvDynamo = class extends
|
|
40
|
+
var KeyvDynamo = class extends import_node_events.default {
|
|
41
41
|
ttlSupport = true;
|
|
42
42
|
sixHoursInMilliseconds = 6 * 60 * 60 * 1e3;
|
|
43
43
|
namespace;
|
|
@@ -56,13 +56,17 @@ var KeyvDynamo = class extends import_events.default {
|
|
|
56
56
|
...options
|
|
57
57
|
};
|
|
58
58
|
this.client = import_lib_dynamodb.DynamoDBDocument.from(new import_client_dynamodb.DynamoDB(this.opts));
|
|
59
|
-
this.tableReady = this.ensureTable(this.opts.tableName).catch(
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
this.tableReady = this.ensureTable(this.opts.tableName).catch(
|
|
60
|
+
(error) => {
|
|
61
|
+
this.emit("error", error);
|
|
62
|
+
}
|
|
63
|
+
);
|
|
62
64
|
}
|
|
63
65
|
async set(key, value, ttl) {
|
|
64
66
|
await this.tableReady;
|
|
65
|
-
const sixHoursFromNowEpoch = Math.floor(
|
|
67
|
+
const sixHoursFromNowEpoch = Math.floor(
|
|
68
|
+
(Date.now() + this.sixHoursInMilliseconds) / 1e3
|
|
69
|
+
);
|
|
66
70
|
const expiresAt = typeof ttl === "number" ? Math.floor((Date.now() + (ttl + 1e3)) / 1e3) : sixHoursFromNowEpoch;
|
|
67
71
|
const putInput = {
|
|
68
72
|
TableName: this.opts.tableName,
|
|
@@ -109,7 +113,9 @@ var KeyvDynamo = class extends import_events.default {
|
|
|
109
113
|
}
|
|
110
114
|
};
|
|
111
115
|
const { Responses: { [this.opts.tableName]: items = [] } = {} } = await this.client.batchGet(batchGetInput);
|
|
112
|
-
return keys.map(
|
|
116
|
+
return keys.map(
|
|
117
|
+
(key) => items.find((item) => item?.id === key)?.value
|
|
118
|
+
);
|
|
113
119
|
}
|
|
114
120
|
async deleteMany(keys) {
|
|
115
121
|
await this.tableReady;
|
|
@@ -148,7 +154,9 @@ var KeyvDynamo = class extends import_events.default {
|
|
|
148
154
|
}
|
|
149
155
|
async ensureTable(tableName) {
|
|
150
156
|
try {
|
|
151
|
-
await this.client.send(
|
|
157
|
+
await this.client.send(
|
|
158
|
+
new import_client_dynamodb.DescribeTableCommand({ TableName: tableName })
|
|
159
|
+
);
|
|
152
160
|
} catch (error) {
|
|
153
161
|
if (error instanceof import_client_dynamodb.ResourceNotFoundException) {
|
|
154
162
|
await this.createTable(tableName);
|
|
@@ -159,23 +167,27 @@ var KeyvDynamo = class extends import_events.default {
|
|
|
159
167
|
}
|
|
160
168
|
async createTable(tableName) {
|
|
161
169
|
try {
|
|
162
|
-
await this.client.send(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
170
|
+
await this.client.send(
|
|
171
|
+
new import_client_dynamodb.CreateTableCommand({
|
|
172
|
+
TableName: tableName,
|
|
173
|
+
KeySchema: [{ AttributeName: "id", KeyType: "HASH" }],
|
|
174
|
+
AttributeDefinitions: [{ AttributeName: "id", AttributeType: "S" }],
|
|
175
|
+
BillingMode: "PAY_PER_REQUEST"
|
|
176
|
+
})
|
|
177
|
+
);
|
|
168
178
|
await (0, import_client_dynamodb.waitUntilTableExists)(
|
|
169
179
|
{ client: this.client, maxWaitTime: 60 },
|
|
170
180
|
{ TableName: tableName }
|
|
171
181
|
);
|
|
172
|
-
await this.client.send(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
182
|
+
await this.client.send(
|
|
183
|
+
new import_client_dynamodb.UpdateTimeToLiveCommand({
|
|
184
|
+
TableName: tableName,
|
|
185
|
+
TimeToLiveSpecification: {
|
|
186
|
+
AttributeName: "expiresAt",
|
|
187
|
+
Enabled: true
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
);
|
|
179
191
|
} catch (error) {
|
|
180
192
|
if (error instanceof import_client_dynamodb.ResourceInUseException) {
|
|
181
193
|
await (0, import_client_dynamodb.waitUntilTableExists)(
|
package/dist/index.d.cts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import EventEmitter from 'events';
|
|
1
|
+
import EventEmitter from 'node:events';
|
|
2
2
|
import { DynamoDBClientConfig } from '@aws-sdk/client-dynamodb';
|
|
3
|
+
import { DynamoDBDocument } from '@aws-sdk/lib-dynamodb';
|
|
3
4
|
import { KeyvStoreAdapter, StoredData } from 'keyv';
|
|
4
5
|
|
|
5
6
|
declare class KeyvDynamo extends EventEmitter implements KeyvStoreAdapter {
|
|
6
7
|
ttlSupport: boolean;
|
|
7
8
|
sixHoursInMilliseconds: number;
|
|
8
9
|
namespace?: string;
|
|
9
|
-
opts: Omit<KeyvDynamoOptions,
|
|
10
|
+
opts: Omit<KeyvDynamoOptions, "tableName"> & {
|
|
10
11
|
tableName: string;
|
|
11
12
|
};
|
|
12
|
-
|
|
13
|
+
readonly client: DynamoDBDocument;
|
|
13
14
|
private readonly tableReady;
|
|
14
15
|
constructor(options: KeyvDynamoOptions | string);
|
|
15
16
|
set(key: string, value: unknown, ttl?: number): Promise<void>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import EventEmitter from 'events';
|
|
1
|
+
import EventEmitter from 'node:events';
|
|
2
2
|
import { DynamoDBClientConfig } from '@aws-sdk/client-dynamodb';
|
|
3
|
+
import { DynamoDBDocument } from '@aws-sdk/lib-dynamodb';
|
|
3
4
|
import { KeyvStoreAdapter, StoredData } from 'keyv';
|
|
4
5
|
|
|
5
6
|
declare class KeyvDynamo extends EventEmitter implements KeyvStoreAdapter {
|
|
6
7
|
ttlSupport: boolean;
|
|
7
8
|
sixHoursInMilliseconds: number;
|
|
8
9
|
namespace?: string;
|
|
9
|
-
opts: Omit<KeyvDynamoOptions,
|
|
10
|
+
opts: Omit<KeyvDynamoOptions, "tableName"> & {
|
|
10
11
|
tableName: string;
|
|
11
12
|
};
|
|
12
|
-
|
|
13
|
+
readonly client: DynamoDBDocument;
|
|
13
14
|
private readonly tableReady;
|
|
14
15
|
constructor(options: KeyvDynamoOptions | string);
|
|
15
16
|
set(key: string, value: unknown, ttl?: number): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
CreateTableCommand,
|
|
5
5
|
DescribeTableCommand,
|
|
6
6
|
DynamoDB,
|
|
7
|
-
ResourceNotFoundException,
|
|
8
7
|
ResourceInUseException,
|
|
8
|
+
ResourceNotFoundException,
|
|
9
9
|
UpdateTimeToLiveCommand,
|
|
10
10
|
waitUntilTableExists
|
|
11
11
|
} from "@aws-sdk/client-dynamodb";
|
|
@@ -31,13 +31,17 @@ var KeyvDynamo = class extends EventEmitter {
|
|
|
31
31
|
...options
|
|
32
32
|
};
|
|
33
33
|
this.client = DynamoDBDocument.from(new DynamoDB(this.opts));
|
|
34
|
-
this.tableReady = this.ensureTable(this.opts.tableName).catch(
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
this.tableReady = this.ensureTable(this.opts.tableName).catch(
|
|
35
|
+
(error) => {
|
|
36
|
+
this.emit("error", error);
|
|
37
|
+
}
|
|
38
|
+
);
|
|
37
39
|
}
|
|
38
40
|
async set(key, value, ttl) {
|
|
39
41
|
await this.tableReady;
|
|
40
|
-
const sixHoursFromNowEpoch = Math.floor(
|
|
42
|
+
const sixHoursFromNowEpoch = Math.floor(
|
|
43
|
+
(Date.now() + this.sixHoursInMilliseconds) / 1e3
|
|
44
|
+
);
|
|
41
45
|
const expiresAt = typeof ttl === "number" ? Math.floor((Date.now() + (ttl + 1e3)) / 1e3) : sixHoursFromNowEpoch;
|
|
42
46
|
const putInput = {
|
|
43
47
|
TableName: this.opts.tableName,
|
|
@@ -84,7 +88,9 @@ var KeyvDynamo = class extends EventEmitter {
|
|
|
84
88
|
}
|
|
85
89
|
};
|
|
86
90
|
const { Responses: { [this.opts.tableName]: items = [] } = {} } = await this.client.batchGet(batchGetInput);
|
|
87
|
-
return keys.map(
|
|
91
|
+
return keys.map(
|
|
92
|
+
(key) => items.find((item) => item?.id === key)?.value
|
|
93
|
+
);
|
|
88
94
|
}
|
|
89
95
|
async deleteMany(keys) {
|
|
90
96
|
await this.tableReady;
|
|
@@ -123,7 +129,9 @@ var KeyvDynamo = class extends EventEmitter {
|
|
|
123
129
|
}
|
|
124
130
|
async ensureTable(tableName) {
|
|
125
131
|
try {
|
|
126
|
-
await this.client.send(
|
|
132
|
+
await this.client.send(
|
|
133
|
+
new DescribeTableCommand({ TableName: tableName })
|
|
134
|
+
);
|
|
127
135
|
} catch (error) {
|
|
128
136
|
if (error instanceof ResourceNotFoundException) {
|
|
129
137
|
await this.createTable(tableName);
|
|
@@ -134,23 +142,27 @@ var KeyvDynamo = class extends EventEmitter {
|
|
|
134
142
|
}
|
|
135
143
|
async createTable(tableName) {
|
|
136
144
|
try {
|
|
137
|
-
await this.client.send(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
145
|
+
await this.client.send(
|
|
146
|
+
new CreateTableCommand({
|
|
147
|
+
TableName: tableName,
|
|
148
|
+
KeySchema: [{ AttributeName: "id", KeyType: "HASH" }],
|
|
149
|
+
AttributeDefinitions: [{ AttributeName: "id", AttributeType: "S" }],
|
|
150
|
+
BillingMode: "PAY_PER_REQUEST"
|
|
151
|
+
})
|
|
152
|
+
);
|
|
143
153
|
await waitUntilTableExists(
|
|
144
154
|
{ client: this.client, maxWaitTime: 60 },
|
|
145
155
|
{ TableName: tableName }
|
|
146
156
|
);
|
|
147
|
-
await this.client.send(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
157
|
+
await this.client.send(
|
|
158
|
+
new UpdateTimeToLiveCommand({
|
|
159
|
+
TableName: tableName,
|
|
160
|
+
TimeToLiveSpecification: {
|
|
161
|
+
AttributeName: "expiresAt",
|
|
162
|
+
Enabled: true
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
);
|
|
154
166
|
} catch (error) {
|
|
155
167
|
if (error instanceof ResourceInUseException) {
|
|
156
168
|
await waitUntilTableExists(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keyv/dynamo",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "DynamoDB storage adapter for Keyv",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -12,29 +12,6 @@
|
|
|
12
12
|
"import": "./dist/index.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
-
"xo": {
|
|
16
|
-
"space": true,
|
|
17
|
-
"rules": {
|
|
18
|
-
"import/no-named-as-default": "off",
|
|
19
|
-
"unicorn/prefer-module": "off",
|
|
20
|
-
"unicorn/prefer-event-target": "off",
|
|
21
|
-
"unicorn/no-array-reduce": "off",
|
|
22
|
-
"unicorn/prefer-object-from-entries": "off",
|
|
23
|
-
"unicorn/prefer-node-protocol": "off",
|
|
24
|
-
"@typescript-eslint/no-unsafe-assignment": "off",
|
|
25
|
-
"@typescript-eslint/no-unsafe-call": "off",
|
|
26
|
-
"@typescript-eslint/no-unsafe-return": "off",
|
|
27
|
-
"@typescript-eslint/no-unsafe-argument": "off",
|
|
28
|
-
"import/extensions": "off",
|
|
29
|
-
"@typescript-eslint/consistent-type-imports": "off",
|
|
30
|
-
"@typescript-eslint/naming-convention": "off",
|
|
31
|
-
"@typescript-eslint/no-floating-promises": "off",
|
|
32
|
-
"import/no-extraneous-dependencies": "off",
|
|
33
|
-
"@typescript-eslint/no-confusing-void-expression": "off",
|
|
34
|
-
"@typescript-eslint/no-empty-function": "off",
|
|
35
|
-
"promise/prefer-await-to-then": "off"
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
15
|
"repository": {
|
|
39
16
|
"type": "git",
|
|
40
17
|
"url": "git+https://github.com/jaredwray/keyv.git"
|
|
@@ -58,13 +35,14 @@
|
|
|
58
35
|
},
|
|
59
36
|
"homepage": "https://github.com/jaredwray/keyv",
|
|
60
37
|
"dependencies": {
|
|
61
|
-
"@aws-sdk/client-dynamodb": "^3.
|
|
62
|
-
"@aws-sdk/lib-dynamodb": "^3.
|
|
38
|
+
"@aws-sdk/client-dynamodb": "^3.883.0",
|
|
39
|
+
"@aws-sdk/lib-dynamodb": "^3.883.0"
|
|
63
40
|
},
|
|
64
41
|
"devDependencies": {
|
|
42
|
+
"@biomejs/biome": "^2.2.3",
|
|
65
43
|
"vitest": "^3.2.4",
|
|
66
44
|
"@keyv/test-suite": "^2.1.1",
|
|
67
|
-
"keyv": "^5.5.
|
|
45
|
+
"keyv": "^5.5.1"
|
|
68
46
|
},
|
|
69
47
|
"tsd": {
|
|
70
48
|
"directory": "test"
|
|
@@ -75,8 +53,8 @@
|
|
|
75
53
|
],
|
|
76
54
|
"scripts": {
|
|
77
55
|
"build": "rimraf ./dist && tsup src/index.ts --format cjs,esm --dts --clean",
|
|
78
|
-
"test": "
|
|
79
|
-
"test:ci": "
|
|
56
|
+
"test": "biome check --write && vitest run --coverage",
|
|
57
|
+
"test:ci": "biome check && vitest --run --sequence.setupFiles=list --coverage",
|
|
80
58
|
"clean": "rimraf ./node_modules ./coverage ./dist"
|
|
81
59
|
}
|
|
82
60
|
}
|