dynoquery 0.1.5 → 0.1.7
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 -20
- package/dist/index-query.js +2 -2
- package/dist/index.d.ts +3 -4
- package/dist/index.js +7 -8
- package/dist/partition.d.ts +16 -13
- package/dist/partition.js +61 -47
- package/package.json +2 -1
- package/dist/model.js +0 -102
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
|
|
@@ -30,7 +29,7 @@ const db = new DynoQuery({
|
|
|
30
29
|
pkPrefix: 'TENANT#A#', // Optional: Global prefix for all partitions (useful for multitenancy)
|
|
31
30
|
// optional endpoint for local development
|
|
32
31
|
// endpoint: 'http://localhost:8000'
|
|
33
|
-
|
|
32
|
+
models: {
|
|
34
33
|
User: { pkPrefix: 'USER#' }, // TENANT#A#USER#
|
|
35
34
|
},
|
|
36
35
|
indexes: {
|
|
@@ -67,24 +66,23 @@ async function example() {
|
|
|
67
66
|
console.log(userMetadata);
|
|
68
67
|
|
|
69
68
|
// Create an item through partition
|
|
70
|
-
|
|
69
|
+
await john.create('PROFILE', { name: 'John Doe', email: 'john@example.com' });
|
|
71
70
|
|
|
72
71
|
// You can also use getPkValue() to get the generated PK for the partition or index
|
|
73
72
|
// This is useful when you need to store it in another attribute (e.g., GSI)
|
|
74
73
|
const cat = db.ByCategory('USER');
|
|
75
|
-
|
|
74
|
+
await john.create('PROFILE', {
|
|
76
75
|
name: 'John Doe',
|
|
77
76
|
email: 'john@example.com',
|
|
78
77
|
GSI1PK: cat.getPkValue(),
|
|
79
78
|
GSI1SK: 'john@example.com'
|
|
80
79
|
});
|
|
81
80
|
|
|
82
|
-
// Update the
|
|
83
|
-
await
|
|
81
|
+
// Update the item (updates both DB and partition cache)
|
|
82
|
+
await john.update('PROFILE', { theme: 'dark' });
|
|
84
83
|
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
await metaModel.save({ lastLogin: new Date().toISOString() });
|
|
84
|
+
// Delete an item
|
|
85
|
+
await john.delete('METADATA');
|
|
88
86
|
|
|
89
87
|
// Advanced Partition usage (Subclassing)
|
|
90
88
|
class UserPartition extends Partition {
|
|
@@ -154,20 +152,14 @@ The main client for interacting with DynamoDB.
|
|
|
154
152
|
- `batchGet(params)`: Batch get items.
|
|
155
153
|
- `batchWrite(params)`: Batch write items.
|
|
156
154
|
|
|
157
|
-
### Model
|
|
158
|
-
A model-based abstraction for a specific data type.
|
|
159
|
-
- `find(id?)`: Find an item by ID (PK suffix).
|
|
160
|
-
- `save(data, id?)`: Save an item.
|
|
161
|
-
- `update(data, id?)`: Update an existing item (partial update).
|
|
162
|
-
- `remove(id?)`: Delete an item.
|
|
163
|
-
|
|
164
155
|
### Partition
|
|
165
|
-
A way to manage
|
|
156
|
+
A way to manage data within a specific partition.
|
|
166
157
|
- `getPkValue()`: Returns the generated partition key value.
|
|
167
158
|
- `get(sk)`: Fetches data for a specific sort key (returns a Promise).
|
|
168
159
|
- `getAll()`: Fetches all items in the partition and caches them. Returns the items.
|
|
169
|
-
- `create(sk, data)`: Creates an item in the partition
|
|
170
|
-
- `
|
|
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.
|
|
171
163
|
- `batchGetInput(...sks)`: Generates items for batch query.
|
|
172
164
|
- `batchWriteInput(...items)`: Generates items for batch write.
|
|
173
165
|
- `batchDeleteInput(...sks)`: Generates items for batch delete.
|
|
@@ -181,7 +173,7 @@ A way to query Global Secondary Indexes.
|
|
|
181
173
|
- `batchGetInput(...sks)`: Generates items for batch query.
|
|
182
174
|
- `batchWriteInput(...items)`: Generates items for batch write.
|
|
183
175
|
- `batchDeleteInput(...sks)`: Generates items for batch delete.
|
|
184
|
-
- Automatically identifies
|
|
176
|
+
- Automatically identifies the model name in results using `__model` (based on registered models) and provides `getPartition()` helper.
|
|
185
177
|
|
|
186
178
|
## License
|
|
187
179
|
|
package/dist/index-query.js
CHANGED
|
@@ -119,9 +119,9 @@ class IndexQuery {
|
|
|
119
119
|
const pkValue = item[pkName];
|
|
120
120
|
if (!pkValue)
|
|
121
121
|
return item;
|
|
122
|
-
const
|
|
122
|
+
const registeredModels = this.db.getRegisteredModels();
|
|
123
123
|
const globalPrefix = this.db.getPkPrefix();
|
|
124
|
-
for (const [name, def] of Object.entries(
|
|
124
|
+
for (const [name, def] of Object.entries(registeredModels)) {
|
|
125
125
|
const fullPrefix = globalPrefix + def.pkPrefix;
|
|
126
126
|
if (pkValue.startsWith(fullPrefix)) {
|
|
127
127
|
// Find the ID by removing the prefix
|
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export interface DynoQueryConfig {
|
|
|
11
11
|
secretAccessKey: string;
|
|
12
12
|
sessionToken?: string;
|
|
13
13
|
};
|
|
14
|
-
|
|
14
|
+
models?: Record<string, {
|
|
15
15
|
pkPrefix: string;
|
|
16
16
|
}>;
|
|
17
17
|
indexes?: Record<string, {
|
|
@@ -34,7 +34,7 @@ export declare class DynoQuery {
|
|
|
34
34
|
private globalPkPrefix;
|
|
35
35
|
private pkName;
|
|
36
36
|
private skName;
|
|
37
|
-
private
|
|
37
|
+
private registeredModels;
|
|
38
38
|
[key: string]: any;
|
|
39
39
|
constructor(config?: DynoQueryConfig);
|
|
40
40
|
/**
|
|
@@ -73,10 +73,9 @@ export declare class DynoQuery {
|
|
|
73
73
|
getPkPrefix(): string;
|
|
74
74
|
getPkName(): string;
|
|
75
75
|
getSkName(): string;
|
|
76
|
-
|
|
76
|
+
getRegisteredModels(): Record<string, {
|
|
77
77
|
pkPrefix: string;
|
|
78
78
|
}>;
|
|
79
79
|
}
|
|
80
|
-
export * from "./model";
|
|
81
80
|
export * from "./partition";
|
|
82
81
|
export * from "./index-query";
|
package/dist/index.js
CHANGED
|
@@ -40,8 +40,8 @@ const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
|
|
|
40
40
|
const partition_1 = require("./partition");
|
|
41
41
|
class DynoQuery {
|
|
42
42
|
constructor(config = {}) {
|
|
43
|
-
this.
|
|
44
|
-
const { tableName, pkName, skName, pkPrefix,
|
|
43
|
+
this.registeredModels = {};
|
|
44
|
+
const { tableName, pkName, skName, pkPrefix, models, indexes } = config, clientConfig = __rest(config, ["tableName", "pkName", "skName", "pkPrefix", "models", "indexes"]);
|
|
45
45
|
this.client = new client_dynamodb_1.DynamoDBClient(clientConfig);
|
|
46
46
|
this.docClient = lib_dynamodb_1.DynamoDBDocumentClient.from(this.client, {
|
|
47
47
|
marshallOptions: {
|
|
@@ -52,9 +52,9 @@ class DynoQuery {
|
|
|
52
52
|
this.globalPkPrefix = pkPrefix || "";
|
|
53
53
|
this.pkName = pkName || "PK";
|
|
54
54
|
this.skName = skName || "SK";
|
|
55
|
-
if (
|
|
56
|
-
this.
|
|
57
|
-
Object.entries(
|
|
55
|
+
if (models) {
|
|
56
|
+
this.registeredModels = models;
|
|
57
|
+
Object.entries(models).forEach(([name, def]) => {
|
|
58
58
|
this[name] = (id) => {
|
|
59
59
|
return new partition_1.Partition(this, { pkPrefix: this.globalPkPrefix + def.pkPrefix }, id);
|
|
60
60
|
};
|
|
@@ -232,11 +232,10 @@ class DynoQuery {
|
|
|
232
232
|
getSkName() {
|
|
233
233
|
return this.skName;
|
|
234
234
|
}
|
|
235
|
-
|
|
236
|
-
return this.
|
|
235
|
+
getRegisteredModels() {
|
|
236
|
+
return this.registeredModels;
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
239
|
exports.DynoQuery = DynoQuery;
|
|
240
|
-
__exportStar(require("./model"), exports);
|
|
241
240
|
__exportStar(require("./partition"), exports);
|
|
242
241
|
__exportStar(require("./index-query"), exports);
|
package/dist/partition.d.ts
CHANGED
|
@@ -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;
|
|
@@ -20,9 +19,23 @@ export declare class Partition {
|
|
|
20
19
|
*/
|
|
21
20
|
getAll<T = any>(): Promise<T[]>;
|
|
22
21
|
/**
|
|
23
|
-
*
|
|
22
|
+
* Create an item in this partition.
|
|
24
23
|
*/
|
|
25
|
-
|
|
24
|
+
create<T = any>(sk: string, data: T): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Update an existing item in this partition.
|
|
27
|
+
*/
|
|
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>;
|
|
33
|
+
/**
|
|
34
|
+
* Get data for a specific SK within this partition.
|
|
35
|
+
* If the partition is loaded, it returns from cache.
|
|
36
|
+
* Otherwise, it fetches the data immediately.
|
|
37
|
+
*/
|
|
38
|
+
get<T = any>(sk: string): Promise<T | null>;
|
|
26
39
|
getPkValue(): string;
|
|
27
40
|
/**
|
|
28
41
|
* Generates items for batch query.
|
|
@@ -40,16 +53,6 @@ export declare class Partition {
|
|
|
40
53
|
* Generates items for batch delete.
|
|
41
54
|
*/
|
|
42
55
|
batchDeleteInput(...sks: string[]): any[];
|
|
43
|
-
/**
|
|
44
|
-
* Create an item in this partition and return the model.
|
|
45
|
-
*/
|
|
46
|
-
create<T = any>(sk: string, data: T): Promise<Model<T>>;
|
|
47
|
-
/**
|
|
48
|
-
* Get data for a specific SK within this partition.
|
|
49
|
-
* If the partition is loaded, it returns from cache.
|
|
50
|
-
* Otherwise, it fetches the data immediately.
|
|
51
|
-
*/
|
|
52
|
-
get<T = any>(sk: string): Promise<T | null>;
|
|
53
56
|
/**
|
|
54
57
|
* Delete all data in this partition.
|
|
55
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 = {};
|
|
@@ -78,23 +77,69 @@ class Partition {
|
|
|
78
77
|
});
|
|
79
78
|
}
|
|
80
79
|
/**
|
|
81
|
-
*
|
|
80
|
+
* Create an item in this partition.
|
|
82
81
|
*/
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
+
});
|
|
91
|
+
}
|
|
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
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Delete an item by its SK within this partition.
|
|
104
|
+
*/
|
|
105
|
+
delete(sk) {
|
|
106
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
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];
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get data for a specific SK within this partition.
|
|
119
|
+
* If the partition is loaded, it returns from cache.
|
|
120
|
+
* Otherwise, it fetches the data immediately.
|
|
121
|
+
*/
|
|
122
|
+
get(sk) {
|
|
123
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
124
|
+
if (this.cache[sk] !== undefined) {
|
|
125
|
+
return this.cache[sk] || null;
|
|
126
|
+
}
|
|
127
|
+
if (this.isLoaded) {
|
|
128
|
+
return null;
|
|
95
129
|
}
|
|
96
|
-
|
|
97
|
-
|
|
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;
|
|
138
|
+
if (data) {
|
|
139
|
+
this.cache[sk] = data;
|
|
140
|
+
}
|
|
141
|
+
return data;
|
|
142
|
+
});
|
|
98
143
|
}
|
|
99
144
|
getPkValue() {
|
|
100
145
|
return this.pkValue;
|
|
@@ -146,37 +191,6 @@ class Partition {
|
|
|
146
191
|
}
|
|
147
192
|
}));
|
|
148
193
|
}
|
|
149
|
-
/**
|
|
150
|
-
* Create an item in this partition and return the model.
|
|
151
|
-
*/
|
|
152
|
-
create(sk, data) {
|
|
153
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
154
|
-
const m = this.model(sk);
|
|
155
|
-
yield m.save(data);
|
|
156
|
-
return m;
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Get data for a specific SK within this partition.
|
|
161
|
-
* If the partition is loaded, it returns from cache.
|
|
162
|
-
* Otherwise, it fetches the data immediately.
|
|
163
|
-
*/
|
|
164
|
-
get(sk) {
|
|
165
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
166
|
-
if (this.cache[sk] !== undefined) {
|
|
167
|
-
return this.cache[sk] || null;
|
|
168
|
-
}
|
|
169
|
-
if (this.isLoaded) {
|
|
170
|
-
return null;
|
|
171
|
-
}
|
|
172
|
-
const model = this.model(sk);
|
|
173
|
-
const data = yield model.find();
|
|
174
|
-
if (data) {
|
|
175
|
-
this.cache[sk] = data;
|
|
176
|
-
}
|
|
177
|
-
return data;
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
194
|
/**
|
|
181
195
|
* Delete all data in this partition.
|
|
182
196
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dynoquery",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/devspikejs/dynoquery.git"
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"scripts": {
|
|
16
16
|
"build": "tsc",
|
|
17
17
|
"test": "jest src",
|
|
18
|
+
"version": "npm run build && git add dist",
|
|
18
19
|
"prepublishOnly": "npm run build"
|
|
19
20
|
},
|
|
20
21
|
"keywords": [
|
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;
|