@cfworker/cosmos 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/client.js +285 -0
- package/dist/cjs/index.js +22 -0
- package/dist/cjs/response.js +60 -0
- package/dist/{retry.d.ts → cjs/retry.d.ts} +1 -1
- package/dist/cjs/retry.js +29 -0
- package/dist/cjs/session.js +55 -0
- package/dist/cjs/signer.js +49 -0
- package/dist/cjs/types.js +2 -0
- package/dist/cjs/util.js +42 -0
- package/dist/esm/client.d.ts +144 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/response.d.ts +24 -0
- package/dist/esm/retry.d.ts +21 -0
- package/dist/esm/session.d.ts +24 -0
- package/dist/esm/signer.d.ts +12 -0
- package/dist/esm/types.d.ts +62 -0
- package/dist/esm/util.d.ts +5 -0
- package/dist/tsconfig-cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +11 -7
- package/src/client.ts +26 -10
- package/src/response.ts +9 -9
- package/src/retry.ts +1 -1
- package/src/session.ts +3 -3
- package/src/signer.ts +7 -4
- package/src/util.ts +2 -2
- package/tsconfig.json +0 -10
- /package/dist/{client.d.ts → cjs/client.d.ts} +0 -0
- /package/dist/{index.d.ts → cjs/index.d.ts} +0 -0
- /package/dist/{response.d.ts → cjs/response.d.ts} +0 -0
- /package/dist/{session.d.ts → cjs/session.d.ts} +0 -0
- /package/dist/{signer.d.ts → cjs/signer.d.ts} +0 -0
- /package/dist/{types.d.ts → cjs/types.d.ts} +0 -0
- /package/dist/{util.d.ts → cjs/util.d.ts} +0 -0
- /package/dist/{client.js → esm/client.js} +0 -0
- /package/dist/{index.js → esm/index.d.ts} +0 -0
- /package/dist/{response.js → esm/response.js} +0 -0
- /package/dist/{retry.js → esm/retry.js} +0 -0
- /package/dist/{session.js → esm/session.js} +0 -0
- /package/dist/{signer.js → esm/signer.js} +0 -0
- /package/dist/{types.js → esm/types.js} +0 -0
- /package/dist/{util.js → esm/util.js} +0 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CosmosClient = void 0;
|
|
4
|
+
const response_js_1 = require("./response.js");
|
|
5
|
+
const retry_js_1 = require("./retry.js");
|
|
6
|
+
const session_js_1 = require("./session.js");
|
|
7
|
+
const signer_js_1 = require("./signer.js");
|
|
8
|
+
const util_js_1 = require("./util.js");
|
|
9
|
+
class CosmosClient {
|
|
10
|
+
endpoint;
|
|
11
|
+
signer;
|
|
12
|
+
retryPolicy;
|
|
13
|
+
consistencyLevel;
|
|
14
|
+
dbId;
|
|
15
|
+
collId;
|
|
16
|
+
enableCrossPartitionQueries;
|
|
17
|
+
systemFetch;
|
|
18
|
+
sessions;
|
|
19
|
+
requestCharges = 0;
|
|
20
|
+
retries = { count: 0, delayMs: 0 };
|
|
21
|
+
constructor(config) {
|
|
22
|
+
let { endpoint, masterKey } = 'connectionString' in config
|
|
23
|
+
? (0, util_js_1.parseConnectionString)(config.connectionString)
|
|
24
|
+
: config;
|
|
25
|
+
if (endpoint.endsWith('/')) {
|
|
26
|
+
endpoint = endpoint.slice(0, -1);
|
|
27
|
+
}
|
|
28
|
+
this.endpoint = endpoint;
|
|
29
|
+
this.signer = (0, signer_js_1.getSigner)(masterKey);
|
|
30
|
+
this.retryPolicy = config.retryPolicy ?? retry_js_1.defaultRetryPolicy;
|
|
31
|
+
this.consistencyLevel = config.consistencyLevel ?? 'Session';
|
|
32
|
+
this.dbId = config.dbId;
|
|
33
|
+
this.collId = config.collId;
|
|
34
|
+
this.enableCrossPartitionQueries =
|
|
35
|
+
config.enableCrossPartitionQueries ?? true;
|
|
36
|
+
this.sessions = config.sessions ?? new session_js_1.DefaultSessionContainer();
|
|
37
|
+
this.systemFetch = config.fetch ?? fetch.bind(globalThis);
|
|
38
|
+
}
|
|
39
|
+
async getDatabases(args = {}) {
|
|
40
|
+
const url = this.endpoint + `/dbs`;
|
|
41
|
+
const request = new Request(url, { method: 'GET' });
|
|
42
|
+
this.setHeaders(request.headers, args);
|
|
43
|
+
const response = await this.fetchWithRetry(request);
|
|
44
|
+
const next = this.getNext(response, args, this.getDatabases);
|
|
45
|
+
return new response_js_1.FeedResponse(response, next, 'Databases');
|
|
46
|
+
}
|
|
47
|
+
async getDatabase(args = {}) {
|
|
48
|
+
const { dbId = this.dbId, ...headers } = args;
|
|
49
|
+
(0, util_js_1.assertArg)('dbId', dbId);
|
|
50
|
+
const url = this.endpoint + (0, util_js_1.uri) `/dbs/${dbId}`;
|
|
51
|
+
const request = new Request(url, { method: 'GET' });
|
|
52
|
+
this.setHeaders(request.headers, headers);
|
|
53
|
+
const response = await this.fetchWithRetry(request);
|
|
54
|
+
return new response_js_1.ItemResponse(response);
|
|
55
|
+
}
|
|
56
|
+
async getCollections(args = {}) {
|
|
57
|
+
const { dbId = this.dbId, ...headers } = args;
|
|
58
|
+
(0, util_js_1.assertArg)('dbId', dbId);
|
|
59
|
+
const url = this.endpoint + (0, util_js_1.uri) `/dbs/${dbId}/colls`;
|
|
60
|
+
const request = new Request(url, { method: 'GET' });
|
|
61
|
+
this.setHeaders(request.headers, headers);
|
|
62
|
+
const response = await this.fetchWithRetry(request);
|
|
63
|
+
const next = this.getNext(response, args, this.getCollections);
|
|
64
|
+
return new response_js_1.FeedResponse(response, next, 'DocumentCollections');
|
|
65
|
+
}
|
|
66
|
+
async getCollection(args = {}) {
|
|
67
|
+
const { dbId = this.dbId, collId = this.collId, ...headers } = args;
|
|
68
|
+
(0, util_js_1.assertArg)('dbId', dbId);
|
|
69
|
+
(0, util_js_1.assertArg)('collId', collId);
|
|
70
|
+
const url = this.endpoint + (0, util_js_1.uri) `/dbs/${dbId}/colls/${collId}`;
|
|
71
|
+
const request = new Request(url, { method: 'GET' });
|
|
72
|
+
this.setHeaders(request.headers, headers);
|
|
73
|
+
const response = await this.fetchWithRetry(request);
|
|
74
|
+
return new response_js_1.ItemResponse(response);
|
|
75
|
+
}
|
|
76
|
+
async createCollection(args) {
|
|
77
|
+
const { dbId = this.dbId, collId = this.collId, indexingPolicy, partitionKey, ...headers } = args;
|
|
78
|
+
(0, util_js_1.assertArg)('dbId', dbId);
|
|
79
|
+
(0, util_js_1.assertArg)('collId', collId);
|
|
80
|
+
const url = this.endpoint + (0, util_js_1.uri) `/dbs/${dbId}/colls`;
|
|
81
|
+
const body = JSON.stringify({ id: collId, indexingPolicy, partitionKey });
|
|
82
|
+
const request = new Request(url, { method: 'POST', body });
|
|
83
|
+
this.setHeaders(request.headers, headers);
|
|
84
|
+
request.headers.set('content-type', 'application/json');
|
|
85
|
+
const response = await this.fetchWithRetry(request);
|
|
86
|
+
return new response_js_1.ItemResponse(response);
|
|
87
|
+
}
|
|
88
|
+
async replaceCollection(args) {
|
|
89
|
+
const { dbId = this.dbId, collId = this.collId, indexingPolicy, partitionKey, ...headers } = args;
|
|
90
|
+
(0, util_js_1.assertArg)('dbId', dbId);
|
|
91
|
+
(0, util_js_1.assertArg)('collId', collId);
|
|
92
|
+
const url = this.endpoint + (0, util_js_1.uri) `/dbs/${dbId}/colls/${collId}`;
|
|
93
|
+
const body = JSON.stringify({ id: collId, indexingPolicy, partitionKey });
|
|
94
|
+
const request = new Request(url, { method: 'PUT', body });
|
|
95
|
+
this.setHeaders(request.headers, headers);
|
|
96
|
+
request.headers.set('content-type', 'application/json');
|
|
97
|
+
const response = await this.fetchWithRetry(request);
|
|
98
|
+
return new response_js_1.ItemResponse(response);
|
|
99
|
+
}
|
|
100
|
+
async deleteCollection(args = {}) {
|
|
101
|
+
const { dbId = this.dbId, collId = this.collId, ...headers } = args;
|
|
102
|
+
(0, util_js_1.assertArg)('dbId', dbId);
|
|
103
|
+
(0, util_js_1.assertArg)('collId', collId);
|
|
104
|
+
const url = this.endpoint + (0, util_js_1.uri) `/dbs/${dbId}/colls/${collId}`;
|
|
105
|
+
const request = new Request(url, { method: 'DELETE' });
|
|
106
|
+
this.setHeaders(request.headers, headers);
|
|
107
|
+
const response = await this.fetchWithRetry(request);
|
|
108
|
+
return response;
|
|
109
|
+
}
|
|
110
|
+
async getDocuments(args) {
|
|
111
|
+
const { dbId = this.dbId, collId = this.collId, ...headers } = args;
|
|
112
|
+
(0, util_js_1.assertArg)('dbId', dbId);
|
|
113
|
+
(0, util_js_1.assertArg)('collId', collId);
|
|
114
|
+
const url = this.endpoint + (0, util_js_1.uri) `/dbs/${dbId}/colls/${collId}/docs`;
|
|
115
|
+
const request = new Request(url, { method: 'GET' });
|
|
116
|
+
this.setHeaders(request.headers, headers);
|
|
117
|
+
const response = await this.fetchWithRetry(request);
|
|
118
|
+
const next = this.getNext(response, args, this.getDocuments);
|
|
119
|
+
return new response_js_1.FeedResponse(response, next, 'Documents');
|
|
120
|
+
}
|
|
121
|
+
async getDocument(args) {
|
|
122
|
+
const { dbId = this.dbId, collId = this.collId, docId, ...headers } = args;
|
|
123
|
+
(0, util_js_1.assertArg)('dbId', dbId);
|
|
124
|
+
(0, util_js_1.assertArg)('collId', collId);
|
|
125
|
+
const url = this.endpoint + (0, util_js_1.uri) `/dbs/${dbId}/colls/${collId}/docs/${docId}`;
|
|
126
|
+
const request = new Request(url, { method: 'GET' });
|
|
127
|
+
this.setHeaders(request.headers, headers);
|
|
128
|
+
const response = await this.fetchWithRetry(request);
|
|
129
|
+
return new response_js_1.ItemResponse(response);
|
|
130
|
+
}
|
|
131
|
+
async createDocument(args) {
|
|
132
|
+
const { dbId = this.dbId, collId = this.collId, document, ...headers } = args;
|
|
133
|
+
(0, util_js_1.assertArg)('dbId', dbId);
|
|
134
|
+
(0, util_js_1.assertArg)('collId', collId);
|
|
135
|
+
const url = this.endpoint + (0, util_js_1.uri) `/dbs/${dbId}/colls/${collId}/docs`;
|
|
136
|
+
const body = toBodyInit(document);
|
|
137
|
+
const request = new Request(url, { method: 'POST', body });
|
|
138
|
+
this.setHeaders(request.headers, headers);
|
|
139
|
+
request.headers.set('content-type', 'application/json');
|
|
140
|
+
const response = await this.fetchWithRetry(request);
|
|
141
|
+
return new response_js_1.ItemResponse(response);
|
|
142
|
+
}
|
|
143
|
+
async replaceDocument(args) {
|
|
144
|
+
const { dbId = this.dbId, collId = this.collId, docId, document, ...headers } = args;
|
|
145
|
+
(0, util_js_1.assertArg)('dbId', dbId);
|
|
146
|
+
(0, util_js_1.assertArg)('collId', collId);
|
|
147
|
+
const url = this.endpoint + (0, util_js_1.uri) `/dbs/${dbId}/colls/${collId}/docs/${docId}`;
|
|
148
|
+
const body = toBodyInit(document);
|
|
149
|
+
const request = new Request(url, { method: 'PUT', body });
|
|
150
|
+
this.setHeaders(request.headers, headers);
|
|
151
|
+
request.headers.set('content-type', 'application/json');
|
|
152
|
+
const response = await this.fetchWithRetry(request);
|
|
153
|
+
return new response_js_1.ItemResponse(response);
|
|
154
|
+
}
|
|
155
|
+
async deleteDocument(args) {
|
|
156
|
+
const { dbId = this.dbId, collId = this.collId, docId, ...headers } = args;
|
|
157
|
+
(0, util_js_1.assertArg)('dbId', dbId);
|
|
158
|
+
(0, util_js_1.assertArg)('collId', collId);
|
|
159
|
+
const url = this.endpoint + (0, util_js_1.uri) `/dbs/${dbId}/colls/${collId}/docs/${docId}`;
|
|
160
|
+
const request = new Request(url, { method: 'DELETE' });
|
|
161
|
+
this.setHeaders(request.headers, headers);
|
|
162
|
+
const response = await this.fetchWithRetry(request);
|
|
163
|
+
return response;
|
|
164
|
+
}
|
|
165
|
+
async queryDocuments(args) {
|
|
166
|
+
const { dbId = this.dbId, collId = this.collId, query, parameters = [], ...headerArgs } = args;
|
|
167
|
+
(0, util_js_1.assertArg)('dbId', dbId);
|
|
168
|
+
(0, util_js_1.assertArg)('collId', collId);
|
|
169
|
+
const headers = Object.assign({
|
|
170
|
+
enableCrossPartition: this.enableCrossPartitionQueries,
|
|
171
|
+
enableScan: false,
|
|
172
|
+
maxItems: -1,
|
|
173
|
+
populateMetrics: false,
|
|
174
|
+
isQuery: true
|
|
175
|
+
}, headerArgs);
|
|
176
|
+
const url = this.endpoint + (0, util_js_1.uri) `/dbs/${dbId}/colls/${collId}/docs`;
|
|
177
|
+
const body = JSON.stringify({ query, parameters });
|
|
178
|
+
const request = new Request(url, { method: 'POST', body });
|
|
179
|
+
this.setHeaders(request.headers, headers);
|
|
180
|
+
request.headers.set('content-type', 'application/query+json');
|
|
181
|
+
const response = await this.fetchWithRetry(request);
|
|
182
|
+
const next = this.getNext(response, args, this.queryDocuments);
|
|
183
|
+
return new response_js_1.FeedResponse(response, next, 'Documents');
|
|
184
|
+
}
|
|
185
|
+
getNext(response, args, fn) {
|
|
186
|
+
return () => {
|
|
187
|
+
const continuation = response.headers.get('x-ms-continuation');
|
|
188
|
+
if (!continuation) {
|
|
189
|
+
throw new Error(`Response is not continuable.`);
|
|
190
|
+
}
|
|
191
|
+
return fn.call(this, Object.assign({}, args, { continuation }));
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
async fetchWithRetry(request, context) {
|
|
195
|
+
const retryRequest = request.clone();
|
|
196
|
+
const response = await this.fetch(request);
|
|
197
|
+
context ??= { attempts: 0, cumulativeWaitMs: 0, request, response };
|
|
198
|
+
context.attempts++;
|
|
199
|
+
context.request = retryRequest;
|
|
200
|
+
context.response = response;
|
|
201
|
+
const { retry, delayMs } = await this.retryPolicy.shouldRetry(context);
|
|
202
|
+
if (!retry) {
|
|
203
|
+
return response;
|
|
204
|
+
}
|
|
205
|
+
if (delayMs !== 0) {
|
|
206
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
207
|
+
context.cumulativeWaitMs += delayMs;
|
|
208
|
+
this.retries.delayMs += delayMs;
|
|
209
|
+
}
|
|
210
|
+
this.retries.count++;
|
|
211
|
+
return this.fetchWithRetry(retryRequest, context);
|
|
212
|
+
}
|
|
213
|
+
async fetch(request) {
|
|
214
|
+
this.sessions.setRequestSession(request);
|
|
215
|
+
await this.signer.sign(request);
|
|
216
|
+
const response = await this.systemFetch(request);
|
|
217
|
+
this.sessions.readResponseSession(response);
|
|
218
|
+
const requestCharge = +(response.headers.get('x-ms-request-charge') || 0);
|
|
219
|
+
this.requestCharges += requestCharge;
|
|
220
|
+
return response;
|
|
221
|
+
}
|
|
222
|
+
setHeaders(headers, args) {
|
|
223
|
+
headers.set('accept', 'application/json');
|
|
224
|
+
headers.set('cache-control', 'no-cache');
|
|
225
|
+
headers.set('x-ms-version', '2018-12-31');
|
|
226
|
+
if (args.activityId) {
|
|
227
|
+
headers.set('x-ms-activity-id', args.activityId);
|
|
228
|
+
}
|
|
229
|
+
const consistencyLevel = args.consistencyLevel || this.consistencyLevel;
|
|
230
|
+
headers.set('x-ms-consistency-level', consistencyLevel);
|
|
231
|
+
if (args.continuation) {
|
|
232
|
+
headers.set('x-ms-continuation', args.continuation);
|
|
233
|
+
}
|
|
234
|
+
if (args.enableScan) {
|
|
235
|
+
headers.set('x-ms-documentdb-query-enable-scan', 'true');
|
|
236
|
+
}
|
|
237
|
+
if (args.ifMatch) {
|
|
238
|
+
headers.set('if-match', args.ifMatch);
|
|
239
|
+
}
|
|
240
|
+
if (args.ifModifiedSince) {
|
|
241
|
+
headers.set('if-modified-since', args.ifModifiedSince.toUTCString());
|
|
242
|
+
}
|
|
243
|
+
if (args.ifNoneMatch) {
|
|
244
|
+
headers.set('if-none-match', args.ifNoneMatch);
|
|
245
|
+
}
|
|
246
|
+
if (args.indexingDirective) {
|
|
247
|
+
headers.set('x-ms-indexing-directive', args.indexingDirective);
|
|
248
|
+
}
|
|
249
|
+
if (args.isQuery) {
|
|
250
|
+
headers.set('x-ms-documentdb-isquery', args.isQuery.toString());
|
|
251
|
+
}
|
|
252
|
+
if (args.isUpsert) {
|
|
253
|
+
headers.set('x-ms-documentdb-is-upsert', args.isUpsert.toString());
|
|
254
|
+
}
|
|
255
|
+
if (args.maxItems) {
|
|
256
|
+
headers.set('x-ms-max-item-count', args.maxItems.toString(10));
|
|
257
|
+
}
|
|
258
|
+
if (args.offerType) {
|
|
259
|
+
headers.set('x-ms-offer-type', args.offerType);
|
|
260
|
+
}
|
|
261
|
+
if (args.offerThroughput) {
|
|
262
|
+
headers.set('x-ms-offer-throughput', args.offerThroughput.toString());
|
|
263
|
+
}
|
|
264
|
+
if (args.populateMetrics) {
|
|
265
|
+
headers.set('x-ms-documentdb-populatequerymetrics', 'true');
|
|
266
|
+
}
|
|
267
|
+
if (args.partitionKey) {
|
|
268
|
+
headers.set('x-ms-documentdb-partitionkey', (0, util_js_1.escapeNonASCII)(JSON.stringify([args.partitionKey])));
|
|
269
|
+
if (args.isQuery) {
|
|
270
|
+
headers.set('x-ms-documentdb-query-enablecrosspartition', 'false');
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
else if (args.enableCrossPartition !== undefined && args.isQuery) {
|
|
274
|
+
headers.set('x-ms-documentdb-query-enablecrosspartition', args.enableCrossPartition.toString());
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
exports.CosmosClient = CosmosClient;
|
|
279
|
+
function toBodyInit(obj) {
|
|
280
|
+
if ((typeof obj === 'string' || DataView.prototype.isPrototypeOf(obj),
|
|
281
|
+
ArrayBuffer.isView(obj) || obj instanceof ReadableStream)) {
|
|
282
|
+
return obj;
|
|
283
|
+
}
|
|
284
|
+
return JSON.stringify(obj);
|
|
285
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./client.js"), exports);
|
|
18
|
+
__exportStar(require("./response.js"), exports);
|
|
19
|
+
__exportStar(require("./session.js"), exports);
|
|
20
|
+
__exportStar(require("./signer.js"), exports);
|
|
21
|
+
__exportStar(require("./types.js"), exports);
|
|
22
|
+
__exportStar(require("./util.js"), exports);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FeedResponse = exports.ItemResponse = exports.CosmosResponse = void 0;
|
|
4
|
+
class CosmosResponse {
|
|
5
|
+
response;
|
|
6
|
+
constructor(response) {
|
|
7
|
+
this.response = response;
|
|
8
|
+
}
|
|
9
|
+
get status() {
|
|
10
|
+
return this.response.status;
|
|
11
|
+
}
|
|
12
|
+
get headers() {
|
|
13
|
+
return this.response.headers;
|
|
14
|
+
}
|
|
15
|
+
get body() {
|
|
16
|
+
return this.response.body;
|
|
17
|
+
}
|
|
18
|
+
get activityId() {
|
|
19
|
+
return this.response.headers.get('x-ms-activity-id');
|
|
20
|
+
}
|
|
21
|
+
get etag() {
|
|
22
|
+
return this.response.headers.get('etag');
|
|
23
|
+
}
|
|
24
|
+
get requestCharge() {
|
|
25
|
+
return parseInt(this.response.headers.get('x-ms-request-charge'));
|
|
26
|
+
}
|
|
27
|
+
get raw() {
|
|
28
|
+
return this.response;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.CosmosResponse = CosmosResponse;
|
|
32
|
+
class ItemResponse extends CosmosResponse {
|
|
33
|
+
constructor(response) {
|
|
34
|
+
super(response);
|
|
35
|
+
}
|
|
36
|
+
json() {
|
|
37
|
+
return this.response.json();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.ItemResponse = ItemResponse;
|
|
41
|
+
class FeedResponse extends CosmosResponse {
|
|
42
|
+
next;
|
|
43
|
+
itemsProperty;
|
|
44
|
+
constructor(response, next, itemsProperty) {
|
|
45
|
+
super(response);
|
|
46
|
+
this.next = next;
|
|
47
|
+
this.itemsProperty = itemsProperty;
|
|
48
|
+
}
|
|
49
|
+
get count() {
|
|
50
|
+
return parseInt(this.response.headers.get('x-ms-item-count'));
|
|
51
|
+
}
|
|
52
|
+
get hasNext() {
|
|
53
|
+
return this.response.headers.has('x-ms-continuation');
|
|
54
|
+
}
|
|
55
|
+
async json() {
|
|
56
|
+
const data = await this.response.json();
|
|
57
|
+
return data[this.itemsProperty];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.FeedResponse = FeedResponse;
|
|
@@ -18,4 +18,4 @@ export declare class DefaultRetryPolicy implements RetryPolicy {
|
|
|
18
18
|
constructor(maxAttempts?: number, maxCumulativeWaitTimeMs?: number, defaultRetryDelayMs?: number);
|
|
19
19
|
shouldRetry(context: RetryContext): Promise<RetryInstruction>;
|
|
20
20
|
}
|
|
21
|
-
export declare const defaultRetryPolicy:
|
|
21
|
+
export declare const defaultRetryPolicy: RetryPolicy;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultRetryPolicy = exports.DefaultRetryPolicy = void 0;
|
|
4
|
+
const session_1 = require("./session");
|
|
5
|
+
class DefaultRetryPolicy {
|
|
6
|
+
maxAttempts;
|
|
7
|
+
maxCumulativeWaitTimeMs;
|
|
8
|
+
defaultRetryDelayMs;
|
|
9
|
+
constructor(maxAttempts = 10, maxCumulativeWaitTimeMs = 30000, defaultRetryDelayMs = 5000) {
|
|
10
|
+
this.maxAttempts = maxAttempts;
|
|
11
|
+
this.maxCumulativeWaitTimeMs = maxCumulativeWaitTimeMs;
|
|
12
|
+
this.defaultRetryDelayMs = defaultRetryDelayMs;
|
|
13
|
+
}
|
|
14
|
+
async shouldRetry(context) {
|
|
15
|
+
if ((0, session_1.readSessionNotAvailable)(context.response)) {
|
|
16
|
+
return { retry: true, delayMs: 0 };
|
|
17
|
+
}
|
|
18
|
+
if (context.response.status !== 429 ||
|
|
19
|
+
context.attempts >= this.maxAttempts ||
|
|
20
|
+
context.cumulativeWaitMs >= this.maxCumulativeWaitTimeMs) {
|
|
21
|
+
return { retry: false, delayMs: 0 };
|
|
22
|
+
}
|
|
23
|
+
const delayMs = +(context.response.headers.get('x-ms-retry-after-ms') ||
|
|
24
|
+
this.defaultRetryDelayMs);
|
|
25
|
+
return { retry: true, delayMs };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.DefaultRetryPolicy = DefaultRetryPolicy;
|
|
29
|
+
exports.defaultRetryPolicy = new DefaultRetryPolicy();
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultSessionContainer = void 0;
|
|
4
|
+
exports.readSessionNotAvailable = readSessionNotAvailable;
|
|
5
|
+
exports.getCollectionId = getCollectionId;
|
|
6
|
+
const readSessionNotAvailableSubstatus = '1002';
|
|
7
|
+
function readSessionNotAvailable(response) {
|
|
8
|
+
return (response.status === 404 &&
|
|
9
|
+
response.headers.get('x-ms-substatus') === readSessionNotAvailableSubstatus);
|
|
10
|
+
}
|
|
11
|
+
function getCollectionId({ url, headers }) {
|
|
12
|
+
const path = headers.get('x-ms-alt-content-path') ?? new URL(url).pathname.substr(1);
|
|
13
|
+
const [, dbId, colls, collId] = path.split('/');
|
|
14
|
+
if (colls !== 'colls' || !collId) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
return { dbId, collId };
|
|
18
|
+
}
|
|
19
|
+
class DefaultSessionContainer {
|
|
20
|
+
tokens;
|
|
21
|
+
constructor(tokens = {}) {
|
|
22
|
+
this.tokens = tokens;
|
|
23
|
+
}
|
|
24
|
+
setRequestSession(request) {
|
|
25
|
+
if (request.headers.get('x-ms-consistency-level') !== 'Session') {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const ids = getCollectionId(request);
|
|
29
|
+
if (!ids) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const token = this.tokens?.[ids.dbId]?.[ids.collId];
|
|
33
|
+
if (token) {
|
|
34
|
+
request.headers.set('x-ms-session-token', token);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
readResponseSession(response) {
|
|
38
|
+
const ids = getCollectionId(response);
|
|
39
|
+
if (!ids) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (readSessionNotAvailable(response)) {
|
|
43
|
+
if (this.tokens[ids.dbId]) {
|
|
44
|
+
delete this.tokens[ids.dbId][ids.collId];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const token = response.headers.get('x-ms-session-token');
|
|
48
|
+
if (!token) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
this.tokens[ids.dbId] ??= {};
|
|
52
|
+
this.tokens[ids.dbId][ids.collId] = token;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.DefaultSessionContainer = DefaultSessionContainer;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Signer = void 0;
|
|
4
|
+
exports.getSigner = getSigner;
|
|
5
|
+
const rfc4648_1 = require("rfc4648");
|
|
6
|
+
class Signer {
|
|
7
|
+
masterkey;
|
|
8
|
+
encoder = new TextEncoder();
|
|
9
|
+
constructor(masterkey) {
|
|
10
|
+
const promiseLike = crypto.subtle.importKey('raw', rfc4648_1.base64.parse(masterkey), { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']);
|
|
11
|
+
this.masterkey = Promise.resolve(promiseLike);
|
|
12
|
+
}
|
|
13
|
+
async sign(request, date = new Date()) {
|
|
14
|
+
const key = await this.masterkey;
|
|
15
|
+
const payload = this.getPayload(request, date);
|
|
16
|
+
const hashed = await crypto.subtle.sign('HMAC', key, payload);
|
|
17
|
+
const signature = rfc4648_1.base64.stringify(new Uint8Array(hashed));
|
|
18
|
+
request.headers.set('authorization', encodeURIComponent(`type=master&ver=1.0&sig=${signature}`));
|
|
19
|
+
request.headers.set('x-ms-date', date.toUTCString());
|
|
20
|
+
}
|
|
21
|
+
getPayload(request, date) {
|
|
22
|
+
const url = new URL(request.url);
|
|
23
|
+
const { resourceType, resourceId } = this.pathnameToResource(url.pathname);
|
|
24
|
+
const method = request.method.toLowerCase();
|
|
25
|
+
const text = `${method}\n${resourceType}\n${resourceId}\n${date
|
|
26
|
+
.toUTCString()
|
|
27
|
+
.toLowerCase()}\n\n`;
|
|
28
|
+
return this.encoder.encode(text);
|
|
29
|
+
}
|
|
30
|
+
pathnameToResource(pathname) {
|
|
31
|
+
const segments = pathname.split('/');
|
|
32
|
+
if (segments.length % 2 === 0) {
|
|
33
|
+
const resourceType = segments[segments.length - 1];
|
|
34
|
+
const resourceId = segments.slice(1, segments.length - 1).join('/');
|
|
35
|
+
return { resourceType, resourceId };
|
|
36
|
+
}
|
|
37
|
+
const resourceType = segments[segments.length - 2];
|
|
38
|
+
const resourceId = segments.slice(1, segments.length).join('/');
|
|
39
|
+
return { resourceType, resourceId };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.Signer = Signer;
|
|
43
|
+
const signers = {};
|
|
44
|
+
function getSigner(masterKey) {
|
|
45
|
+
if (!signers[masterKey]) {
|
|
46
|
+
signers[masterKey] = new Signer(masterKey);
|
|
47
|
+
}
|
|
48
|
+
return signers[masterKey];
|
|
49
|
+
}
|
package/dist/cjs/util.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.escapeNonASCII = escapeNonASCII;
|
|
4
|
+
exports.assertArg = assertArg;
|
|
5
|
+
exports.uri = uri;
|
|
6
|
+
exports.parseConnectionString = parseConnectionString;
|
|
7
|
+
function escapeNonASCII(s) {
|
|
8
|
+
return s.replace(/[\u0080-\uFFFF]/g, m => '\\u' + m.charCodeAt(0).toString(16).padStart(4, '0'));
|
|
9
|
+
}
|
|
10
|
+
function assertArg(name, value) {
|
|
11
|
+
if (!value) {
|
|
12
|
+
throw new Error(`${name} is required.`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function uri(strings, ...values) {
|
|
16
|
+
let s = strings[0];
|
|
17
|
+
for (let i = 0; i < values.length; i++) {
|
|
18
|
+
s += encodeURIComponent(values[i]) + strings[i + 1];
|
|
19
|
+
}
|
|
20
|
+
return s;
|
|
21
|
+
}
|
|
22
|
+
function parseConnectionString(connString) {
|
|
23
|
+
const props = {};
|
|
24
|
+
connString.split(';').forEach(kv => {
|
|
25
|
+
const pos = kv.indexOf('=');
|
|
26
|
+
if (pos < 1) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const key = kv.slice(0, pos);
|
|
30
|
+
const val = kv.slice(pos + 1);
|
|
31
|
+
if (key && val) {
|
|
32
|
+
props[key] = val;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
if (!props.AccountEndpoint || !props.AccountKey) {
|
|
36
|
+
throw new Error('Invalid connection string');
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
endpoint: props.AccountEndpoint,
|
|
40
|
+
masterKey: props.AccountKey
|
|
41
|
+
};
|
|
42
|
+
}
|