@gscdump/analysis 0.25.6 → 0.25.7

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.
@@ -2388,6 +2388,34 @@ const dataQueryAnalyzer = defineAnalyzer({
2388
2388
  };
2389
2389
  }
2390
2390
  });
2391
+ const DEFAULT_LIMIT = 1e3;
2392
+ const MAX_LIMIT = 5e4;
2393
+ function clampLimit(limit, fallback = DEFAULT_LIMIT) {
2394
+ const n = Number(limit ?? fallback);
2395
+ if (!Number.isFinite(n) || n <= 0) return fallback;
2396
+ return Math.min(n, MAX_LIMIT);
2397
+ }
2398
+ function clampOffset(offset) {
2399
+ const n = Number(offset ?? 0);
2400
+ if (!Number.isFinite(n) || n < 0) return 0;
2401
+ return Math.floor(n);
2402
+ }
2403
+ function paginateClause(input) {
2404
+ const l = clampLimit(input.limit);
2405
+ const o = clampOffset(input.offset);
2406
+ return o > 0 ? `LIMIT ${l} OFFSET ${o}` : `LIMIT ${l}`;
2407
+ }
2408
+ function paginateInMemory(rows, input) {
2409
+ const l = clampLimit(input.limit, rows.length);
2410
+ const o = clampOffset(input.offset);
2411
+ return rows.slice(o, o + l);
2412
+ }
2413
+ function resolveSort(input, allowed, defaults) {
2414
+ return {
2415
+ sortBy: input.sortBy && allowed.includes(input.sortBy) ? input.sortBy : defaults.sortBy,
2416
+ sortDir: input.sortDir === "asc" || input.sortDir === "desc" ? input.sortDir : defaults.sortDir
2417
+ };
2418
+ }
2391
2419
  const sortResults$1 = createMetricSorter("lostClicks", {
2392
2420
  lostClicks: "desc",
2393
2421
  declinePercent: "desc",
@@ -2441,7 +2469,6 @@ const decayAnalyzer = defineAnalyzer({
2441
2469
  const { current: cur, previous: prev } = comparisonOf(params);
2442
2470
  const minPreviousClicks = params.minPreviousClicks ?? 50;
2443
2471
  const threshold = params.threshold ?? .2;
2444
- const limit = params.limit ?? 2e3;
2445
2472
  return {
2446
2473
  sql: `
2447
2474
  WITH cur AS (
@@ -2505,7 +2532,7 @@ const decayAnalyzer = defineAnalyzer({
2505
2532
  FROM joined
2506
2533
  WHERE declinePercent >= ? AND lostClicks > 0
2507
2534
  ORDER BY lostClicks DESC
2508
- LIMIT ${Number(limit)}
2535
+ LIMIT 2000
2509
2536
  `,
2510
2537
  params: [
2511
2538
  cur.startDate,
@@ -2529,25 +2556,28 @@ const decayAnalyzer = defineAnalyzer({
2529
2556
  }
2530
2557
  };
2531
2558
  },
2532
- reduceSql(rows) {
2533
- const arr = Array.isArray(rows) ? rows : [];
2559
+ reduceSql(rows, params) {
2560
+ const mapped = (Array.isArray(rows) ? rows : []).map((r) => ({
2561
+ page: str$12(r.page),
2562
+ currentClicks: num(r.currentClicks),
2563
+ previousClicks: num(r.previousClicks),
2564
+ lostClicks: num(r.lostClicks),
2565
+ declinePercent: num(r.declinePercent),
2566
+ currentPosition: num(r.currentPosition),
2567
+ previousPosition: num(r.previousPosition),
2568
+ positionDrop: num(r.positionDrop),
2569
+ series: parseJsonList$8(r.seriesJson).map((s) => ({
2570
+ week: str$12(s.week),
2571
+ clicks: num(s.clicks),
2572
+ impressions: num(s.impressions)
2573
+ }))
2574
+ }));
2534
2575
  return {
2535
- results: arr.map((r) => ({
2536
- page: str$12(r.page),
2537
- currentClicks: num(r.currentClicks),
2538
- previousClicks: num(r.previousClicks),
2539
- lostClicks: num(r.lostClicks),
2540
- declinePercent: num(r.declinePercent),
2541
- currentPosition: num(r.currentPosition),
2542
- previousPosition: num(r.previousPosition),
2543
- positionDrop: num(r.positionDrop),
2544
- series: parseJsonList$8(r.seriesJson).map((s) => ({
2545
- week: str$12(s.week),
2546
- clicks: num(s.clicks),
2547
- impressions: num(s.impressions)
2548
- }))
2549
- })),
2550
- meta: { total: arr.length }
2576
+ results: paginateInMemory(mapped, {
2577
+ limit: params.limit ?? 2e3,
2578
+ offset: params.offset
2579
+ }),
2580
+ meta: { total: mapped.length }
2551
2581
  };
2552
2582
  },
2553
2583
  buildRows(params) {
@@ -3426,34 +3456,6 @@ const moversAnalyzer = defineAnalyzer({
3426
3456
  })), [], params);
3427
3457
  }
3428
3458
  });
3429
- const DEFAULT_LIMIT = 1e3;
3430
- const MAX_LIMIT = 5e4;
3431
- function clampLimit(limit, fallback = DEFAULT_LIMIT) {
3432
- const n = Number(limit ?? fallback);
3433
- if (!Number.isFinite(n) || n <= 0) return fallback;
3434
- return Math.min(n, MAX_LIMIT);
3435
- }
3436
- function clampOffset(offset) {
3437
- const n = Number(offset ?? 0);
3438
- if (!Number.isFinite(n) || n < 0) return 0;
3439
- return Math.floor(n);
3440
- }
3441
- function paginateClause(input) {
3442
- const l = clampLimit(input.limit);
3443
- const o = clampOffset(input.offset);
3444
- return o > 0 ? `LIMIT ${l} OFFSET ${o}` : `LIMIT ${l}`;
3445
- }
3446
- function paginateInMemory(rows, input) {
3447
- const l = clampLimit(input.limit, rows.length);
3448
- const o = clampOffset(input.offset);
3449
- return rows.slice(o, o + l);
3450
- }
3451
- function resolveSort(input, allowed, defaults) {
3452
- return {
3453
- sortBy: input.sortBy && allowed.includes(input.sortBy) ? input.sortBy : defaults.sortBy,
3454
- sortDir: input.sortDir === "asc" || input.sortDir === "desc" ? input.sortDir : defaults.sortDir
3455
- };
3456
- }
3457
3459
  const EXPECTED_CTR_BY_POSITION = {
3458
3460
  1: .3,
3459
3461
  2: .15,
@@ -2388,6 +2388,28 @@ const dataQueryAnalyzer = defineAnalyzer({
2388
2388
  };
2389
2389
  }
2390
2390
  });
2391
+ const DEFAULT_LIMIT = 1e3;
2392
+ const MAX_LIMIT = 5e4;
2393
+ function clampLimit(limit, fallback = DEFAULT_LIMIT) {
2394
+ const n = Number(limit ?? fallback);
2395
+ if (!Number.isFinite(n) || n <= 0) return fallback;
2396
+ return Math.min(n, MAX_LIMIT);
2397
+ }
2398
+ function clampOffset(offset) {
2399
+ const n = Number(offset ?? 0);
2400
+ if (!Number.isFinite(n) || n < 0) return 0;
2401
+ return Math.floor(n);
2402
+ }
2403
+ function paginateClause(input) {
2404
+ const l = clampLimit(input.limit);
2405
+ const o = clampOffset(input.offset);
2406
+ return o > 0 ? `LIMIT ${l} OFFSET ${o}` : `LIMIT ${l}`;
2407
+ }
2408
+ function paginateInMemory(rows, input) {
2409
+ const l = clampLimit(input.limit, rows.length);
2410
+ const o = clampOffset(input.offset);
2411
+ return rows.slice(o, o + l);
2412
+ }
2391
2413
  const sortResults$1 = createMetricSorter("lostClicks", {
2392
2414
  lostClicks: "desc",
2393
2415
  declinePercent: "desc",
@@ -2441,7 +2463,6 @@ const decayAnalyzer = defineAnalyzer({
2441
2463
  const { current: cur, previous: prev } = comparisonOf(params);
2442
2464
  const minPreviousClicks = params.minPreviousClicks ?? 50;
2443
2465
  const threshold = params.threshold ?? .2;
2444
- const limit = params.limit ?? 2e3;
2445
2466
  return {
2446
2467
  sql: `
2447
2468
  WITH cur AS (
@@ -2505,7 +2526,7 @@ const decayAnalyzer = defineAnalyzer({
2505
2526
  FROM joined
2506
2527
  WHERE declinePercent >= ? AND lostClicks > 0
2507
2528
  ORDER BY lostClicks DESC
2508
- LIMIT ${Number(limit)}
2529
+ LIMIT 2000
2509
2530
  `,
2510
2531
  params: [
2511
2532
  cur.startDate,
@@ -2529,25 +2550,28 @@ const decayAnalyzer = defineAnalyzer({
2529
2550
  }
2530
2551
  };
2531
2552
  },
2532
- reduceSql(rows) {
2533
- const arr = Array.isArray(rows) ? rows : [];
2553
+ reduceSql(rows, params) {
2554
+ const mapped = (Array.isArray(rows) ? rows : []).map((r) => ({
2555
+ page: str$12(r.page),
2556
+ currentClicks: num(r.currentClicks),
2557
+ previousClicks: num(r.previousClicks),
2558
+ lostClicks: num(r.lostClicks),
2559
+ declinePercent: num(r.declinePercent),
2560
+ currentPosition: num(r.currentPosition),
2561
+ previousPosition: num(r.previousPosition),
2562
+ positionDrop: num(r.positionDrop),
2563
+ series: parseJsonList$8(r.seriesJson).map((s) => ({
2564
+ week: str$12(s.week),
2565
+ clicks: num(s.clicks),
2566
+ impressions: num(s.impressions)
2567
+ }))
2568
+ }));
2534
2569
  return {
2535
- results: arr.map((r) => ({
2536
- page: str$12(r.page),
2537
- currentClicks: num(r.currentClicks),
2538
- previousClicks: num(r.previousClicks),
2539
- lostClicks: num(r.lostClicks),
2540
- declinePercent: num(r.declinePercent),
2541
- currentPosition: num(r.currentPosition),
2542
- previousPosition: num(r.previousPosition),
2543
- positionDrop: num(r.positionDrop),
2544
- series: parseJsonList$8(r.seriesJson).map((s) => ({
2545
- week: str$12(s.week),
2546
- clicks: num(s.clicks),
2547
- impressions: num(s.impressions)
2548
- }))
2549
- })),
2550
- meta: { total: arr.length }
2570
+ results: paginateInMemory(mapped, {
2571
+ limit: params.limit ?? 2e3,
2572
+ offset: params.offset
2573
+ }),
2574
+ meta: { total: mapped.length }
2551
2575
  };
2552
2576
  },
2553
2577
  buildRows(params) {
@@ -3426,28 +3450,6 @@ const moversAnalyzer = defineAnalyzer({
3426
3450
  })), [], params);
3427
3451
  }
3428
3452
  });
3429
- const DEFAULT_LIMIT = 1e3;
3430
- const MAX_LIMIT = 5e4;
3431
- function clampLimit(limit, fallback = DEFAULT_LIMIT) {
3432
- const n = Number(limit ?? fallback);
3433
- if (!Number.isFinite(n) || n <= 0) return fallback;
3434
- return Math.min(n, MAX_LIMIT);
3435
- }
3436
- function clampOffset(offset) {
3437
- const n = Number(offset ?? 0);
3438
- if (!Number.isFinite(n) || n < 0) return 0;
3439
- return Math.floor(n);
3440
- }
3441
- function paginateClause(input) {
3442
- const l = clampLimit(input.limit);
3443
- const o = clampOffset(input.offset);
3444
- return o > 0 ? `LIMIT ${l} OFFSET ${o}` : `LIMIT ${l}`;
3445
- }
3446
- function paginateInMemory(rows, input) {
3447
- const l = clampLimit(input.limit, rows.length);
3448
- const o = clampOffset(input.offset);
3449
- return rows.slice(o, o + l);
3450
- }
3451
3453
  const EXPECTED_CTR_BY_POSITION = {
3452
3454
  1: .3,
3453
3455
  2: .15,
package/dist/index.mjs CHANGED
@@ -2754,6 +2754,28 @@ const dataQueryAnalyzer = defineAnalyzer$1({
2754
2754
  };
2755
2755
  }
2756
2756
  });
2757
+ const DEFAULT_LIMIT$1 = 1e3;
2758
+ const MAX_LIMIT = 5e4;
2759
+ function clampLimit(limit, fallback = DEFAULT_LIMIT$1) {
2760
+ const n = Number(limit ?? fallback);
2761
+ if (!Number.isFinite(n) || n <= 0) return fallback;
2762
+ return Math.min(n, MAX_LIMIT);
2763
+ }
2764
+ function clampOffset(offset) {
2765
+ const n = Number(offset ?? 0);
2766
+ if (!Number.isFinite(n) || n < 0) return 0;
2767
+ return Math.floor(n);
2768
+ }
2769
+ function paginateClause(input) {
2770
+ const l = clampLimit(input.limit);
2771
+ const o = clampOffset(input.offset);
2772
+ return o > 0 ? `LIMIT ${l} OFFSET ${o}` : `LIMIT ${l}`;
2773
+ }
2774
+ function paginateInMemory(rows, input) {
2775
+ const l = clampLimit(input.limit, rows.length);
2776
+ const o = clampOffset(input.offset);
2777
+ return rows.slice(o, o + l);
2778
+ }
2757
2779
  const sortResults$1 = createMetricSorter("lostClicks", {
2758
2780
  lostClicks: "desc",
2759
2781
  declinePercent: "desc",
@@ -2807,7 +2829,6 @@ const decayAnalyzer = defineAnalyzer$1({
2807
2829
  const { current: cur, previous: prev } = comparisonOf$1(params);
2808
2830
  const minPreviousClicks = params.minPreviousClicks ?? 50;
2809
2831
  const threshold = params.threshold ?? .2;
2810
- const limit = params.limit ?? 2e3;
2811
2832
  return {
2812
2833
  sql: `
2813
2834
  WITH cur AS (
@@ -2871,7 +2892,7 @@ const decayAnalyzer = defineAnalyzer$1({
2871
2892
  FROM joined
2872
2893
  WHERE declinePercent >= ? AND lostClicks > 0
2873
2894
  ORDER BY lostClicks DESC
2874
- LIMIT ${Number(limit)}
2895
+ LIMIT 2000
2875
2896
  `,
2876
2897
  params: [
2877
2898
  cur.startDate,
@@ -2895,25 +2916,28 @@ const decayAnalyzer = defineAnalyzer$1({
2895
2916
  }
2896
2917
  };
2897
2918
  },
2898
- reduceSql(rows) {
2899
- const arr = Array.isArray(rows) ? rows : [];
2919
+ reduceSql(rows, params) {
2920
+ const mapped = (Array.isArray(rows) ? rows : []).map((r) => ({
2921
+ page: str$12(r.page),
2922
+ currentClicks: num$1(r.currentClicks),
2923
+ previousClicks: num$1(r.previousClicks),
2924
+ lostClicks: num$1(r.lostClicks),
2925
+ declinePercent: num$1(r.declinePercent),
2926
+ currentPosition: num$1(r.currentPosition),
2927
+ previousPosition: num$1(r.previousPosition),
2928
+ positionDrop: num$1(r.positionDrop),
2929
+ series: parseJsonList$8(r.seriesJson).map((s) => ({
2930
+ week: str$12(s.week),
2931
+ clicks: num$1(s.clicks),
2932
+ impressions: num$1(s.impressions)
2933
+ }))
2934
+ }));
2900
2935
  return {
2901
- results: arr.map((r) => ({
2902
- page: str$12(r.page),
2903
- currentClicks: num$1(r.currentClicks),
2904
- previousClicks: num$1(r.previousClicks),
2905
- lostClicks: num$1(r.lostClicks),
2906
- declinePercent: num$1(r.declinePercent),
2907
- currentPosition: num$1(r.currentPosition),
2908
- previousPosition: num$1(r.previousPosition),
2909
- positionDrop: num$1(r.positionDrop),
2910
- series: parseJsonList$8(r.seriesJson).map((s) => ({
2911
- week: str$12(s.week),
2912
- clicks: num$1(s.clicks),
2913
- impressions: num$1(s.impressions)
2914
- }))
2915
- })),
2916
- meta: { total: arr.length }
2936
+ results: paginateInMemory(mapped, {
2937
+ limit: params.limit ?? 2e3,
2938
+ offset: params.offset
2939
+ }),
2940
+ meta: { total: mapped.length }
2917
2941
  };
2918
2942
  },
2919
2943
  buildRows(params) {
@@ -3788,28 +3812,6 @@ const moversAnalyzer = defineAnalyzer$1({
3788
3812
  })), [], params);
3789
3813
  }
3790
3814
  });
3791
- const DEFAULT_LIMIT$1 = 1e3;
3792
- const MAX_LIMIT = 5e4;
3793
- function clampLimit(limit, fallback = DEFAULT_LIMIT$1) {
3794
- const n = Number(limit ?? fallback);
3795
- if (!Number.isFinite(n) || n <= 0) return fallback;
3796
- return Math.min(n, MAX_LIMIT);
3797
- }
3798
- function clampOffset(offset) {
3799
- const n = Number(offset ?? 0);
3800
- if (!Number.isFinite(n) || n < 0) return 0;
3801
- return Math.floor(n);
3802
- }
3803
- function paginateClause(input) {
3804
- const l = clampLimit(input.limit);
3805
- const o = clampOffset(input.offset);
3806
- return o > 0 ? `LIMIT ${l} OFFSET ${o}` : `LIMIT ${l}`;
3807
- }
3808
- function paginateInMemory(rows, input) {
3809
- const l = clampLimit(input.limit, rows.length);
3810
- const o = clampOffset(input.offset);
3811
- return rows.slice(o, o + l);
3812
- }
3813
3815
  const EXPECTED_CTR_BY_POSITION = {
3814
3816
  1: .3,
3815
3817
  2: .15,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gscdump/analysis",
3
3
  "type": "module",
4
- "version": "0.25.6",
4
+ "version": "0.25.7",
5
5
  "description": "GSC analyzers — striking-distance, opportunity, movers, decay, brand, clustering, concentration, seasonality. Pure row-based + DuckDB-native.",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",
@@ -70,9 +70,9 @@
70
70
  },
71
71
  "dependencies": {
72
72
  "drizzle-orm": "1.0.0-rc.3",
73
- "@gscdump/engine": "0.25.6",
74
- "@gscdump/engine-gsc-api": "0.25.6",
75
- "gscdump": "0.25.6"
73
+ "@gscdump/engine": "0.25.7",
74
+ "@gscdump/engine-gsc-api": "0.25.7",
75
+ "gscdump": "0.25.7"
76
76
  },
77
77
  "devDependencies": {
78
78
  "vitest": "^4.1.7"