@cfworker/cosmos 1.12.0 → 1.13.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/README.md CHANGED
@@ -44,10 +44,14 @@ import { CosmosClient } from '@cfworker/cosmos';
44
44
 
45
45
  // 🚨️ Do not commit your Cosmos DB master key to source control!
46
46
  // Use a bundler like Rollup, Parcel, or Webpack to interpolate your master key at build-time.
47
- const masterKey = '...top secret master key copied from the azure portal...';
47
+ const accountKey = '...top secret master key copied from the azure portal...';
48
48
  const endpoint = 'https://xxxxxxxxxxxx.documents.azure.com';
49
49
 
50
- const client = new CosmosClient({ endpoint, masterKey });
50
+ const client = new CosmosClient({ endpoint, accountKey });
51
+
52
+ // or
53
+
54
+ const client = new CosmosClient({ connectionString });
51
55
  ```
52
56
 
53
57
  ### Specify consistency level
@@ -58,7 +62,7 @@ You may override the default value when constructing the CosmosClient.
58
62
  ```ts
59
63
  const consistencyLevel = 'Eventual';
60
64
 
61
- const client = new CosmosClient({ endpoint, masterKey, consistencyLevel });
65
+ const client = new CosmosClient({ endpoint, accountKey, consistencyLevel });
62
66
  ```
63
67
 
64
68
  Most methods on CosmosClient accept a `consistencyLevel` argument to enable overriding the client's consistency level on a case-by-case basis.
@@ -76,7 +80,7 @@ You may specify default values for these arguments when constructing the CosmosC
76
80
  const dbId = 'my-db';
77
81
  const collId = 'my-coll';
78
82
 
79
- const client = new CosmosClient({ endpoint, masterKey, dbId, collId });
83
+ const client = new CosmosClient({ endpoint, accountKey, dbId, collId });
80
84
  ```
81
85
 
82
86
  ### Authenticating with resource tokens
package/dist/client.d.ts CHANGED
@@ -1,15 +1,17 @@
1
1
  import { FeedResponse, ItemResponse } from './response.js';
2
2
  import { RetryPolicy } from './retry.js';
3
3
  import { SessionContainer } from './session.js';
