@wavebirdai/api 0.1.0-beta.8 → 0.1.0-beta.9

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/README.md CHANGED
@@ -9,7 +9,7 @@ You need a saved Wavebird Test project and placement in Dashboard, a Server Test
9
9
  1. Install the package and generate the route files for your app directory:
10
10
 
11
11
  ```sh
12
- npm install @wavebirdai/api@0.1.0-beta.6
12
+ npm install @wavebirdai/api@0.1.0-beta.9
13
13
  ./node_modules/.bin/wavebird-next init --lang ts --root . --app-dir src/app
14
14
  ```
15
15
 
package/dist/browser.js CHANGED
@@ -31,7 +31,8 @@ export function createPublisherAds(options) {
31
31
  const turnBinding = options.turnBinding === true;
32
32
  const validId = value => typeof value === "string" && /^[A-Za-z0-9_-]{1,128}$/.test(value);
33
33
  if (turnBinding && !validId(options.sessionId)) throw new Error("publisher_trusted_session_required");
34
- const timing = options.timing || "during", consentMode = options.consentMode || "wavebird_consent";
34
+ const timing = options.timing === undefined ? "during" : options.timing;
35
+ const consentMode = options.consentMode === undefined ? "wavebird_consent" : options.consentMode;
35
36
  if (!["before", "during", "after"].includes(timing) || !["wavebird_consent", "own_cmp"].includes(consentMode)) throw new Error("Invalid publisher configuration");
36
37
  let binding = { userId: options.userId, conversationId: options.conversationId,
37
38
  sessionId: turnBinding ? options.sessionId : crypto.randomUUID() };
package/dist/server.js CHANGED
@@ -7,6 +7,9 @@ const PREFERENCE_TTL = 30 * 24 * 60 * 60;
7
7
  const MAX_PUBLISHER_BODY_BYTES = 16 * 1024;
8
8
  const MAX_WAVEBIRD_RESPONSE_BYTES = 256 * 1024;
9
9
  const MAX_PARALLEL_WAVEBIRD_REQUESTS = 2;
10
+ const MAX_ALLOWED_SIZES = 8;
11
+ const MAX_SIZE_EDGE = 4096;
12
+ const MAX_ENVELOPE_EDGE = 8192;
10
13
  const ID = /^[A-Za-z0-9_-]{1,128}$/;
11
14
  const JOB_ID = /^job_[A-Za-z0-9_-]{1,128}$/;
12
15
  const PLACEMENT_KEY = /^[a-z0-9][a-z0-9_-]{0,63}$/;
@@ -39,11 +42,15 @@ function normalizeOptions(options) {
39
42
  if (options.gdprApplies !== undefined && typeof options.gdprApplies !== "boolean") throw new Error("publisher_gdpr_invalid");
40
43
  if (!Array.isArray(options.allowedFormats) || options.allowedFormats.length === 0 || options.allowedFormats.some(value => !["banner", "native", "clip"].includes(value))) throw new Error("publisher_formats_invalid");
41
44
  if (!["above", "below", "sidebar", "between"].includes(options.positionHint)) throw new Error("publisher_position_invalid");
42
- if (!Array.isArray(options.allowedSizes) || options.allowedSizes.length === 0 || options.allowedSizes.some(size => !size || typeof size !== "object" || Object.keys(size).some(key => !["width", "height", "formats"].includes(key)) || !Number.isSafeInteger(size.width) || !Number.isSafeInteger(size.height) || size.width < 1 || size.height < 1 ||
45
+ if (!Array.isArray(options.allowedSizes) || options.allowedSizes.length === 0 || options.allowedSizes.length > MAX_ALLOWED_SIZES || options.allowedSizes.some(size => !size || typeof size !== "object" || Object.keys(size).some(key => !["width", "height", "formats"].includes(key)) || !Number.isSafeInteger(size.width) || !Number.isSafeInteger(size.height) || size.width < 1 || size.height < 1 || size.width > MAX_SIZE_EDGE || size.height > MAX_SIZE_EDGE ||
43
46
  (size.formats !== undefined && (!Array.isArray(size.formats) || size.formats.length === 0 || size.formats.some(format => !options.allowedFormats.includes(format)))))) throw new Error("publisher_sizes_invalid");
47
+ if (new Set(options.allowedSizes.map(size => `${size.width}x${size.height}`)).size !== options.allowedSizes.length)
48
+ throw new Error("publisher_sizes_invalid");
44
49
  const maxWidth = options.maxWidth === undefined ? options.allowedSizes.reduce((max, size) => Math.max(max, size.width), 0) : options.maxWidth;
45
50
  const maxHeight = options.maxHeight === undefined ? options.allowedSizes.reduce((max, size) => Math.max(max, size.height), 0) : options.maxHeight;
46
- if (!Number.isSafeInteger(maxWidth) || maxWidth < 1 || !Number.isSafeInteger(maxHeight) || maxHeight < 1) throw new Error("publisher_envelope_invalid");
51
+ if (!Number.isSafeInteger(maxWidth) || maxWidth < 1 || maxWidth > MAX_ENVELOPE_EDGE ||
52
+ !Number.isSafeInteger(maxHeight) || maxHeight < 1 || maxHeight > MAX_ENVELOPE_EDGE)
53
+ throw new Error("publisher_envelope_invalid");
47
54
  const eligibleSizes = options.allowedSizes.filter(size => size.width <= maxWidth && size.height <= maxHeight);
48
55
  const hasFloor = Object.hasOwn(options, "bidfloor");
49
56
  const hasCurrency = Object.hasOwn(options, "bidfloorCurrency");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wavebirdai/api",
3
- "version": "0.1.0-beta.8",
3
+ "version": "0.1.0-beta.9",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Integrate Banner, Native, and Clip placements into authenticated chat apps with server-side keys, consent, and generation lifecycle handling",
package/src/browser.js CHANGED
@@ -31,7 +31,8 @@ export function createPublisherAds(options) {
31
31
  const turnBinding = options.turnBinding === true;
32
32
  const validId = value => typeof value === "string" && /^[A-Za-z0-9_-]{1,128}$/.test(value);
33
33
  if (turnBinding && !validId(options.sessionId)) throw new Error("publisher_trusted_session_required");
34
- const timing = options.timing || "during", consentMode = options.consentMode || "wavebird_consent";
34
+ const timing = options.timing === undefined ? "during" : options.timing;
35
+ const consentMode = options.consentMode === undefined ? "wavebird_consent" : options.consentMode;
35
36
  if (!["before", "during", "after"].includes(timing) || !["wavebird_consent", "own_cmp"].includes(consentMode)) throw new Error("Invalid publisher configuration");
36
37
  let binding = { userId: options.userId, conversationId: options.conversationId,
37
38
  sessionId: turnBinding ? options.sessionId : crypto.randomUUID() };
package/src/server.js CHANGED
@@ -7,6 +7,9 @@ const PREFERENCE_TTL = 30 * 24 * 60 * 60;
7
7
  const MAX_PUBLISHER_BODY_BYTES = 16 * 1024;
8
8
  const MAX_WAVEBIRD_RESPONSE_BYTES = 256 * 1024;
9
9
  const MAX_PARALLEL_WAVEBIRD_REQUESTS = 2;
10
+ const MAX_ALLOWED_SIZES = 8;
11
+ const MAX_SIZE_EDGE = 4096;
12
+ const MAX_ENVELOPE_EDGE = 8192;
10
13
  const ID = /^[A-Za-z0-9_-]{1,128}$/;
11
14
  const JOB_ID = /^job_[A-Za-z0-9_-]{1,128}$/;
12
15
  const PLACEMENT_KEY = /^[a-z0-9][a-z0-9_-]{0,63}$/;
@@ -39,11 +42,15 @@ function normalizeOptions(options) {
39
42
  if (options.gdprApplies !== undefined && typeof options.gdprApplies !== "boolean") throw new Error("publisher_gdpr_invalid");
40
43
  if (!Array.isArray(options.allowedFormats) || options.allowedFormats.length === 0 || options.allowedFormats.some(value => !["banner", "native", "clip"].includes(value))) throw new Error("publisher_formats_invalid");
41
44
  if (!["above", "below", "sidebar", "between"].includes(options.positionHint)) throw new Error("publisher_position_invalid");
42
- if (!Array.isArray(options.allowedSizes) || options.allowedSizes.length === 0 || options.allowedSizes.some(size => !size || typeof size !== "object" || Object.keys(size).some(key => !["width", "height", "formats"].includes(key)) || !Number.isSafeInteger(size.width) || !Number.isSafeInteger(size.height) || size.width < 1 || size.height < 1 ||
45
+ if (!Array.isArray(options.allowedSizes) || options.allowedSizes.length === 0 || options.allowedSizes.length > MAX_ALLOWED_SIZES || options.allowedSizes.some(size => !size || typeof size !== "object" || Object.keys(size).some(key => !["width", "height", "formats"].includes(key)) || !Number.isSafeInteger(size.width) || !Number.isSafeInteger(size.height) || size.width < 1 || size.height < 1 || size.width > MAX_SIZE_EDGE || size.height > MAX_SIZE_EDGE ||
43
46
  (size.formats !== undefined && (!Array.isArray(size.formats) || size.formats.length === 0 || size.formats.some(format => !options.allowedFormats.includes(format)))))) throw new Error("publisher_sizes_invalid");
47
+ if (new Set(options.allowedSizes.map(size => `${size.width}x${size.height}`)).size !== options.allowedSizes.length)
48
+ throw new Error("publisher_sizes_invalid");
44
49
  const maxWidth = options.maxWidth === undefined ? options.allowedSizes.reduce((max, size) => Math.max(max, size.width), 0) : options.maxWidth;
45
50
  const maxHeight = options.maxHeight === undefined ? options.allowedSizes.reduce((max, size) => Math.max(max, size.height), 0) : options.maxHeight;
46
- if (!Number.isSafeInteger(maxWidth) || maxWidth < 1 || !Number.isSafeInteger(maxHeight) || maxHeight < 1) throw new Error("publisher_envelope_invalid");
51
+ if (!Number.isSafeInteger(maxWidth) || maxWidth < 1 || maxWidth > MAX_ENVELOPE_EDGE ||
52
+ !Number.isSafeInteger(maxHeight) || maxHeight < 1 || maxHeight > MAX_ENVELOPE_EDGE)
53
+ throw new Error("publisher_envelope_invalid");
47
54
  const eligibleSizes = options.allowedSizes.filter(size => size.width <= maxWidth && size.height <= maxHeight);
48
55
  const hasFloor = Object.hasOwn(options, "bidfloor");
49
56
  const hasCurrency = Object.hasOwn(options, "bidfloorCurrency");