dynoquery 0.1.4 → 0.1.6

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
@@ -12,7 +12,6 @@ npm install dynoquery
12
12
 
13
13
  - Basic CRUD operations (create, get, update, delete)
14
14
  - Optimized for **Single-Table Design**
15
- - Model-based approach for easy data management
16
15
  - Query and Scan support
17
16
  - Batch operations (batchGet, batchWrite)
18
17
  - TypeScript support
@@ -31,9 +30,10 @@ const db = new DynoQuery({
31
30
  // optional endpoint for local development
32
31
  // endpoint: 'http://localhost:8000'
33
32
  partitions: {
34
- User: { pkPrefix: 'USER#' },
33
+ User: { pkPrefix: 'USER#' }, // TENANT#A#USER#
35
34
  },
36
35
  indexes: {
36
+ // TENANT#A#CAT#
37
37
  ByCategory: { indexName: 'GSI1', pkPrefix: 'CAT#' } // pkName defaults to GSI1PK, skName defaults to GSI1SK
38
38
  }
39
39
  });
@@ -66,14 +66,23 @@ async function example() {
66
66
  console.log(userMetadata);
67
67
 
68
68
  // Create an item through partition
69
- const profileModel = await john.create('PROFILE', { name: 'John Doe', email: 'john@example.com' });
69
+ await john.create('PROFILE', { name: 'John Doe', email: 'john@example.com' });
70
70
 
71
- // Update the model (updates both DB and partition cache)
72
- await profileModel.update({ theme: 'dark' });
71
+ // You can also use getPkValue() to get the generated PK for the partition or index
72
+ // This is useful when you need to store it in another attribute (e.g., GSI)
73
+ const cat = db.ByCategory('USER');
74
+ await john.create('PROFILE', {
75
+ name: 'John Doe',
76
+ email: 'john@example.com',
77
+ GSI1PK: cat.getPkValue(),
78
+ GSI1SK: 'john@example.com'
79
+ });
80
+
81
+ // Update the item (updates both DB and partition cache)
82
+ await john.update('PROFILE', { theme: 'dark' });
73
83
 
74
- // If you need the Model instance for save/delete without immediate create:
75
- const metaModel = john.model('METADATA');
76
- await metaModel.save({ lastLogin: new Date().toISOString() });
84
+ // Delete an item
85
+ await john.delete('METADATA');
77
86
 
78
87
  // Advanced Partition usage (Subclassing)
79
88
  class UserPartition extends Partition {
@@ -88,6 +97,48 @@ async function example() {
88
97
  }
89
98
  ```
90
99
 
100
+ ### Batch Operations
101
+
102
+ If you have a `tableName` configured in `DynoQuery`, you can use the `Items` property in `batchGet` and `batchWrite` to automatically target that table.
103
+
104
+ You can also generate items for `batchGet` using the `batchGetInput` method from partitions and indexes:
105
+
106
+ ```typescript
107
+ const john = db.User('john@example.com');
108
+ const jack = db.User('jack@example.com');
109
+ const cat = db.ByCategory('1');
110
+
111
+ const batchItem1 = john.batchGetInput('METADATA');
112
+ const batchOthers = cat.batchGetInput('METADATA', 'DATA', 'PROFILE');
113
+ const batchCat = cat.batchGetInput(); // No sk defined, so will get partition key only
114
+
115
+ await db.batchGet(batchItem1, batchOthers, batchCat);
116
+ ```
117
+
118
+ ```typescript
119
+ // batchGet with explicit Items
120
+ await db.batchGet({
121
+ Items: [
122
+ { PK: 'USER#1', SK: 'METADATA' },
123
+ { PK: 'USER#2', SK: 'METADATA' }
124
+ ]
125
+ });
126
+
127
+ // batchWrite with simplified Items (automatically wrapped in PutRequest)
128
+ await db.batchWrite({
129
+ Items: [
130
+ { PK: 'USER#3', SK: 'METADATA', name: 'Alice' },
131
+ {
132
+ DeleteRequest: {
133
+ Key: { PK: 'USER#1', SK: 'SESSION#123' }
134
+ }
135
+ }
136
+ ]
137
+ });
138
+ ```
139
+
140
+ You can still use the standard AWS SDK `RequestItems` if you need to target multiple tables or if you prefer the original syntax.
141
+
91
142
  ## API Reference
92
143
 
93
144
  ### DynoQuery
@@ -101,25 +152,27 @@ The main client for interacting with DynamoDB.
101
152
  - `batchGet(params)`: Batch get items.
102
153
  - `batchWrite(params)`: Batch write items.
103
154
 
104
- ### Model
105
- A model-based abstraction for a specific data type.
106
- - `find(id?)`: Find an item by ID (PK suffix).
107
- - `save(data, id?)`: Save an item.
108
- - `update(data, id?)`: Update an existing item (partial update).
109
- - `remove(id?)`: Delete an item.
110
-
111
155
  ### Partition
112
- A way to manage models and data within a specific partition.
156
+ A way to manage data within a specific partition.
157
+ - `getPkValue()`: Returns the generated partition key value.
113
158
  - `get(sk)`: Fetches data for a specific sort key (returns a Promise).
114
159
  - `getAll()`: Fetches all items in the partition and caches them. Returns the items.
115
- - `create(sk, data)`: Creates an item in the partition and returns its `Model`.
116
- - `model(sk)`: Get a `Model` instance for a specific sort key.
160
+ - `create(sk, data)`: Creates an item in the partition.
161
+ - `update(sk, data)`: Updates an existing item (partial update).
162
+ - `delete(sk)`: Deletes an item.
163
+ - `batchGetInput(...sks)`: Generates items for batch query.
164
+ - `batchWriteInput(...items)`: Generates items for batch write.
165
+ - `batchDeleteInput(...sks)`: Generates items for batch delete.
117
166
  - `deleteAll()`: Deletes all items in the partition.
118
167
 
119
168
  ### IndexQuery
120
169
  A way to query Global Secondary Indexes.
170
+ - `getPkValue()`: Returns the generated partition key value for this index.
121
171
  - `get(skValue | options)`: Query items in the index. Supports `skValue` (string) for `begins_with` search, or an options object with `skValue`, `limit`, and `scanIndexForward`.
122
172
  - `getAll()`: Fetches all items in the index for the given partition key.
173
+ - `batchGetInput(...sks)`: Generates items for batch query.
174
+ - `batchWriteInput(...items)`: Generates items for batch write.
175
+ - `batchDeleteInput(...sks)`: Generates items for batch delete.
123
176
  - Automatically identifies models in results using `__model` and provides `getPartition()` helper.
124
177
 
125
178
  ## License
@@ -21,5 +21,18 @@ export declare class IndexQuery {
21
21
  scanIndexForward?: boolean;
22
22
  }): Promise<T[]>;
23
23
  getAll<T = any>(): Promise<T[]>;
24
+ getPkValue(): string;
25
+ /**
26
+ * Generates items for batch query.
27
+ */
28
+ batchGetInput(...sks: string[]): any[];
29
+ /**
30
+ * Generates items for batch write (put).
31
+ */
32
+ batchWriteInput(...items: any[]): any[];
33
+ /**
34
+ * Generates items for batch delete.
35
+ */
36
+ batchDeleteInput(...sks: string[]): any[];
24
37
  private mapItemToModel;
25
38
  }
@@ -68,6 +68,52 @@ class IndexQuery {
68
68
  return this.get();
69
69
  });
70
70
  }
71
+ getPkValue() {
72
+ return this.pkValue;
73
+ }
74
+ /**
75
+ * Generates items for batch query.
76
+ */
77
+ batchGetInput(...sks) {
78
+ if (sks.length === 0) {
79
+ return [{
80
+ TableName: this.tableName,
81
+ Key: { [this.pkName]: this.pkValue }
82
+ }];
83
+ }
84
+ return sks.map(sk => ({
85
+ TableName: this.tableName,
86
+ Key: {
87
+ [this.pkName]: this.pkValue,
88
+ [this.skName]: sk
89
+ }
90
+ }));
91
+ }
92
+ /**
93
+ * Generates items for batch write (put).
94
+ */
95
+ batchWriteInput(...items) {
96
+ return items.map(item => ({
97
+ TableName: this.tableName,
98
+ PutRequest: {
99
+ Item: Object.assign({ [this.pkName]: this.pkValue }, item)
100
+ }
101
+ }));
102
+ }
103
+ /**
104
+ * Generates items for batch delete.
105
+ */
106
+ batchDeleteInput(...sks) {
107
+ return sks.map(sk => ({
108
+ TableName: this.tableName,
109
+ DeleteRequest: {
110
+ Key: {
111
+ [this.pkName]: this.pkValue,
112
+ [this.skName]: sk
113
+ }
114
+ }
115
+ }));
116
+ }
71
117
  mapItemToModel(item) {
72
118
  const pkName = this.db.getPkName();
73
119
  const pkValue = item[pkName];
package/dist/index.d.ts CHANGED
@@ -21,6 +21,12 @@ export interface DynoQueryConfig {
21
21
  pkPrefix?: string;
22
22
  }>;
23
23
  }
24
+ export type BatchGetInput = BatchGetCommandInput & {
25
+ Items?: any[];
26
+ };
27
+ export type BatchWriteInput = BatchWriteCommandInput & {
28
+ Items?: any[];
29
+ };
24
30
  export declare class DynoQuery {
25
31
  private client;
26
32
  private docClient;
@@ -58,11 +64,11 @@ export declare class DynoQuery {
58
64
  /**
59
65
  * Get multiple items by their primary keys.
60
66
  */
61
- batchGet(params: BatchGetCommandInput): Promise<import("@aws-sdk/lib-dynamodb").BatchGetCommandOutput>;
67
+ batchGet(params: BatchGetInput | any, ...additionalItems: any[][]): Promise<import("@aws-sdk/lib-dynamodb").BatchGetCommandOutput>;
62
68
  /**
63
69
  * Put or delete multiple items in one or more tables.
64
70
  */
65
- batchWrite(params: BatchWriteCommandInput): Promise<import("@aws-sdk/lib-dynamodb").BatchWriteCommandOutput>;
71
+ batchWrite(params: BatchWriteInput): Promise<import("@aws-sdk/lib-dynamodb").BatchWriteCommandOutput>;
66
72
  getTableName(): string | undefined;
67
73
  getPkPrefix(): string;
68
74
  getPkName(): string;
@@ -71,6 +77,5 @@ export declare class DynoQuery {
71
77
  pkPrefix: string;
72
78
  }>;
73
79
  }
74
- export * from "./model";
75
80
  export * from "./partition";
76
81
  export * from "./index-query";
package/dist/index.js CHANGED
@@ -22,6 +22,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
22
22
  step((generator = generator.apply(thisArg, _arguments || [])).next());
23
23
  });
24
24
  };
25
+ var __rest = (this && this.__rest) || function (s, e) {
26
+ var t = {};
27
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
28
+ t[p] = s[p];
29
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
30
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
31
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
32
+ t[p[i]] = s[p[i]];
33
+ }
34
+ return t;
35
+ };
25
36
  Object.defineProperty(exports, "__esModule", { value: true });
26
37
  exports.DynoQuery = void 0;
27
38
  const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
@@ -30,35 +41,28 @@ const partition_1 = require("./partition");
30
41
  class DynoQuery {
31
42
  constructor(config = {}) {
32
43
  this.registeredPartitions = {};
33
- const clientConfig = Object.assign({}, config);
34
- // Remove properties that are not part of DynamoDBClientConfig
35
- delete clientConfig.tableName;
36
- delete clientConfig.pkPrefix;
37
- delete clientConfig.partitions;
38
- delete clientConfig.indexes;
39
- delete clientConfig.pkName;
40
- delete clientConfig.skName;
44
+ const { tableName, pkName, skName, pkPrefix, partitions, indexes } = config, clientConfig = __rest(config, ["tableName", "pkName", "skName", "pkPrefix", "partitions", "indexes"]);
41
45
  this.client = new client_dynamodb_1.DynamoDBClient(clientConfig);
42
46
  this.docClient = lib_dynamodb_1.DynamoDBDocumentClient.from(this.client, {
43
47
  marshallOptions: {
44
48
  removeUndefinedValues: true,
45
49
  }
46
50
  });
47
- this.defaultTableName = config.tableName;
48
- this.globalPkPrefix = config.pkPrefix || "";
49
- this.pkName = config.pkName || "PK";
50
- this.skName = config.skName || "SK";
51
- if (config.partitions) {
52
- this.registeredPartitions = config.partitions;
53
- Object.entries(config.partitions).forEach(([name, def]) => {
51
+ this.defaultTableName = tableName;
52
+ this.globalPkPrefix = pkPrefix || "";
53
+ this.pkName = pkName || "PK";
54
+ this.skName = skName || "SK";
55
+ if (partitions) {
56
+ this.registeredPartitions = partitions;
57
+ Object.entries(partitions).forEach(([name, def]) => {
54
58
  this[name] = (id) => {
55
59
  return new partition_1.Partition(this, { pkPrefix: this.globalPkPrefix + def.pkPrefix }, id);
56
60
  };
57
61
  });
58
62
  }
59
- if (config.indexes) {
63
+ if (indexes) {
60
64
  const { IndexQuery } = require("./index-query");
61
- Object.entries(config.indexes).forEach(([name, def]) => {
65
+ Object.entries(indexes).forEach(([name, def]) => {
62
66
  this[name] = (id) => {
63
67
  return new IndexQuery(this, {
64
68
  indexName: def.indexName,
@@ -146,16 +150,46 @@ class DynoQuery {
146
150
  /**
147
151
  * Get multiple items by their primary keys.
148
152
  */
149
- batchGet(params) {
153
+ batchGet(params, ...additionalItems) {
150
154
  return __awaiter(this, void 0, void 0, function* () {
151
- if (this.defaultTableName && params.RequestItems) {
152
- // Note: Batch operations are a bit trickier because TableName is a key in RequestItems
153
- // This wrapper doesn't automatically add it to RequestItems yet,
154
- // but let's see if we should handle it.
155
- // For now, let's keep it as is or add it if RequestItems is empty?
156
- // Usually BatchGetCommandInput is complex.
155
+ let finalParams;
156
+ if (params && !params.RequestItems && !params.Items && (Array.isArray(params) || additionalItems.length > 0)) {
157
+ // Handle the case where arguments are multiple arrays of items
158
+ const allItems = Array.isArray(params) ? [...params] : [];
159
+ additionalItems.forEach(chunk => {
160
+ if (Array.isArray(chunk)) {
161
+ allItems.push(...chunk);
162
+ }
163
+ else {
164
+ allItems.push(chunk);
165
+ }
166
+ });
167
+ finalParams = {
168
+ Items: allItems
169
+ };
170
+ }
171
+ else {
172
+ finalParams = params;
157
173
  }
158
- const command = new lib_dynamodb_1.BatchGetCommand(params);
174
+ if (!finalParams.RequestItems && finalParams.Items) {
175
+ finalParams.RequestItems = {};
176
+ finalParams.Items.forEach((item) => {
177
+ const tableName = item.TableName || this.defaultTableName;
178
+ if (!tableName) {
179
+ throw new Error("TableName must be provided for batch operations if no default tableName is set");
180
+ }
181
+ if (!finalParams.RequestItems[tableName]) {
182
+ finalParams.RequestItems[tableName] = { Keys: [] };
183
+ }
184
+ const key = item.Key || item;
185
+ finalParams.RequestItems[tableName].Keys.push(key);
186
+ });
187
+ delete finalParams.Items;
188
+ }
189
+ else if (!finalParams.RequestItems && this.defaultTableName) {
190
+ finalParams.RequestItems = {};
191
+ }
192
+ const command = new lib_dynamodb_1.BatchGetCommand(finalParams);
159
193
  return yield this.docClient.send(command);
160
194
  });
161
195
  }
@@ -164,6 +198,24 @@ class DynoQuery {
164
198
  */
165
199
  batchWrite(params) {
166
200
  return __awaiter(this, void 0, void 0, function* () {
201
+ if (!params.RequestItems && params.Items) {
202
+ params.RequestItems = {};
203
+ params.Items.forEach((item) => {
204
+ const tableName = item.TableName || this.defaultTableName;
205
+ if (!tableName) {
206
+ throw new Error("TableName must be provided for batch operations if no default tableName is set");
207
+ }
208
+ if (!params.RequestItems[tableName]) {
209
+ params.RequestItems[tableName] = [];
210
+ }
211
+ const request = item.PutRequest || item.DeleteRequest ? item : { PutRequest: { Item: item } };
212
+ params.RequestItems[tableName].push(request);
213
+ });
214
+ delete params.Items;
215
+ }
216
+ else if (!params.RequestItems && this.defaultTableName) {
217
+ params.RequestItems = {};
218
+ }
167
219
  const command = new lib_dynamodb_1.BatchWriteCommand(params);
168
220
  return yield this.docClient.send(command);
169
221
  });
@@ -185,6 +237,5 @@ class DynoQuery {
185
237
  }
186
238
  }
187
239
  exports.DynoQuery = DynoQuery;
188
- __exportStar(require("./model"), exports);
189
240
  __exportStar(require("./partition"), exports);
190
241
  __exportStar(require("./index-query"), exports);
@@ -1,5 +1,4 @@
1
1
  import { DynoQuery } from "./index";
2
- import { Model } from "./model";
3
2
  export interface PartitionConfig {
4
3
  tableName?: string;
5
4
  pk?: string;
@@ -8,7 +7,7 @@ export interface PartitionConfig {
8
7
  export declare class Partition {
9
8
  protected db: DynoQuery;
10
9
  protected tableName?: string;
11
- protected pk: string;
10
+ protected pkValue: string;
12
11
  protected pkName: string;
13
12
  protected skName: string;
14
13
  protected cache: Record<string, any>;
@@ -20,20 +19,40 @@ export declare class Partition {
20
19
  */
21
20
  getAll<T = any>(): Promise<T[]>;
22
21
  /**
23
- * Get a model instance for a specific SK within this partition.
22
+ * Create an item in this partition.
24
23
  */
25
- model<T = any>(sk: string): Model<T>;
26
- getPK(): string;
24
+ create<T = any>(sk: string, data: T): Promise<void>;
27
25
  /**
28
- * Create an item in this partition and return the model.
26
+ * Update an existing item in this partition.
29
27
  */
30
- create<T = any>(sk: string, data: T): Promise<Model<T>>;
28
+ update<T = any>(sk: string, data: Partial<T>): Promise<void>;
29
+ /**
30
+ * Delete an item by its SK within this partition.
31
+ */
32
+ delete(sk: string): Promise<void>;
31
33
  /**
32
34
  * Get data for a specific SK within this partition.
33
35
  * If the partition is loaded, it returns from cache.
34
36
  * Otherwise, it fetches the data immediately.
35
37
  */
36
38
  get<T = any>(sk: string): Promise<T | null>;
39
+ getPkValue(): string;
40
+ /**
41
+ * Generates items for batch query.
42
+ * If no SKs are provided, it might not be very useful for batchGet (which requires full keys),
43
+ * but the requirement says "will get all by pkValue" if no sk defined.
44
+ * Actually, BatchGetItem requires both PK and SK if the table has both.
45
+ * If it's for IndexQuery, it might be different.
46
+ */
47
+ batchGetInput(...sks: string[]): any[];
48
+ /**
49
+ * Generates items for batch write (put).
50
+ */
51
+ batchWriteInput(...items: any[]): any[];
52
+ /**
53
+ * Generates items for batch delete.
54
+ */
55
+ batchDeleteInput(...sks: string[]): any[];
37
56
  /**
38
57
  * Delete all data in this partition.
39
58
  */
package/dist/partition.js CHANGED
@@ -10,7 +10,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.Partition = void 0;
13
- const model_1 = require("./model");
14
13
  class Partition {
15
14
  constructor(db, config, id) {
16
15
  this.cache = {};
@@ -20,7 +19,7 @@ class Partition {
20
19
  this.pkName = db.getPkName();
21
20
  this.skName = db.getSkName();
22
21
  if (config.pk) {
23
- this.pk = config.pk;
22
+ this.pkValue = config.pk;
24
23
  }
25
24
  else {
26
25
  const globalPrefix = db.getPkPrefix();
@@ -41,10 +40,10 @@ class Partition {
41
40
  if (globalPrefix && !partitionPrefix.startsWith(globalPrefix)) {
42
41
  finalPrefix = globalPrefix + partitionPrefix;
43
42
  }
44
- this.pk = `${finalPrefix}${id || ""}`;
43
+ this.pkValue = `${finalPrefix}${id || ""}`;
45
44
  }
46
45
  else {
47
- throw new Error("Either pk or pkPrefix must be provided in PartitionConfig");
46
+ throw new Error("Either pkValue or pkPrefix must be provided in PartitionConfig");
48
47
  }
49
48
  }
50
49
  if (!this.tableName) {
@@ -64,7 +63,7 @@ class Partition {
64
63
  "#pk": this.pkName,
65
64
  },
66
65
  ExpressionAttributeValues: {
67
- ":pk": this.pk,
66
+ ":pk": this.pkValue,
68
67
  },
69
68
  });
70
69
  const items = (response.Items || []);
@@ -78,35 +77,41 @@ class Partition {
78
77
  });
79
78
  }
80
79
  /**
81
- * Get a model instance for a specific SK within this partition.
80
+ * Create an item in this partition.
82
81
  */
83
- model(sk) {
84
- const config = {
85
- tableName: this.tableName,
86
- pkPrefix: this.pk, // In this context, pk is fixed, so prefix is the full PK
87
- skValue: sk,
88
- onUpdate: (updatedSk, data) => {
89
- if (data === null) {
90
- delete this.cache[updatedSk];
91
- }
92
- else {
93
- this.cache[updatedSk] = data;
94
- }
95
- }
96
- };
97
- return new model_1.Model(this.db, config);
82
+ create(sk, data) {
83
+ return __awaiter(this, void 0, void 0, function* () {
84
+ const item = Object.assign({ [this.pkName]: this.pkValue, [this.skName]: sk }, data);
85
+ yield this.db.create({
86
+ TableName: this.tableName,
87
+ Item: item,
88
+ });
89
+ this.cache[sk] = item;
90
+ });
98
91
  }
99
- getPK() {
100
- return this.pk;
92
+ /**
93
+ * Update an existing item in this partition.
94
+ */
95
+ update(sk, data) {
96
+ return __awaiter(this, void 0, void 0, function* () {
97
+ const current = (yield this.get(sk)) || {};
98
+ const updated = Object.assign(Object.assign({}, current), data);
99
+ yield this.create(sk, updated);
100
+ });
101
101
  }
102
102
  /**
103
- * Create an item in this partition and return the model.
103
+ * Delete an item by its SK within this partition.
104
104
  */
105
- create(sk, data) {
105
+ delete(sk) {
106
106
  return __awaiter(this, void 0, void 0, function* () {
107
- const m = this.model(sk);
108
- yield m.save(data);
109
- return m;
107
+ yield this.db.delete({
108
+ TableName: this.tableName,
109
+ Key: {
110
+ [this.pkName]: this.pkValue,
111
+ [this.skName]: sk,
112
+ },
113
+ });
114
+ delete this.cache[sk];
110
115
  });
111
116
  }
112
117
  /**
@@ -122,14 +127,70 @@ class Partition {
122
127
  if (this.isLoaded) {
123
128
  return null;
124
129
  }
125
- const model = this.model(sk);
126
- const data = yield model.find();
130
+ const response = yield this.db.get({
131
+ TableName: this.tableName,
132
+ Key: {
133
+ [this.pkName]: this.pkValue,
134
+ [this.skName]: sk,
135
+ },
136
+ });
137
+ const data = response.Item || null;
127
138
  if (data) {
128
139
  this.cache[sk] = data;
129
140
  }
130
141
  return data;
131
142
  });
132
143
  }
144
+ getPkValue() {
145
+ return this.pkValue;
146
+ }
147
+ /**
148
+ * Generates items for batch query.
149
+ * If no SKs are provided, it might not be very useful for batchGet (which requires full keys),
150
+ * but the requirement says "will get all by pkValue" if no sk defined.
151
+ * Actually, BatchGetItem requires both PK and SK if the table has both.
152
+ * If it's for IndexQuery, it might be different.
153
+ */
154
+ batchGetInput(...sks) {
155
+ if (sks.length === 0) {
156
+ return [{
157
+ TableName: this.tableName,
158
+ Key: { [this.pkName]: this.pkValue }
159
+ }];
160
+ }
161
+ return sks.map(sk => ({
162
+ TableName: this.tableName,
163
+ Key: {
164
+ [this.pkName]: this.pkValue,
165
+ [this.skName]: sk
166
+ }
167
+ }));
168
+ }
169
+ /**
170
+ * Generates items for batch write (put).
171
+ */
172
+ batchWriteInput(...items) {
173
+ return items.map(item => ({
174
+ TableName: this.tableName,
175
+ PutRequest: {
176
+ Item: Object.assign({ [this.pkName]: this.pkValue }, item)
177
+ }
178
+ }));
179
+ }
180
+ /**
181
+ * Generates items for batch delete.
182
+ */
183
+ batchDeleteInput(...sks) {
184
+ return sks.map(sk => ({
185
+ TableName: this.tableName,
186
+ DeleteRequest: {
187
+ Key: {
188
+ [this.pkName]: this.pkValue,
189
+ [this.skName]: sk
190
+ }
191
+ }
192
+ }));
193
+ }
133
194
  /**
134
195
  * Delete all data in this partition.
135
196
  */
@@ -142,7 +203,7 @@ class Partition {
142
203
  "#pk": this.pkName,
143
204
  },
144
205
  ExpressionAttributeValues: {
145
- ":pk": this.pk,
206
+ ":pk": this.pkValue,
146
207
  },
147
208
  });
148
209
  if (response.Items && response.Items.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dynoquery",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/devspikejs/dynoquery.git"
package/dist/model.js DELETED
@@ -1,102 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.Model = void 0;
13
- class Model {
14
- constructor(db, config) {
15
- this.db = db;
16
- this.tableName = config.tableName || db.getTableName();
17
- this.pkPrefix = config.pkPrefix;
18
- this.skValue = config.skValue;
19
- this.pkName = db.getPkName();
20
- this.skName = db.getSkName();
21
- this.onUpdate = config.onUpdate;
22
- if (!this.tableName) {
23
- throw new Error("TableName must be provided in ModelConfig or DynoQueryConfig");
24
- }
25
- }
26
- getTableName() {
27
- return this.tableName;
28
- }
29
- getPK(id = "") {
30
- return `${this.pkPrefix}${id}`;
31
- }
32
- /**
33
- * Find an item by its identifier (part of the PK).
34
- * Assumes the SK is fixed as defined in ModelConfig.
35
- */
36
- find() {
37
- return __awaiter(this, arguments, void 0, function* (id = "") {
38
- const response = yield this.db.get({
39
- TableName: this.getTableName(),
40
- Key: {
41
- [this.pkName]: this.getPK(id),
42
- [this.skName]: this.skValue,
43
- },
44
- });
45
- return response.Item || null;
46
- });
47
- }
48
- /**
49
- * Save an item.
50
- */
51
- save(data_1) {
52
- return __awaiter(this, arguments, void 0, function* (data, id = "") {
53
- const item = Object.assign({ [this.pkName]: this.getPK(id), [this.skName]: this.skValue }, data);
54
- yield this.db.create({
55
- TableName: this.getTableName(),
56
- Item: item,
57
- });
58
- if (this.onUpdate) {
59
- this.onUpdate(this.skValue, item);
60
- }
61
- });
62
- }
63
- /**
64
- * Update an existing item.
65
- */
66
- update(data_1) {
67
- return __awaiter(this, arguments, void 0, function* (data, id = "") {
68
- // For simplicity in this wrapper, we use create (PutItem) to update the whole item
69
- // but the user might expect a partial update if we use UpdateCommand.
70
- // However, for single table and this kind of wrapper, often we just put the whole item.
71
- // If we want to support partial updates in the cache, we need the current item.
72
- const response = yield this.db.get({
73
- TableName: this.getTableName(),
74
- Key: {
75
- [this.pkName]: this.getPK(id),
76
- [this.skName]: this.skValue,
77
- },
78
- });
79
- const current = response.Item || {};
80
- const updated = Object.assign(Object.assign({}, current), data);
81
- yield this.save(updated, id);
82
- });
83
- }
84
- /**
85
- * Delete an item by its identifier.
86
- */
87
- remove() {
88
- return __awaiter(this, arguments, void 0, function* (id = "") {
89
- yield this.db.delete({
90
- TableName: this.getTableName(),
91
- Key: {
92
- [this.pkName]: this.getPK(id),
93
- [this.skName]: this.skValue,
94
- },
95
- });
96
- if (this.onUpdate) {
97
- this.onUpdate(this.skValue, null);
98
- }
99
- });
100
- }
101
- }
102
- exports.Model = Model;