@keyv/dynamo 1.0.1 → 1.2.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,32 @@ e.g:
35
35
  const keyv = new KeyvDynamo({ tableName: 'cacheTable' });
36
36
  ```
37
37
 
38
+ ### Using the `createKeyv` helper function
39
+
40
+ The `createKeyv` function is a convenience method that creates a new Keyv instance with the DynamoDB adapter. It automatically sets `useKeyPrefix` to `false` to allow the adapter to handle key prefixing:
41
+
42
+ ```js
43
+ import { createKeyv } from '@keyv/dynamo';
44
+
45
+ const keyv = createKeyv({
46
+ endpoint: 'http://localhost:8000',
47
+ tableName: 'cacheTable',
48
+ namespace: 'my-app'
49
+ });
50
+ ```
51
+
52
+ ### Accessing the DynamoDB Client
53
+
54
+ The DynamoDB client is exposed as a property for advanced use cases:
55
+
56
+ ```js
57
+ const store = new KeyvDynamo();
58
+ const dynamoClient = store.client; // DynamoDBDocument instance
59
+
60
+ // You can use the client directly for custom operations
61
+ await dynamoClient.get({ TableName: 'keyv', Key: { id: 'myKey' } });
62
+ ```
63
+
38
64
  ## Usage with NestJS
39
65
 
40
66
  Since DynamoDB has a 400KB limit per item, compressing data can help in some cases.
package/dist/index.cjs CHANGED
@@ -30,14 +30,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ Keyv: () => import_keyv2.Keyv,
33
34
  KeyvDynamo: () => KeyvDynamo,
35
+ createKeyv: () => createKeyv,
34
36
  default: () => index_default
35
37
  });
36
38
  module.exports = __toCommonJS(index_exports);
37
- var import_events = __toESM(require("events"), 1);
39
+ var import_node_events = __toESM(require("events"), 1);
38
40
  var import_client_dynamodb = require("@aws-sdk/client-dynamodb");
39
41
  var import_lib_dynamodb = require("@aws-sdk/lib-dynamodb");
40
- var KeyvDynamo = class extends import_events.default {
42
+ var import_keyv = require("keyv");
43
+ var import_keyv2 = require("keyv");
44
+ var KeyvDynamo = class extends import_node_events.default {
41
45
  ttlSupport = true;
42
46
  sixHoursInMilliseconds = 6 * 60 * 60 * 1e3;
43
47
  namespace;
@@ -56,13 +60,17 @@ var KeyvDynamo = class extends import_events.default {
56
60
  ...options
57
61
  };
58
62
  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
- });
63
+ this.tableReady = this.ensureTable(this.opts.tableName).catch(
64
+ (error) => {
65
+ this.emit("error", error);
66
+ }
67
+ );
62
68
  }
63
69
  async set(key, value, ttl) {
64
70
  await this.tableReady;
65
- const sixHoursFromNowEpoch = Math.floor((Date.now() + this.sixHoursInMilliseconds) / 1e3);
71
+ const sixHoursFromNowEpoch = Math.floor(
72
+ (Date.now() + this.sixHoursInMilliseconds) / 1e3
73
+ );
66
74
  const expiresAt = typeof ttl === "number" ? Math.floor((Date.now() + (ttl + 1e3)) / 1e3) : sixHoursFromNowEpoch;
67
75
  const putInput = {
68
76
  TableName: this.opts.tableName,
@@ -109,7 +117,9 @@ var KeyvDynamo = class extends import_events.default {
109
117
  }
110
118
  };
111
119
  const { Responses: { [this.opts.tableName]: items = [] } = {} } = await this.client.batchGet(batchGetInput);
112
- return keys.map((key) => items.find((item) => item?.id === key)?.value);
120
+ return keys.map(
121
+ (key) => items.find((item) => item?.id === key)?.value
122
+ );
113
123
  }
114
124
  async deleteMany(keys) {
115
125
  await this.tableReady;
@@ -148,7 +158,9 @@ var KeyvDynamo = class extends import_events.default {
148
158
  }
149
159
  async ensureTable(tableName) {
150
160
  try {
151
- await this.client.send(new import_client_dynamodb.DescribeTableCommand({ TableName: tableName }));
161
+ await this.client.send(
162
+ new import_client_dynamodb.DescribeTableCommand({ TableName: tableName })
163
+ );
152
164
  } catch (error) {
153
165
  if (error instanceof import_client_dynamodb.ResourceNotFoundException) {
154
166
  await this.createTable(tableName);
@@ -159,23 +171,27 @@ var KeyvDynamo = class extends import_events.default {
159
171
  }
160
172
  async createTable(tableName) {
161
173
  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
- }));
174
+ await this.client.send(
175
+ new import_client_dynamodb.CreateTableCommand({
176
+ TableName: tableName,
177
+ KeySchema: [{ AttributeName: "id", KeyType: "HASH" }],
178
+ AttributeDefinitions: [{ AttributeName: "id", AttributeType: "S" }],
179
+ BillingMode: "PAY_PER_REQUEST"
180
+ })
181
+ );
168
182
  await (0, import_client_dynamodb.waitUntilTableExists)(
169
183
  { client: this.client, maxWaitTime: 60 },
170
184
  { TableName: tableName }
171
185
  );
172
- await this.client.send(new import_client_dynamodb.UpdateTimeToLiveCommand({
173
- TableName: tableName,
174
- TimeToLiveSpecification: {
175
- AttributeName: "expiresAt",
176
- Enabled: true
177
- }
178
- }));
186
+ await this.client.send(
187
+ new import_client_dynamodb.UpdateTimeToLiveCommand({
188
+ TableName: tableName,
189
+ TimeToLiveSpecification: {
190
+ AttributeName: "expiresAt",
191
+ Enabled: true
192
+ }
193
+ })
194
+ );
179
195
  } catch (error) {
180
196
  if (error instanceof import_client_dynamodb.ResourceInUseException) {
181
197
  await (0, import_client_dynamodb.waitUntilTableExists)(
@@ -189,7 +205,23 @@ var KeyvDynamo = class extends import_events.default {
189
205
  }
190
206
  };
191
207
  var index_default = KeyvDynamo;
208
+ function createKeyv(options) {
209
+ const adapter = new KeyvDynamo(options ?? {});
210
+ if (typeof options === "object" && options?.namespace) {
211
+ adapter.namespace = options.namespace;
212
+ const keyv2 = new import_keyv.Keyv(adapter, {
213
+ namespace: options.namespace,
214
+ useKeyPrefix: false
215
+ });
216
+ return keyv2;
217
+ }
218
+ const keyv = new import_keyv.Keyv(adapter, { useKeyPrefix: false });
219
+ keyv.namespace = void 0;
220
+ return keyv;
221
+ }
192
222
  // Annotate the CommonJS export names for ESM import in node:
193
223
  0 && (module.exports = {
194
- KeyvDynamo
224
+ Keyv,
225
+ KeyvDynamo,
226
+ createKeyv
195
227
  });
package/dist/index.d.cts CHANGED
@@ -1,15 +1,17 @@
1
- import EventEmitter from 'events';
1
+ import EventEmitter from 'node:events';
2
2
  import { DynamoDBClientConfig } from '@aws-sdk/client-dynamodb';
3
- import { KeyvStoreAdapter, StoredData } from 'keyv';
3
+ import { DynamoDBDocument } from '@aws-sdk/lib-dynamodb';
4
+ import { KeyvStoreAdapter, StoredData, Keyv } from 'keyv';
5
+ export { Keyv } from 'keyv';
4
6
 
5
7
  declare class KeyvDynamo extends EventEmitter implements KeyvStoreAdapter {
6
8
  ttlSupport: boolean;
7
9
  sixHoursInMilliseconds: number;
8
10
  namespace?: string;
9
- opts: Omit<KeyvDynamoOptions, 'tableName'> & {
11
+ opts: Omit<KeyvDynamoOptions, "tableName"> & {
10
12
  tableName: string;
11
13
  };
12
- private readonly client;
14
+ readonly client: DynamoDBDocument;
13
15
  private readonly tableReady;
14
16
  constructor(options: KeyvDynamoOptions | string);
15
17
  set(key: string, value: unknown, ttl?: number): Promise<void>;
@@ -28,5 +30,11 @@ type KeyvDynamoOptions = {
28
30
  dialect?: string;
29
31
  tableName?: string;
30
32
  } & DynamoDBClientConfig;
33
+ /**
34
+ * Will create a Keyv instance with the DynamoDB adapter. This will also set the namespace and useKeyPrefix to false.
35
+ * @param options - Options for the adapter including DynamoDB client configuration and table settings.
36
+ * @returns {Keyv} - Keyv instance with the DynamoDB adapter
37
+ */
38
+ declare function createKeyv(options?: KeyvDynamoOptions | string): Keyv;
31
39
 
32
- export { KeyvDynamo, type KeyvDynamoOptions, KeyvDynamo as default };
40
+ export { KeyvDynamo, type KeyvDynamoOptions, createKeyv, KeyvDynamo as default };
package/dist/index.d.ts CHANGED
@@ -1,15 +1,17 @@
1
- import EventEmitter from 'events';
1
+ import EventEmitter from 'node:events';
2
2
  import { DynamoDBClientConfig } from '@aws-sdk/client-dynamodb';
3
- import { KeyvStoreAdapter, StoredData } from 'keyv';
3
+ import { DynamoDBDocument } from '@aws-sdk/lib-dynamodb';
4
+ import { KeyvStoreAdapter, StoredData, Keyv } from 'keyv';
5
+ export { Keyv } from 'keyv';
4
6
 
5
7
  declare class KeyvDynamo extends EventEmitter implements KeyvStoreAdapter {
6
8
  ttlSupport: boolean;
7
9
  sixHoursInMilliseconds: number;
8
10
  namespace?: string;
9
- opts: Omit<KeyvDynamoOptions, 'tableName'> & {
11
+ opts: Omit<KeyvDynamoOptions, "tableName"> & {
10
12
  tableName: string;
11
13
  };
12
- private readonly client;
14
+ readonly client: DynamoDBDocument;
13
15
  private readonly tableReady;
14
16
  constructor(options: KeyvDynamoOptions | string);
15
17
  set(key: string, value: unknown, ttl?: number): Promise<void>;
@@ -28,5 +30,11 @@ type KeyvDynamoOptions = {
28
30
  dialect?: string;
29
31
  tableName?: string;
30
32
  } & DynamoDBClientConfig;
33
+ /**
34
+ * Will create a Keyv instance with the DynamoDB adapter. This will also set the namespace and useKeyPrefix to false.
35
+ * @param options - Options for the adapter including DynamoDB client configuration and table settings.
36
+ * @returns {Keyv} - Keyv instance with the DynamoDB adapter
37
+ */
38
+ declare function createKeyv(options?: KeyvDynamoOptions | string): Keyv;
31
39
 
32
- export { KeyvDynamo, type KeyvDynamoOptions, KeyvDynamo as default };
40
+ export { KeyvDynamo, type KeyvDynamoOptions, createKeyv, KeyvDynamo as default };
package/dist/index.js CHANGED
@@ -4,14 +4,16 @@ 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";
12
12
  import {
13
13
  DynamoDBDocument
14
14
  } from "@aws-sdk/lib-dynamodb";
15
+ import { Keyv } from "keyv";
16
+ import { Keyv as Keyv2 } from "keyv";
15
17
  var KeyvDynamo = class extends EventEmitter {
16
18
  ttlSupport = true;
17
19
  sixHoursInMilliseconds = 6 * 60 * 60 * 1e3;
@@ -31,13 +33,17 @@ var KeyvDynamo = class extends EventEmitter {
31
33
  ...options
32
34
  };
33
35
  this.client = DynamoDBDocument.from(new DynamoDB(this.opts));
34
- this.tableReady = this.ensureTable(this.opts.tableName).catch((error) => {
35
- this.emit("error", error);
36
- });
36
+ this.tableReady = this.ensureTable(this.opts.tableName).catch(
37
+ (error) => {
38
+ this.emit("error", error);
39
+ }
40
+ );
37
41
  }
38
42
  async set(key, value, ttl) {
39
43
  await this.tableReady;
40
- const sixHoursFromNowEpoch = Math.floor((Date.now() + this.sixHoursInMilliseconds) / 1e3);
44
+ const sixHoursFromNowEpoch = Math.floor(
45
+ (Date.now() + this.sixHoursInMilliseconds) / 1e3
46
+ );
41
47
  const expiresAt = typeof ttl === "number" ? Math.floor((Date.now() + (ttl + 1e3)) / 1e3) : sixHoursFromNowEpoch;
42
48
  const putInput = {
43
49
  TableName: this.opts.tableName,
@@ -84,7 +90,9 @@ var KeyvDynamo = class extends EventEmitter {
84
90
  }
85
91
  };
86
92
  const { Responses: { [this.opts.tableName]: items = [] } = {} } = await this.client.batchGet(batchGetInput);
87
- return keys.map((key) => items.find((item) => item?.id === key)?.value);
93
+ return keys.map(
94
+ (key) => items.find((item) => item?.id === key)?.value
95
+ );
88
96
  }
89
97
  async deleteMany(keys) {
90
98
  await this.tableReady;
@@ -123,7 +131,9 @@ var KeyvDynamo = class extends EventEmitter {
123
131
  }
124
132
  async ensureTable(tableName) {
125
133
  try {
126
- await this.client.send(new DescribeTableCommand({ TableName: tableName }));
134
+ await this.client.send(
135
+ new DescribeTableCommand({ TableName: tableName })
136
+ );
127
137
  } catch (error) {
128
138
  if (error instanceof ResourceNotFoundException) {
129
139
  await this.createTable(tableName);
@@ -134,23 +144,27 @@ var KeyvDynamo = class extends EventEmitter {
134
144
  }
135
145
  async createTable(tableName) {
136
146
  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
- }));
147
+ await this.client.send(
148
+ new CreateTableCommand({
149
+ TableName: tableName,
150
+ KeySchema: [{ AttributeName: "id", KeyType: "HASH" }],
151
+ AttributeDefinitions: [{ AttributeName: "id", AttributeType: "S" }],
152
+ BillingMode: "PAY_PER_REQUEST"
153
+ })
154
+ );
143
155
  await waitUntilTableExists(
144
156
  { client: this.client, maxWaitTime: 60 },
145
157
  { TableName: tableName }
146
158
  );
147
- await this.client.send(new UpdateTimeToLiveCommand({
148
- TableName: tableName,
149
- TimeToLiveSpecification: {
150
- AttributeName: "expiresAt",
151
- Enabled: true
152
- }
153
- }));
159
+ await this.client.send(
160
+ new UpdateTimeToLiveCommand({
161
+ TableName: tableName,
162
+ TimeToLiveSpecification: {
163
+ AttributeName: "expiresAt",
164
+ Enabled: true
165
+ }
166
+ })
167
+ );
154
168
  } catch (error) {
155
169
  if (error instanceof ResourceInUseException) {
156
170
  await waitUntilTableExists(
@@ -164,7 +178,23 @@ var KeyvDynamo = class extends EventEmitter {
164
178
  }
165
179
  };
166
180
  var index_default = KeyvDynamo;
181
+ function createKeyv(options) {
182
+ const adapter = new KeyvDynamo(options ?? {});
183
+ if (typeof options === "object" && options?.namespace) {
184
+ adapter.namespace = options.namespace;
185
+ const keyv2 = new Keyv(adapter, {
186
+ namespace: options.namespace,
187
+ useKeyPrefix: false
188
+ });
189
+ return keyv2;
190
+ }
191
+ const keyv = new Keyv(adapter, { useKeyPrefix: false });
192
+ keyv.namespace = void 0;
193
+ return keyv;
194
+ }
167
195
  export {
196
+ Keyv2 as Keyv,
168
197
  KeyvDynamo,
198
+ createKeyv,
169
199
  index_default as default
170
200
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keyv/dynamo",
3
- "version": "1.0.1",
3
+ "version": "1.2.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,16 @@
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.896.0",
39
+ "@aws-sdk/lib-dynamodb": "^3.896.0"
63
40
  },
64
41
  "devDependencies": {
42
+ "@biomejs/biome": "^2.2.4",
65
43
  "vitest": "^3.2.4",
66
- "@keyv/test-suite": "^2.1.1",
67
- "keyv": "^5.5.0"
44
+ "@keyv/test-suite": "^2.1.1"
45
+ },
46
+ "peerDependencies": {
47
+ "keyv": "^5.5.3"
68
48
  },
69
49
  "tsd": {
70
50
  "directory": "test"
@@ -75,8 +55,10 @@
75
55
  ],
76
56
  "scripts": {
77
57
  "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",
58
+ "lint": "biome check --write --error-on-warnings",
59
+ "lint:ci": "biome check --error-on-warnings",
60
+ "test": "pnpm lint && vitest run --coverage",
61
+ "test:ci": "pnpm lint:ci && vitest --run --sequence.setupFiles=list --coverage",
80
62
  "clean": "rimraf ./node_modules ./coverage ./dist"
81
63
  }
82
64
  }