@usagekit/providers 0.9.0 → 0.9.1

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.
@@ -113,8 +113,15 @@ export const descriptor = {
113
113
  },
114
114
  free("serp.google.organic.tasks_ready", "Google organic SERP, tasks ready", "GET", "/v3/serp/google/organic/tasks_ready"),
115
115
  free("serp.google.organic.task_get.advanced", "Google organic SERP, task get advanced", "GET", "/v3/serp/google/organic/task_get/advanced/:id"),
116
- ...labs.map(([name, label]) => live(`dataforseo_labs.google.${name}.live`, label, `/v3/dataforseo_labs/google/${name}/live`, ["itemCount", "clickstream"])),
117
- ...backlinks.map(([name, label]) => live(`backlinks.${name}.live`, label, `/v3/backlinks/${name}/live`, ["itemCount"])),
116
+ ...labs.map(([name, label]) => live(`dataforseo_labs.google.${name}.live`, label, `/v3/dataforseo_labs/google/${name}/live`, [
117
+ "itemCount",
118
+ "clickstream",
119
+ ...(name === "historical_rank_overview" ? ["dateFrom", "dateTo"] : []),
120
+ ])),
121
+ ...backlinks.map(([name, label]) => live(`backlinks.${name}.live`, label, `/v3/backlinks/${name}/live`, [
122
+ "itemCount",
123
+ ...(name === "history" ? ["dateFrom", "dateTo"] : []),
124
+ ])),
118
125
  free("appendix.user_data", "User data (balance, limits, prices)", "GET", "/v3/appendix/user_data"),
119
126
  free("dataforseo_labs.status", "Labs status", "GET", "/v3/dataforseo_labs/status"),
120
127
  ],
@@ -1,5 +1,6 @@
1
1
  import { addQuantity, formatQuantity } from "@usagekit/core";
2
2
  import { descriptor } from "./descriptor.js";
3
+ import { historyWindowOptions } from "./history-window.js";
3
4
  import { listEstimate } from "../prices.js";
4
5
  import { pointer } from "../pointer.js";
5
6
  import { decimalQuantity, moneyFromDollars, requestsMeasured } from "../receipts.js";
