@nextad/auction 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +57 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/package.json +6 -1
- package/.editorconfig +0 -0
- package/src/Auction.ts +0 -125
- package/src/BidComparator.ts +0 -50
- package/src/exceptions/index.ts +0 -9
- package/src/index.ts +0 -2
- package/src/types/index.ts +0 -22
- package/test/tsconfig.json +0 -12
- package/test/units/Auction.test.ts +0 -176
- package/tsconfig.json +0 -29
- package/tsup.config.ts +0 -9
- package/vitest.config.ts +0 -14
package/dist/index.d.mts
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
import { Bid, BidResponse } from 'iab-openrtb/v26';
|
2
|
+
|
3
|
+
type BidInformation = {
|
4
|
+
currency?: string;
|
5
|
+
seat?: string;
|
6
|
+
version: string;
|
7
|
+
};
|
8
|
+
interface CurrencyRates {
|
9
|
+
/** ISO 4217 Currency Code (Example: USD, JPY, EUR) */
|
10
|
+
[currency: string]: number;
|
11
|
+
}
|
12
|
+
interface ConversionRates {
|
13
|
+
/** convert rate of base currency */
|
14
|
+
[baseCurrency: string]: CurrencyRates;
|
15
|
+
}
|
16
|
+
interface CurrencyConversionData {
|
17
|
+
dataAsOf: string;
|
18
|
+
generatedAt: string;
|
19
|
+
conversions: ConversionRates;
|
20
|
+
}
|
21
|
+
|
22
|
+
type AuctionType = "open" | "closed";
|
23
|
+
type AuctionOptions = {
|
24
|
+
lossProcessing?: boolean;
|
25
|
+
currencyConversionData?: CurrencyConversionData;
|
26
|
+
};
|
27
|
+
declare class Auction {
|
28
|
+
private losingBids;
|
29
|
+
private bids;
|
30
|
+
private itemIds;
|
31
|
+
private status;
|
32
|
+
private options;
|
33
|
+
private bidInformation;
|
34
|
+
constructor(itemOrImpressionIds: string | string[], options?: AuctionOptions);
|
35
|
+
getStatus(): AuctionType;
|
36
|
+
getLosingBids(): {
|
37
|
+
v26: Bid[];
|
38
|
+
};
|
39
|
+
getBidInformation(bid: Bid): BidInformation | undefined;
|
40
|
+
getBidInformations(): WeakMap<Bid, BidInformation>;
|
41
|
+
placeBidResponseV26(bidResponse: BidResponse): this;
|
42
|
+
end(): Bid;
|
43
|
+
private setLosingBids;
|
44
|
+
private handleLossBids;
|
45
|
+
private handleLossBid;
|
46
|
+
}
|
47
|
+
|
48
|
+
declare class BidNotFoundException {
|
49
|
+
name: string;
|
50
|
+
message: string;
|
51
|
+
}
|
52
|
+
declare class AlreadyEndedAuctionException {
|
53
|
+
name: string;
|
54
|
+
message: string;
|
55
|
+
}
|
56
|
+
|
57
|
+
export { AlreadyEndedAuctionException, Auction, BidNotFoundException };
|
package/dist/index.d.ts
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
import { Bid, BidResponse } from 'iab-openrtb/v26';
|
2
|
+
|
3
|
+
type BidInformation = {
|
4
|
+
currency?: string;
|
5
|
+
seat?: string;
|
6
|
+
version: string;
|
7
|
+
};
|
8
|
+
interface CurrencyRates {
|
9
|
+
/** ISO 4217 Currency Code (Example: USD, JPY, EUR) */
|
10
|
+
[currency: string]: number;
|
11
|
+
}
|
12
|
+
interface ConversionRates {
|
13
|
+
/** convert rate of base currency */
|
14
|
+
[baseCurrency: string]: CurrencyRates;
|
15
|
+
}
|
16
|
+
interface CurrencyConversionData {
|
17
|
+
dataAsOf: string;
|
18
|
+
generatedAt: string;
|
19
|
+
conversions: ConversionRates;
|
20
|
+
}
|
21
|
+
|
22
|
+
type AuctionType = "open" | "closed";
|
23
|
+
type AuctionOptions = {
|
24
|
+
lossProcessing?: boolean;
|
25
|
+
currencyConversionData?: CurrencyConversionData;
|
26
|
+
};
|
27
|
+
declare class Auction {
|
28
|
+
private losingBids;
|
29
|
+
private bids;
|
30
|
+
private itemIds;
|
31
|
+
private status;
|
32
|
+
private options;
|
33
|
+
private bidInformation;
|
34
|
+
constructor(itemOrImpressionIds: string | string[], options?: AuctionOptions);
|
35
|
+
getStatus(): AuctionType;
|
36
|
+
getLosingBids(): {
|
37
|
+
v26: Bid[];
|
38
|
+
};
|
39
|
+
getBidInformation(bid: Bid): BidInformation | undefined;
|
40
|
+
getBidInformations(): WeakMap<Bid, BidInformation>;
|
41
|
+
placeBidResponseV26(bidResponse: BidResponse): this;
|
42
|
+
end(): Bid;
|
43
|
+
private setLosingBids;
|
44
|
+
private handleLossBids;
|
45
|
+
private handleLossBid;
|
46
|
+
}
|
47
|
+
|
48
|
+
declare class BidNotFoundException {
|
49
|
+
name: string;
|
50
|
+
message: string;
|
51
|
+
}
|
52
|
+
declare class AlreadyEndedAuctionException {
|
53
|
+
name: string;
|
54
|
+
message: string;
|
55
|
+
}
|
56
|
+
|
57
|
+
export { AlreadyEndedAuctionException, Auction, BidNotFoundException };
|
package/dist/index.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";var u=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var v=Object.prototype.hasOwnProperty;var f=(s,i)=>{for(var e in i)u(s,e,{get:i[e],enumerable:!0})},m=(s,i,e,r)=>{if(i&&typeof i=="object"||typeof i=="function")for(let t of l(i))!v.call(s,t)&&t!==e&&u(s,t,{get:()=>i[t],enumerable:!(r=h(i,t))||r.enumerable});return s};var g=s=>m(u({},"__esModule",{value:!0}),s);var y={};f(y,{AlreadyEndedAuctionException:()=>a,Auction:()=>B,BidNotFoundException:()=>o});module.exports=g(y);var c=class{static getHighestBidV26(i,e,r){return r?i.reduce((t,n)=>{let d=this.convertPrice(t,e,r);return this.convertPrice(n,e,r)>d?n:t}):i.reduce((t,n)=>{let d=t.price*100;return n.price*100>d?n:t})}static convertPrice(i,e,r){let t=i.price,n=r.conversions[e.get(i)?.currency||"USD"];if(!n)return t*100;let p=n["USD"];return t*(p||1)*100}};var o=class{name="BidNotFoundException";message="Bid is not found."},a=class{name="AlreadyEndedAuctionException";message="Auction is already ended."};var B=class{losingBids;bids;itemIds=[];status;options;bidInformation;constructor(i,e={}){this.options={lossProcessing:!0,...e},this.bids={v26:[]},this.losingBids={v26:[]},this.status="open",this.bidInformation=new WeakMap,typeof i=="string"?this.itemIds.push(i):this.itemIds.push(...i)}getStatus(){return this.status}getLosingBids(){return this.losingBids}getBidInformation(i){return this.bidInformation.get(i)}getBidInformations(){return this.bidInformation}placeBidResponseV26(i){if(i.seatbid){let e=i.seatbid.flatMap(r=>r.bid.map(t=>(this.bidInformation.set(t,{currency:i.cur,version:"2.6",seat:r.seat}),t)));this.bids.v26.push(...e)}return this}end(){if(this.status!=="open")throw new a;if(!this.bids.v26.length)throw new o;let i=c.getHighestBidV26(this.bids.v26,this.bidInformation,this.options.currencyConversionData);return this.setLosingBids(i),this.handleLossBids(),this.status="closed",i}setLosingBids(i){this.losingBids.v26.push(...this.bids.v26.filter(e=>e.id!==i.id))}handleLossBids(){this.losingBids.v26.forEach(i=>{this.handleLossBid(i)})}handleLossBid(i){this.options.lossProcessing&&i.lurl&&fetch(i.lurl,{keepalive:!0})}};0&&(module.exports={AlreadyEndedAuctionException,Auction,BidNotFoundException});
|
package/dist/index.mjs
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
var o=class{static getHighestBidV26(i,e,s){return s?i.reduce((t,r)=>{let n=this.convertPrice(t,e,s);return this.convertPrice(r,e,s)>n?r:t}):i.reduce((t,r)=>{let n=t.price*100;return r.price*100>n?r:t})}static convertPrice(i,e,s){let t=i.price,r=s.conversions[e.get(i)?.currency||"USD"];if(!r)return t*100;let p=r["USD"];return t*(p||1)*100}};var a=class{name="BidNotFoundException";message="Bid is not found."},d=class{name="AlreadyEndedAuctionException";message="Auction is already ended."};var u=class{losingBids;bids;itemIds=[];status;options;bidInformation;constructor(i,e={}){this.options={lossProcessing:!0,...e},this.bids={v26:[]},this.losingBids={v26:[]},this.status="open",this.bidInformation=new WeakMap,typeof i=="string"?this.itemIds.push(i):this.itemIds.push(...i)}getStatus(){return this.status}getLosingBids(){return this.losingBids}getBidInformation(i){return this.bidInformation.get(i)}getBidInformations(){return this.bidInformation}placeBidResponseV26(i){if(i.seatbid){let e=i.seatbid.flatMap(s=>s.bid.map(t=>(this.bidInformation.set(t,{currency:i.cur,version:"2.6",seat:s.seat}),t)));this.bids.v26.push(...e)}return this}end(){if(this.status!=="open")throw new d;if(!this.bids.v26.length)throw new a;let i=o.getHighestBidV26(this.bids.v26,this.bidInformation,this.options.currencyConversionData);return this.setLosingBids(i),this.handleLossBids(),this.status="closed",i}setLosingBids(i){this.losingBids.v26.push(...this.bids.v26.filter(e=>e.id!==i.id))}handleLossBids(){this.losingBids.v26.forEach(i=>{this.handleLossBid(i)})}handleLossBid(i){this.options.lossProcessing&&i.lurl&&fetch(i.lurl,{keepalive:!0})}};export{d as AlreadyEndedAuctionException,u as Auction,a as BidNotFoundException};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@nextad/auction",
|
3
|
-
"version": "0.1.
|
3
|
+
"version": "0.1.5",
|
4
4
|
"description": "",
|
5
5
|
"keywords": [],
|
6
6
|
"author": "Kai Miyamoto",
|
@@ -25,6 +25,11 @@
|
|
25
25
|
"import": "./dist/index.mjs",
|
26
26
|
"require": "./dist/index.js"
|
27
27
|
},
|
28
|
+
"files": [
|
29
|
+
"dist",
|
30
|
+
"README.md",
|
31
|
+
"LICENSE"
|
32
|
+
],
|
28
33
|
"scripts": {
|
29
34
|
"test": "vitest",
|
30
35
|
"build": "tsup"
|
package/.editorconfig
DELETED
File without changes
|
package/src/Auction.ts
DELETED
@@ -1,125 +0,0 @@
|
|
1
|
-
import { BidComparator } from "./BidComparator";
|
2
|
-
import {
|
3
|
-
AlreadyEndedAuctionException,
|
4
|
-
BidNotFoundException,
|
5
|
-
} from "./exceptions";
|
6
|
-
import type {
|
7
|
-
BidResponse as BaseBidResponseV26,
|
8
|
-
Bid as BidV26,
|
9
|
-
} from "iab-openrtb/v26";
|
10
|
-
import type { BidInformation, CurrencyConversionData } from "./types";
|
11
|
-
|
12
|
-
type AuctionType = "open" | "closed";
|
13
|
-
|
14
|
-
type AuctionOptions = {
|
15
|
-
lossProcessing?: boolean;
|
16
|
-
currencyConversionData?: CurrencyConversionData;
|
17
|
-
};
|
18
|
-
|
19
|
-
export class Auction {
|
20
|
-
private losingBids: {
|
21
|
-
v26: BidV26[];
|
22
|
-
};
|
23
|
-
private bids: {
|
24
|
-
v26: BidV26[];
|
25
|
-
};
|
26
|
-
|
27
|
-
private itemIds: string[] = [];
|
28
|
-
private status: AuctionType;
|
29
|
-
private options: AuctionOptions;
|
30
|
-
private bidInformation: WeakMap<BidV26, BidInformation>;
|
31
|
-
|
32
|
-
public constructor(
|
33
|
-
itemOrImpressionIds: string | string[],
|
34
|
-
options: AuctionOptions = {}
|
35
|
-
) {
|
36
|
-
this.options = {
|
37
|
-
lossProcessing: true,
|
38
|
-
...options,
|
39
|
-
};
|
40
|
-
|
41
|
-
this.bids = {
|
42
|
-
v26: [],
|
43
|
-
};
|
44
|
-
this.losingBids = {
|
45
|
-
v26: [],
|
46
|
-
};
|
47
|
-
this.status = "open";
|
48
|
-
this.bidInformation = new WeakMap();
|
49
|
-
|
50
|
-
if (typeof itemOrImpressionIds === "string") {
|
51
|
-
this.itemIds.push(itemOrImpressionIds);
|
52
|
-
} else {
|
53
|
-
this.itemIds.push(...itemOrImpressionIds);
|
54
|
-
}
|
55
|
-
}
|
56
|
-
|
57
|
-
public getStatus(): AuctionType {
|
58
|
-
return this.status;
|
59
|
-
}
|
60
|
-
|
61
|
-
public getLosingBids(): { v26: BidV26[] } {
|
62
|
-
return this.losingBids;
|
63
|
-
}
|
64
|
-
|
65
|
-
public placeBidResponseV26(bidResponse: BaseBidResponseV26): this {
|
66
|
-
if (bidResponse.seatbid) {
|
67
|
-
const bids: BidV26[] = bidResponse.seatbid.flatMap((seatbid) => {
|
68
|
-
return seatbid.bid.map((bid) => {
|
69
|
-
this.bidInformation.set(bid, {
|
70
|
-
currency: bidResponse.cur,
|
71
|
-
version: "2.6",
|
72
|
-
seat: seatbid.seat,
|
73
|
-
});
|
74
|
-
return bid;
|
75
|
-
});
|
76
|
-
});
|
77
|
-
|
78
|
-
this.bids.v26.push(...bids);
|
79
|
-
}
|
80
|
-
|
81
|
-
return this;
|
82
|
-
}
|
83
|
-
|
84
|
-
public end(): BidV26 {
|
85
|
-
if (this.status !== "open") {
|
86
|
-
throw new AlreadyEndedAuctionException();
|
87
|
-
}
|
88
|
-
|
89
|
-
if (!this.bids.v26.length) {
|
90
|
-
throw new BidNotFoundException();
|
91
|
-
}
|
92
|
-
|
93
|
-
const highestBid = BidComparator.getHighestBidV26(
|
94
|
-
this.bids.v26,
|
95
|
-
this.bidInformation,
|
96
|
-
this.options.currencyConversionData
|
97
|
-
);
|
98
|
-
|
99
|
-
this.setLosingBids(highestBid);
|
100
|
-
this.handleLossBids();
|
101
|
-
this.status = "closed";
|
102
|
-
|
103
|
-
return highestBid;
|
104
|
-
}
|
105
|
-
|
106
|
-
private setLosingBids(winningBid: BidV26): void {
|
107
|
-
this.losingBids.v26.push(
|
108
|
-
...this.bids.v26.filter((bid) => bid.id !== winningBid.id)
|
109
|
-
);
|
110
|
-
}
|
111
|
-
|
112
|
-
private handleLossBids(): void {
|
113
|
-
this.losingBids.v26.forEach((bid) => {
|
114
|
-
this.handleLossBid(bid);
|
115
|
-
});
|
116
|
-
}
|
117
|
-
|
118
|
-
private handleLossBid(bid: BidV26): void {
|
119
|
-
if (this.options.lossProcessing && bid.lurl) {
|
120
|
-
fetch(bid.lurl, {
|
121
|
-
keepalive: true,
|
122
|
-
});
|
123
|
-
}
|
124
|
-
}
|
125
|
-
}
|
package/src/BidComparator.ts
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
import type { BidInformation, CurrencyConversionData } from "./types";
|
2
|
-
import type { Bid as BidV26 } from "iab-openrtb/v26";
|
3
|
-
|
4
|
-
export class BidComparator {
|
5
|
-
public static getHighestBidV26(
|
6
|
-
bids: BidV26[],
|
7
|
-
bidInformation: WeakMap<BidV26, BidInformation>,
|
8
|
-
currencyConversionData?: CurrencyConversionData
|
9
|
-
): BidV26 {
|
10
|
-
if (!currencyConversionData) {
|
11
|
-
return bids.reduce((highest, current) => {
|
12
|
-
const highestPrice = highest.price * 100;
|
13
|
-
const currentPrice = current.price * 100;
|
14
|
-
return currentPrice > highestPrice ? current : highest;
|
15
|
-
});
|
16
|
-
}
|
17
|
-
|
18
|
-
return bids.reduce((highest, current) => {
|
19
|
-
const highestPrice = this.convertPrice(
|
20
|
-
highest,
|
21
|
-
bidInformation,
|
22
|
-
currencyConversionData
|
23
|
-
);
|
24
|
-
const currentPrice = this.convertPrice(
|
25
|
-
current,
|
26
|
-
bidInformation,
|
27
|
-
currencyConversionData
|
28
|
-
);
|
29
|
-
return currentPrice > highestPrice ? current : highest;
|
30
|
-
});
|
31
|
-
}
|
32
|
-
|
33
|
-
private static convertPrice(
|
34
|
-
bid: BidV26,
|
35
|
-
bidInformation: WeakMap<BidV26, BidInformation>,
|
36
|
-
conversionData: CurrencyConversionData
|
37
|
-
): number {
|
38
|
-
const price = bid.price;
|
39
|
-
const rates =
|
40
|
-
conversionData.conversions[bidInformation.get(bid)?.currency || "USD"];
|
41
|
-
|
42
|
-
if (!rates) {
|
43
|
-
return price * 100;
|
44
|
-
}
|
45
|
-
|
46
|
-
const targetCurrency = "USD";
|
47
|
-
const rate = rates[targetCurrency];
|
48
|
-
return price * (rate || 1) * 100;
|
49
|
-
}
|
50
|
-
}
|
package/src/exceptions/index.ts
DELETED
package/src/index.ts
DELETED
package/src/types/index.ts
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
export type BidInformation = {
|
2
|
-
currency?: string;
|
3
|
-
seat?: string;
|
4
|
-
version: string;
|
5
|
-
};
|
6
|
-
|
7
|
-
|
8
|
-
export interface CurrencyRates {
|
9
|
-
/** ISO 4217 Currency Code (Example: USD, JPY, EUR) */
|
10
|
-
[currency: string]: number;
|
11
|
-
}
|
12
|
-
|
13
|
-
interface ConversionRates {
|
14
|
-
/** convert rate of base currency */
|
15
|
-
[baseCurrency: string]: CurrencyRates;
|
16
|
-
}
|
17
|
-
|
18
|
-
export interface CurrencyConversionData {
|
19
|
-
dataAsOf: string;
|
20
|
-
generatedAt: string;
|
21
|
-
conversions: ConversionRates;
|
22
|
-
}
|
package/test/tsconfig.json
DELETED
@@ -1,176 +0,0 @@
|
|
1
|
-
import { openrtbFaker } from "@nextad/faker";
|
2
|
-
import { Auction } from "@/Auction";
|
3
|
-
import {
|
4
|
-
AlreadyEndedAuctionException,
|
5
|
-
BidNotFoundException,
|
6
|
-
} from "@/exceptions";
|
7
|
-
|
8
|
-
describe("Auction", () => {
|
9
|
-
it("returns highest bid from bids with specified item(impression) when auction ends", () => {
|
10
|
-
const sut = new Auction("impid-1");
|
11
|
-
const bidResponse = openrtbFaker.v26.bidResponse
|
12
|
-
.addBannerBid({ impid: "impid-1", price: 10 })
|
13
|
-
.make();
|
14
|
-
const bidResponse2 = openrtbFaker.v26.bidResponse
|
15
|
-
.addBannerBid({ impid: "impid-1", price: 20 })
|
16
|
-
.make();
|
17
|
-
sut.placeBidResponseV26(bidResponse);
|
18
|
-
sut.placeBidResponseV26(bidResponse2);
|
19
|
-
|
20
|
-
const result = sut.end();
|
21
|
-
|
22
|
-
expect(result.id).toBe(bidResponse2.seatbid![0].bid[0].id);
|
23
|
-
});
|
24
|
-
|
25
|
-
it("returns highest bid from bids with specified items(impressions) when auction ends", () => {
|
26
|
-
const sut = new Auction(["impid-1", "impid-2"]);
|
27
|
-
const bidResponse = openrtbFaker.v26.bidResponse
|
28
|
-
.addBannerBid({ impid: "impid-1", price: 10 })
|
29
|
-
.make();
|
30
|
-
const bidResponse2 = openrtbFaker.v26.bidResponse
|
31
|
-
.addBannerBid({ impid: "impid-1", price: 20 })
|
32
|
-
.addVideoBid({ impid: "impid-2", price: 30 })
|
33
|
-
.make();
|
34
|
-
sut.placeBidResponseV26(bidResponse);
|
35
|
-
sut.placeBidResponseV26(bidResponse2);
|
36
|
-
|
37
|
-
const result = sut.end();
|
38
|
-
|
39
|
-
expect(result.id).toBe(bidResponse2.seatbid![0].bid[1].id);
|
40
|
-
});
|
41
|
-
|
42
|
-
it("returns highest bid considering currency when auction ends", () => {
|
43
|
-
const sut = new Auction("impid-1", {
|
44
|
-
currencyConversionData: {
|
45
|
-
dataAsOf: "2021-01-01",
|
46
|
-
generatedAt: "2021-01-01",
|
47
|
-
conversions: {
|
48
|
-
JPY: {
|
49
|
-
USD: 0.09,
|
50
|
-
},
|
51
|
-
},
|
52
|
-
},
|
53
|
-
});
|
54
|
-
const bidResponse = openrtbFaker.v26.bidResponse
|
55
|
-
.withCurrency("JPY")
|
56
|
-
.addBannerBid({ impid: "impid-1", price: 10 })
|
57
|
-
.make();
|
58
|
-
const bidResponse2 = openrtbFaker.v26.bidResponse
|
59
|
-
.withCurrency("USD")
|
60
|
-
.addBannerBid({ impid: "impid-1", price: 5 })
|
61
|
-
.make();
|
62
|
-
sut.placeBidResponseV26(bidResponse);
|
63
|
-
sut.placeBidResponseV26(bidResponse2);
|
64
|
-
|
65
|
-
const result = sut.end();
|
66
|
-
|
67
|
-
expect(result.id).toBe(bidResponse2.seatbid![0].bid[0].id);
|
68
|
-
});
|
69
|
-
|
70
|
-
it("throws error when attempting to end auction without bids", () => {
|
71
|
-
const sut = new Auction("impid-1");
|
72
|
-
|
73
|
-
expect(() => sut.end()).toThrow(BidNotFoundException);
|
74
|
-
});
|
75
|
-
it("returns losing bids when auction ends", () => {
|
76
|
-
const sut = new Auction(["impid-1", "impid-2"]);
|
77
|
-
const bidResponse = openrtbFaker.v26.bidResponse
|
78
|
-
.addBannerBid({
|
79
|
-
impid: "impid-1",
|
80
|
-
price: 10,
|
81
|
-
})
|
82
|
-
.addBannerBid({
|
83
|
-
impid: "impid-2",
|
84
|
-
price: 20,
|
85
|
-
})
|
86
|
-
.make();
|
87
|
-
sut.placeBidResponseV26(bidResponse);
|
88
|
-
|
89
|
-
sut.end();
|
90
|
-
|
91
|
-
const losingBids = sut.getLosingBids();
|
92
|
-
expect(losingBids.v26.length).toBe(1);
|
93
|
-
expect(losingBids.v26[0].id).toBe(bidResponse.seatbid![0].bid[0].id);
|
94
|
-
});
|
95
|
-
|
96
|
-
it("throws error when attempting to already ended auction", () => {
|
97
|
-
const sut = new Auction("impid-1");
|
98
|
-
const bidResponse = openrtbFaker.v26.bidResponse
|
99
|
-
.addBannerBid({ impid: "impid-1", price: 10 })
|
100
|
-
.make();
|
101
|
-
sut.placeBidResponseV26(bidResponse);
|
102
|
-
sut.end();
|
103
|
-
|
104
|
-
expect(() => sut.end()).toThrow(AlreadyEndedAuctionException);
|
105
|
-
});
|
106
|
-
|
107
|
-
it("sends loss notification when bid contains loss notice url", () => {
|
108
|
-
const fetchMock = vi.fn();
|
109
|
-
vi.stubGlobal("fetch", fetchMock);
|
110
|
-
const sut = new Auction(["impid-1", "impid-2"]);
|
111
|
-
const bidResponse = openrtbFaker.v26.bidResponse
|
112
|
-
.addBannerBid({
|
113
|
-
impid: "impid-1",
|
114
|
-
price: 10,
|
115
|
-
lurl: "https://example.com/lurl",
|
116
|
-
})
|
117
|
-
.addBannerBid({
|
118
|
-
impid: "impid-2",
|
119
|
-
price: 20,
|
120
|
-
})
|
121
|
-
.make();
|
122
|
-
sut.placeBidResponseV26(bidResponse);
|
123
|
-
|
124
|
-
sut.end();
|
125
|
-
|
126
|
-
expect(fetchMock).toHaveBeenCalledOnce();
|
127
|
-
expect(fetchMock).toHaveBeenCalledWith("https://example.com/lurl", {
|
128
|
-
keepalive: true,
|
129
|
-
});
|
130
|
-
});
|
131
|
-
|
132
|
-
it("does not send loss notification when bid does not contain loss notice url", () => {
|
133
|
-
const fetchMock = vi.fn();
|
134
|
-
vi.stubGlobal("fetch", fetchMock);
|
135
|
-
const sut = new Auction(["impid-1", "impid-2"]);
|
136
|
-
const bidResponse = openrtbFaker.v26.bidResponse
|
137
|
-
.addBannerBid({
|
138
|
-
impid: "impid-1",
|
139
|
-
price: 10,
|
140
|
-
})
|
141
|
-
.addBannerBid({
|
142
|
-
impid: "impid-2",
|
143
|
-
price: 20,
|
144
|
-
})
|
145
|
-
.make();
|
146
|
-
sut.placeBidResponseV26(bidResponse);
|
147
|
-
|
148
|
-
sut.end();
|
149
|
-
|
150
|
-
expect(fetchMock).not.toHaveBeenCalled();
|
151
|
-
});
|
152
|
-
|
153
|
-
it("does not send loss notification when loss processing is specified as false", () => {
|
154
|
-
const fetchMock = vi.fn();
|
155
|
-
vi.stubGlobal("fetch", fetchMock);
|
156
|
-
const sut = new Auction(["impid-1", "impid-2"], {
|
157
|
-
lossProcessing: false,
|
158
|
-
});
|
159
|
-
const bidResponse = openrtbFaker.v26.bidResponse
|
160
|
-
.addBannerBid({
|
161
|
-
impid: "impid-1",
|
162
|
-
price: 10,
|
163
|
-
lurl: "https://example.com/lurl",
|
164
|
-
})
|
165
|
-
.addBannerBid({
|
166
|
-
impid: "impid-2",
|
167
|
-
price: 20,
|
168
|
-
})
|
169
|
-
.make();
|
170
|
-
sut.placeBidResponseV26(bidResponse);
|
171
|
-
|
172
|
-
sut.end();
|
173
|
-
|
174
|
-
expect(fetchMock).not.toHaveBeenCalled();
|
175
|
-
});
|
176
|
-
});
|
package/tsconfig.json
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"compilerOptions": {
|
3
|
-
"target": "es2022",
|
4
|
-
"lib": ["es2022", "esnext.disposable", "dom"],
|
5
|
-
|
6
|
-
"module": "ESNext",
|
7
|
-
"moduleDetection": "force",
|
8
|
-
"allowJs": true,
|
9
|
-
|
10
|
-
"moduleResolution": "Bundler",
|
11
|
-
"allowImportingTsExtensions": true,
|
12
|
-
"verbatimModuleSyntax": true,
|
13
|
-
"isolatedModules": true,
|
14
|
-
"preserveConstEnums": true,
|
15
|
-
"noEmit": true,
|
16
|
-
|
17
|
-
"skipLibCheck": true,
|
18
|
-
"strict": true,
|
19
|
-
"noFallthroughCasesInSwitch": true,
|
20
|
-
"forceConsistentCasingInFileNames": true,
|
21
|
-
|
22
|
-
"baseUrl": ".",
|
23
|
-
"paths": {
|
24
|
-
"@/*": ["src/*"]
|
25
|
-
}
|
26
|
-
},
|
27
|
-
"include": ["**/*.ts"],
|
28
|
-
"exclude": ["node_modules"]
|
29
|
-
}
|
package/tsup.config.ts
DELETED
package/vitest.config.ts
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
import { fileURLToPath } from "node:url";
|
2
|
-
import path from "node:path";
|
3
|
-
import { defineConfig } from "vitest/config";
|
4
|
-
|
5
|
-
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
6
|
-
|
7
|
-
export default defineConfig({
|
8
|
-
test: {
|
9
|
-
globals: true,
|
10
|
-
alias: {
|
11
|
-
"@": path.resolve(__dirname, "src"),
|
12
|
-
},
|
13
|
-
},
|
14
|
-
});
|