@pnp/sp-commonjs
Advanced tools
Comparing version 3.0.0-v3nightly.20220025 to 3.0.0-v3nightly.20220026
@@ -28,4 +28,11 @@ import { TimelinePipe } from "@pnp/core-commonjs"; | ||
} | ||
/** | ||
* Creates a batched version of the supplied base, meaning that all chained fluent operations from the new base are part of the batch | ||
* | ||
* @param base The base from which to initialize the batch | ||
* @param props Any properties used to initialize the batch functionality | ||
* @returns A tuple of [behavior used to assign objects to the batch, the execute function used to resolve the batch requests] | ||
*/ | ||
export declare function createBatch(base: ISPQueryable, props?: ISPBatchProps): [TimelinePipe, () => Promise<void>]; | ||
export {}; | ||
//# sourceMappingURL=batching.d.ts.map |
@@ -22,4 +22,18 @@ "use strict"; | ||
}; | ||
/** | ||
* Tracks on a batched instance that registration is complete (the child request has gotten to the send moment and the request is included in the batch) | ||
*/ | ||
const RegistrationCompleteSym = Symbol.for("batch_registration"); | ||
/** | ||
* Tracks on a batched instance that the child request timeline lifecycle is complete (called in child.dispose) | ||
*/ | ||
const RequestCompleteSym = Symbol.for("batch_request"); | ||
/** | ||
* Tracks on a batched instance the original set of observers which are returned once the batch is complete | ||
*/ | ||
const ObserverTrackerSym = Symbol.for("batch_original_observers"); | ||
/** | ||
* Special batch parsing behavior used to convert the batch response text into a set of Response objects for each request | ||
* @returns A parser behavior | ||
*/ | ||
function BatchParse() { | ||
@@ -31,2 +45,5 @@ return queryable_1.parseBinderWithErrorCheck(async (response) => { | ||
} | ||
/** | ||
* Internal class used to execute the batch request through the timeline lifecycle | ||
*/ | ||
class BatchQueryable extends spqueryable_js_1._SPQueryable { | ||
@@ -36,8 +53,14 @@ constructor(base, requestBaseUrl = base.toUrl().replace(/_api[\\|/].*$/i, "")) { | ||
this.requestBaseUrl = requestBaseUrl; | ||
// this will copy over the current observables from the web associated with this batch | ||
this.using(core_1.CopyFrom(base, "replace")); | ||
// this will copy over the current observables from the base associated with this batch | ||
// this will replace any other parsing present | ||
this.using(BatchParse()); | ||
this.using(core_1.CopyFrom(base, "replace"), BatchParse()); | ||
} | ||
} | ||
/** | ||
* Creates a batched version of the supplied base, meaning that all chained fluent operations from the new base are part of the batch | ||
* | ||
* @param base The base from which to initialize the batch | ||
* @param props Any properties used to initialize the batch functionality | ||
* @returns A tuple of [behavior used to assign objects to the batch, the execute function used to resolve the batch requests] | ||
*/ | ||
function createBatch(base, props) { | ||
@@ -138,3 +161,5 @@ const registrationPromises = []; | ||
} | ||
}), Promise.resolve(void (0))).then(() => Promise.all(completePromises).then(() => void (0))); | ||
}), Promise.resolve(void (0))).then(() => Promise.all(completePromises).then(() => { | ||
requests.length = 0; | ||
})); | ||
}; | ||
@@ -146,2 +171,4 @@ const register = (instance) => { | ||
} | ||
// we need to track the observers from the original instance and put them back later (see comment below) | ||
this[ObserverTrackerSym] = spqueryable_js_1.SPQueryable(this); | ||
// we need to ensure we wait to start execute until all our batch children hit the .send method to be fully registered | ||
@@ -158,2 +185,3 @@ registrationPromises.push(new Promise((resolve) => { | ||
let requestTuple; | ||
// this is the promise that user code will see | ||
const promise = new Promise((resolve, reject) => { | ||
@@ -163,2 +191,3 @@ requestTuple = [this, url.toString(), init, resolve, reject]; | ||
this.log(`[batch:${batchId}] (${(new Date()).getTime()}) Adding request ${init.method} ${url.toString()} to batch.`, 0); | ||
// add the request information into the batch | ||
requests.push(requestTuple); | ||
@@ -169,6 +198,21 @@ // we need to ensure we wait to resolve execute until all our batch children have fully completed their request timelines | ||
})); | ||
// indicate that registration of this request is complete | ||
this[RegistrationCompleteSym](); | ||
return promise; | ||
return promise.then((r) => { | ||
// there is a code path where you may invoke a batch, say on items.add, whose return | ||
// is an object like { data: any, item: IItem }. The expectation from v1 on is `item` in that object | ||
// is immediately usable to make additional queries. Without this step when that IItem instance is | ||
// created using "this.getById" within IITems.add all of the current observers of "this" are | ||
// linked to the IItem instance created (expected), BUT they will be the set of observers setup | ||
// to handle the batch, meaning invoking `item` will result in a half batched call that | ||
// doesn't really work. To deliver the expected functionality we "reset" the | ||
// observers using the original instance, mimicing the behavior had | ||
// the IItem been created from that base without a batch involved. We use CopyFrom to ensure | ||
// that we maintain the references to the InternalResolve and InternalReject events through | ||
// the end of this timeline lifecycle. This works because CopyFrom by design uses Object.keys | ||
// which ignores symbol properties. | ||
this.using(core_1.CopyFrom(this[ObserverTrackerSym], "replace")); | ||
return r; | ||
}); | ||
}); | ||
// we need to know when each request in the batch's timeline has completed | ||
instance.on.dispose(function () { | ||
@@ -184,2 +228,6 @@ if (core_1.isFunc(this[RequestCompleteSym])) { | ||
} | ||
if (this[ObserverTrackerSym]) { | ||
// remove the symbol props we added for good hygene | ||
delete this[ObserverTrackerSym]; | ||
} | ||
}); | ||
@@ -206,2 +254,3 @@ return instance; | ||
let statusText; | ||
let headers = {}; | ||
for (let i = 0; i < lines.length; ++i) { | ||
@@ -211,3 +260,3 @@ const line = lines[i]; | ||
case "batch": | ||
if (line.substr(0, header.length) === header) { | ||
if (line.substring(0, header.length) === header) { | ||
state = "batchHeaders"; | ||
@@ -240,6 +289,13 @@ } | ||
} | ||
else { | ||
const headerParts = line.split(":"); | ||
if ((headerParts === null || headerParts === void 0 ? void 0 : headerParts.length) === 2) { | ||
headers[headerParts[0].trim()] = headerParts[1].trim(); | ||
} | ||
} | ||
break; | ||
case "body": | ||
responses.push((status === 204) ? new Response() : new Response(line, { status: status, statusText: statusText })); | ||
responses.push(new Response(status === 204 ? null : line, { status, statusText, headers })); | ||
state = "batch"; | ||
headers = {}; | ||
break; | ||
@@ -246,0 +302,0 @@ } |
@@ -174,3 +174,3 @@ import { _SPCollection, IDeleteableWithETag, _SPInstance, ISPQueryable, ISPInstance } from "../spqueryable.js"; | ||
export interface IItemUpdateResultData { | ||
"odata.etag": string; | ||
etag: string; | ||
} | ||
@@ -177,0 +177,0 @@ export interface IItemDeleteParams { |
@@ -62,3 +62,3 @@ "use strict"; | ||
async add(properties = {}) { | ||
return operations_js_1.spPost(exports.Items(this, ""), queryable_1.body(properties)).then((data) => ({ | ||
return operations_js_1.spPost(this, queryable_1.body(properties)).then((data) => ({ | ||
data: data, | ||
@@ -141,4 +141,3 @@ item: this.getById(data.Id), | ||
})); | ||
const poster = exports.Item(this).using(ItemUpdatedParser()); | ||
const data = await operations_js_1.spPost(poster, postBody); | ||
const data = await operations_js_1.spPost(exports.Item(this).using(ItemUpdatedParser()), postBody); | ||
return { | ||
@@ -276,5 +275,5 @@ data, | ||
return queryable_1.parseBinderWithErrorCheck(async (r) => ({ | ||
"odata.etag": r.headers.get("etag"), | ||
etag: r.headers.get("etag"), | ||
})); | ||
} | ||
//# sourceMappingURL=types.js.map |
{ | ||
"name": "@pnp/sp-commonjs", | ||
"version": "3.0.0-v3nightly.20220025", | ||
"version": "3.0.0-v3nightly.20220026", | ||
"description": "pnp - provides a fluent api for working with SharePoint REST", | ||
@@ -9,4 +9,4 @@ "main": "./presets/all.js", | ||
"tslib": "2.3.1", | ||
"@pnp/core-commonjs": "3.0.0-v3nightly.20220025", | ||
"@pnp/queryable-commonjs": "3.0.0-v3nightly.20220025" | ||
"@pnp/core-commonjs": "3.0.0-v3nightly.20220026", | ||
"@pnp/queryable-commonjs": "3.0.0-v3nightly.20220026" | ||
}, | ||
@@ -13,0 +13,0 @@ "author": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1095328
17767
+ Added@pnp/core-commonjs@3.0.0-v3nightly.20220026(transitive)
+ Added@pnp/queryable-commonjs@3.0.0-v3nightly.20220026(transitive)
- Removed@pnp/core-commonjs@3.0.0-v3nightly.20220025(transitive)
- Removed@pnp/queryable-commonjs@3.0.0-v3nightly.20220025(transitive)