diff --git a/README.md b/README.md index e5f27bb..32e5018 100644 --- a/README.md +++ b/README.md @@ -425,11 +425,11 @@ A working example of both targeting and event witnessing is available in the dem ## Integrating Prebid -The Optable Web SDK can fetch targeting data from a DCN and prepare an audience taxonomy object similar to the one described in [the prebid.js first party data documentation](https://docs.prebid.org/features/firstPartyData.html#segments-and-taxonomy). The `prebidUserDataFromCache()` function returns the object from the targeting data stored by `targeting()` API calls in `LocalStorage`. +The Optable Web SDK can fetch targeting data from a DCN and prepare an audience taxonomy object similar to the one described in [the prebid.js first party data documentation](https://docs.prebid.org/features/firstPartyData.html#segments-and-taxonomy). The `prebidORTB2FromCache()` function returns the object from the targeting data stored by `targeting()` API calls in `LocalStorage`. ### Seller Defined Audiences -The HTML code snippet below shows how `prebidUserDataFromCache()` can be used to retrieve targeting data from the `LocalStorage` administered by the Optable SDK, and write Seller Defined Audiences (SDA) into [prebid.js](https://prebid.org/product-suite/prebid-js/) which is also loaded into the page, using `pbjs.setConfig({ ortb2: { user: { data: [ { ... } ] } } })` as documented in [the prebid.js first party data documentation](https://docs.prebid.org/features/firstPartyData.html#segments-and-taxonomy). The `targeting()` API is also called in order to retrieve and locally store the latest matching activations from `dcn.customer.com/my-site`. +The HTML code snippet below shows how `prebidORTB2FromCache()` can be used to retrieve targeting data from the `LocalStorage` administered by the Optable SDK, and write Seller Defined Audiences (SDA) into [prebid.js](https://prebid.org/product-suite/prebid-js/) which is also loaded into the page, using `pbjs.mergeConfig({ ortb2: ortb2 })` as documented in [the prebid.js first party data documentation](https://docs.prebid.org/features/firstPartyData.html#segments-and-taxonomy). The `targeting()` API is also called in order to retrieve and locally store the latest matching activations from `dcn.customer.com/my-site`. Note that [prebid.js bidder adapters](https://docs.prebid.org/dev-docs/bidders.html) can subsequently retrieve the data from the [global config](https://docs.prebid.org/features/firstPartyData.html#supplying-global-data). @@ -503,16 +503,8 @@ For a working demo showing a `pbjs` and GAM integrated together, see the [demo p pbjs.que.push(function () { optable.cmd.push(function () { - const pbdata = optable.instance.prebidUserDataFromCache(); - if (pbdata.length > 0) { - pbjs.setConfig({ - ortb2: { - user: { - data: pbdata, - }, - }, - }); - } + const ortb2 = optable.instance.prebidORTB2FromCache(); + pbjs.mergeConfig({ ortb2: ortb2 }); // ... etc ... diff --git a/demos/vanilla/nocookies/targeting/prebid.html.tpl b/demos/vanilla/nocookies/targeting/prebid.html.tpl index 4d3ddc5..362b149 100644 --- a/demos/vanilla/nocookies/targeting/prebid.html.tpl +++ b/demos/vanilla/nocookies/targeting/prebid.html.tpl @@ -153,19 +153,11 @@ pbjs.que.push(function () { optable.cmd.push(function () { - const pbdata = optable.instance.prebidUserDataFromCache(); - if (pbdata.length > 0) { - pbjs.setConfig({ - ortb2: { - user: { - data: pbdata - } - } - }); + const ortb2 = optable.instance.prebidORTB2FromCache(); + pbjs.mergeConfig({ ortb2: ortb2 }); - console.log("[OptableSDK] pbjs.setConfig(ortb2.user.data)"); - console.log(pbdata); - } + console.log("[OptableSDK] pbjs.mergeConfig(ortb2)"); + console.log(ortb2); pbjs.setConfig({ priceGranularity: "low", @@ -240,7 +232,7 @@ we also pass matching active cohorts to GAM.