4
- import { Collection, ConsistencyLevel, Database, Document, IndexingDirective, IndexingPolicy, OfferType, PartitionKeyDefinition, Resource } from './types.js';
5
- export interface CosmosClientConfig {
6
- endpoint: string;
7
- masterKey: string;
4
+ import { Collection, ConnectionInfo, ConsistencyLevel, Database, Document, IndexingDirective, IndexingPolicy, OfferType, PartitionKeyDefinition, Resource } from './types.js';
5
+ export declare type CosmosClientConfig = (ConnectionInfo & CosmosClientConfigBase) | ({
6
+ connectionString: string;
7
+ } & CosmosClientConfigBase);
8
+ interface CosmosClientConfigBase {
8
9
  retryPolicy?: RetryPolicy;
9
10
  consistencyLevel?: ConsistencyLevel;
10
11
  dbId?: string;
11
12
  collId?: string;
12
13
  sessions?: SessionContainer;
14
+ enableCrossPartitionQueries?: boolean;
13
15
  fetch?: typeof fetch;
14
16
  }
15
17
  export declare class CosmosClient {
@@ -19,6 +21,7 @@ export declare class CosmosClient {
19
21
  private readonly consistencyLevel;
20
22
  private readonly dbId;
21
23
  private readonly collId;
24
+ private readonly enableCrossPartitionQueries;
22
25
  private readonly systemFetch;
23
26
  readonly sessions: SessionContainer;
24
27
  requestCharges: number;
package/dist/client.js CHANGED
@@ -2,19 +2,27 @@ import { FeedResponse, ItemResponse } from './response.js';
2
2
  import { defaultRetryPolicy } from './retry.js';
3
3
  import { DefaultSessionContainer } from './session.js';
4
4
  import { getSigner } from './signer.js';
5
- import { assertArg, escapeNonASCII, uri } from './util.js';
5
+ import { assertArg, escapeNonASCII, parseConnectionString, uri } from './util.js';
6
6
  export class CosmosClient {
7
7
  constructor(config) {
8
8
  this.requestCharges = 0;
9
9
  this.retries = { count: 0, delayMs: 0 };
10
- this.endpoint = config.endpoint;
11
- this.signer = getSigner(config.masterKey);
10
+ let { endpoint, accountKey } = 'connectionString' in config
11
+ ? parseConnectionString(config.connectionString)
12
+ : config;
13
+ if (endpoint.endsWith('/')) {
14
+ endpoint = endpoint.slice(0, -1);
15
+ }
16
+ this.endpoint = endpoint;
17
+ this.signer = getSigner(accountKey);
12
18
  this.retryPolicy = config.retryPolicy ?? defaultRetryPolicy;
13
19
  this.consistencyLevel = config.consistencyLevel ?? 'Session';
14
20
  this.dbId = config.dbId;
15
21
  this.collId = config.collId;
22
+ this.enableCrossPartitionQueries =
23
+ config.enableCrossPartitionQueries ?? true;
16
24
  this.sessions = config.sessions ?? new DefaultSessionContainer();
17
- this.systemFetch = config.fetch ?? fetch.bind(self);
25
+ this.systemFetch = config.fetch ?? fetch.bind(globalThis);
18
26
  }
19
27
  async getDatabases(args = {}) {
20
28
  const url = this.endpoint + `/dbs`;
@@ -147,7 +155,7 @@ export class CosmosClient {
147
155
  assertArg('dbId', dbId);
148
156
  assertArg('collId', collId);
149
157
  const headers = Object.assign({
150
- enableCrossPartition: false,
158
+ enableCrossPartition: this.enableCrossPartitionQueries,
151
159
  enableScan: false,
152
160
  maxItems: -1,
153
161
  populateMetrics: false,
package/dist/signer.d.ts CHANGED
@@ -9,4 +9,4 @@ export declare class Signer {
9
9
  resourceId: string;
10
10
  };
11
11
  }
12
- export declare function getSigner(masterkey: string): Signer;
12
+ export declare function getSigner(accountKey: string): Signer;
package/dist/signer.js CHANGED
@@ -35,9 +35,9 @@ export class Signer {
35
35
  }
36
36
  }
37
37
  const signers = {};
38
- export function getSigner(masterkey) {
39
- if (!signers[masterkey]) {
40
- signers[masterkey] = new Signer(masterkey);
38
+ export function getSigner(accountKey) {
39
+ if (!signers[accountKey]) {
40
+ signers[accountKey] = new Signer(accountKey);
41
41
  }
42
- return signers[masterkey];
42
+ return signers[accountKey];
43
43
  }
package/dist/types.d.ts CHANGED
@@ -56,3 +56,7 @@ export interface Collection extends PersistedResource {
56
56
  _udfs: 'udfs/';
57
57
  _conflicts: 'conflicts/';
58
58
  }
59
+ export interface ConnectionInfo {
60
+ endpoint: string;
61
+ accountKey: string;
62
+ }
package/dist/util.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { ConnectionInfo } from './types';
1
2
  export declare function escapeNonASCII(s: string): string;
2
3
  export declare function assertArg(name: string, value: any): asserts value;
3
4
  export declare function uri(strings: TemplateStringsArray, ...values: any[]): string;
5
+ export declare function parseConnectionString(connString: string): ConnectionInfo;
package/dist/util.js CHANGED
@@ -13,3 +13,24 @@ export function uri(strings, ...values) {
13
13
  }
14
14
  return s;
15
15
  }
16
+ export function parseConnectionString(connString) {
17
+ const props = {};
18
+ connString.split(';').forEach(kv => {
19
+ const pos = kv.indexOf('=');
20
+ if (pos < 1) {
21
+ return;
22
+ }
23
+ const key = kv.slice(0, pos);
24
+ const val = kv.slice(pos + 1);
25
+ if (key && val) {
26
+ props[key] = val;
27
+ }
28
+ });
29
+ if (!props.AccountEndpoint || !props.AccountKey) {
30
+ throw new Error('Invalid connection string');
31
+ }
32
+ return {
33
+ endpoint: props.AccountEndpoint,
34
+ accountKey: props.AccountKey
35
+ };
36
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cfworker/cosmos",
3
- "version": "1.12.0",
3
+ "version": "1.13.0",
4
4
  "description": "Azure Cosmos DB client for Cloudflare Workers and service workers",
5
5
  "keywords": [
6
6
  "azure",
@@ -37,16 +37,16 @@
37
37
  "test": "cfworker test test/**/*.spec.ts"
38
38
  },
39
39
  "dependencies": {
40
- "@cfworker/worker-types": "^1.12.0",
40
+ "@cfworker/worker-types": "^1.12.1",
41
41
  "@cloudflare/workers-types": "^2.2.2",
42
- "base64-arraybuffer": "^1.0.1"
42
+ "base64-arraybuffer": "^1.0.2"
43
43
  },
44
44
  "devDependencies": {
45
- "@cfworker/dev": "^1.12.0",
46
- "@types/chai": "^4.2.22",
47
- "@types/mocha": "^9.0.0",
48
- "chai": "^4.3.4",
49
- "mocha": "^9.1.3",
50
- "typescript": "^4.5.2"
45
+ "@cfworker/dev": "^1.14.0",
46
+ "@types/chai": "^4.3.0",
47
+ "@types/mocha": "^9.1.0",
48
+ "chai": "^4.3.6",
49
+ "mocha": "^9.2.1",
50
+ "typescript": "^4.5.5"
51
51
  }
52
52
  }
package/src/client.ts CHANGED
@@ -4,6 +4,7 @@ import { DefaultSessionContainer, SessionContainer } from './session.js';
4
4
  import { getSigner, Signer } from './signer.js';
5
5
  import {
6
6
  Collection,
7
+ ConnectionInfo,
7
8
  ConsistencyLevel,
8
9
  Database,
9
10
  Document,
@@ -13,21 +14,25 @@ import {
13
14
  PartitionKeyDefinition,
14
15
  Resource
15
16
  } from './types.js';
16
- import { assertArg, escapeNonASCII, uri } from './util.js';
17
-
18
- export interface CosmosClientConfig {
19
- /**
20
- * Cosmos DB endpoint.
21
- * @example
22
- * "https://xxxxxxxxxx.documents.azure.com"
23
- */
24
- endpoint: string;
25
-
26
- /**
27
- * Cosmos DB master key.
28
- */
29
- masterKey: string;
30
-
17
+ import {
18
+ assertArg,
19
+ escapeNonASCII,
20
+ parseConnectionString,
21
+ uri
22
+ } from './util.js';
23
+
24
+ export type CosmosClientConfig =
25
+ | (ConnectionInfo & CosmosClientConfigBase)
26
+ | ({
27
+ /**
28
+ * Cosmos DB connection string.
29
+ * @example
30
+ * "AccountEndpoint=https://xxxxxxxxxx.documents.azure.com:443/;accountKey=xxxxxxxxxx;"
31
+ */
32
+ connectionString: string;
33
+ } & CosmosClientConfigBase);
34
+
35
+ interface CosmosClientConfigBase {
31
36
  /**
32
37
  * The retry policy to use when requests are throttled.
33
38
  */
@@ -54,6 +59,11 @@ export interface CosmosClientConfig {
54
59
  */
55
60
  sessions?: SessionContainer;
56
61
 
62
+ /**
63
+ * Enables cross partition queries. This can be overriden on individual queries. Defaults to true.
64
+ */
65
+ enableCrossPartitionQueries?: boolean;
66
+
57
67
  /**
58
68
  * System fetch function
59
69
  */
@@ -67,20 +77,30 @@ export class CosmosClient {
67
77
  private readonly consistencyLevel: ConsistencyLevel;
68
78
  private readonly dbId: string | undefined;
69
79
  private readonly collId: string | undefined;
80
+ private readonly enableCrossPartitionQueries: boolean;
70
81
  private readonly systemFetch: typeof fetch;
71
82
  public readonly sessions: SessionContainer;
72
83
  public requestCharges = 0;
73
84
  public retries = { count: 0, delayMs: 0 };
74
85
 
75
86
  constructor(config: CosmosClientConfig) {
76
- this.endpoint = config.endpoint;
77
- this.signer = getSigner(config.masterKey);
87
+ let { endpoint, accountKey } =
88
+ 'connectionString' in config
89
+ ? parseConnectionString(config.connectionString)
90
+ : config;
91
+ if (endpoint.endsWith('/')) {
92
+ endpoint = endpoint.slice(0, -1);
93
+ }
94
+ this.endpoint = endpoint;
95
+ this.signer = getSigner(accountKey);
78
96
  this.retryPolicy = config.retryPolicy ?? defaultRetryPolicy;
79
97
  this.consistencyLevel = config.consistencyLevel ?? 'Session';
80
98
  this.dbId = config.dbId;
81
99
  this.collId = config.collId;
100
+ this.enableCrossPartitionQueries =
101
+ config.enableCrossPartitionQueries ?? true;
82
102
  this.sessions = config.sessions ?? new DefaultSessionContainer();
83
- this.systemFetch = config.fetch ?? fetch.bind(self);
103
+ this.systemFetch = config.fetch ?? fetch.bind(globalThis);
84
104
  }
85
105
 
86
106
  public async getDatabases(
@@ -270,7 +290,7 @@ export class CosmosClient {
270
290
 
271
291
  const headers = Object.assign(
272
292
  {
273
- enableCrossPartition: false,
293
+ enableCrossPartition: this.enableCrossPartitionQueries,
274
294
  enableScan: false,
275
295
  maxItems: -1,
276
296
  populateMetrics: false,
package/src/signer.ts CHANGED
@@ -55,9 +55,9 @@ export class Signer {
55
55
 
56
56
  const signers: Record<string, Signer> = {};
57
57
 
58
- export function getSigner(masterkey: string) {
59
- if (!signers[masterkey]) {
60
- signers[masterkey] = new Signer(masterkey);
58
+ export function getSigner(accountKey: string) {
59
+ if (!signers[accountKey]) {
60
+ signers[accountKey] = new Signer(accountKey);
61
61
  }
62
- return signers[masterkey];
62
+ return signers[accountKey];
63
63
  }
package/src/types.ts CHANGED
@@ -66,3 +66,17 @@ export interface Collection extends PersistedResource {
66
66
  _udfs: 'udfs/';
67
67
  _conflicts: 'conflicts/';
68
68
  }
69
+
70
+ export interface ConnectionInfo {
71
+ /**
72
+ * Cosmos DB endpoint.
73
+ * @example
74
+ * "https://xxxxxxxxxx.documents.azure.com"
75
+ */
76
+ endpoint: string;
77
+
78
+ /**
79
+ * Cosmos DB key.
80
+ */
81
+ accountKey: string;
82
+ }
package/src/util.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { ConnectionInfo } from './types';
2
+
1
3
  /**
2
4
  * Escape non-ASCII characters as \uXXXX
3
5
  */
@@ -29,3 +31,29 @@ export function uri(strings: TemplateStringsArray, ...values: any[]) {
29
31
  }
30
32
  return s;
31
33
  }
34
+
35
+ /**
36
+ * Parses a connection string for Cosmos DB.
37
+ * @param connString Cosmos DB connection string.
38
+ */
39
+ export function parseConnectionString(connString: string): ConnectionInfo {
40
+ const props: Record<string, string> = {};
41
+ connString.split(';').forEach(kv => {
42
+ const pos = kv.indexOf('=');
43
+ if (pos < 1) {
44
+ return;
45
+ }
46
+ const key = kv.slice(0, pos);
47
+ const val = kv.slice(pos + 1);
48
+ if (key && val) {
49
+ props[key] = val;
50
+ }
51
+ });
52
+ if (!props.AccountEndpoint || !props.AccountKey) {
53
+ throw new Error('Invalid connection string');
54
+ }
55
+ return {
56
+ endpoint: props.AccountEndpoint,
57
+ accountKey: props.AccountKey
58
+ };
59
+ }