@typespec/ts-http-runtime
Version:
Isomorphic client library for making HTTP requests in node.js and browser.
210 lines (209 loc) • 6.81 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var pipeline_exports = {};
__export(pipeline_exports, {
createEmptyPipeline: () => createEmptyPipeline
});
module.exports = __toCommonJS(pipeline_exports);
const ValidPhaseNames = /* @__PURE__ */ new Set(["Deserialize", "Serialize", "Retry", "Sign"]);
class HttpPipeline {
_policies = [];
_orderedPolicies;
constructor(policies) {
this._policies = policies?.slice(0) ?? [];
this._orderedPolicies = void 0;
}
addPolicy(policy, options = {}) {
if (options.phase && options.afterPhase) {
throw new Error("Policies inside a phase cannot specify afterPhase.");
}
if (options.phase && !ValidPhaseNames.has(options.phase)) {
throw new Error(`Invalid phase name: ${options.phase}`);
}
if (options.afterPhase && !ValidPhaseNames.has(options.afterPhase)) {
throw new Error(`Invalid afterPhase name: ${options.afterPhase}`);
}
this._policies.push({
policy,
options
});
this._orderedPolicies = void 0;
}
removePolicy(options) {
const removedPolicies = [];
this._policies = this._policies.filter((policyDescriptor) => {
if (options.name && policyDescriptor.policy.name === options.name || options.phase && policyDescriptor.options.phase === options.phase) {
removedPolicies.push(policyDescriptor.policy);
return false;
} else {
return true;
}
});
this._orderedPolicies = void 0;
return removedPolicies;
}
sendRequest(httpClient, request) {
const policies = this.getOrderedPolicies();
const pipeline = policies.reduceRight(
(next, policy) => {
return (req) => {
return policy.sendRequest(req, next);
};
},
(req) => httpClient.sendRequest(req)
);
return pipeline(request);
}
getOrderedPolicies() {
if (!this._orderedPolicies) {
this._orderedPolicies = this.orderPolicies();
}
return this._orderedPolicies;
}
clone() {
return new HttpPipeline(this._policies);
}
static create() {
return new HttpPipeline();
}
orderPolicies() {
const result = [];
const policyMap = /* @__PURE__ */ new Map();
function createPhase(name) {
return {
name,
policies: /* @__PURE__ */ new Set(),
hasRun: false,
hasAfterPolicies: false
};
}
const serializePhase = createPhase("Serialize");
const noPhase = createPhase("None");
const deserializePhase = createPhase("Deserialize");
const retryPhase = createPhase("Retry");
const signPhase = createPhase("Sign");
const orderedPhases = [serializePhase, noPhase, deserializePhase, retryPhase, signPhase];
function getPhase(phase) {
if (phase === "Retry") {
return retryPhase;
} else if (phase === "Serialize") {
return serializePhase;
} else if (phase === "Deserialize") {
return deserializePhase;
} else if (phase === "Sign") {
return signPhase;
} else {
return noPhase;
}
}
for (const descriptor of this._policies) {
const policy = descriptor.policy;
const options = descriptor.options;
const policyName = policy.name;
if (policyMap.has(policyName)) {
throw new Error("Duplicate policy names not allowed in pipeline");
}
const node = {
policy,
dependsOn: /* @__PURE__ */ new Set(),
dependants: /* @__PURE__ */ new Set()
};
if (options.afterPhase) {
node.afterPhase = getPhase(options.afterPhase);
node.afterPhase.hasAfterPolicies = true;
}
policyMap.set(policyName, node);
const phase = getPhase(options.phase);
phase.policies.add(node);
}
for (const descriptor of this._policies) {
const { policy, options } = descriptor;
const policyName = policy.name;
const node = policyMap.get(policyName);
if (!node) {
throw new Error(`Missing node for policy ${policyName}`);
}
if (options.afterPolicies) {
for (const afterPolicyName of options.afterPolicies) {
const afterNode = policyMap.get(afterPolicyName);
if (afterNode) {
node.dependsOn.add(afterNode);
afterNode.dependants.add(node);
}
}
}
if (options.beforePolicies) {
for (const beforePolicyName of options.beforePolicies) {
const beforeNode = policyMap.get(beforePolicyName);
if (beforeNode) {
beforeNode.dependsOn.add(node);
node.dependants.add(beforeNode);
}
}
}
}
function walkPhase(phase) {
phase.hasRun = true;
for (const node of phase.policies) {
if (node.afterPhase && (!node.afterPhase.hasRun || node.afterPhase.policies.size)) {
continue;
}
if (node.dependsOn.size === 0) {
result.push(node.policy);
for (const dependant of node.dependants) {
dependant.dependsOn.delete(node);
}
policyMap.delete(node.policy.name);
phase.policies.delete(node);
}
}
}
function walkPhases() {
for (const phase of orderedPhases) {
walkPhase(phase);
if (phase.policies.size > 0 && phase !== noPhase) {
if (!noPhase.hasRun) {
walkPhase(noPhase);
}
return;
}
if (phase.hasAfterPolicies) {
walkPhase(noPhase);
}
}
}
let iteration = 0;
while (policyMap.size > 0) {
iteration++;
const initialResultLength = result.length;
walkPhases();
if (result.length <= initialResultLength && iteration > 1) {
throw new Error("Cannot satisfy policy dependencies due to requirements cycle.");
}
}
return result;
}
}
function createEmptyPipeline() {
return HttpPipeline.create();
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
createEmptyPipeline
});
//# sourceMappingURL=pipeline.js.map