- In this example, we use the prebidUserDataFromCache() API to retrieve any targeting data from browser + In this example, we use the prebidORTB2FromCache() API to retrieve any targeting data from browser LocalStorage, in order to pass it to Prebid.js via seller defined audiences. We also call the SDK targeting API which will fetch the latest targeting data from our DCN and cache it locally for later use. Since these two events happen asynchronously, it's possible that the targeting data passed to GAM is slightly outdated. diff --git a/demos/vanilla/targeting/prebid.html.tpl b/demos/vanilla/targeting/prebid.html.tpl index d3cd511..fbaeaf2 100644 --- a/demos/vanilla/targeting/prebid.html.tpl +++ b/demos/vanilla/targeting/prebid.html.tpl @@ -152,18 +152,10 @@ pbjs.que.push(function () { optable.cmd.push(function () { - const pbdata = optable.instance.prebidUserDataFromCache(); - if (pbdata.length > 0) { - pbjs.setConfig({ - ortb2: { - user: { - data: pbdata - } - } - }); + const ortb2 = optable.instance.prebidORTB2FromCache(); + pbjs.mergeConfig({ ortb2: ortb2 }); - console.log("[OptableSDK] pbjs.setConfig(ortb2.user.data)"); - } + console.log("[OptableSDK] pbjs.mergeConfig(ortb2)"); pbjs.setConfig({ priceGranularity: "low", @@ -238,7 +230,7 @@ we also pass matching active cohorts to GAM.

