@gscdump/analysis 0.7.1 → 0.7.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.
@@ -1,150 +0,0 @@
1
- import { MS_PER_DAY, daysAgo, toIsoDate } from "gscdump";
2
- function defaultEndDate() {
3
- return daysAgo(3);
4
- }
5
- function defaultStartDate() {
6
- return daysAgo(31);
7
- }
8
- function periodOf(params) {
9
- return {
10
- startDate: params.startDate || defaultStartDate(),
11
- endDate: params.endDate || defaultEndDate()
12
- };
13
- }
14
- function comparisonOf(params) {
15
- if (!params.prevStartDate || !params.prevEndDate) throw new Error(`${params.type} analysis requires prevStartDate and prevEndDate`);
16
- return {
17
- current: periodOf(params),
18
- previous: {
19
- startDate: params.prevStartDate,
20
- endDate: params.prevEndDate
21
- }
22
- };
23
- }
24
- function parseIso(s) {
25
- return /* @__PURE__ */ new Date(`${s}T00:00:00Z`);
26
- }
27
- function addDays(d, n) {
28
- return new Date(d.getTime() + n * MS_PER_DAY);
29
- }
30
- function daysBetween(start, end) {
31
- return Math.round((parseIso(end).getTime() - parseIso(start).getTime()) / MS_PER_DAY) + 1;
32
- }
33
- function resolveWindow(opts) {
34
- const anchor = opts.anchor ? parseIso(opts.anchor) : /* @__PURE__ */ new Date();
35
- const anchorIso = toIsoDate(anchor);
36
- let start;
37
- let end;
38
- switch (opts.preset) {
39
- case "last-7d":
40
- end = anchorIso;
41
- start = toIsoDate(addDays(anchor, -6));
42
- break;
43
- case "last-28d":
44
- end = anchorIso;
45
- start = toIsoDate(addDays(anchor, -27));
46
- break;
47
- case "last-30d":
48
- end = anchorIso;
49
- start = toIsoDate(addDays(anchor, -29));
50
- break;
51
- case "last-90d":
52
- end = anchorIso;
53
- start = toIsoDate(addDays(anchor, -89));
54
- break;
55
- case "last-180d":
56
- end = anchorIso;
57
- start = toIsoDate(addDays(anchor, -179));
58
- break;
59
- case "last-365d":
60
- end = anchorIso;
61
- start = toIsoDate(addDays(anchor, -364));
62
- break;
63
- case "mtd":
64
- end = anchorIso;
65
- start = toIsoDate(new Date(Date.UTC(anchor.getUTCFullYear(), anchor.getUTCMonth(), 1)));
66
- break;
67
- case "ytd":
68
- end = anchorIso;
69
- start = toIsoDate(new Date(Date.UTC(anchor.getUTCFullYear(), 0, 1)));
70
- break;
71
- case "custom":
72
- if (!opts.start || !opts.end) throw new Error("resolveWindow: preset=custom requires start and end");
73
- start = opts.start;
74
- end = opts.end;
75
- break;
76
- }
77
- const days = daysBetween(start, end);
78
- const result = {
79
- start,
80
- end,
81
- days
82
- };
83
- const mode = opts.comparison ?? "none";
84
- if (mode === "prev-period") {
85
- const prevEnd = toIsoDate(addDays(parseIso(start), -1));
86
- result.comparison = {
87
- start: toIsoDate(addDays(parseIso(prevEnd), -(days - 1))),
88
- end: prevEnd
89
- };
90
- } else if (mode === "yoy") {
91
- const prevEnd = toIsoDate(addDays(parseIso(end), -365));
92
- result.comparison = {
93
- start: toIsoDate(addDays(parseIso(start), -365)),
94
- end: prevEnd
95
- };
96
- }
97
- return result;
98
- }
99
- function windowToPeriod(w) {
100
- return {
101
- startDate: w.start,
102
- endDate: w.end
103
- };
104
- }
105
- function windowToComparisonPeriod(w) {
106
- if (!w.comparison) return void 0;
107
- return {
108
- current: {
109
- startDate: w.start,
110
- endDate: w.end
111
- },
112
- previous: {
113
- startDate: w.comparison.start,
114
- endDate: w.comparison.end
115
- }
116
- };
117
- }
118
- const DEFAULT_FILL = {
119
- clicks: 0,
120
- impressions: 0,
121
- ctr: 0,
122
- position: 0
123
- };
124
- function padTimeseries(rows, options) {
125
- const { startDate, endDate } = options;
126
- const dateKey = options.dateKey ?? "date";
127
- const fill = options.fill ?? DEFAULT_FILL;
128
- const byDate = /* @__PURE__ */ new Map();
129
- for (const row of rows) {
130
- const d = String(row[dateKey]);
131
- const bucket = byDate.get(d);
132
- if (bucket) bucket.push(row);
133
- else byDate.set(d, [row]);
134
- }
135
- const result = [];
136
- const start = /* @__PURE__ */ new Date(`${startDate}T00:00:00Z`);
137
- const end = /* @__PURE__ */ new Date(`${endDate}T00:00:00Z`);
138
- if (Number.isNaN(start.getTime()) || Number.isNaN(end.getTime())) throw new Error(`padTimeseries: invalid date range ${startDate}..${endDate}`);
139
- for (let cursorMs = start.getTime(), endMs = end.getTime(); cursorMs <= endMs; cursorMs += MS_PER_DAY) {
140
- const dateStr = toIsoDate(new Date(cursorMs));
141
- const existing = byDate.get(dateStr);
142
- if (existing) result.push(...existing);
143
- else result.push({
144
- ...fill,
145
- [dateKey]: dateStr
146
- });
147
- }
148
- return result;
149
- }
150
- export { comparisonOf, defaultEndDate, defaultStartDate, padTimeseries, periodOf, resolveWindow, windowToComparisonPeriod, windowToPeriod };