ag-common 0.0.765 → 0.0.767

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.
@@ -0,0 +1,5 @@
1
+ import type { Container } from '@azure/cosmos';
2
+ export declare function deleteItemCosmos(container: Container, pk: string): Promise<void>;
3
+ export declare function deleteItemsByField(container: Container, field: string, value: string | number | boolean): Promise<{
4
+ error?: string;
5
+ }>;
@@ -0,0 +1,111 @@
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.deleteItemCosmos = deleteItemCosmos;
13
+ exports.deleteItemsByField = deleteItemsByField;
14
+ const log_1 = require("../../../common/helpers/log");
15
+ const withRetry_1 = require("../withRetry");
16
+ const utils_1 = require("./utils");
17
+ function deleteItemCosmos(container, pk) {
18
+ return __awaiter(this, void 0, void 0, function* () {
19
+ try {
20
+ // First query to find items with matching PK
21
+ const querySpec = {
22
+ query: 'SELECT * FROM c WHERE c.PK = @pk',
23
+ parameters: [{ name: '@pk', value: pk }],
24
+ };
25
+ const { resources: items } = yield container.items
26
+ .query(querySpec)
27
+ .fetchAll();
28
+ // Delete each found item and collect their IDs
29
+ for (const item of items) {
30
+ (0, log_1.warn)('deleting items:', item.id, pk);
31
+ yield container.item(item.id, pk).delete();
32
+ }
33
+ }
34
+ catch (e) {
35
+ const em = e.message;
36
+ (0, log_1.error)('Error deleting item:', em);
37
+ throw e;
38
+ }
39
+ });
40
+ }
41
+ function deleteItemsByField(container, field, value) {
42
+ return __awaiter(this, void 0, void 0, function* () {
43
+ try {
44
+ const query = `
45
+ SELECT c.id, c.PK
46
+ FROM c
47
+ WHERE c.${field} = @value
48
+ `;
49
+ const { resources } = yield container.items
50
+ .query({
51
+ query,
52
+ parameters: [{ name: '@value', value }],
53
+ })
54
+ .fetchAll();
55
+ if (resources.length === 0) {
56
+ return {};
57
+ }
58
+ (0, log_1.info)(`Deleting ${resources.length} items where ${field} = ${value} from Cosmos`);
59
+ //throw if item.id or PK doesn't exist on an item
60
+ resources.forEach((item) => {
61
+ if (!item.id || !item.PK) {
62
+ throw new Error('Item missing required fields: ' + JSON.stringify(item));
63
+ }
64
+ });
65
+ const operations = resources.map((item) => ({
66
+ id: item.id,
67
+ partitionKey: item.PK,
68
+ operationType: 'Delete',
69
+ }));
70
+ for (let i = 0; i < operations.length; i += utils_1.BULK_CHUNK_SIZE) {
71
+ const chunk = operations.slice(i, i + utils_1.BULK_CHUNK_SIZE);
72
+ // Execute bulk operation with retry
73
+ yield (0, withRetry_1.withRetry)(() => __awaiter(this, void 0, void 0, function* () {
74
+ (0, log_1.info)(`Deleting chunk ${i / utils_1.BULK_CHUNK_SIZE + 1} of ${Math.ceil(operations.length / utils_1.BULK_CHUNK_SIZE)}`);
75
+ const bulkResponse = yield container.items.bulk(chunk);
76
+ //if an item contains a statuscode 429, then throw an error
77
+ bulkResponse.forEach((response) => {
78
+ if (response.statusCode === 429) {
79
+ throw new Error('429');
80
+ }
81
+ });
82
+ // Process results
83
+ let successCount = 0;
84
+ let failureCount = 0;
85
+ bulkResponse.forEach((response, index) => {
86
+ if (response.statusCode === 204) {
87
+ successCount++;
88
+ }
89
+ else if (response.statusCode === 404) {
90
+ failureCount++;
91
+ }
92
+ else {
93
+ const item = chunk[index];
94
+ (0, log_1.error)(`Failed to delete item - ID: ${item.id}, PK: ${item.partitionKey}, Status: ${response.statusCode}`, response.resourceBody);
95
+ failureCount++;
96
+ }
97
+ });
98
+ (0, log_1.info)(`Chunk ${i / utils_1.BULK_CHUNK_SIZE + 1}/${Math.ceil(operations.length / utils_1.BULK_CHUNK_SIZE)} results - Success: ${successCount}, Failed: ${failureCount}`);
99
+ return bulkResponse;
100
+ }), `bulk_delete_chunk_${i / utils_1.BULK_CHUNK_SIZE + 1}`);
101
+ }
102
+ (0, log_1.info)('All items deleted successfully');
103
+ return {};
104
+ }
105
+ catch (e) {
106
+ const em = e.message;
107
+ (0, log_1.error)('Error deleting items:', em);
108
+ throw e;
109
+ }
110
+ });
111
+ }
@@ -0,0 +1,28 @@
1
+ import type { Container } from '@azure/cosmos';
2
+ export declare function getItemCosmos<T>(container: Container, partitionValue: string): Promise<T | null>;
3
+ export declare function getItemsByCosmos<T>(container: Container, partitionValues: string[]): Promise<T[]>;
4
+ export declare function queryItemsByText<T>(container: Container, searchFields: {
5
+ fieldName: string;
6
+ fieldValue: string;
7
+ type: 'contains' | 'equals';
8
+ }[], operator?: 'AND' | 'OR'): Promise<T[] | {
9
+ error: string;
10
+ }>;
11
+ export declare function scanCosmos<T>(container: Container): Promise<T[] | {
12
+ error: string;
13
+ }>;
14
+ export declare function queryItemsByNumber<T>(container: Container, options: {
15
+ type: string;
16
+ field: string;
17
+ minValue?: number;
18
+ limit?: number;
19
+ descending?: boolean;
20
+ }): Promise<T[] | {
21
+ error: string;
22
+ }>;
23
+ export declare function queryItemsByType<T>(container: Container, type: string): Promise<T[] | {
24
+ error: string;
25
+ }>;
26
+ export declare function queryItemsByRelevancy<T>(container: Container, type: string, limit?: number): Promise<T[] | {
27
+ error: string;
28
+ }>;
@@ -0,0 +1,233 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.getItemCosmos = getItemCosmos;
16
+ exports.getItemsByCosmos = getItemsByCosmos;
17
+ exports.queryItemsByText = queryItemsByText;
18
+ exports.scanCosmos = scanCosmos;
19
+ exports.queryItemsByNumber = queryItemsByNumber;
20
+ exports.queryItemsByType = queryItemsByType;
21
+ exports.queryItemsByRelevancy = queryItemsByRelevancy;
22
+ const node_cache_1 = __importDefault(require("node-cache"));
23
+ const log_1 = require("../../../common/helpers/log");
24
+ // Create a NodeCache instance with 5 second TTL
25
+ const cache = new node_cache_1.default({ stdTTL: 5 });
26
+ function getItemCosmos(container, partitionValue) {
27
+ return __awaiter(this, void 0, void 0, function* () {
28
+ try {
29
+ const querySpec = {
30
+ query: 'SELECT TOP 1 * FROM c WHERE c.PK = @val',
31
+ parameters: [
32
+ {
33
+ name: '@val',
34
+ value: partitionValue,
35
+ },
36
+ ],
37
+ };
38
+ const { resources, requestCharge } = yield container.items
39
+ .query(querySpec)
40
+ .fetchAll();
41
+ (0, log_1.info)(`getItemCosmos:${partitionValue}. chg=${requestCharge}`);
42
+ if (resources.length > 0) {
43
+ return resources[0];
44
+ }
45
+ else {
46
+ return null;
47
+ }
48
+ }
49
+ catch (e) {
50
+ if (e.message.includes('404')) {
51
+ return null;
52
+ }
53
+ const em = e.message;
54
+ (0, log_1.error)('Error deleting item:', em);
55
+ throw e;
56
+ }
57
+ });
58
+ }
59
+ function getItemsByCosmos(container, partitionValues) {
60
+ return __awaiter(this, void 0, void 0, function* () {
61
+ try {
62
+ if (!partitionValues.length) {
63
+ return [];
64
+ }
65
+ const querySpec = {
66
+ query: 'SELECT * FROM c WHERE ARRAY_CONTAINS(@values, c.PK)',
67
+ parameters: [
68
+ {
69
+ name: '@values',
70
+ value: partitionValues,
71
+ },
72
+ ],
73
+ };
74
+ const { resources, requestCharge } = yield container.items
75
+ .query(querySpec)
76
+ .fetchAll();
77
+ (0, log_1.info)(`getItemsByCosmos: fetched ${resources.length} items. chg=${requestCharge}`);
78
+ return resources;
79
+ }
80
+ catch (e) {
81
+ const em = e.message;
82
+ (0, log_1.error)('Error getting multiple items:', em);
83
+ throw e;
84
+ }
85
+ });
86
+ }
87
+ function escapeSqlString(str) {
88
+ return str.replace(/'/g, "''");
89
+ }
90
+ function queryItemsCosmos(container, query, parameters) {
91
+ return __awaiter(this, void 0, void 0, function* () {
92
+ try {
93
+ const querySpec = {
94
+ query,
95
+ parameters: parameters
96
+ ? Object.entries(parameters).map(([name, value]) => ({
97
+ name: `@${name}`,
98
+ value,
99
+ }))
100
+ : undefined,
101
+ };
102
+ const { resources, requestCharge } = yield container.items
103
+ .query(querySpec)
104
+ .fetchAll();
105
+ return { resources, requestCharge };
106
+ }
107
+ catch (e) {
108
+ const em = e.message;
109
+ (0, log_1.error)('Error queryItemsCosmos item:', em);
110
+ return { error: em };
111
+ }
112
+ });
113
+ }
114
+ function queryItemsByText(container_1, searchFields_1) {
115
+ return __awaiter(this, arguments, void 0, function* (container, searchFields, operator = 'AND') {
116
+ try {
117
+ const conditions = searchFields.map((field, index) => field.type === 'contains' //true to ignore case
118
+ ? `CONTAINS(c.${field.fieldName}, @value${index}, true)`
119
+ : `c.${field.fieldName} = @value${index}`);
120
+ const query = `SELECT * FROM c WHERE ${conditions.join(` ${operator} `)}`;
121
+ const parameters = searchFields.reduce((acc, field, index) => {
122
+ acc[`value${index}`] = escapeSqlString(field.fieldValue);
123
+ return acc;
124
+ }, {});
125
+ const x = yield queryItemsCosmos(container, query, parameters);
126
+ (0, log_1.debug)(`queryItemsByText: ${JSON.stringify(searchFields)}, operator=${operator}. chg=${x.requestCharge}`);
127
+ if ('error' in x) {
128
+ throw x.error;
129
+ }
130
+ return x.resources;
131
+ }
132
+ catch (e) {
133
+ const em = e.message;
134
+ (0, log_1.error)('Error queryItemsByText item:', em);
135
+ return { error: em };
136
+ }
137
+ });
138
+ }
139
+ function scanCosmos(container) {
140
+ return __awaiter(this, void 0, void 0, function* () {
141
+ try {
142
+ const query = `SELECT * FROM c`;
143
+ const x = yield queryItemsCosmos(container, query, {});
144
+ (0, log_1.info)(`scan. chg=${x.requestCharge}`);
145
+ if ('error' in x) {
146
+ throw x.error;
147
+ }
148
+ return x.resources;
149
+ }
150
+ catch (e) {
151
+ const em = e.message;
152
+ (0, log_1.error)('Error queryItemsByText item:', em);
153
+ return { error: em };
154
+ }
155
+ });
156
+ }
157
+ function queryItemsByNumber(container, options) {
158
+ return __awaiter(this, void 0, void 0, function* () {
159
+ try {
160
+ const { type, field, minValue = 0, limit, descending = true } = options;
161
+ const query = `
162
+ SELECT * FROM c
163
+ WHERE IS_NUMBER(c.${field})
164
+ AND c.${field} > @minValue
165
+ AND c.type = @type
166
+ ORDER BY c.${field} ${descending ? 'DESC' : 'ASC'}
167
+ ${limit ? 'OFFSET 0 LIMIT @limit' : ''}
168
+ `;
169
+ const parameters = {
170
+ type,
171
+ minValue,
172
+ };
173
+ if (limit) {
174
+ parameters.limit = limit;
175
+ }
176
+ const x = yield queryItemsCosmos(container, query, parameters);
177
+ (0, log_1.debug)(`queryItemsByNumber: type=${type}, field=${field}, minValue=${minValue}, limit=${limit}. chg=${x.requestCharge}`);
178
+ if ('error' in x) {
179
+ throw x.error;
180
+ }
181
+ return x.resources;
182
+ }
183
+ catch (e) {
184
+ const em = e.message;
185
+ (0, log_1.error)('Error queryItemsByNumber:', em);
186
+ return { error: em };
187
+ }
188
+ });
189
+ }
190
+ function queryItemsByType(container, type) {
191
+ return __awaiter(this, void 0, void 0, function* () {
192
+ try {
193
+ // Check if data is in cache
194
+ const cacheKey = `queryItemsByType:${type}`;
195
+ const cachedData = cache.get(cacheKey);
196
+ if (cachedData) {
197
+ (0, log_1.info)(`queryItemsByType: type=${type}. [CACHE HIT]`);
198
+ return cachedData;
199
+ }
200
+ const query = `
201
+ SELECT * FROM c
202
+ WHERE c.type = @type
203
+ `;
204
+ const parameters = {
205
+ type,
206
+ };
207
+ const x = yield queryItemsCosmos(container, query, parameters);
208
+ (0, log_1.info)(`queryItemsByType: type=${type}. chg=${x.requestCharge}`);
209
+ if ('error' in x) {
210
+ throw x.error;
211
+ }
212
+ const result = x.resources;
213
+ // Store result in cache
214
+ cache.set(cacheKey, result);
215
+ return result;
216
+ }
217
+ catch (e) {
218
+ const em = e.message;
219
+ (0, log_1.error)('Error queryItemsByType:', em);
220
+ return { error: em };
221
+ }
222
+ });
223
+ }
224
+ function queryItemsByRelevancy(container, type, limit) {
225
+ return __awaiter(this, void 0, void 0, function* () {
226
+ return queryItemsByNumber(container, {
227
+ type,
228
+ field: 'relevancy',
229
+ limit,
230
+ descending: true,
231
+ });
232
+ });
233
+ }
@@ -0,0 +1,44 @@
1
+ import { type CosmosSettings } from './utils';
2
+ export declare class Cosmos {
3
+ private container;
4
+ constructor(settings: CosmosSettings);
5
+ getItem<T>(partitionValue: string): Promise<T | null>;
6
+ getItemsBy<T>(partitionValues: string[]): Promise<T[]>;
7
+ queryItemsByText<T>(searchFields: {
8
+ fieldName: string;
9
+ fieldValue: string;
10
+ type: 'contains' | 'equals';
11
+ }[], operator?: 'AND' | 'OR'): Promise<T[] | {
12
+ error: string;
13
+ }>;
14
+ scan<T>(): Promise<T[] | {
15
+ error: string;
16
+ }>;
17
+ queryItemsByNumber<T>(options: {
18
+ type: string;
19
+ field: string;
20
+ minValue?: number;
21
+ limit?: number;
22
+ descending?: boolean;
23
+ }): Promise<T[] | {
24
+ error: string;
25
+ }>;
26
+ queryItemsByType<T>(type: string): Promise<T[] | {
27
+ error: string;
28
+ }>;
29
+ queryItemsByRelevancy<T>(type: string, limit?: number): Promise<T[] | {
30
+ error: string;
31
+ }>;
32
+ putItem<T extends {
33
+ PK: string;
34
+ }>(item: T): Promise<T>;
35
+ putItems<T extends {
36
+ PK: string;
37
+ }>(items: T[]): Promise<{
38
+ error?: string;
39
+ }>;
40
+ deleteItem(pk: string): Promise<void>;
41
+ deleteItemsByField(field: string, value: string | number | boolean): Promise<{
42
+ error?: string;
43
+ }>;
44
+ }
@@ -0,0 +1,80 @@
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.Cosmos = void 0;
13
+ const delete_1 = require("./delete");
14
+ const get_1 = require("./get");
15
+ const utils_1 = require("./utils");
16
+ const write_1 = require("./write");
17
+ class Cosmos {
18
+ constructor(settings) {
19
+ this.container = (0, utils_1.createContainer)(settings);
20
+ }
21
+ // Get operations
22
+ getItem(partitionValue) {
23
+ return __awaiter(this, void 0, void 0, function* () {
24
+ return (0, get_1.getItemCosmos)(this.container, partitionValue);
25
+ });
26
+ }
27
+ getItemsBy(partitionValues) {
28
+ return __awaiter(this, void 0, void 0, function* () {
29
+ return (0, get_1.getItemsByCosmos)(this.container, partitionValues);
30
+ });
31
+ }
32
+ queryItemsByText(searchFields_1) {
33
+ return __awaiter(this, arguments, void 0, function* (searchFields, operator = 'AND') {
34
+ return (0, get_1.queryItemsByText)(this.container, searchFields, operator);
35
+ });
36
+ }
37
+ scan() {
38
+ return __awaiter(this, void 0, void 0, function* () {
39
+ return (0, get_1.scanCosmos)(this.container);
40
+ });
41
+ }
42
+ queryItemsByNumber(options) {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ return (0, get_1.queryItemsByNumber)(this.container, options);
45
+ });
46
+ }
47
+ queryItemsByType(type) {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ return (0, get_1.queryItemsByType)(this.container, type);
50
+ });
51
+ }
52
+ queryItemsByRelevancy(type, limit) {
53
+ return __awaiter(this, void 0, void 0, function* () {
54
+ return (0, get_1.queryItemsByRelevancy)(this.container, type, limit);
55
+ });
56
+ }
57
+ // Write operations
58
+ putItem(item) {
59
+ return __awaiter(this, void 0, void 0, function* () {
60
+ return (0, write_1.putItemCosmos)(this.container, item);
61
+ });
62
+ }
63
+ putItems(items) {
64
+ return __awaiter(this, void 0, void 0, function* () {
65
+ return (0, write_1.putItemsCosmos)(this.container, items);
66
+ });
67
+ }
68
+ // Delete operations
69
+ deleteItem(pk) {
70
+ return __awaiter(this, void 0, void 0, function* () {
71
+ return (0, delete_1.deleteItemCosmos)(this.container, pk);
72
+ });
73
+ }
74
+ deleteItemsByField(field, value) {
75
+ return __awaiter(this, void 0, void 0, function* () {
76
+ return (0, delete_1.deleteItemsByField)(this.container, field, value);
77
+ });
78
+ }
79
+ }
80
+ exports.Cosmos = Cosmos;
@@ -0,0 +1,9 @@
1
+ import type { Container } from '@azure/cosmos';
2
+ export declare const BULK_CHUNK_SIZE = 50;
3
+ export interface CosmosSettings {
4
+ endpoint: string;
5
+ key: string;
6
+ database_name: string;
7
+ container_name: string;
8
+ }
9
+ export declare function createContainer(settings: CosmosSettings): Container;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BULK_CHUNK_SIZE = void 0;
4
+ exports.createContainer = createContainer;
5
+ const cosmos_1 = require("@azure/cosmos");
6
+ exports.BULK_CHUNK_SIZE = 50;
7
+ function createContainer(settings) {
8
+ if (!settings.endpoint ||
9
+ !settings.key ||
10
+ !settings.database_name ||
11
+ !settings.container_name) {
12
+ throw new Error('no cosmos settings');
13
+ }
14
+ const client = new cosmos_1.CosmosClient(settings);
15
+ const database = client.database(settings.database_name);
16
+ const container = database.container(settings.container_name);
17
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
18
+ if (!container) {
19
+ throw new Error('error, cosmos container undefined!!');
20
+ }
21
+ return container;
22
+ }
@@ -0,0 +1,9 @@
1
+ import type { Container } from '@azure/cosmos';
2
+ export declare function putItemCosmos<T extends {
3
+ PK: string;
4
+ }>(container: Container, item: T): Promise<T>;
5
+ export declare function putItemsCosmos<T extends {
6
+ PK: string;
7
+ }>(container: Container, items: T[]): Promise<{
8
+ error?: string;
9
+ }>;
@@ -0,0 +1,107 @@
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.putItemCosmos = putItemCosmos;
13
+ exports.putItemsCosmos = putItemsCosmos;
14
+ const log_1 = require("../../../common/helpers/log");
15
+ const withRetry_1 = require("../withRetry");
16
+ const utils_1 = require("./utils");
17
+ function putItemCosmos(container, item) {
18
+ return __awaiter(this, void 0, void 0, function* () {
19
+ try {
20
+ // First, try to find existing item with the same PK
21
+ const querySpec = {
22
+ query: 'SELECT * FROM c WHERE c.PK = @pk',
23
+ parameters: [{ name: '@pk', value: item.PK }],
24
+ };
25
+ const { resources: existingItems } = yield container.items
26
+ .query(querySpec)
27
+ .fetchAll();
28
+ if (existingItems.length > 0) {
29
+ // If item exists, update it with the existing ID
30
+ const existingItem = existingItems[0];
31
+ const updatedItem = Object.assign(Object.assign({}, item), { id: existingItem.id });
32
+ const { resource: result } = yield container.items.upsert(updatedItem);
33
+ return result;
34
+ }
35
+ else {
36
+ // If no existing item, create new one (let Cosmos generate the id)
37
+ const newItem = Object.assign(Object.assign({}, item), { id: undefined });
38
+ const { resource: result } = yield container.items.create(newItem);
39
+ return result;
40
+ }
41
+ }
42
+ catch (e) {
43
+ const em = e.message;
44
+ (0, log_1.error)('Error upserting item:', em);
45
+ throw e;
46
+ }
47
+ });
48
+ }
49
+ function putItemsCosmos(container, items) {
50
+ return __awaiter(this, void 0, void 0, function* () {
51
+ try {
52
+ if (items.length === 0) {
53
+ return {};
54
+ }
55
+ (0, log_1.info)(`Bulk writing ${items.length} items to Cosmos`);
56
+ for (let i = 0; i < items.length; i += utils_1.BULK_CHUNK_SIZE) {
57
+ const chunk = items.slice(i, i + utils_1.BULK_CHUNK_SIZE);
58
+ // Execute bulk operation with retry
59
+ yield (0, withRetry_1.withRetry)(() => __awaiter(this, void 0, void 0, function* () {
60
+ (0, log_1.info)(`Writing chunk ${i / utils_1.BULK_CHUNK_SIZE + 1} of ${Math.ceil(items.length / utils_1.BULK_CHUNK_SIZE)}`);
61
+ const operations = yield Promise.all(chunk.map((item) => __awaiter(this, void 0, void 0, function* () {
62
+ // Query to check if item exists
63
+ const querySpec = {
64
+ query: 'SELECT * FROM c WHERE c.PK = @pk',
65
+ parameters: [{ name: '@pk', value: item.PK }],
66
+ };
67
+ const { resources: existingItems } = yield container.items
68
+ .query(querySpec)
69
+ .fetchAll();
70
+ const existingItem = existingItems[0];
71
+ return {
72
+ operationType: 'Upsert',
73
+ partitionKey: item.PK,
74
+ resourceBody: Object.assign(Object.assign({}, item), { id: existingItem === null || existingItem === void 0 ? void 0 : existingItem.id }),
75
+ };
76
+ })));
77
+ const bulkResponse = yield container.items.bulk(operations);
78
+ // Process results
79
+ let successCount = 0;
80
+ let failureCount = 0;
81
+ bulkResponse.forEach((response, index) => {
82
+ if (response.statusCode === 429) {
83
+ throw new Error('429');
84
+ }
85
+ if (response.statusCode >= 200 && response.statusCode < 300) {
86
+ successCount++;
87
+ }
88
+ else {
89
+ const item = chunk[index];
90
+ (0, log_1.error)(`Failed to write item - PK: ${item.PK}, Status: ${response.statusCode}`, response.resourceBody);
91
+ failureCount++;
92
+ }
93
+ });
94
+ (0, log_1.info)(`Chunk ${i / utils_1.BULK_CHUNK_SIZE + 1}/${Math.ceil(items.length / utils_1.BULK_CHUNK_SIZE)} results - Success: ${successCount}, Failed: ${failureCount}`);
95
+ return bulkResponse;
96
+ }), `bulk_write_chunk_${i / utils_1.BULK_CHUNK_SIZE + 1}`);
97
+ }
98
+ (0, log_1.info)('All items written successfully');
99
+ return {};
100
+ }
101
+ catch (e) {
102
+ const em = e.message;
103
+ (0, log_1.error)('Error bulk writing items:', em);
104
+ throw e;
105
+ }
106
+ });
107
+ }
@@ -10,3 +10,4 @@ export * from './ssm';
10
10
  export * from './ssmInfra';
11
11
  export * from './sts';
12
12
  export * from './validations';
13
+ export * from './cosmos';
@@ -26,3 +26,4 @@ __exportStar(require("./ssm"), exports);
26
26
  __exportStar(require("./ssmInfra"), exports);
27
27
  __exportStar(require("./sts"), exports);
28
28
  __exportStar(require("./validations"), exports);
29
+ __exportStar(require("./cosmos"), exports);
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.0.765",
2
+ "version": "0.0.767",
3
3
  "name": "ag-common",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
@@ -25,10 +25,12 @@
25
25
  "@aws-sdk/client-sts": "^3.879.0",
26
26
  "@aws-sdk/lib-dynamodb": "^3.879.0",
27
27
  "@aws-sdk/s3-presigned-post": "^3.879.0",
28
+ "@azure/cosmos": "^4.5.1",
28
29
  "aws-cdk-lib": "^2.213.0",
29
30
  "buffer": "^6.0.3",
30
31
  "jsonwebtoken": "^9.0.2",
31
32
  "jwks-rsa": "^3.2.0",
33
+ "node-cache": "^5.1.2",
32
34
  "react": "^19.1.1",
33
35
  "react-dom": "^19.1.1",
34
36
  "typescript": "^5.9.2"