@@ -253,6 +254,7 @@ export const extractors = {
253
254
  return {};
254
255
  const task = first, options = {};
255
256
  const keys = operation.optionKeys ?? [];
257
+ Object.assign(options, historyWindowOptions(operation.id, task));
256
258
  if (operation.billable) {
257
259
  const fields = operation.requestPricing;
258
260
  const unlisted = !fields ||
@@ -304,9 +306,8 @@ export const extractors = {
304
306
  task.limit === undefined
305
307
  ? operation.requestPricing?.priceFields.limit?.defaultCount
306
308
  : task.limit
307
- : // Summary returns one row. History has no documented request count.
309
+ : // Summary returns one row; explicit history dates were bounded above.
308
310
  // https://docs.dataforseo.com/v3/backlinks/summary/live/
309
- // https://docs.dataforseo.com/v3/backlinks/history/live/
310
311
  operation.id === "backlinks.summary.live"
311
312
  ? 1
312
313
  : undefined;
@@ -0,0 +1,5 @@
1
+ /** Both history APIs return at most one item per month. Include partial boundary months.
2
+ * https://docs.dataforseo.com/v3/backlinks-history-live/
3
+ * https://docs.dataforseo.com/v3/dataforseo_labs-google-historical_rank_overview-live/
4
+ */
5
+ export declare function historyWindowOptions(operation: string, task: Readonly<Record<string, unknown>>): Record<string, string>;
@@ -0,0 +1,36 @@
1
+ const historyOperations = new Set([
2
+ "backlinks.history.live",
3
+ "dataforseo_labs.google.historical_rank_overview.live",
4
+ ]);
5
+ function validDate(value) {
6
+ if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}$/.test(value))
7
+ return false;
8
+ const date = new Date(`${value}T00:00:00Z`);
9
+ return Number.isFinite(date.getTime()) && date.toISOString().slice(0, 10) === value;
10
+ }
11
+ /** Both history APIs return at most one item per month. Include partial boundary months.
12
+ * https://docs.dataforseo.com/v3/backlinks-history-live/
13
+ * https://docs.dataforseo.com/v3/dataforseo_labs-google-historical_rank_overview-live/
14
+ */
15
+ export function historyWindowOptions(operation, task) {
16
+ if (!historyOperations.has(operation))
17
+ return {};
18
+ const from = task.date_from;
19
+ const to = task.date_to;
20
+ const options = {};
21
+ if (validDate(from))
22
+ options.dateFrom = from;
23
+ else if (from !== undefined)
24
+ options.pricingUnknown = "true";
25
+ if (validDate(to))
26
+ options.dateTo = to;
27
+ else if (to !== undefined)
28
+ options.pricingUnknown = "true";
29
+ if (!validDate(from) || !validDate(to))
30
+ return options;
31
+ if (from > to)
32
+ return { ...options, pricingUnknown: "true" };
33
+ const monthIndex = (date) => Number(date.slice(0, 4)) * 12 + Number(date.slice(5, 7));
34
+ options.itemCount = String(monthIndex(to) - monthIndex(from) + 1);
35
+ return options;
36
+ }
@@ -7,7 +7,7 @@ export const requestPricing = {
7
7
  // Request field inventory: https://docs.dataforseo.com/v3/backlinks/backlinks/live/
8
8
  "backlinks.backlinks.live": {
9
9
  source: "https://docs.dataforseo.com/v3/backlinks/backlinks/live/",
10
- formula: "2.4 + 0.0036 * rowCount cents; summary one row, backlinks limit, history count unknown",
10
+ formula: "2.4 + 0.0036 * rowCount cents; summary one row, backlinks limit, history inclusive month bound with explicit dates",
11
11
  priceFields: {
12
12
  limit: {
13
13
  formula: "(base + per-item * limit); documented default, 1..1000; zero unknown",
@@ -32,13 +32,13 @@ export const requestPricing = {
32
32
  // Request field inventory: https://docs.dataforseo.com/v3/backlinks/history/live/
33
33
  "backlinks.history.live": {
34
34
  source: "https://docs.dataforseo.com/v3/backlinks/history/live/",
35
- formula: "2.4 + 0.0036 * rowCount cents; summary one row, backlinks limit, history count unknown",
35
+ formula: "2.4 + 0.0036 * rowCount cents; history inclusive month bound with explicit dates",
36
36
  priceFields: {
37
37
  date_from: {
38
- formula: "changes returned row count; count not derivable from the request",
38
+ formula: "inclusive first calendar month; both dates required to bound item count",
39
39
  },
40
40
  date_to: {
41
- formula: "changes returned row count; count not derivable from the request",
41
+ formula: "inclusive last calendar month; both dates required to bound item count",
42
42
  },
43
43
  },
44
44
  neutralFields: ["target", "rank_scale", "tag"],
@@ -46,7 +46,7 @@ export const requestPricing = {
46
46
  // Request field inventory: https://docs.dataforseo.com/v3/backlinks/summary/live/
47
47
  "backlinks.summary.live": {
48
48
  source: "https://docs.dataforseo.com/v3/backlinks/summary/live/",
49
- formula: "2.4 + 0.0036 * rowCount cents; summary one row, backlinks limit, history count unknown",
49
+ formula: "2.4 + 0.0036 * rowCount cents; summary one row, backlinks limit, history inclusive month bound with explicit dates",
50
50
  priceFields: {},
51
51
  neutralFields: [
52
52
  "target",
@@ -63,7 +63,7 @@ export const requestPricing = {
63
63
  // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/domain_rank_overview/live/
64
64
  "dataforseo_labs.google.domain_rank_overview.live": {
65
65
  source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/domain_rank_overview/live/",
66
- formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
66
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count requires explicit date bounds; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
67
67
  priceFields: {
68
68
  limit: {
69
69
  formula: "(base + per-item * limit); documented default, 1..1000; zero unknown",
@@ -84,16 +84,16 @@ export const requestPricing = {
84
84
  // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/historical_rank_overview/live/
85
85
  "dataforseo_labs.google.historical_rank_overview.live": {
86
86
  source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/historical_rank_overview/live/",
87
- formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
87
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count requires explicit date bounds; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
88
88
  priceFields: {
89
89
  include_clickstream_data: {
90
90
  formula: "true doubles entire request charge",
91
91
  },
92
92
  date_from: {
93
- formula: "changes returned row count; count not derivable from the request",
93
+ formula: "inclusive first calendar month; both dates required to bound item count",
94
94
  },
95
95
  date_to: {
96
- formula: "changes returned row count; count not derivable from the request",
96
+ formula: "inclusive last calendar month; both dates required to bound item count",
97
97
  },
98
98
  },
99
99
  neutralFields: [
@@ -110,7 +110,7 @@ export const requestPricing = {
110
110
  // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_ideas/live/
111
111
  "dataforseo_labs.google.keyword_ideas.live": {
112
112
  source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_ideas/live/",
113
- formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
113
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count requires explicit date bounds; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
114
114
  priceFields: {
115
115
  include_clickstream_data: {
116
116
  formula: "true doubles entire request charge",
@@ -142,7 +142,7 @@ export const requestPricing = {
142
142
  // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_overview/live/
143
143
  "dataforseo_labs.google.keyword_overview.live": {
144
144
  source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_overview/live/",
145
- formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
145
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count requires explicit date bounds; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
146
146
  priceFields: {
147
147
  keywords: {
148
148
  formula: "base + 0.012 cents * keywords.length; clickstream doubles total",
@@ -163,7 +163,7 @@ export const requestPricing = {
163
163
  // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_suggestions/live/
164
164
  "dataforseo_labs.google.keyword_suggestions.live": {
165
165
  source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_suggestions/live/",
166
- formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
166
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count requires explicit date bounds; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
167
167
  priceFields: {
168
168
  include_seed_keyword: {
169
169
  formula: "false neutral; true unknown because extra item count is unconfirmed",
@@ -199,7 +199,7 @@ export const requestPricing = {
199
199
  // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/ranked_keywords/live/
200
200
  "dataforseo_labs.google.ranked_keywords.live": {
201
201
  source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/ranked_keywords/live/",
202
- formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
202
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count requires explicit date bounds; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
203
203
  priceFields: {
204
204
  include_clickstream_data: {
205
205
  formula: "true doubles entire request charge",
@@ -228,7 +228,7 @@ export const requestPricing = {
228
228
  // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/related_keywords/live/
229
229
  "dataforseo_labs.google.related_keywords.live": {
230
230
  source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/related_keywords/live/",
231
- formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
231
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count requires explicit date bounds; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
232
232
  priceFields: {
233
233
  include_seed_keyword: {
234
234
  formula: "false neutral; true unknown because extra item count is unconfirmed",
@@ -261,7 +261,7 @@ export const requestPricing = {
261
261
  // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/relevant_pages/live/
262
262
  "dataforseo_labs.google.relevant_pages.live": {
263
263
  source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/relevant_pages/live/",
264
- formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
264
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count requires explicit date bounds; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
265
265
  priceFields: {
266
266
  include_clickstream_data: {
267
267
  formula: "true doubles entire request charge",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usagekit/providers",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "description": "Provider descriptors, catalog, price tables, extractors, fixtures and probes.",
@@ -31,7 +31,7 @@
31
31
  "prepack": "node ../../scripts/package-license.mjs"
32
32
  },
33
33
  "dependencies": {
34
- "@usagekit/core": "0.9.0"
34
+ "@usagekit/core": "0.9.1"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "vitest": ">=5.0.1 <6",