- In this example, we use the prebidUserDataFromCache() API to retrieve any targeting data from browser + In this example, we use the prebidORTB2FromCache() API to retrieve any targeting data from browser LocalStorage, in order to pass it to Prebid.js via seller defined audiences. We also call the SDK targeting API which will fetch the latest targeting data from our DCN and cache it locally for later use. Since these two events happen asynchronously, it's possible that the targeting data passed to Prebid is slightly outdated. diff --git a/lib/edge/rtb2.ts b/lib/edge/rtb2.ts new file mode 100644 index 0000000..ec91f93 --- /dev/null +++ b/lib/edge/rtb2.ts @@ -0,0 +1,43 @@ +// Based on https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/extensions/2.x_official_extensions/eids.md +type UserSegment = { + id?: string + name?: string + value?: string + ext?: any +}; + +type UserData = { + id?: string + name?: string + segment?: UserSegment[] + ext?: { segtax: number } +}; + +type ExtendedIdentifierUID = { + id: string + atype: UIDAgentType; + ext?: any; +} + +type ExtendedIdentifiers = { + source: string; + uids: ExtendedIdentifierUID[]; +} + + +type UserExt = { + eids?: ExtendedIdentifiers[]; +} + +type User = { + data?: UserData[] + ext?: UserExt +} + +enum UIDAgentType { + DeviceID = 1, + InAppImpression = 2, + PersonID = 3, +} + +export { User, UIDAgentType } diff --git a/lib/edge/targeting.test.js b/lib/edge/targeting.test.js index afb9c3e..f28f6c0 100644 --- a/lib/edge/targeting.test.js +++ b/lib/edge/targeting.test.js @@ -1,9 +1,10 @@ -import { PrebidUserData, TargetingKeyValues } from "./targeting"; +import { PrebidORTB2, TargetingKeyValues } from "./targeting"; -describe("PrebidUserData", () => { +describe("PrebidORTB2", () => { test("returns empty array on empty input", () => { - expect(PrebidUserData(null)).toEqual([]) - expect(PrebidUserData({})).toEqual([]) + const empty = { user: { data: [], ext: { eids: []} }} + expect(PrebidORTB2(null)).toEqual(empty) + expect(PrebidORTB2({})).toEqual(empty) }) test("returns for each targeting audiences a user segments compatible with ortb2.user.data", () => { @@ -16,8 +17,13 @@ describe("PrebidUserData", () => { ] }; - expect(PrebidUserData(targeting)).toEqual( - [{name: "optable.co", segment: [{ id: "a"}, {id: "b"}, {id: "c"}], ext: {segtax: 123}}] + expect(PrebidORTB2(targeting)).toEqual( + { + user: { + data: [{name: "optable.co", segment: [{ id: "a"}, {id: "b"}, {id: "c"}], ext: {segtax: 123}}], + ext: { eids: [{ source: "uidapi.com", uids: [{id: "d", atype: 3}]}] }, + }, + } ) }) }) diff --git a/lib/edge/targeting.ts b/lib/edge/targeting.ts index 8f70dd6..7037041 100644 --- a/lib/edge/targeting.ts +++ b/lib/edge/targeting.ts @@ -1,6 +1,7 @@ import type { OptableConfig } from "../config"; import { fetch } from "../core/network"; import { LocalStorage } from "../core/storage"; +import {UIDAgentType, User as RTB2User} from "./rtb2"; type Identifier = { id: string; @@ -49,29 +50,36 @@ function TargetingClearCache(config: OptableConfig) { ls.clearTargeting(); } -type PrebidUserSegment = Identifier -type PrebidSegtax = { segtax: number }; -type PrebidUserSegmentProvider = { name: string; ext: PrebidSegtax; segment: PrebidUserSegment[] }; -type PrebidUserData = PrebidUserSegmentProvider[]; +type PrebidORTB2 = {user?: RTB2User} /* * Prebid.js supports passing seller-defined audiences to compatible * bidder adapters. * - * We return the contents to be pushed to ortb2.user.data and passed to - * bidder adapters via setConfig(ortb2.user.data)... the caller is free + * We return the contents to be merged in ortb2 and passed to + * bidder adapters via mergeConfig(ortb2)... the caller is free * to append additional objects before setting the final result. * * References: * https://docs.prebid.org/features/firstPartyData.html#segments-and-taxonomy * https://iabtechlab.com/wp-content/uploads/2021/03/IABTechLab_Taxonomy_and_Data_Transparency_Standards_to_Support_Seller-defined_Audience_and_Context_Signaling_2021-03.pdf */ -function PrebidUserData(tdata: TargetingResponse | null): PrebidUserData { - return (tdata?.audience ?? []).map((identifiers) => ({ - name: identifiers.provider, - segment: identifiers.ids, - ext: { segtax: identifiers.rtb_segtax }, - })) +function PrebidORTB2(tdata: TargetingResponse | null): PrebidORTB2 { + return { + user: { + data: (tdata?.audience ?? []).map((identifiers) => ({ + name: identifiers.provider, + segment: identifiers.ids, + ext: { segtax: identifiers.rtb_segtax }, + })), + ext: { + eids: (tdata?.user ?? []).map((identifiers) => ({ + source: identifiers.provider, + uids: identifiers.ids.map(({ id }) => ({ id, atype: UIDAgentType.PersonID })), + })), + } + } + } } type TargetingKeyValues = { [key: string]: string[] }; @@ -99,7 +107,7 @@ export { TargetingFromCache, TargetingClearCache, TargetingResponse, - PrebidUserData, + PrebidORTB2, TargetingKeyValues, }; export default Targeting; diff --git a/lib/sdk.ts b/lib/sdk.ts index cf3251f..4399a45 100644 --- a/lib/sdk.ts +++ b/lib/sdk.ts @@ -4,11 +4,11 @@ import type { ProfileTraits } from "./edge/profile"; import { Identify } from "./edge/identify"; import { TargetingKeyValues, - PrebidUserData, TargetingResponse, Targeting, TargetingFromCache, - TargetingClearCache + TargetingClearCache, + PrebidORTB2 } from "./edge/targeting"; import { Witness } from "./edge/witness"; import { Profile } from "./edge/profile"; @@ -40,13 +40,13 @@ class OptableSDK { TargetingClearCache(this.dcn); } - async prebidUserData(): Promise { - return PrebidUserData(await this.targeting()) + async prebidORTB2(): Promise { + return PrebidORTB2(await this.targeting()) } - prebidUserDataFromCache(): PrebidUserData { + prebidORTB2FromCache(): PrebidORTB2 { const tdata = this.targetingFromCache() - return PrebidUserData(tdata); + return PrebidORTB2(tdata); } async targetingKeyValues(): Promise { @@ -78,8 +78,8 @@ class OptableSDK { return TargetingKeyValues(tdata) } - static PrebidUserData(tdata: TargetingResponse): PrebidUserData { - return PrebidUserData(tdata) + static PrebidORTB2(tdata: TargetingResponse): PrebidORTB2 { + return PrebidORTB2(tdata) } } diff --git a/package-lock.json b/package-lock.json index 746fe48..21cc4f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3328,6 +3328,64 @@ "node": ">=8" } }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, "node_modules/@sinonjs/commons": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", @@ -3711,9 +3769,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", - "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -4621,9 +4679,9 @@ "dev": true }, "node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", "dev": true, "engines": { "node": ">=0.10" @@ -8147,9 +8205,9 @@ } }, "node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", "dev": true, "dependencies": { "big.js": "^5.2.2", @@ -8305,9 +8363,9 @@ } }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -9508,9 +9566,9 @@ } }, "node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "dependencies": { "buffer-from": "^1.0.0", @@ -9746,14 +9804,15 @@ } }, "node_modules/terser": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.1.tgz", - "integrity": "sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg==", + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", + "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", "dev": true, "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.19" + "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" @@ -9866,15 +9925,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/terser/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -13923,6 +13973,55 @@ } } }, + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, "@sinonjs/commons": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", @@ -14290,9 +14389,9 @@ "dev": true }, "acorn": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", - "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "dev": true }, "acorn-globals": { @@ -15032,9 +15131,9 @@ "dev": true }, "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", "dev": true }, "deep-is": { @@ -17823,9 +17922,9 @@ "dev": true }, "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", "dev": true, "requires": { "big.js": "^5.2.2", @@ -17949,9 +18048,9 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -18934,9 +19033,9 @@ } }, "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -19134,22 +19233,15 @@ } }, "terser": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.1.tgz", - "integrity": "sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg==", + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", + "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", "dev": true, "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.19" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } + "source-map-support": "~0.5.20" } }, "terser-webpack-plugin": {