@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 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 import_events = __toESM(require("events"), 1);
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 import_events.default {
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((error) => {
60
- this.emit("error", error);
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((Date.now() + this.sixHoursInMilliseconds) / 1e3);
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((key) => items.find((item) => item?.id === key)?.value);
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(new import_client_dynamodb.DescribeTableCommand({ TableName: tableName }));
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(new import_client_dynamodb.CreateTableCommand({
163
- TableName: tableName,
164
- KeySchema: [{ AttributeName: "id", KeyType: "HASH" }],
165
- AttributeDefinitions: [{ AttributeName: "id", AttributeType: "S" }],
166
- BillingMode: "PAY_PER_REQUEST"
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(new import_client_dynamodb.UpdateTimeToLiveCommand({
173
- TableName: tableName,
174
- TimeToLiveSpecification: {
175
- AttributeName: "expiresAt",
176
- Enabled: true
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, 'tableName'> & {
10
+ opts: Omit<KeyvDynamoOptions, "tableName"> & {
10
11
  tableName: string;
11
12
  };
12
- private readonly client;
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, 'tableName'> & {
10
+ opts: Omit<KeyvDynamoOptions, "tableName"> & {
10
11
  tableName: string;
11
12
  };
12
- private readonly client;
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((error) => {
35
- this.emit("error", error);
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((Date.now() + this.sixHoursInMilliseconds) / 1e3);
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((key) => items.find((item) => item?.id === key)?.value);
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(new DescribeTableCommand({ TableName: tableName }));
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(new CreateTableCommand({
138
- TableName: tableName,
139
- KeySchema: [{ AttributeName: "id", KeyType: "HASH" }],
140
- AttributeDefinitions: [{ AttributeName: "id", AttributeType: "S" }],
141
- BillingMode: "PAY_PER_REQUEST"
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(new UpdateTimeToLiveCommand({
148
- TableName: tableName,
149
- TimeToLiveSpecification: {
150
- AttributeName: "expiresAt",
151
- Enabled: true
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.1",
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.859.0",
62
- "@aws-sdk/lib-dynamodb": "^3.859.0"
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.0"
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": "xo --fix && vitest run --coverage",
79
- "test:ci": "xo && vitest --run --sequence.setupFiles=list --coverage",
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
  }