[Tables] Call onResponse when handling TalbeAlreadyExists response (#18914)
* Call onResponse when handling TalbeAlreadyExists response * Fix format and lint
This commit is contained in:
Родитель
b45fa3efdf
Коммит
fbb3a3ca6a
|
@ -17,6 +17,7 @@ Azure Cosmos DB provides a Table API for applications that are written for Azure
|
|||
- The Azure Tables client library can seamlessly target either Azure table storage or Azure Cosmos DB table service endpoints with no code changes.
|
||||
|
||||
Key links:
|
||||
|
||||
- [Source code](https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/tables/data-tables/)
|
||||
- [Package (NPM)](https://www.npmjs.com/package/@azure/data-tables)
|
||||
- [API reference documentation](https://docs.microsoft.com/javascript/api/@azure/data-tables)
|
||||
|
@ -123,6 +124,7 @@ const { TableServiceClient, AzureNamedKeyCredential } = require("@azure/data-tab
|
|||
The `TableServiceClient` requires a URL to the table service and an access credential. It also optionally accepts some settings in the `options` parameter.
|
||||
|
||||
#### `TableServiceClient` with TokenCredential (AAD)
|
||||
|
||||
Azure Tables provides integration with Azure Active Directory (Azure AD) for identity-based authentication of requests
|
||||
to the Table service when targeting a Storage endpoint. With Azure AD, you can use role-based access control (RBAC) to
|
||||
grant access to your Azure Table resources to users, groups, or applications.
|
||||
|
@ -202,6 +204,30 @@ main();
|
|||
#### Create a new table
|
||||
|
||||
You can create a table through a `TableServiceClient` instance calling the `createTable` function. This function takes the name of the table to create as a parameter.
|
||||
Note that `createTable` won't throw an error when the table already exists.
|
||||
|
||||
```javascript
|
||||
const { TableServiceClient, AzureNamedKeyCredential } = require("@azure/data-tables");
|
||||
|
||||
const account = "<account>";
|
||||
const accountKey = "<accountkey>";
|
||||
|
||||
const credential = new AzureNamedKeyCredential(account, accountKey);
|
||||
const serviceClient = new TableServiceClient(
|
||||
`https://${account}.table.core.windows.net`,
|
||||
credential
|
||||
);
|
||||
|
||||
async function main() {
|
||||
const tableName = `newtable`;
|
||||
// If the table 'newTable' already exists, createTable doesn' throw
|
||||
await serviceClient.createTable(tableName);
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
Here is a sample that demonstrates how to test if the table already exists when attempting to create it:
|
||||
|
||||
```javascript
|
||||
const { TableServiceClient, AzureNamedKeyCredential } = require("@azure/data-tables");
|
||||
|
@ -217,7 +243,13 @@ const serviceClient = new TableServiceClient(
|
|||
|
||||
async function main() {
|
||||
const tableName = `newtable${new Date().getTime()}`;
|
||||
await serviceClient.createTable(tableName);
|
||||
await serviceClient.createTable(tableName, {
|
||||
onResponse: (response) => {
|
||||
if (response.status === 409) {
|
||||
console.log(`Table ${tableName} already exists`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
|
@ -247,6 +279,7 @@ const client = new TableClient(`https://${account}.table.core.windows.net`, tabl
|
|||
```
|
||||
|
||||
#### `TableClient` with `TokenCredential` (Azure Active Directory)
|
||||
|
||||
Azure Tables provides integration with Azure Active Directory (Azure AD) for identity-based authentication of requests
|
||||
to the Table service when targeting a Storage endpoint. With Azure AD, you can use role-based access control (RBAC) to
|
||||
grant access to your Azure Table resources to users, groups, or applications.
|
||||
|
@ -356,33 +389,31 @@ main();
|
|||
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.
|
||||
|
||||
### Connecting to Azurite with Connection String shortcut
|
||||
|
||||
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.
|
||||
|
||||
```typescript
|
||||
import { TableClient } from "@azure/data-tables"
|
||||
import { TableClient } from "@azure/data-tables";
|
||||
|
||||
const connectionString = "UseDevelopmentStorage=true";
|
||||
const client = TableClient.fromConnectionString(connectionString, "myTable");
|
||||
```
|
||||
|
||||
### Connecting to Azurite without Connection String shortcut
|
||||
|
||||
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.
|
||||
|
||||
```typescript
|
||||
import { TableClient, AzureNamedKeyCredential } from "@azure/data-tables"
|
||||
import { TableClient, AzureNamedKeyCredential } from "@azure/data-tables";
|
||||
|
||||
const client = new TableClient(
|
||||
"<Azurite-http-table-endpoint>",
|
||||
"myTable",
|
||||
new AzureNamedKeyCredential(
|
||||
"<Azurite-account-name>",
|
||||
"<Azurite-account-key>"
|
||||
),
|
||||
new AzureNamedKeyCredential("<Azurite-account-name>", "<Azurite-account-key>"),
|
||||
{ allowInsecureConnection: true }
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### General
|
||||
|
|
|
@ -2,38 +2,38 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
TableEntity,
|
||||
ListTableEntitiesOptions,
|
||||
GetTableEntityResponse,
|
||||
UpdateTableEntityOptions,
|
||||
DeleteTableEntityOptions,
|
||||
GetTableEntityOptions,
|
||||
UpdateMode,
|
||||
CreateTableEntityResponse,
|
||||
TableEntityQueryOptions,
|
||||
TableServiceClientOptions as TableClientOptions,
|
||||
TableEntityResult,
|
||||
TransactionAction,
|
||||
TableTransactionResponse,
|
||||
SignedIdentifier,
|
||||
DeleteTableEntityOptions,
|
||||
GetAccessPolicyResponse,
|
||||
TableEntityResultPage
|
||||
GetTableEntityOptions,
|
||||
GetTableEntityResponse,
|
||||
ListTableEntitiesOptions,
|
||||
SignedIdentifier,
|
||||
TableServiceClientOptions as TableClientOptions,
|
||||
TableEntity,
|
||||
TableEntityQueryOptions,
|
||||
TableEntityResult,
|
||||
TableEntityResultPage,
|
||||
TableTransactionResponse,
|
||||
TransactionAction,
|
||||
UpdateMode,
|
||||
UpdateTableEntityOptions
|
||||
} from "./models";
|
||||
import {
|
||||
UpdateEntityResponse,
|
||||
UpsertEntityResponse,
|
||||
DeleteTableEntityResponse,
|
||||
SetAccessPolicyResponse
|
||||
SetAccessPolicyResponse,
|
||||
UpdateEntityResponse,
|
||||
UpsertEntityResponse
|
||||
} from "./generatedModels";
|
||||
import { TableQueryEntitiesOptionalParams } from "./generated/models";
|
||||
import { getClientParamsFromConnectionString } from "./utils/connectionString";
|
||||
import {
|
||||
isNamedKeyCredential,
|
||||
isSASCredential,
|
||||
isTokenCredential,
|
||||
NamedKeyCredential,
|
||||
SASCredential,
|
||||
TokenCredential
|
||||
TokenCredential,
|
||||
isNamedKeyCredential,
|
||||
isSASCredential,
|
||||
isTokenCredential
|
||||
} from "@azure/core-auth";
|
||||
import { tablesNamedKeyCredentialPolicy } from "./tablesNamedCredentialPolicy";
|
||||
import "@azure/core-paging";
|
||||
|
@ -68,6 +68,7 @@ import { isCosmosEndpoint } from "./utils/isCosmosEndpoint";
|
|||
import { cosmosPatchPolicy } from "./cosmosPathPolicy";
|
||||
import { decodeContinuationToken, encodeContinuationToken } from "./utils/continuationToken";
|
||||
import { escapeQuotes } from "./odata";
|
||||
import { handleTableAlreadyExists } from "./utils/errorHelpers";
|
||||
|
||||
/**
|
||||
* A TableClient represents a Client to the Azure Tables service allowing you
|
||||
|
@ -324,7 +325,7 @@ export class TableClient {
|
|||
* // calling create table will create the table used
|
||||
* // to instantiate the TableClient.
|
||||
* // Note: If the table already
|
||||
* // exists this function doesn't fail.
|
||||
* // exists this function doesn't throw.
|
||||
* await client.createTable();
|
||||
* ```
|
||||
*/
|
||||
|
@ -334,12 +335,7 @@ export class TableClient {
|
|||
try {
|
||||
await this.table.create({ name: this.tableName }, updatedOptions);
|
||||
} catch (e) {
|
||||
if (e.statusCode === 409) {
|
||||
logger.info("TableClient-createTable: Table Already Exists");
|
||||
} else {
|
||||
span.setStatus({ code: SpanStatusCode.ERROR, message: e.message });
|
||||
throw e;
|
||||
}
|
||||
handleTableAlreadyExists(e, { ...updatedOptions, span, logger, tableName: this.tableName });
|
||||
} finally {
|
||||
span.end();
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
PipelineResponse,
|
||||
PipelineRequest,
|
||||
SendRequest,
|
||||
PipelinePolicy,
|
||||
PipelineRequest,
|
||||
PipelineResponse,
|
||||
SendRequest,
|
||||
createHttpHeaders,
|
||||
createPipelineRequest
|
||||
} from "@azure/core-rest-pipeline";
|
||||
|
|
|
@ -5,24 +5,24 @@ import { GeneratedClient } from "./generated/generatedClient";
|
|||
import { Service, Table } from "./generated";
|
||||
import {
|
||||
ListTableItemsOptions,
|
||||
TableServiceClientOptions,
|
||||
TableItem,
|
||||
TableQueryOptions,
|
||||
TableItem
|
||||
TableServiceClientOptions
|
||||
} from "./models";
|
||||
import {
|
||||
GetStatisticsResponse,
|
||||
GetPropertiesResponse,
|
||||
SetPropertiesOptions,
|
||||
GetStatisticsResponse,
|
||||
ServiceProperties,
|
||||
SetPropertiesOptions,
|
||||
SetPropertiesResponse
|
||||
} from "./generatedModels";
|
||||
import { getClientParamsFromConnectionString } from "./utils/connectionString";
|
||||
import {
|
||||
isNamedKeyCredential,
|
||||
NamedKeyCredential,
|
||||
SASCredential,
|
||||
isSASCredential,
|
||||
TokenCredential,
|
||||
isNamedKeyCredential,
|
||||
isSASCredential,
|
||||
isTokenCredential
|
||||
} from "@azure/core-auth";
|
||||
import "@azure/core-paging";
|
||||
|
@ -38,6 +38,7 @@ import { Pipeline } from "@azure/core-rest-pipeline";
|
|||
import { isCredential } from "./utils/isCredential";
|
||||
import { tablesSASTokenPolicy } from "./tablesSASTokenPolicy";
|
||||
import { TableItemResultPage } from "./models";
|
||||
import { handleTableAlreadyExists } from "./utils/errorHelpers";
|
||||
|
||||
/**
|
||||
* A TableServiceClient represents a Client to the Azure Tables service allowing you
|
||||
|
@ -246,17 +247,9 @@ export class TableServiceClient {
|
|||
public async createTable(name: string, options: OperationOptions = {}): Promise<void> {
|
||||
const { span, updatedOptions } = createSpan("TableServiceClient-createTable", options);
|
||||
try {
|
||||
await this.table.create(
|
||||
{ name },
|
||||
{ ...updatedOptions, responsePreference: "return-content" }
|
||||
);
|
||||
await this.table.create({ name }, { ...updatedOptions });
|
||||
} catch (e) {
|
||||
if (e.statusCode === 409) {
|
||||
logger.info("TableServiceClient-createTable: Table Already Exists");
|
||||
} else {
|
||||
span.setStatus({ code: SpanStatusCode.ERROR, message: e.message });
|
||||
throw e;
|
||||
}
|
||||
handleTableAlreadyExists(e, { ...updatedOptions, span, logger, tableName: name });
|
||||
} finally {
|
||||
span.end();
|
||||
}
|
||||
|
|
|
@ -2,36 +2,36 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
createHttpHeaders,
|
||||
createPipelineRequest,
|
||||
Pipeline,
|
||||
PipelineRequest,
|
||||
PipelineResponse,
|
||||
RestError,
|
||||
Pipeline,
|
||||
PipelineRequest
|
||||
createHttpHeaders,
|
||||
createPipelineRequest
|
||||
} from "@azure/core-rest-pipeline";
|
||||
import {
|
||||
ServiceClient,
|
||||
OperationOptions,
|
||||
ServiceClient,
|
||||
ServiceClientOptions,
|
||||
serializationPolicy,
|
||||
serializationPolicyName,
|
||||
ServiceClientOptions
|
||||
serializationPolicyName
|
||||
} from "@azure/core-client";
|
||||
import {
|
||||
DeleteTableEntityOptions,
|
||||
TableEntity,
|
||||
UpdateMode,
|
||||
UpdateTableEntityOptions,
|
||||
TableTransactionResponse,
|
||||
TableTransactionEntityResponse,
|
||||
TransactionAction
|
||||
TableTransactionResponse,
|
||||
TransactionAction,
|
||||
UpdateMode,
|
||||
UpdateTableEntityOptions
|
||||
} from "./models";
|
||||
import {
|
||||
isNamedKeyCredential,
|
||||
isSASCredential,
|
||||
isTokenCredential,
|
||||
NamedKeyCredential,
|
||||
SASCredential,
|
||||
TokenCredential
|
||||
TokenCredential,
|
||||
isNamedKeyCredential,
|
||||
isSASCredential,
|
||||
isTokenCredential
|
||||
} from "@azure/core-auth";
|
||||
import { getAuthorizationHeader } from "./tablesNamedCredentialPolicy";
|
||||
import { TableClientLike } from "./utils/internalModels";
|
||||
|
@ -40,14 +40,14 @@ import { SpanStatusCode } from "@azure/core-tracing";
|
|||
import { TableServiceErrorOdataError } from "./generated";
|
||||
import { getTransactionHeaders } from "./utils/transactionHeaders";
|
||||
import {
|
||||
getTransactionHttpRequestBody,
|
||||
getInitialTransactionBody
|
||||
getInitialTransactionBody,
|
||||
getTransactionHttpRequestBody
|
||||
} from "./utils/transactionHelpers";
|
||||
import { signURLWithSAS } from "./tablesSASTokenPolicy";
|
||||
import {
|
||||
transactionHeaderFilterPolicy,
|
||||
transactionRequestAssemblePolicy,
|
||||
transactionHeaderFilterPolicyName,
|
||||
transactionRequestAssemblePolicy,
|
||||
transactionRequestAssemblePolicyName
|
||||
} from "./TablePolicies";
|
||||
import { isCosmosEndpoint } from "./utils/isCosmosEndpoint";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { createClientLogger, AzureLogger } from "@azure/logger";
|
||||
import { AzureLogger, createClientLogger } from "@azure/logger";
|
||||
|
||||
/**
|
||||
* The \@azure/logger configuration for this package.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
import { TableGetAccessPolicyHeaders, TableInsertEntityHeaders } from "./generated/models";
|
||||
import { OperationOptions, CommonClientOptions } from "@azure/core-client";
|
||||
import { CommonClientOptions, OperationOptions } from "@azure/core-client";
|
||||
|
||||
/**
|
||||
* Represents the Create or Delete Entity operation to be included in a Transaction request
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
accountSasResourceTypesToString
|
||||
} from "./accountSasResourceTypes";
|
||||
import { accountSasServicesFromString, accountSasServicesToString } from "./accountSasServices";
|
||||
import { ipRangeToString, SasIPRange } from "./sasIPRange";
|
||||
import { SasIPRange, ipRangeToString } from "./sasIPRange";
|
||||
import { SasProtocol, SasQueryParameters } from "./sasQueryParameters";
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { isNamedKeyCredential, NamedKeyCredential } from "@azure/core-auth";
|
||||
import { NamedKeyCredential, isNamedKeyCredential } from "@azure/core-auth";
|
||||
import { AccountSasPermissions, accountSasPermissionsFromString } from "./accountSasPermissions";
|
||||
import {
|
||||
AccountSasServices,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { isNamedKeyCredential, NamedKeyCredential } from "@azure/core-auth";
|
||||
import { NamedKeyCredential, isNamedKeyCredential } from "@azure/core-auth";
|
||||
import { tableSasPermissionsFromString } from "./tableSasPermisions";
|
||||
import {
|
||||
generateTableSasQueryParameters,
|
||||
TableSasSignatureValues
|
||||
TableSasSignatureValues,
|
||||
generateTableSasQueryParameters
|
||||
} from "./tableSasSignatureValues";
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import { truncatedISO8061Date } from "../utils/truncateISO8061Date";
|
||||
import { UserDelegationKey } from "./models";
|
||||
import { ipRangeToString, SasIPRange } from "./sasIPRange";
|
||||
import { SasIPRange, ipRangeToString } from "./sasIPRange";
|
||||
|
||||
/**
|
||||
* Protocols for generated SAS.
|
||||
|
|
|
@ -11,7 +11,7 @@ import { NamedKeyCredential } from "@azure/core-auth";
|
|||
import { computeHMACSHA256 } from "../utils/computeHMACSHA256";
|
||||
import { SERVICE_VERSION } from "../utils/constants";
|
||||
import { truncatedISO8061Date } from "../utils/truncateISO8061Date";
|
||||
import { ipRangeToString, SasIPRange } from "./sasIPRange";
|
||||
import { SasIPRange, ipRangeToString } from "./sasIPRange";
|
||||
import { SasProtocol, SasQueryParameters } from "./sasQueryParameters";
|
||||
import { TableSasPermissions, tableSasPermissionsToString } from "./tableSasPermisions";
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
import { base64Encode, base64Decode } from "./utils/bufferSerializer";
|
||||
import { base64Decode, base64Encode } from "./utils/bufferSerializer";
|
||||
import { EdmTypes, SignedIdentifier, TableEntityQueryOptions } from "./models";
|
||||
import { truncatedISO8061Date } from "./utils/truncateISO8061Date";
|
||||
import {
|
||||
SignedIdentifier as GeneratedSignedIdentifier,
|
||||
QueryOptions as GeneratedQueryOptions
|
||||
QueryOptions as GeneratedQueryOptions,
|
||||
SignedIdentifier as GeneratedSignedIdentifier
|
||||
} from "./generated/models";
|
||||
|
||||
const propertyCaseMap: Map<string, string> = new Map<string, string>([
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
PipelineResponse,
|
||||
PipelinePolicy,
|
||||
PipelineRequest,
|
||||
SendRequest,
|
||||
PipelinePolicy
|
||||
PipelineResponse,
|
||||
SendRequest
|
||||
} from "@azure/core-rest-pipeline";
|
||||
import { NamedKeyCredential } from "@azure/core-auth";
|
||||
import { HeaderConstants } from "./utils/constants";
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
PipelineResponse,
|
||||
PipelinePolicy,
|
||||
PipelineRequest,
|
||||
SendRequest,
|
||||
PipelinePolicy
|
||||
PipelineResponse,
|
||||
SendRequest
|
||||
} from "@azure/core-rest-pipeline";
|
||||
import { SASCredential } from "@azure/core-auth";
|
||||
import { URL, URLSearchParams } from "./utils/url";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { base64Encode, base64Decode } from "./bufferSerializer";
|
||||
import { base64Decode, base64Encode } from "./bufferSerializer";
|
||||
|
||||
export interface ContinuationToken {
|
||||
nextPartitionKey: string;
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { OperationOptions, OperationRequest } from "@azure/core-client";
|
||||
import { PipelineResponse, RestError } from "@azure/core-rest-pipeline";
|
||||
import { SpanStatusCode } from "@azure/core-tracing";
|
||||
import { AzureLogger } from "@azure/logger";
|
||||
import { TableServiceError } from "../generated";
|
||||
|
||||
export type TableServiceErrorResponse = PipelineResponse & {
|
||||
/**
|
||||
* The parsed HTTP response headers.
|
||||
*/
|
||||
parsedHeaders?: Record<string, unknown>;
|
||||
/**
|
||||
* The response body as parsed JSON or XML.
|
||||
*/
|
||||
parsedBody: TableServiceError;
|
||||
/**
|
||||
* The request that generated the response.
|
||||
*/
|
||||
request: OperationRequest;
|
||||
};
|
||||
|
||||
export function handleTableAlreadyExists(
|
||||
error: unknown,
|
||||
options: OperationOptions & { tableName?: string; span?: any; logger?: AzureLogger } = {}
|
||||
): void {
|
||||
const responseError = getErrorResponse(error);
|
||||
if (
|
||||
responseError &&
|
||||
responseError.status === 409 &&
|
||||
responseError.parsedBody.odataError?.code === "TableAlreadyExists"
|
||||
) {
|
||||
options.logger?.info(`Table ${options.tableName} already Exists`);
|
||||
|
||||
if (options.onResponse) {
|
||||
options.onResponse(responseError, {});
|
||||
}
|
||||
} else {
|
||||
options?.span.setStatus({ code: SpanStatusCode.ERROR, message: (error as Error)?.message });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
function getErrorResponse(error: unknown): TableServiceErrorResponse | undefined {
|
||||
if (!isRestError(error)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const errorResponse: TableServiceErrorResponse = error.response as TableServiceErrorResponse;
|
||||
|
||||
if (!errorResponse || !isTableServiceErrorResponse(errorResponse.parsedBody)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return errorResponse;
|
||||
}
|
||||
|
||||
function isRestError(error: unknown): error is RestError {
|
||||
return (error as RestError).name === "RestError";
|
||||
}
|
||||
|
||||
function isTableServiceErrorResponse(
|
||||
errorResponseBody: any
|
||||
): errorResponseBody is TableServiceError {
|
||||
return Boolean(errorResponseBody?.odataError);
|
||||
}
|
|
@ -2,19 +2,19 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
TableServiceClientOptions,
|
||||
TableEntity,
|
||||
CreateTableEntityResponse,
|
||||
DeleteTableEntityOptions,
|
||||
GetTableEntityOptions,
|
||||
GetTableEntityResponse,
|
||||
ListTableEntitiesOptions,
|
||||
UpdateMode,
|
||||
UpdateTableEntityOptions,
|
||||
TableEntity,
|
||||
TableEntityResult,
|
||||
TableItem,
|
||||
TableServiceClientOptions,
|
||||
TableTransactionResponse,
|
||||
TransactionAction,
|
||||
TableTransactionResponse
|
||||
UpdateMode,
|
||||
UpdateTableEntityOptions
|
||||
} from "../models";
|
||||
import { Pipeline, PipelineRequest } from "@azure/core-rest-pipeline";
|
||||
import { NamedKeyCredential } from "@azure/core-auth";
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
isNamedKeyCredential,
|
||||
isSASCredential,
|
||||
isTokenCredential,
|
||||
NamedKeyCredential,
|
||||
SASCredential,
|
||||
TokenCredential
|
||||
TokenCredential,
|
||||
isNamedKeyCredential,
|
||||
isSASCredential,
|
||||
isTokenCredential
|
||||
} from "@azure/core-auth";
|
||||
|
||||
export function isCredential(
|
||||
|
|
|
@ -5,10 +5,10 @@ import { assert } from "chai";
|
|||
|
||||
import { Edm } from "../../src";
|
||||
import {
|
||||
serialize,
|
||||
deserialize,
|
||||
serializeSignedIdentifiers,
|
||||
deserializeSignedIdentifier
|
||||
deserializeSignedIdentifier,
|
||||
serialize,
|
||||
serializeSignedIdentifiers
|
||||
} from "../../src/serialization";
|
||||
import { isNode8 } from "@azure/test-utils";
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
import { Context } from "mocha";
|
||||
import {
|
||||
SendRequest,
|
||||
PipelineRequest,
|
||||
PipelineResponse,
|
||||
SendRequest,
|
||||
createHttpHeaders,
|
||||
createPipelineRequest
|
||||
} from "@azure/core-rest-pipeline";
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import { extractConnectionStringParts } from "../../src/utils/connectionString";
|
||||
import { Context } from "mocha";
|
||||
import { base64Encode, base64Decode } from "../../src/utils/bufferSerializer";
|
||||
import { base64Decode, base64Encode } from "../../src/utils/bufferSerializer";
|
||||
import { isNode } from "@azure/test-utils";
|
||||
import { assert } from "chai";
|
||||
import { ConnectionString } from "../../src/utils/internalModels";
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
import { TableClient } from "../../src";
|
||||
import { Context } from "mocha";
|
||||
import { record, Recorder, isPlaybackMode } from "@azure-tools/test-recorder";
|
||||
import { recordedEnvironmentSetup, createTableClient } from "./utils/recordedClient";
|
||||
import { Recorder, isPlaybackMode, record } from "@azure-tools/test-recorder";
|
||||
import { createTableClient, recordedEnvironmentSetup } from "./utils/recordedClient";
|
||||
import { isNode } from "@azure/test-utils";
|
||||
import { assert } from "chai";
|
||||
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { RestError, TableClient, TableServiceClient } from "../../src";
|
||||
import { Context } from "mocha";
|
||||
import { assert } from "chai";
|
||||
import { createTableClient, createTableServiceClient } from "./utils/recordedClient";
|
||||
import { createHttpHeaders } from "@azure/core-rest-pipeline";
|
||||
import { TableServiceErrorResponse } from "../../src/utils/errorHelpers";
|
||||
|
||||
describe("TableClient CreationHandling", () => {
|
||||
let client: TableClient;
|
||||
beforeEach(function(this: Context) {
|
||||
client = createTableClient("testTable");
|
||||
});
|
||||
|
||||
it("should not thorw if table already exists", async function() {
|
||||
// Mock core-client throwing on error to verify consistenty that don't throw the error
|
||||
client.pipeline.addPolicy({
|
||||
name: "TableAlreadyExists",
|
||||
sendRequest: async (req) => {
|
||||
const mockedResponse: TableServiceErrorResponse = {
|
||||
headers: createHttpHeaders(),
|
||||
request: req,
|
||||
status: 409,
|
||||
bodyAsText: "",
|
||||
parsedBody: {
|
||||
odataError: {
|
||||
code: "TableAlreadyExists"
|
||||
}
|
||||
}
|
||||
};
|
||||
throw new RestError("TableAlreadyExists", {
|
||||
statusCode: 409,
|
||||
response: mockedResponse
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
await client.createTable({
|
||||
onResponse: (response) => {
|
||||
assert.equal(response.status, 409);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should throw when 409 and not TableAlreadyExists", async function() {
|
||||
// Mock core-client throwing on error to verify consistenty that we surface the error
|
||||
client.pipeline.addPolicy({
|
||||
name: "Other409Error",
|
||||
sendRequest: async (req) => {
|
||||
const mockedResponse: TableServiceErrorResponse = {
|
||||
headers: createHttpHeaders(),
|
||||
request: req,
|
||||
status: 409,
|
||||
bodyAsText: "",
|
||||
parsedBody: { odataError: { code: "TableBeingDeleted" } }
|
||||
};
|
||||
throw new RestError("TableBeingDeleted", { statusCode: 409, response: mockedResponse });
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await client.createTable();
|
||||
assert.fail("Expected error");
|
||||
} catch (error) {
|
||||
assert.equal((error as RestError).statusCode, 409);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("TableServiceClient CreationHandling", () => {
|
||||
let client: TableServiceClient;
|
||||
beforeEach(function(this: Context) {
|
||||
client = createTableServiceClient();
|
||||
});
|
||||
|
||||
it("should not thorw if table already exists", async function() {
|
||||
const tableName = `tableExists`;
|
||||
// Mock core-client throwing on error to verify consistenty that don't throw the error
|
||||
client.pipeline.addPolicy({
|
||||
name: "TableAlreadyExists",
|
||||
sendRequest: async (req) => {
|
||||
const mockedResponse: TableServiceErrorResponse = {
|
||||
headers: createHttpHeaders(),
|
||||
request: req,
|
||||
status: 409,
|
||||
bodyAsText: "",
|
||||
parsedBody: {
|
||||
odataError: {
|
||||
code: "TableAlreadyExists"
|
||||
}
|
||||
}
|
||||
};
|
||||
throw new RestError("TableAlreadyExists", {
|
||||
statusCode: 409,
|
||||
response: mockedResponse
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
await client.createTable(tableName, {
|
||||
onResponse: (response) => {
|
||||
assert.equal(response.status, 409);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should throw when 409 and not TableAlreadyExists", async function() {
|
||||
const tableName = `throwError`;
|
||||
// Mock core-client throwing on error to verify consistenty that we surface the error
|
||||
client.pipeline.addPolicy({
|
||||
name: "Other409Error",
|
||||
sendRequest: async (req) => {
|
||||
const mockedResponse: TableServiceErrorResponse = {
|
||||
headers: createHttpHeaders(),
|
||||
request: req,
|
||||
status: 409,
|
||||
bodyAsText: "",
|
||||
parsedBody: {
|
||||
odataError: {
|
||||
code: "TableBeingDeleted"
|
||||
}
|
||||
}
|
||||
};
|
||||
throw new RestError("TableBeingDeleted", {
|
||||
statusCode: 409,
|
||||
response: mockedResponse
|
||||
});
|
||||
}
|
||||
});
|
||||
try {
|
||||
await client.createTable(tableName);
|
||||
assert.fail("Expected error");
|
||||
} catch (error) {
|
||||
assert.equal((error as RestError).statusCode, 409);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,11 +1,11 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { odata, TableClient, TableEntityResult, TransactionAction } from "../../src";
|
||||
import { TableClient, TableEntityResult, TransactionAction, odata } from "../../src";
|
||||
import { assert } from "chai";
|
||||
import { createTableClient, recordedEnvironmentSetup } from "./utils/recordedClient";
|
||||
import { isNode } from "@azure/test-utils";
|
||||
import { isLiveMode, record, Recorder } from "@azure-tools/test-recorder";
|
||||
import { Recorder, isLiveMode, record } from "@azure-tools/test-recorder";
|
||||
import { Context } from "mocha";
|
||||
|
||||
describe("SpecialCharacters", function() {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { TableClient, TableEntity, Edm, odata, TableEntityResult } from "../../src";
|
||||
import { Edm, TableClient, TableEntity, TableEntityResult, odata } from "../../src";
|
||||
import { Context } from "mocha";
|
||||
import { assert } from "chai";
|
||||
import { record, Recorder, isPlaybackMode, isLiveMode } from "@azure-tools/test-recorder";
|
||||
import { Recorder, isLiveMode, isPlaybackMode, record } from "@azure-tools/test-recorder";
|
||||
import {
|
||||
recordedEnvironmentSetup,
|
||||
CreateClientMode,
|
||||
createTableClient,
|
||||
CreateClientMode
|
||||
recordedEnvironmentSetup
|
||||
} from "./utils/recordedClient";
|
||||
import { isNode, isNode8 } from "@azure/test-utils";
|
||||
import { FullOperationResponse } from "@azure/core-client";
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
import { TableItem, TableItemResultPage, TableServiceClient } from "../../src";
|
||||
import { Context } from "mocha";
|
||||
import { record, Recorder, isPlaybackMode, isLiveMode } from "@azure-tools/test-recorder";
|
||||
import { Recorder, isLiveMode, isPlaybackMode, record } from "@azure-tools/test-recorder";
|
||||
import {
|
||||
recordedEnvironmentSetup,
|
||||
CreateClientMode,
|
||||
createTableServiceClient,
|
||||
CreateClientMode
|
||||
recordedEnvironmentSetup
|
||||
} from "./utils/recordedClient";
|
||||
import { isNode } from "@azure/test-utils";
|
||||
import { assert } from "chai";
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { TableClient, odata, TransactionAction, TableTransaction } from "../../src";
|
||||
import { TableClient, TableTransaction, TransactionAction, odata } from "../../src";
|
||||
import { Context } from "mocha";
|
||||
import { assert } from "chai";
|
||||
import { record, Recorder, isPlaybackMode, isLiveMode } from "@azure-tools/test-recorder";
|
||||
import { Recorder, isLiveMode, isPlaybackMode, record } from "@azure-tools/test-recorder";
|
||||
import {
|
||||
recordedEnvironmentSetup,
|
||||
CreateClientMode,
|
||||
createTableClient,
|
||||
CreateClientMode
|
||||
recordedEnvironmentSetup
|
||||
} from "./utils/recordedClient";
|
||||
import { isNode } from "@azure/test-utils";
|
||||
import { Uuid } from "../../src/utils/uuid";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { env, RecorderEnvironmentSetup } from "@azure-tools/test-recorder";
|
||||
import { RecorderEnvironmentSetup, env } from "@azure-tools/test-recorder";
|
||||
|
||||
import { ClientSecretCredential } from "@azure/identity";
|
||||
import { TableClient, TableServiceClient } from "../../../src";
|
||||
|
|
Загрузка…
Ссылка в новой задаче