@jaypie/dynamodb 0.1.0 → 0.1.2
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/dist/cjs/client.d.ts +1 -1
- package/dist/cjs/entities.d.ts +16 -47
- package/dist/cjs/index.cjs +228 -140
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +1 -2
- package/dist/cjs/mcp/admin/createTable.d.ts +8 -0
- package/dist/cjs/mcp/admin/dockerCompose.d.ts +12 -0
- package/dist/cjs/mcp/admin/index.d.ts +3 -0
- package/dist/cjs/mcp/admin/status.d.ts +9 -0
- package/dist/cjs/mcp/autoInit.d.ts +5 -0
- package/dist/cjs/mcp/index.cjs +1095 -0
- package/dist/cjs/mcp/index.cjs.map +1 -0
- package/dist/cjs/mcp/index.d.ts +17 -0
- package/dist/cjs/queries.d.ts +36 -25
- package/dist/cjs/types.d.ts +6 -6
- package/dist/esm/client.d.ts +1 -1
- package/dist/esm/entities.d.ts +16 -47
- package/dist/esm/index.d.ts +1 -2
- package/dist/esm/index.js +229 -141
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/mcp/admin/createTable.d.ts +8 -0
- package/dist/esm/mcp/admin/dockerCompose.d.ts +12 -0
- package/dist/esm/mcp/admin/index.d.ts +3 -0
- package/dist/esm/mcp/admin/status.d.ts +9 -0
- package/dist/esm/mcp/autoInit.d.ts +5 -0
- package/dist/esm/mcp/index.d.ts +17 -0
- package/dist/esm/mcp/index.js +1089 -0
- package/dist/esm/mcp/index.js.map +1 -0
- package/dist/esm/queries.d.ts +36 -25
- package/dist/esm/types.d.ts +6 -6
- package/package.json +16 -3
package/dist/cjs/client.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type { DynamoClientConfig } from "./types.js";
|
|
|
6
6
|
*
|
|
7
7
|
* @param config - Client configuration
|
|
8
8
|
*/
|
|
9
|
-
export declare function initClient(config
|
|
9
|
+
export declare function initClient(config?: DynamoClientConfig): void;
|
|
10
10
|
/**
|
|
11
11
|
* Get the initialized DynamoDB Document Client
|
|
12
12
|
* @throws ConfigurationError if client has not been initialized
|
package/dist/cjs/entities.d.ts
CHANGED
|
@@ -1,71 +1,40 @@
|
|
|
1
1
|
import type { FabricEntity } from "./types.js";
|
|
2
|
-
/**
|
|
3
|
-
* Parameters for getEntity
|
|
4
|
-
*/
|
|
5
|
-
export interface GetEntityParams {
|
|
6
|
-
/** Entity ID (sort key) */
|
|
7
|
-
id: string;
|
|
8
|
-
/** Entity model (partition key) */
|
|
9
|
-
model: string;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Parameters for putEntity
|
|
13
|
-
*/
|
|
14
|
-
export interface PutEntityParams<T extends FabricEntity> {
|
|
15
|
-
/** The entity to save */
|
|
16
|
-
entity: T;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Parameters for updateEntity
|
|
20
|
-
*/
|
|
21
|
-
export interface UpdateEntityParams<T extends FabricEntity> {
|
|
22
|
-
/** The entity with updated fields */
|
|
23
|
-
entity: T;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Parameters for deleteEntity (soft delete)
|
|
27
|
-
*/
|
|
28
|
-
export interface DeleteEntityParams {
|
|
29
|
-
/** Entity ID (sort key) */
|
|
30
|
-
id: string;
|
|
31
|
-
/** Entity model (partition key) */
|
|
32
|
-
model: string;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Parameters for archiveEntity
|
|
36
|
-
*/
|
|
37
|
-
export interface ArchiveEntityParams {
|
|
38
|
-
/** Entity ID (sort key) */
|
|
39
|
-
id: string;
|
|
40
|
-
/** Entity model (partition key) */
|
|
41
|
-
model: string;
|
|
42
|
-
}
|
|
43
2
|
/**
|
|
44
3
|
* Get a single entity by primary key
|
|
45
4
|
*/
|
|
46
|
-
export declare
|
|
5
|
+
export declare const getEntity: import("@jaypie/vocabulary").ServiceHandlerFunction<Record<string, unknown>, FabricEntity | null>;
|
|
47
6
|
/**
|
|
48
7
|
* Put (create or replace) an entity
|
|
49
8
|
* Auto-populates GSI index keys via indexEntity
|
|
9
|
+
*
|
|
10
|
+
* Note: This is a regular async function (not serviceHandler) because it accepts
|
|
11
|
+
* complex FabricEntity objects that can't be coerced by vocabulary's type system.
|
|
50
12
|
*/
|
|
51
|
-
export declare function putEntity
|
|
13
|
+
export declare function putEntity({ entity, }: {
|
|
14
|
+
entity: FabricEntity;
|
|
15
|
+
}): Promise<FabricEntity>;
|
|
52
16
|
/**
|
|
53
17
|
* Update an existing entity
|
|
54
18
|
* Auto-populates GSI index keys and sets updatedAt
|
|
19
|
+
*
|
|
20
|
+
* Note: This is a regular async function (not serviceHandler) because it accepts
|
|
21
|
+
* complex FabricEntity objects that can't be coerced by vocabulary's type system.
|
|
55
22
|
*/
|
|
56
|
-
export declare function updateEntity
|
|
23
|
+
export declare function updateEntity({ entity, }: {
|
|
24
|
+
entity: FabricEntity;
|
|
25
|
+
}): Promise<FabricEntity>;
|
|
57
26
|
/**
|
|
58
27
|
* Soft delete an entity by setting deletedAt timestamp
|
|
59
28
|
* Re-indexes with appropriate suffix based on archived/deleted state
|
|
60
29
|
*/
|
|
61
|
-
export declare
|
|
30
|
+
export declare const deleteEntity: import("@jaypie/vocabulary").ServiceHandlerFunction<Record<string, unknown>, boolean>;
|
|
62
31
|
/**
|
|
63
32
|
* Archive an entity by setting archivedAt timestamp
|
|
64
33
|
* Re-indexes with appropriate suffix based on archived/deleted state
|
|
65
34
|
*/
|
|
66
|
-
export declare
|
|
35
|
+
export declare const archiveEntity: import("@jaypie/vocabulary").ServiceHandlerFunction<Record<string, unknown>, boolean>;
|
|
67
36
|
/**
|
|
68
37
|
* Hard delete an entity (permanently removes from table)
|
|
69
38
|
* Use with caution - prefer deleteEntity for soft delete
|
|
70
39
|
*/
|
|
71
|
-
export declare
|
|
40
|
+
export declare const destroyEntity: import("@jaypie/vocabulary").ServiceHandlerFunction<Record<string, unknown>, boolean>;
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
var clientDynamodb = require('@aws-sdk/client-dynamodb');
|
|
4
4
|
var libDynamodb = require('@aws-sdk/lib-dynamodb');
|
|
5
5
|
var errors = require('@jaypie/errors');
|
|
6
|
+
var vocabulary = require('@jaypie/vocabulary');
|
|
6
7
|
|
|
8
|
+
// Environment variable names
|
|
9
|
+
const ENV_AWS_REGION = "AWS_REGION";
|
|
10
|
+
const ENV_DYNAMODB_TABLE_NAME = "DYNAMODB_TABLE_NAME";
|
|
11
|
+
// Defaults
|
|
7
12
|
const DEFAULT_REGION = "us-east-1";
|
|
8
13
|
const LOCAL_CREDENTIALS = {
|
|
9
14
|
accessKeyId: "local",
|
|
@@ -26,8 +31,9 @@ function isLocalEndpoint(endpoint) {
|
|
|
26
31
|
*
|
|
27
32
|
* @param config - Client configuration
|
|
28
33
|
*/
|
|
29
|
-
function initClient(config) {
|
|
30
|
-
const { endpoint
|
|
34
|
+
function initClient(config = {}) {
|
|
35
|
+
const { endpoint } = config;
|
|
36
|
+
const region = config.region ?? process.env[ENV_AWS_REGION] ?? DEFAULT_REGION;
|
|
31
37
|
// Auto-detect local mode and use dummy credentials
|
|
32
38
|
const credentials = config.credentials ??
|
|
33
39
|
(isLocalEndpoint(endpoint) ? LOCAL_CREDENTIALS : undefined);
|
|
@@ -41,7 +47,7 @@ function initClient(config) {
|
|
|
41
47
|
removeUndefinedValues: true,
|
|
42
48
|
},
|
|
43
49
|
});
|
|
44
|
-
tableName = config.tableName;
|
|
50
|
+
tableName = config.tableName ?? process.env[ENV_DYNAMODB_TABLE_NAME] ?? null;
|
|
45
51
|
}
|
|
46
52
|
/**
|
|
47
53
|
* Get the initialized DynamoDB Document Client
|
|
@@ -187,25 +193,51 @@ function indexEntity(entity, suffix = "") {
|
|
|
187
193
|
}
|
|
188
194
|
|
|
189
195
|
/**
|
|
190
|
-
*
|
|
196
|
+
* Calculate suffix based on entity's archived/deleted state
|
|
191
197
|
*/
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
198
|
+
function calculateEntitySuffix(entity) {
|
|
199
|
+
const hasArchived = Boolean(entity.archivedAt);
|
|
200
|
+
const hasDeleted = Boolean(entity.deletedAt);
|
|
201
|
+
if (hasArchived && hasDeleted) {
|
|
202
|
+
return ARCHIVED_SUFFIX + DELETED_SUFFIX;
|
|
203
|
+
}
|
|
204
|
+
if (hasArchived) {
|
|
205
|
+
return ARCHIVED_SUFFIX;
|
|
206
|
+
}
|
|
207
|
+
if (hasDeleted) {
|
|
208
|
+
return DELETED_SUFFIX;
|
|
209
|
+
}
|
|
210
|
+
return "";
|
|
202
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Get a single entity by primary key
|
|
214
|
+
*/
|
|
215
|
+
const getEntity = vocabulary.serviceHandler({
|
|
216
|
+
alias: "getEntity",
|
|
217
|
+
description: "Get a single entity by primary key",
|
|
218
|
+
input: {
|
|
219
|
+
id: { type: String, description: "Entity ID (sort key)" },
|
|
220
|
+
model: { type: String, description: "Entity model (partition key)" },
|
|
221
|
+
},
|
|
222
|
+
service: async ({ id, model }) => {
|
|
223
|
+
const docClient = getDocClient();
|
|
224
|
+
const tableName = getTableName();
|
|
225
|
+
const command = new libDynamodb.GetCommand({
|
|
226
|
+
Key: { id, model },
|
|
227
|
+
TableName: tableName,
|
|
228
|
+
});
|
|
229
|
+
const response = await docClient.send(command);
|
|
230
|
+
return response.Item ?? null;
|
|
231
|
+
},
|
|
232
|
+
});
|
|
203
233
|
/**
|
|
204
234
|
* Put (create or replace) an entity
|
|
205
235
|
* Auto-populates GSI index keys via indexEntity
|
|
236
|
+
*
|
|
237
|
+
* Note: This is a regular async function (not serviceHandler) because it accepts
|
|
238
|
+
* complex FabricEntity objects that can't be coerced by vocabulary's type system.
|
|
206
239
|
*/
|
|
207
|
-
async function putEntity(
|
|
208
|
-
const { entity } = params;
|
|
240
|
+
async function putEntity({ entity, }) {
|
|
209
241
|
const docClient = getDocClient();
|
|
210
242
|
const tableName = getTableName();
|
|
211
243
|
// Auto-populate index keys
|
|
@@ -220,9 +252,11 @@ async function putEntity(params) {
|
|
|
220
252
|
/**
|
|
221
253
|
* Update an existing entity
|
|
222
254
|
* Auto-populates GSI index keys and sets updatedAt
|
|
255
|
+
*
|
|
256
|
+
* Note: This is a regular async function (not serviceHandler) because it accepts
|
|
257
|
+
* complex FabricEntity objects that can't be coerced by vocabulary's type system.
|
|
223
258
|
*/
|
|
224
|
-
async function updateEntity(
|
|
225
|
-
const { entity } = params;
|
|
259
|
+
async function updateEntity({ entity, }) {
|
|
226
260
|
const docClient = getDocClient();
|
|
227
261
|
const tableName = getTableName();
|
|
228
262
|
// Update timestamp and re-index
|
|
@@ -237,98 +271,102 @@ async function updateEntity(params) {
|
|
|
237
271
|
await docClient.send(command);
|
|
238
272
|
return updatedEntity;
|
|
239
273
|
}
|
|
240
|
-
/**
|
|
241
|
-
* Calculate suffix based on entity's archived/deleted state
|
|
242
|
-
*/
|
|
243
|
-
function calculateEntitySuffix(entity) {
|
|
244
|
-
const hasArchived = Boolean(entity.archivedAt);
|
|
245
|
-
const hasDeleted = Boolean(entity.deletedAt);
|
|
246
|
-
if (hasArchived && hasDeleted) {
|
|
247
|
-
return ARCHIVED_SUFFIX + DELETED_SUFFIX;
|
|
248
|
-
}
|
|
249
|
-
if (hasArchived) {
|
|
250
|
-
return ARCHIVED_SUFFIX;
|
|
251
|
-
}
|
|
252
|
-
if (hasDeleted) {
|
|
253
|
-
return DELETED_SUFFIX;
|
|
254
|
-
}
|
|
255
|
-
return "";
|
|
256
|
-
}
|
|
257
274
|
/**
|
|
258
275
|
* Soft delete an entity by setting deletedAt timestamp
|
|
259
276
|
* Re-indexes with appropriate suffix based on archived/deleted state
|
|
260
277
|
*/
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
278
|
+
const deleteEntity = vocabulary.serviceHandler({
|
|
279
|
+
alias: "deleteEntity",
|
|
280
|
+
description: "Soft delete an entity (sets deletedAt timestamp)",
|
|
281
|
+
input: {
|
|
282
|
+
id: { type: String, description: "Entity ID (sort key)" },
|
|
283
|
+
model: { type: String, description: "Entity model (partition key)" },
|
|
284
|
+
},
|
|
285
|
+
service: async ({ id, model }) => {
|
|
286
|
+
const docClient = getDocClient();
|
|
287
|
+
const tableName = getTableName();
|
|
288
|
+
// Fetch the current entity
|
|
289
|
+
const existing = await getEntity({ id, model });
|
|
290
|
+
if (!existing) {
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
const now = new Date().toISOString();
|
|
294
|
+
// Build updated entity with deletedAt
|
|
295
|
+
const updatedEntity = {
|
|
296
|
+
...existing,
|
|
297
|
+
deletedAt: now,
|
|
298
|
+
updatedAt: now,
|
|
299
|
+
};
|
|
300
|
+
// Calculate suffix based on combined state (may already be archived)
|
|
301
|
+
const suffix = calculateEntitySuffix(updatedEntity);
|
|
302
|
+
const deletedEntity = indexEntity(updatedEntity, suffix);
|
|
303
|
+
const command = new libDynamodb.PutCommand({
|
|
304
|
+
Item: deletedEntity,
|
|
305
|
+
TableName: tableName,
|
|
306
|
+
});
|
|
307
|
+
await docClient.send(command);
|
|
308
|
+
return true;
|
|
309
|
+
},
|
|
310
|
+
});
|
|
287
311
|
/**
|
|
288
312
|
* Archive an entity by setting archivedAt timestamp
|
|
289
313
|
* Re-indexes with appropriate suffix based on archived/deleted state
|
|
290
314
|
*/
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
315
|
+
const archiveEntity = vocabulary.serviceHandler({
|
|
316
|
+
alias: "archiveEntity",
|
|
317
|
+
description: "Archive an entity (sets archivedAt timestamp)",
|
|
318
|
+
input: {
|
|
319
|
+
id: { type: String, description: "Entity ID (sort key)" },
|
|
320
|
+
model: { type: String, description: "Entity model (partition key)" },
|
|
321
|
+
},
|
|
322
|
+
service: async ({ id, model }) => {
|
|
323
|
+
const docClient = getDocClient();
|
|
324
|
+
const tableName = getTableName();
|
|
325
|
+
// Fetch the current entity
|
|
326
|
+
const existing = await getEntity({ id, model });
|
|
327
|
+
if (!existing) {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
const now = new Date().toISOString();
|
|
331
|
+
// Build updated entity with archivedAt
|
|
332
|
+
const updatedEntity = {
|
|
333
|
+
...existing,
|
|
334
|
+
archivedAt: now,
|
|
335
|
+
updatedAt: now,
|
|
336
|
+
};
|
|
337
|
+
// Calculate suffix based on combined state (may already be deleted)
|
|
338
|
+
const suffix = calculateEntitySuffix(updatedEntity);
|
|
339
|
+
const archivedEntity = indexEntity(updatedEntity, suffix);
|
|
340
|
+
const command = new libDynamodb.PutCommand({
|
|
341
|
+
Item: archivedEntity,
|
|
342
|
+
TableName: tableName,
|
|
343
|
+
});
|
|
344
|
+
await docClient.send(command);
|
|
345
|
+
return true;
|
|
346
|
+
},
|
|
347
|
+
});
|
|
317
348
|
/**
|
|
318
349
|
* Hard delete an entity (permanently removes from table)
|
|
319
350
|
* Use with caution - prefer deleteEntity for soft delete
|
|
320
351
|
*/
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
})
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
352
|
+
const destroyEntity = vocabulary.serviceHandler({
|
|
353
|
+
alias: "destroyEntity",
|
|
354
|
+
description: "Hard delete an entity (permanently removes from table)",
|
|
355
|
+
input: {
|
|
356
|
+
id: { type: String, description: "Entity ID (sort key)" },
|
|
357
|
+
model: { type: String, description: "Entity model (partition key)" },
|
|
358
|
+
},
|
|
359
|
+
service: async ({ id, model }) => {
|
|
360
|
+
const docClient = getDocClient();
|
|
361
|
+
const tableName = getTableName();
|
|
362
|
+
const command = new libDynamodb.DeleteCommand({
|
|
363
|
+
Key: { id, model },
|
|
364
|
+
TableName: tableName,
|
|
365
|
+
});
|
|
366
|
+
await docClient.send(command);
|
|
367
|
+
return true;
|
|
368
|
+
},
|
|
369
|
+
});
|
|
332
370
|
|
|
333
371
|
/**
|
|
334
372
|
* Calculate the suffix based on archived/deleted flags
|
|
@@ -377,76 +415,126 @@ async function executeQuery(indexName, keyValue, options = {}) {
|
|
|
377
415
|
* Query entities by organizational unit (parent hierarchy)
|
|
378
416
|
* Uses indexOu GSI
|
|
379
417
|
*
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
* @throws ConfigurationError if both archived and deleted are true
|
|
418
|
+
* Note: This is a regular async function (not serviceHandler) because it accepts
|
|
419
|
+
* complex startKey objects that can't be coerced by vocabulary's type system.
|
|
383
420
|
*/
|
|
384
|
-
async function queryByOu(
|
|
385
|
-
const { archived, deleted, model, ou, ...options } = params;
|
|
421
|
+
async function queryByOu({ archived = false, ascending = false, deleted = false, limit, model, ou, startKey, }) {
|
|
386
422
|
const suffix = calculateSuffix({ archived, deleted });
|
|
387
423
|
const keyValue = buildIndexOu(ou, model) + suffix;
|
|
388
|
-
return executeQuery(INDEX_OU, keyValue,
|
|
424
|
+
return executeQuery(INDEX_OU, keyValue, {
|
|
425
|
+
ascending,
|
|
426
|
+
limit,
|
|
427
|
+
startKey,
|
|
428
|
+
});
|
|
389
429
|
}
|
|
390
430
|
/**
|
|
391
431
|
* Query a single entity by human-friendly alias
|
|
392
432
|
* Uses indexAlias GSI
|
|
393
|
-
*
|
|
394
|
-
* @param params.archived - Query archived entities instead of active ones
|
|
395
|
-
* @param params.deleted - Query deleted entities instead of active ones
|
|
396
|
-
* @throws ConfigurationError if both archived and deleted are true
|
|
397
|
-
* @returns The matching entity or null if not found
|
|
398
433
|
*/
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
434
|
+
const queryByAlias = vocabulary.serviceHandler({
|
|
435
|
+
alias: "queryByAlias",
|
|
436
|
+
description: "Query a single entity by human-friendly alias",
|
|
437
|
+
input: {
|
|
438
|
+
alias: { type: String, description: "Human-friendly alias" },
|
|
439
|
+
archived: {
|
|
440
|
+
type: Boolean,
|
|
441
|
+
default: false,
|
|
442
|
+
required: false,
|
|
443
|
+
description: "Query archived entities instead of active ones",
|
|
444
|
+
},
|
|
445
|
+
deleted: {
|
|
446
|
+
type: Boolean,
|
|
447
|
+
default: false,
|
|
448
|
+
required: false,
|
|
449
|
+
description: "Query deleted entities instead of active ones",
|
|
450
|
+
},
|
|
451
|
+
model: { type: String, description: "Entity model name" },
|
|
452
|
+
ou: { type: String, description: "Organizational unit (@ for root)" },
|
|
453
|
+
},
|
|
454
|
+
service: async ({ alias, archived, deleted, model, ou, }) => {
|
|
455
|
+
const aliasStr = alias;
|
|
456
|
+
const archivedBool = archived;
|
|
457
|
+
const deletedBool = deleted;
|
|
458
|
+
const modelStr = model;
|
|
459
|
+
const ouStr = ou;
|
|
460
|
+
const suffix = calculateSuffix({ archived: archivedBool, deleted: deletedBool });
|
|
461
|
+
const keyValue = buildIndexAlias(ouStr, modelStr, aliasStr) + suffix;
|
|
462
|
+
const result = await executeQuery(INDEX_ALIAS, keyValue, {
|
|
463
|
+
limit: 1,
|
|
464
|
+
});
|
|
465
|
+
return result.items[0] ?? null;
|
|
466
|
+
},
|
|
467
|
+
});
|
|
406
468
|
/**
|
|
407
469
|
* Query entities by category classification
|
|
408
470
|
* Uses indexClass GSI
|
|
409
471
|
*
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
* @throws ConfigurationError if both archived and deleted are true
|
|
472
|
+
* Note: This is a regular async function (not serviceHandler) because it accepts
|
|
473
|
+
* complex startKey objects that can't be coerced by vocabulary's type system.
|
|
413
474
|
*/
|
|
414
|
-
async function queryByClass(
|
|
415
|
-
const { archived, deleted, model, ou, recordClass, ...options } = params;
|
|
475
|
+
async function queryByClass({ archived = false, ascending = false, deleted = false, limit, model, ou, recordClass, startKey, }) {
|
|
416
476
|
const suffix = calculateSuffix({ archived, deleted });
|
|
417
477
|
const keyValue = buildIndexClass(ou, model, recordClass) + suffix;
|
|
418
|
-
return executeQuery(INDEX_CLASS, keyValue,
|
|
478
|
+
return executeQuery(INDEX_CLASS, keyValue, {
|
|
479
|
+
ascending,
|
|
480
|
+
limit,
|
|
481
|
+
startKey,
|
|
482
|
+
});
|
|
419
483
|
}
|
|
420
484
|
/**
|
|
421
485
|
* Query entities by type classification
|
|
422
486
|
* Uses indexType GSI
|
|
423
487
|
*
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
* @throws ConfigurationError if both archived and deleted are true
|
|
488
|
+
* Note: This is a regular async function (not serviceHandler) because it accepts
|
|
489
|
+
* complex startKey objects that can't be coerced by vocabulary's type system.
|
|
427
490
|
*/
|
|
428
|
-
async function queryByType(
|
|
429
|
-
const { archived, deleted, model, ou, type, ...options } = params;
|
|
491
|
+
async function queryByType({ archived = false, ascending = false, deleted = false, limit, model, ou, startKey, type, }) {
|
|
430
492
|
const suffix = calculateSuffix({ archived, deleted });
|
|
431
493
|
const keyValue = buildIndexType(ou, model, type) + suffix;
|
|
432
|
-
return executeQuery(INDEX_TYPE, keyValue,
|
|
494
|
+
return executeQuery(INDEX_TYPE, keyValue, {
|
|
495
|
+
ascending,
|
|
496
|
+
limit,
|
|
497
|
+
startKey,
|
|
498
|
+
});
|
|
433
499
|
}
|
|
434
500
|
/**
|
|
435
501
|
* Query a single entity by external ID
|
|
436
502
|
* Uses indexXid GSI
|
|
437
|
-
*
|
|
438
|
-
* @param params.archived - Query archived entities instead of active ones
|
|
439
|
-
* @param params.deleted - Query deleted entities instead of active ones
|
|
440
|
-
* @throws ConfigurationError if both archived and deleted are true
|
|
441
|
-
* @returns The matching entity or null if not found
|
|
442
503
|
*/
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
504
|
+
const queryByXid = vocabulary.serviceHandler({
|
|
505
|
+
alias: "queryByXid",
|
|
506
|
+
description: "Query a single entity by external ID",
|
|
507
|
+
input: {
|
|
508
|
+
archived: {
|
|
509
|
+
type: Boolean,
|
|
510
|
+
default: false,
|
|
511
|
+
required: false,
|
|
512
|
+
description: "Query archived entities instead of active ones",
|
|
513
|
+
},
|
|
514
|
+
deleted: {
|
|
515
|
+
type: Boolean,
|
|
516
|
+
default: false,
|
|
517
|
+
required: false,
|
|
518
|
+
description: "Query deleted entities instead of active ones",
|
|
519
|
+
},
|
|
520
|
+
model: { type: String, description: "Entity model name" },
|
|
521
|
+
ou: { type: String, description: "Organizational unit (@ for root)" },
|
|
522
|
+
xid: { type: String, description: "External ID" },
|
|
523
|
+
},
|
|
524
|
+
service: async ({ archived, deleted, model, ou, xid, }) => {
|
|
525
|
+
const archivedBool = archived;
|
|
526
|
+
const deletedBool = deleted;
|
|
527
|
+
const modelStr = model;
|
|
528
|
+
const ouStr = ou;
|
|
529
|
+
const xidStr = xid;
|
|
530
|
+
const suffix = calculateSuffix({ archived: archivedBool, deleted: deletedBool });
|
|
531
|
+
const keyValue = buildIndexXid(ouStr, modelStr, xidStr) + suffix;
|
|
532
|
+
const result = await executeQuery(INDEX_XID, keyValue, {
|
|
533
|
+
limit: 1,
|
|
534
|
+
});
|
|
535
|
+
return result.items[0] ?? null;
|
|
536
|
+
},
|
|
537
|
+
});
|
|
450
538
|
|
|
451
539
|
exports.APEX = APEX;
|
|
452
540
|
exports.ARCHIVED_SUFFIX = ARCHIVED_SUFFIX;
|