@azure/data-tables 12.1.2-alpha.20211012.1 → 12.2.0-alpha.20211019.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Release History
2
2
 
3
+ ## 12.2.0 (Unreleased)
4
+
5
+ ### Features Added
6
+ - Take `continuationToken` as a `PageSetting` and expose it in the page when listing entities `byPage`. [#18179](https://github.com/Azure/azure-sdk-for-js/pull/18179)
7
+
8
+ ### Breaking Changes
9
+
10
+ ### Bugs Fixed
11
+ - Document usage of SDK with Azurite. [#18211](https://github.com/Azure/azure-sdk-for-js/pull/18211)
12
+ - Issue #17407 - Correctly handle etag in select filter. [#18211](https://github.com/Azure/azure-sdk-for-js/pull/18211)
13
+ - Issue #18079 - Correctly handle creating entities with properties containing empty strings "". Fixes Insert throws "Unknown EDM type object" error with property value { value: "", type: "String" }. [#18211](https://github.com/Azure/azure-sdk-for-js/pull/18211)
14
+ - Issue #18148 - Correctly deserialize Decimal numbers checking for isSafeInteger. Fixes listEntities always returns an Int32 type for a value of "1.23456789012346e+24". [#18211](https://github.com/Azure/azure-sdk-for-js/pull/18211)
15
+
16
+ ### Other Changes
17
+
3
18
  ## 12.1.2 (2021-09-07)
4
19
 
5
20
  ### Bugs Fixed
package/README.md CHANGED
@@ -351,6 +351,38 @@ async function main() {
351
351
  main();
352
352
  ```
353
353
 
354
+ ## Azurite and Storage Emulator
355
+
356
+ The Azure Tables Client SDK also works with Azurite, an Azure Storage and Tables API compatible server emulator. Please refer to the ([Azurite repository](https://github.com/Azure/Azurite#azurite-v3)) on how to get started using it.
357
+
358
+ ### Connecting to Azurite with Connection String shortcut
359
+ The easiest way to connect to Azurite from your application is to configure a connection string that references the shortcut `UseDevelopmentStorage=true`. The shortcut is equivalent to the full connection string for the emulator, which specifies the account name, the account key, and the emulator endpoints for each of the Azure Storage services: ([see more](https://github.com/Azure/Azurite#http-connection-strings)). Using this shortcut, the Azure Tables Client SDK would setup the default connection string and `allowInsecureConnection` in the client options.
360
+
361
+ ```typescript
362
+ import { TableClient } from "@azure/data-tables"
363
+
364
+ const connectionString = "UseDevelopmentStorage=true";
365
+ const client = TableClient.fromConnectionString(connectionString, "myTable");
366
+ ```
367
+
368
+ ### Connecting to Azurite without Connection String shortcut
369
+ You can connect to azurite manually without using the connection string shortcut by specifying the service URL and `AzureNamedKeyCredential` or a custom connection string. However, `allowInsecureConnection` will need to be set manually in case Azurite runs in an `http` endpoint.
370
+
371
+ ```typescript
372
+ import { TableClient, AzureNamedKeyCredential } from "@azure/data-tables"
373
+
374
+ const client = new TableClient(
375
+ "<Azurite-http-table-endpoint>",
376
+ "myTable",
377
+ new AzureNamedKeyCredential(
378
+ "<Azurite-account-name>",
379
+ "<Azurite-account-key>"
380
+ ),
381
+ { allowInsecureConnection: true }
382
+ );
383
+ ```
384
+
385
+
354
386
  ## Troubleshooting
355
387
 
356
388
  ### General
package/dist/index.js CHANGED
@@ -3068,7 +3068,7 @@ class GeneratedClientContext extends coreClient.ServiceClient {
3068
3068
  const defaults = {
3069
3069
  requestContentType: "application/json; charset=utf-8"
3070
3070
  };
3071
- const packageDetails = `azsdk-js-data-tables/12.1.2`;
3071
+ const packageDetails = `azsdk-js-data-tables/12.2.0`;
3072
3072
  const userAgentPrefix = options.userAgentOptions && options.userAgentOptions.userAgentPrefix
3073
3073
  ? `${options.userAgentOptions.userAgentPrefix} ${packageDetails}`
3074
3074
  : `${packageDetails}`;
@@ -4051,11 +4051,16 @@ function prepateTransactionPipeline(pipeline, bodyParts, changesetId, isCosmos)
4051
4051
  // Licensed under the MIT license.
4052
4052
  /**
4053
4053
  * Encodes a byte array in base64 format.
4054
- * @param value - The Uint8Aray to encode
4054
+ * @param value - The Uint8Aray or string to encode
4055
4055
  */
4056
4056
  function base64Encode(value) {
4057
- const bufferValue = value instanceof Buffer ? value : Buffer.from(value.buffer);
4058
- return bufferValue.toString("base64");
4057
+ if (value instanceof Uint8Array) {
4058
+ const bufferValue = value instanceof Buffer ? value : Buffer.from(value.buffer);
4059
+ return bufferValue.toString("base64");
4060
+ }
4061
+ else {
4062
+ return Buffer.from(value).toString("base64");
4063
+ }
4059
4064
  }
4060
4065
  /**
4061
4066
  * Decodes a base64 string into a byte array.
@@ -4129,7 +4134,7 @@ function serializeObject(obj) {
4129
4134
  return serializedValue;
4130
4135
  }
4131
4136
  function getSerializedValue(value) {
4132
- if (typeof value === "object" && (value === null || value === void 0 ? void 0 : value.value) && (value === null || value === void 0 ? void 0 : value.type)) {
4137
+ if (typeof value === "object" && (value === null || value === void 0 ? void 0 : value.value) !== undefined && (value === null || value === void 0 ? void 0 : value.type) !== undefined) {
4133
4138
  return serializeObject(value);
4134
4139
  }
4135
4140
  else {
@@ -4220,7 +4225,7 @@ function inferTypedObject(propertyName, value) {
4220
4225
  */
4221
4226
  function getTypedNumber(value) {
4222
4227
  const valueStr = String(value);
4223
- if (Number.isInteger(value)) {
4228
+ if (Number.isSafeInteger(value)) {
4224
4229
  return { value: valueStr, type: "Int32" };
4225
4230
  }
4226
4231
  else {
@@ -4264,6 +4269,19 @@ function deserializeSignedIdentifier(signedIdentifiers) {
4264
4269
  };
4265
4270
  });
4266
4271
  }
4272
+ function serializeQueryOptions(query) {
4273
+ const { select } = query, queryOptions = tslib.__rest(query, ["select"]);
4274
+ const mappedQuery = Object.assign({}, queryOptions);
4275
+ // Properties that are always returned by the service but are not allowed in select
4276
+ const excludeFromSelect = ["etag", "odata.etag"];
4277
+ if (select) {
4278
+ mappedQuery.select = select
4279
+ .filter((p) => !excludeFromSelect.includes(p))
4280
+ .map(translatePropertyNameForSerialization)
4281
+ .join(",");
4282
+ }
4283
+ return mappedQuery;
4284
+ }
4267
4285
 
4268
4286
  // Copyright (c) Microsoft Corporation.
4269
4287
  // This is used as a workaround to be able to stub generateUuid
@@ -4274,6 +4292,33 @@ class Uuid {
4274
4292
  }
4275
4293
  }
4276
4294
 
4295
+ // Copyright (c) Microsoft Corporation.
4296
+ /**
4297
+ * Encodes the nextPartitionKey and nextRowKey into a single continuation token
4298
+ */
4299
+ function encodeContinuationToken(nextPartitionKey = "", nextRowKey = "") {
4300
+ if (!nextPartitionKey && !nextRowKey) {
4301
+ return undefined;
4302
+ }
4303
+ const continuationToken = JSON.stringify({
4304
+ nextPartitionKey,
4305
+ nextRowKey
4306
+ });
4307
+ return base64Encode(continuationToken);
4308
+ }
4309
+ /**
4310
+ * Decodes a continuationToken into an object containing a nextPartitionKey and nextRowKey
4311
+ */
4312
+ function decodeContinuationToken(encodedToken) {
4313
+ const decodedToken = base64Decode(encodedToken);
4314
+ let tokenStr = "";
4315
+ for (const byte of decodedToken) {
4316
+ tokenStr += String.fromCharCode(byte);
4317
+ }
4318
+ const continuationToken = JSON.parse(tokenStr);
4319
+ return continuationToken;
4320
+ }
4321
+
4277
4322
  // Copyright (c) Microsoft Corporation.
4278
4323
  /**
4279
4324
  * A TableClient represents a Client to the Azure Tables service allowing you
@@ -4440,7 +4485,7 @@ class TableClient {
4440
4485
  }
4441
4486
  try {
4442
4487
  const _a = updatedOptions || {}, { disableTypeConversion, queryOptions } = _a, getEntityOptions = tslib.__rest(_a, ["disableTypeConversion", "queryOptions"]);
4443
- await this.table.queryEntitiesWithPartitionAndRowKey(this.tableName, partitionKey, rowKey, Object.assign(Object.assign({}, getEntityOptions), { queryOptions: this.convertQueryOptions(queryOptions || {}), onResponse }));
4488
+ await this.table.queryEntitiesWithPartitionAndRowKey(this.tableName, partitionKey, rowKey, Object.assign(Object.assign({}, getEntityOptions), { queryOptions: serializeQueryOptions(queryOptions || {}), onResponse }));
4444
4489
  const tableEntity = deserialize(parsedBody, disableTypeConversion !== null && disableTypeConversion !== void 0 ? disableTypeConversion : false);
4445
4490
  return tableEntity;
4446
4491
  }
@@ -4496,6 +4541,9 @@ class TableClient {
4496
4541
  },
4497
4542
  byPage: (settings) => {
4498
4543
  const pageOptions = Object.assign(Object.assign({}, options), { queryOptions: Object.assign(Object.assign({}, options.queryOptions), { top: settings === null || settings === void 0 ? void 0 : settings.maxPageSize }) });
4544
+ if (settings === null || settings === void 0 ? void 0 : settings.continuationToken) {
4545
+ pageOptions.continuationToken = settings.continuationToken;
4546
+ }
4499
4547
  return this.listEntitiesPage(tableName, pageOptions);
4500
4548
  }
4501
4549
  };
@@ -4504,11 +4552,9 @@ class TableClient {
4504
4552
  return tslib.__asyncGenerator(this, arguments, function* listEntitiesAll_1() {
4505
4553
  var e_1, _a;
4506
4554
  const firstPage = yield tslib.__await(this._listEntities(tableName, options));
4507
- const { nextPartitionKey, nextRowKey } = firstPage;
4508
4555
  yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(firstPage)));
4509
- if (nextRowKey && nextPartitionKey) {
4510
- const optionsWithContinuation = Object.assign(Object.assign({}, options), { nextPartitionKey,
4511
- nextRowKey });
4556
+ if (firstPage.continuationToken) {
4557
+ const optionsWithContinuation = Object.assign(Object.assign({}, options), { continuationToken: firstPage.continuationToken });
4512
4558
  try {
4513
4559
  for (var _b = tslib.__asyncValues(this.listEntitiesPage(tableName, optionsWithContinuation)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) {
4514
4560
  const page = _c.value;
@@ -4531,8 +4577,8 @@ class TableClient {
4531
4577
  try {
4532
4578
  let result = yield tslib.__await(this._listEntities(tableName, updatedOptions));
4533
4579
  yield yield tslib.__await(result);
4534
- while (result.nextPartitionKey && result.nextRowKey) {
4535
- const optionsWithContinuation = Object.assign(Object.assign({}, updatedOptions), { nextPartitionKey: result.nextPartitionKey, nextRowKey: result.nextRowKey });
4580
+ while (result.continuationToken) {
4581
+ const optionsWithContinuation = Object.assign(Object.assign({}, updatedOptions), { continuationToken: result.continuationToken });
4536
4582
  result = yield tslib.__await(this._listEntities(tableName, optionsWithContinuation));
4537
4583
  yield yield tslib.__await(result);
4538
4584
  }
@@ -4551,13 +4597,23 @@ class TableClient {
4551
4597
  }
4552
4598
  async _listEntities(tableName, options = {}) {
4553
4599
  const { disableTypeConversion = false } = options;
4554
- const queryOptions = this.convertQueryOptions(options.queryOptions || {});
4555
- const { xMsContinuationNextPartitionKey: nextPartitionKey, xMsContinuationNextRowKey: nextRowKey, value } = await this.table.queryEntities(tableName, Object.assign(Object.assign({}, options), { queryOptions }));
4600
+ const queryOptions = serializeQueryOptions(options.queryOptions || {});
4601
+ const listEntitiesOptions = Object.assign(Object.assign({}, options), { queryOptions });
4602
+ // If a continuation token is used, decode it and set the next row and partition key
4603
+ if (options.continuationToken) {
4604
+ const continuationToken = decodeContinuationToken(options.continuationToken);
4605
+ listEntitiesOptions.nextRowKey = continuationToken.nextRowKey;
4606
+ listEntitiesOptions.nextPartitionKey = continuationToken.nextPartitionKey;
4607
+ }
4608
+ const { xMsContinuationNextPartitionKey: nextPartitionKey, xMsContinuationNextRowKey: nextRowKey, value } = await this.table.queryEntities(tableName, listEntitiesOptions);
4556
4609
  const tableEntities = deserializeObjectsArray(value !== null && value !== void 0 ? value : [], disableTypeConversion);
4557
- return Object.assign([...tableEntities], {
4558
- nextPartitionKey,
4559
- nextRowKey
4610
+ // Encode nextPartitionKey and nextRowKey as a single continuation token and add it as a
4611
+ // property to the page.
4612
+ const continuationToken = encodeContinuationToken(nextPartitionKey, nextRowKey);
4613
+ const page = Object.assign([...tableEntities], {
4614
+ continuationToken
4560
4615
  });
4616
+ return page;
4561
4617
  }
4562
4618
  /**
4563
4619
  * Insert entity in the table.
@@ -4866,14 +4922,6 @@ class TableClient {
4866
4922
  }
4867
4923
  return this.transactionClient.submitTransaction();
4868
4924
  }
4869
- convertQueryOptions(query) {
4870
- const { select } = query, queryOptions = tslib.__rest(query, ["select"]);
4871
- const mappedQuery = Object.assign({}, queryOptions);
4872
- if (select) {
4873
- mappedQuery.select = select.join(",");
4874
- }
4875
- return mappedQuery;
4876
- }
4877
4925
  /**
4878
4926
  *
4879
4927
  * Creates an instance of TableClient from connection string.