New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@azure/core-lro

Package Overview
Dependencies
Maintainers
3
Versions
408
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@azure/core-lro - npm Package Compare versions

Comparing version 2.0.1-alpha.20210713.1 to 2.1.0-alpha.20210714.3

dist-esm/src/lroEngine/azureAsyncPolling.js

4

CHANGELOG.md
# Release History
## 2.0.1 (Unreleased)
## 2.1.0 (Unreleased)
### Features Added
- Provides a long-running operation engine.
### Breaking Changes

@@ -8,0 +10,0 @@

@@ -5,2 +5,3 @@ // Copyright (c) Microsoft Corporation.

export * from "./poller";
export * from "./lroEngine";
//# sourceMappingURL=index.js.map

@@ -5,2 +5,4 @@ 'use strict';

var logger$1 = require('@azure/logger');
// Copyright (c) Microsoft Corporation.

@@ -400,2 +402,337 @@ // Licensed under the MIT license.

// Copyright (c) Microsoft Corporation.
/**
* The `@azure/logger` configuration for this package.
* @internal
*/
const logger = logger$1.createClientLogger("core-lro");
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/**
* Detects where the continuation token is and returns it. Notice that azure-asyncoperation
* must be checked first before the other location headers because there are scenarios
* where both azure-asyncoperation and location could be present in the same response but
* azure-asyncoperation should be the one to use for polling.
*/
function getPollingUrl(rawResponse, defaultPath) {
var _a, _b, _c;
return ((_c = (_b = (_a = getAzureAsyncOperation(rawResponse)) !== null && _a !== void 0 ? _a : getLocation(rawResponse)) !== null && _b !== void 0 ? _b : getOperationLocation(rawResponse)) !== null && _c !== void 0 ? _c : defaultPath);
}
function getLocation(rawResponse) {
return rawResponse.headers["location"];
}
function getOperationLocation(rawResponse) {
return rawResponse.headers["operation-location"];
}
function getAzureAsyncOperation(rawResponse) {
return rawResponse.headers["azure-asyncoperation"];
}
function inferLroMode(requestPath, requestMethod, rawResponse) {
if (getAzureAsyncOperation(rawResponse) !== undefined) {
return {
mode: "AzureAsync",
resourceLocation: requestMethod === "PUT"
? requestPath
: requestMethod === "POST"
? getLocation(rawResponse)
: undefined
};
}
else if (getLocation(rawResponse) !== undefined ||
getOperationLocation(rawResponse) !== undefined) {
return {
mode: "Location"
};
}
else if (["PUT", "PATCH"].includes(requestMethod)) {
return {
mode: "Body"
};
}
return {};
}
class SimpleRestError extends Error {
constructor(message, statusCode) {
super(message);
this.name = "RestError";
this.statusCode = statusCode;
Object.setPrototypeOf(this, SimpleRestError.prototype);
}
}
function isUnexpectedInitialResponse(rawResponse) {
const code = rawResponse.statusCode;
if (![203, 204, 202, 201, 200, 500].includes(code)) {
throw new SimpleRestError(`Received unexpected HTTP status code ${code} in the initial response. This may indicate a server issue.`, code);
}
return false;
}
function isUnexpectedPollingResponse(rawResponse) {
const code = rawResponse.statusCode;
if (![202, 201, 200, 500].includes(code)) {
throw new SimpleRestError(`Received unexpected HTTP status code ${code} while polling. This may indicate a server issue.`, code);
}
return false;
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
const successStates = ["succeeded"];
const failureStates = ["failed", "canceled", "cancelled"];
// Copyright (c) Microsoft Corporation.
function getResponseStatus(rawResponse) {
var _a, _b;
const { status } = (_a = rawResponse.body) !== null && _a !== void 0 ? _a : {};
return (_b = status === null || status === void 0 ? void 0 : status.toLowerCase()) !== null && _b !== void 0 ? _b : "succeeded";
}
function isAzureAsyncPollingDone(rawResponse) {
const state = getResponseStatus(rawResponse);
if (isUnexpectedPollingResponse(rawResponse) || failureStates.includes(state)) {
throw new Error(`The long running operation has failed. The provisioning state: ${state}.`);
}
return successStates.includes(state);
}
/**
* Sends a request to the URI of the provisioned resource if needed.
*/
async function sendFinalRequest(lro, resourceLocation, lroResourceLocationConfig) {
switch (lroResourceLocationConfig) {
case "original-uri":
return lro.sendPollRequest(lro.requestPath);
case "azure-async-operation":
return undefined;
case "location":
default:
return lro.sendPollRequest(resourceLocation !== null && resourceLocation !== void 0 ? resourceLocation : lro.requestPath);
}
}
function processAzureAsyncOperationResult(lro, resourceLocation, lroResourceLocationConfig) {
return (response) => {
if (isAzureAsyncPollingDone(response.rawResponse)) {
if (resourceLocation === undefined) {
return Object.assign(Object.assign({}, response), { done: true });
}
else {
return Object.assign(Object.assign({}, response), { done: false, next: async () => {
const finalResponse = await sendFinalRequest(lro, resourceLocation, lroResourceLocationConfig);
return Object.assign(Object.assign({}, (finalResponse !== null && finalResponse !== void 0 ? finalResponse : response)), { done: true });
} });
}
}
return Object.assign(Object.assign({}, response), { done: false });
};
}
// Copyright (c) Microsoft Corporation.
function getProvisioningState(rawResponse) {
var _a, _b, _c;
const { properties, provisioningState } = (_a = rawResponse.body) !== null && _a !== void 0 ? _a : {};
const state = (_b = properties === null || properties === void 0 ? void 0 : properties.provisioningState) !== null && _b !== void 0 ? _b : provisioningState;
return (_c = state === null || state === void 0 ? void 0 : state.toLowerCase()) !== null && _c !== void 0 ? _c : "succeeded";
}
function isBodyPollingDone(rawResponse) {
const state = getProvisioningState(rawResponse);
if (isUnexpectedPollingResponse(rawResponse) || failureStates.includes(state)) {
throw new Error(`The long running operation has failed. The provisioning state: ${state}.`);
}
return successStates.includes(state);
}
/**
* Creates a polling strategy based on BodyPolling which uses the provisioning state
* from the result to determine the current operation state
*/
function processBodyPollingOperationResult(response) {
return Object.assign(Object.assign({}, response), { done: isBodyPollingDone(response.rawResponse) });
}
// Copyright (c) Microsoft Corporation.
function isLocationPollingDone(rawResponse) {
return !isUnexpectedPollingResponse(rawResponse) && rawResponse.statusCode !== 202;
}
function processLocationPollingOperationResult(response) {
return Object.assign(Object.assign({}, response), { done: isLocationPollingDone(response.rawResponse) });
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
function processPassthroughOperationResult(response) {
return Object.assign(Object.assign({}, response), { done: true });
}
// Copyright (c) Microsoft Corporation.
/**
* creates a stepping function that maps an LRO state to another.
*/
function createGetLroStatusFromResponse(lroPrimitives, config, lroResourceLocationConfig) {
switch (config.mode) {
case "AzureAsync": {
return processAzureAsyncOperationResult(lroPrimitives, config.resourceLocation, lroResourceLocationConfig);
}
case "Location": {
return processLocationPollingOperationResult;
}
case "Body": {
return processBodyPollingOperationResult;
}
default: {
return processPassthroughOperationResult;
}
}
}
/**
* Creates a polling operation.
*/
function createPoll(lroPrimitives) {
return async (path, pollerConfig, getLroStatusFromResponse) => {
const response = await lroPrimitives.sendPollRequest(path);
const retryAfter = response.rawResponse.headers["retry-after"];
if (retryAfter !== undefined) {
const retryAfterInMs = parseInt(retryAfter);
pollerConfig.intervalInMs = isNaN(retryAfterInMs)
? calculatePollingIntervalFromDate(new Date(retryAfter), pollerConfig.intervalInMs)
: retryAfterInMs;
}
return getLroStatusFromResponse(response);
};
}
function calculatePollingIntervalFromDate(retryAfterDate, defaultIntervalInMs) {
const timeNow = Math.floor(new Date().getTime());
const retryAfterTime = retryAfterDate.getTime();
if (timeNow < retryAfterTime) {
return retryAfterTime - timeNow;
}
return defaultIntervalInMs;
}
/**
* Creates a callback to be used to initialize the polling operation state.
* @param state - of the polling operation
* @param operationSpec - of the LRO
* @param callback - callback to be called when the operation is done
* @returns callback that initializes the state of the polling operation
*/
function createInitializeState(state, requestPath, requestMethod) {
return (response) => {
if (isUnexpectedInitialResponse(response.rawResponse))
;
state.initialRawResponse = response.rawResponse;
state.isStarted = true;
state.pollingURL = getPollingUrl(state.initialRawResponse, requestPath);
state.config = inferLroMode(requestPath, requestMethod, state.initialRawResponse);
/** short circuit polling if body polling is done in the initial request */
if (state.config.mode === undefined ||
(state.config.mode === "Body" && isBodyPollingDone(state.initialRawResponse))) {
state.result = response.flatResponse;
state.isCompleted = true;
}
logger.verbose(`LRO: initial state: ${JSON.stringify(state)}`);
return Boolean(state.isCompleted);
};
}
// Copyright (c) Microsoft Corporation.
class GenericPollOperation {
constructor(state, lro, lroResourceLocationConfig) {
this.state = state;
this.lro = lro;
this.lroResourceLocationConfig = lroResourceLocationConfig;
}
setPollerConfig(pollerConfig) {
this.pollerConfig = pollerConfig;
}
/**
* General update function for LROPoller, the general process is as follows
* 1. Check initial operation result to determine the strategy to use
* - Strategies: Location, Azure-AsyncOperation, Original Uri
* 2. Check if the operation result has a terminal state
* - Terminal state will be determined by each strategy
* 2.1 If it is terminal state Check if a final GET request is required, if so
* send final GET request and return result from operation. If no final GET
* is required, just return the result from operation.
* - Determining what to call for final request is responsibility of each strategy
* 2.2 If it is not terminal state, call the polling operation and go to step 1
* - Determining what to call for polling is responsibility of each strategy
* - Strategies will always use the latest URI for polling if provided otherwise
* the last known one
*/
async update(options) {
var _a, _b;
const state = this.state;
if (!state.isStarted) {
const initializeState = createInitializeState(state, this.lro.requestPath, this.lro.requestMethod);
const response = await this.lro.sendInitialRequest();
initializeState(response);
}
if (!state.isCompleted) {
if (!this.poll || !this.getLroStatusFromResponse) {
if (!state.config) {
throw new Error("Bad state: LRO mode is undefined. Please check if the serialized state is well-formed.");
}
this.getLroStatusFromResponse = createGetLroStatusFromResponse(this.lro, state.config, this.lroResourceLocationConfig);
this.poll = createPoll(this.lro);
}
if (!state.pollingURL) {
throw new Error("Bad state: polling URL is undefined. Please check if the serialized state is well-formed.");
}
const currentState = await this.poll(state.pollingURL, this.pollerConfig, this.getLroStatusFromResponse);
logger.verbose(`LRO: polling response: ${JSON.stringify(currentState.rawResponse)}`);
if (currentState.done) {
state.result = currentState.flatResponse;
state.isCompleted = true;
}
else {
this.poll = (_a = currentState.next) !== null && _a !== void 0 ? _a : this.poll;
state.pollingURL = getPollingUrl(currentState.rawResponse, state.pollingURL);
}
}
logger.verbose(`LRO: current state: ${JSON.stringify(state)}`);
(_b = options === null || options === void 0 ? void 0 : options.fireProgress) === null || _b === void 0 ? void 0 : _b.call(options, state);
return this;
}
async cancel() {
this.state.isCancelled = true;
return this;
}
/**
* Serializes the Poller operation.
*/
toString() {
return JSON.stringify({
state: this.state
});
}
}
// Copyright (c) Microsoft Corporation.
function deserializeState(serializedState) {
try {
return JSON.parse(serializedState).state;
}
catch (e) {
throw new Error(`LroEngine: Unable to deserialize state: ${serializedState}`);
}
}
/**
* The LRO Engine, a class that performs polling.
*/
class LroEngine extends Poller {
constructor(lro, options) {
const { intervalInMs = 2000, resumeFrom } = options || {};
const state = resumeFrom
? deserializeState(resumeFrom)
: {};
const operation = new GenericPollOperation(state, lro, options === null || options === void 0 ? void 0 : options.lroResourceLocationConfig);
super(operation);
this.config = { intervalInMs: intervalInMs };
operation.setPollerConfig(this.config);
}
/**
* The method used by the poller to wait before attempting to update its operation.
*/
delay() {
return new Promise((resolve) => setTimeout(() => resolve(), this.config.intervalInMs));
}
}
exports.LroEngine = LroEngine;
exports.Poller = Poller;

@@ -402,0 +739,0 @@ exports.PollerCancelledError = PollerCancelledError;

@@ -5,4 +5,4 @@ {

"sdk-type": "client",
"version": "2.0.1-alpha.20210713.1",
"description": "LRO Polling strategy for the Azure SDK in TypeScript",
"version": "2.1.0-alpha.20210714.3",
"description": "Isomorphic client library for supporting long-running operations in node.js and browser.",
"tags": [

@@ -95,4 +95,3 @@ "isomorphic",

"@azure/abort-controller": "^1.0.0",
"@azure/core-tracing": "1.0.0-preview.12",
"events": "^3.0.0",
"@azure/logger": "^1.0.0",
"tslib": "^2.2.0"

@@ -102,9 +101,6 @@ },

"@azure/core-http": "^2.0.0",
"@azure/core-rest-pipeline": "^1.1.0",
"@azure/eslint-plugin-azure-sdk": "^3.0.0-alpha",
"@azure/dev-tool": "^1.0.0-alpha",
"@microsoft/api-extractor": "7.7.11",
"@rollup/plugin-commonjs": "11.0.2",
"@rollup/plugin-multi-entry": "^3.0.0",
"@rollup/plugin-node-resolve": "^8.0.0",
"@rollup/plugin-replace": "^2.2.0",
"@types/chai": "^4.1.6",

@@ -134,6 +130,2 @@ "@types/mocha": "^7.0.2",

"rollup": "^1.16.3",
"rollup-plugin-shim": "^1.0.0",
"rollup-plugin-sourcemaps": "^0.4.2",
"rollup-plugin-terser": "^5.1.1",
"rollup-plugin-visualizer": "^4.0.4",
"ts-node": "^9.0.0",

@@ -140,0 +132,0 @@ "typescript": "~4.2.0",

@@ -12,2 +12,69 @@ import { AbortSignalLike } from '@azure/abort-controller';

/**
* Description of a long running operation.
*/
export declare interface LongRunningOperation<T> {
/**
* The request path.
*/
requestPath: string;
/**
* The HTTP request method.
*/
requestMethod: string;
/**
* A function that can be used to send initial request to the service.
*/
sendInitialRequest: () => Promise<LroResponse<T>>;
/**
* A function that can be used to poll for the current status of a long running operation.
*/
sendPollRequest: (path: string) => Promise<LroResponse<T>>;
}
/**
* The LRO Engine, a class that performs polling.
*/
export declare class LroEngine<TResult, TState extends PollOperationState<TResult>> extends Poller<TState, TResult> {
private config;
constructor(lro: LongRunningOperation<TResult>, options?: LroEngineOptions);
/**
* The method used by the poller to wait before attempting to update its operation.
*/
delay(): Promise<void>;
}
/**
* Options for the LRO poller.
*/
export declare interface LroEngineOptions {
/**
* Defines how much time the poller is going to wait before making a new request to the service.
*/
intervalInMs?: number;
/**
* A serialized poller which can be used to resume an existing paused Long-Running-Operation.
*/
resumeFrom?: string;
/**
* The potential location of the result of the LRO if specified by the LRO extension in the swagger.
*/
lroResourceLocationConfig?: LroResourceLocationConfig;
}
/**
* The potential location of the result of the LRO if specified by the LRO extension in the swagger.
*/
export declare type LroResourceLocationConfig = "azure-async-operation" | "location" | "original-uri";
/**
* The type of the response of a LRO.
*/
export declare interface LroResponse<T> {
/** The flattened response */
flatResponse: T;
/** The raw response */
rawResponse: RawResponse;
}
/**
* A class that represents the definition of a program that polls through consecutive requests

@@ -449,2 +516,16 @@ * until it reaches a state of completion.

/**
* Simple type of the raw response.
*/
export declare interface RawResponse {
/** The HTTP status code */
statusCode: number;
/** A HttpHeaders collection in the response represented as a simple JSON object where all header names have been normalized to be lower-case. */
headers: {
[headerName: string]: string;
};
/** The parsed response body */
body?: unknown;
}
export { }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc