diff --git a/src/lib/messages/bulkrequest.js b/src/lib/messages/bulkrequest.js index 819fc6b..c743527 100644 --- a/src/lib/messages/bulkrequest.js +++ b/src/lib/messages/bulkrequest.js @@ -76,9 +76,10 @@ export class BulkRequest { /** * Apply the operations specified by the supplied BulkRequest * @param {typeof SCIMMY.Types.Resource[]} [resourceTypes] - resource type classes to be used while processing bulk operations, defaults to declared resources + * @param {*} [ctx] - any additional context information to pass to the ingress, egress, and degress handlers * @returns {SCIMMY.Messages.BulkResponse} a new BulkResponse Message instance with results of the requested operations */ - async apply(resourceTypes = Object.values(Resources.declared())) { + async apply(resourceTypes = Object.values(Resources.declared()), ctx) { // Bail out if BulkRequest message has already been applied if (this.#dispatched) throw new TypeError("BulkRequest 'apply' method must not be called more than once"); @@ -198,7 +199,7 @@ export class BulkRequest { const {id} = await new TargetResource().write(Object.entries(data) // Remove any values that reference a bulkId .filter(([,v]) => !JSON.stringify(v).includes("bulkId:")) - .reduce((res, [k, v]) => Object.assign(res, {[k]: v}), {})); + .reduce((res, [k, v]) => Object.assign(res, {[k]: v}), {}), ctx); // Set the ID for future use and resolve pending references Object.assign(data, {id}) @@ -210,7 +211,7 @@ export class BulkRequest { data = Object.assign(JSON.parse(jsonData.replaceAll(`bulkId:${referenceId}`, await reference)), {id: data.id}); } catch (ex) { // Referenced POST operation precondition failed, remove any created resource and bail out - if (bulkId && data.id) await new TargetResource(data.id).dispose(); + if (bulkId && data.id) await new TargetResource(data.id).dispose(ctx); // If we're following on from a prior failure, no need to explain why, otherwise, explain the failure if (ex instanceof ErrorMessage && (!!errorLimit && errorCount >= errorLimit && index > lastErrorIndex)) return; @@ -226,16 +227,16 @@ export class BulkRequest { switch (method.toUpperCase()) { case "POST": case "PUT": - value = await resource.write(data); + value = await resource.write(data, ctx); if (bulkId && !resource.id && value?.id) bulkIds.get(bulkId).resolve(value?.id); break; case "PATCH": - value = await resource.patch(data); + value = await resource.patch(data, ctx); break; case "DELETE": - await resource.dispose(); + await resource.dispose(ctx); break; } diff --git a/src/lib/messages/searchrequest.js b/src/lib/messages/searchrequest.js index 7a6af6e..d333c09 100644 --- a/src/lib/messages/searchrequest.js +++ b/src/lib/messages/searchrequest.js @@ -105,9 +105,10 @@ export class SearchRequest { /** * Apply a search request operation, retrieving results from specified resource types * @param {typeof SCIMMY.Types.Resource[]} [resourceTypes] - resource type classes to be used while processing the search request, defaults to declared resources + * @param {*} [ctx] - any additional context information to pass to the egress handler * @returns {SCIMMY.Messages.ListResponse} a ListResponse message with results of the search request */ - async apply(resourceTypes = Object.values(Resources.declared())) { + async apply(resourceTypes = Object.values(Resources.declared()), ctx) { // Make sure all specified resource types extend the Resource type class so operations can be processed correctly if (!Array.isArray(resourceTypes) || !resourceTypes.every(r => r.prototype instanceof Types.Resource)) throw new TypeError("Expected 'resourceTypes' parameter to be an array of Resource type classes in 'apply' method of SearchRequest"); @@ -122,12 +123,12 @@ export class SearchRequest { // If only one resource type, just read from it if (resourceTypes.length === 1) { const [Resource] = resourceTypes; - return new Resource({...this, ...request}).read(); + return new Resource({...this, ...request}).read(ctx); } // Otherwise, read from all resources and return collected results else { // Read from, and unwrap results for, supplied resource types - const results = await Promise.all(resourceTypes.map((Resource) => new Resource(request).read())) + const results = await Promise.all(resourceTypes.map((Resource) => new Resource(request).read(ctx))) .then((r) => r.map((l) => l.Resources)); // Collect the results in a list response with specified constraints diff --git a/test/lib/messages/bulkrequest.js b/test/lib/messages/bulkrequest.js index d95575d..3275f6b 100644 --- a/test/lib/messages/bulkrequest.js +++ b/test/lib/messages/bulkrequest.js @@ -352,7 +352,7 @@ describe("SCIMMY.Messages.BulkRequest", () => { await (new BulkRequest({...template, Operations})).apply([TestStubbed]); - assert.ok(stub.called && stub.getCall(0)?.args?.length === 0, + assert.ok(stub.calledOnce, "Instance method 'apply' did not dispose of newly created resource when circular bulkId operation failed"); }); @@ -384,7 +384,7 @@ describe("SCIMMY.Messages.BulkRequest", () => { await (new BulkRequest({...template, Operations})).apply([TestStubbed]); - assert.ok(method !== "DELETE" ? stub.calledWithMatch(data) : stub.getCall(0)?.args?.length === 0, + assert.ok(method !== "DELETE" ? stub.calledWith(sinon.match.same(data)) : stub.calledOnce, `Instance method 'apply' did not call resource instance '${fn}' method when 'method' attribute value was ${method}`); }); }