@gscdump/analysis 3.0.0 → 3.2.0
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 +10 -7
- package/dist/analyzer/all.mjs +9 -9
- package/dist/analyzers/bipartite-pagerank.mjs +1 -1
- package/dist/analyzers/brand.mjs +2 -2
- package/dist/analyzers/cannibalization.mjs +2 -2
- package/dist/analyzers/clustering.mjs +2 -2
- package/dist/analyzers/concentration.mjs +2 -2
- package/dist/analyzers/dark-traffic.mjs +1 -1
- package/dist/analyzers/decay.mjs +2 -2
- package/dist/analyzers/device-gap.mjs +1 -1
- package/dist/analyzers/intent-atlas.mjs +1 -1
- package/dist/analyzers/keyword-breadth.mjs +1 -1
- package/dist/analyzers/long-tail.mjs +1 -1
- package/dist/analyzers/movers.mjs +2 -2
- package/dist/analyzers/opportunity.mjs +1 -1
- package/dist/analyzers/position-distribution.mjs +1 -1
- package/dist/analyzers/position-volatility.mjs +1 -1
- package/dist/analyzers/query-migration.mjs +1 -1
- package/dist/analyzers/seasonality.mjs +2 -2
- package/dist/analyzers/stl-decompose.mjs +1 -1
- package/dist/analyzers/striking-distance.mjs +1 -1
- package/dist/analyzers/survival.mjs +1 -1
- package/dist/analyzers/trends.mjs +1 -1
- package/dist/analyzers/zero-click.mjs +1 -1
- package/dist/browser.d.mts +1 -1
- package/dist/index.d.mts +2 -13
- package/dist/index.mjs +4 -15
- package/dist/query/index.mjs +1 -1
- package/dist/query-dimension.d.mts +3 -0
- package/dist/query-dimension.mjs +3 -0
- package/package.json +9 -4
package/README.md
CHANGED
|
@@ -16,8 +16,11 @@ npm install @gscdump/analysis
|
|
|
16
16
|
|
|
17
17
|
| Subpath | Use when |
|
|
18
18
|
|---|---|
|
|
19
|
-
| `@gscdump/analysis` |
|
|
19
|
+
| `@gscdump/analysis` | Pure analyzers, `analyzeInBrowser`, and shared analyzer contracts. |
|
|
20
20
|
| `@gscdump/analysis/registry` | Pre-built `defaultAnalyzerRegistry` (rows + sql). Convenience for callers who don't care about bundle size. |
|
|
21
|
+
| `@gscdump/analysis/errors` | Typed analysis failures and rendering helpers. |
|
|
22
|
+
| `@gscdump/analysis/report` | Report registry and runtime. |
|
|
23
|
+
| `@gscdump/analysis/source` | Portable source factories. |
|
|
21
24
|
|
|
22
25
|
The contract layer (`Analyzer`, `Plan`, `Capability`, `AnalysisParams`, `AnalysisResult`, `AnalysisQuerySource`, `runAnalyzerFromSource`, `createAnalyzerRegistry`, `defineAnalyzer`, period helpers, `createEngineQuerySource`) lives in `@gscdump/engine` under the `/analyzer`, `/analysis-types`, `/period`, `/source`, and `/resolver` subpaths. Most are re-exported from `@gscdump/analysis` for convenience.
|
|
23
26
|
|
|
@@ -44,11 +47,11 @@ const decay = analyzeDecay(currentRows, previousRows)
|
|
|
44
47
|
Meta-analyses live in the report layer. Run a composed evidence report via `runReport`:
|
|
45
48
|
|
|
46
49
|
```ts
|
|
50
|
+
import { defaultAnalyzerRegistry } from '@gscdump/analysis/registry'
|
|
47
51
|
import {
|
|
48
|
-
defaultAnalyzerRegistry,
|
|
49
52
|
defaultReportRegistry,
|
|
50
53
|
runReport,
|
|
51
|
-
} from '@gscdump/analysis'
|
|
54
|
+
} from '@gscdump/analysis/report'
|
|
52
55
|
import { resolveWindow } from '@gscdump/engine/period'
|
|
53
56
|
|
|
54
57
|
const report = defaultReportRegistry.getReport('health')!
|
|
@@ -76,7 +79,7 @@ const movers = await analyzeMoversFromSource(source, { current, previous })
|
|
|
76
79
|
SQL-native path. `SQL_ANALYZERS` dispatch through `runAnalyzerFromSource` against an engine-backed source.
|
|
77
80
|
|
|
78
81
|
```ts
|
|
79
|
-
import { ROW_ANALYZERS, SQL_ANALYZERS } from '@gscdump/analysis'
|
|
82
|
+
import { ROW_ANALYZERS, SQL_ANALYZERS } from '@gscdump/analysis/registry'
|
|
80
83
|
import { createAnalyzerRegistry, runAnalyzerFromSource } from '@gscdump/engine/analyzer'
|
|
81
84
|
import { createEngineQuerySource } from '@gscdump/engine/source'
|
|
82
85
|
|
|
@@ -145,8 +148,8 @@ Available source factories:
|
|
|
145
148
|
|
|
146
149
|
- `createGscApiQuerySource({ client, siteUrl })` — `@gscdump/engine-gsc-api`
|
|
147
150
|
- `createLiveGscSource({ accessToken, siteUrl })` — `@gscdump/engine-gsc-api`
|
|
148
|
-
- `createCompositeSource({ engine, gsc })` — `@gscdump/analysis`; engine first, GSC fallback
|
|
149
|
-
- `createInMemoryQuerySource({ queryRows })` — `@gscdump/analysis`
|
|
151
|
+
- `createCompositeSource({ engine, gsc })` — `@gscdump/analysis/source`; engine first, GSC fallback
|
|
152
|
+
- `createInMemoryQuerySource({ queryRows })` — `@gscdump/analysis/source`
|
|
150
153
|
- `createEngineQuerySource({ engine, ctx })` — `@gscdump/engine/source`
|
|
151
154
|
- `createSqliteQuerySource({ ... })` — `@gscdump/engine-sqlite`
|
|
152
155
|
|
|
@@ -172,7 +175,7 @@ Presets: `last-7d`, `last-28d`, `last-30d`, `last-90d`, `last-180d`, `last-365d`
|
|
|
172
175
|
| Row analyzers (`analyzeMovers`, `analyzeDecay`, ...) | Public |
|
|
173
176
|
| Source factories + `analyzeFromSource` | Public |
|
|
174
177
|
| `Analyzer<P, R>` contract + `createAnalyzerRegistry` (re-exported from `@gscdump/engine/analyzer`) | Public |
|
|
175
|
-
| Source factories
|
|
178
|
+
| Source factories under `@gscdump/analysis/source` | Public |
|
|
176
179
|
| Per-analyzer modules under `analysis/src/analyzers/<name>` | Private |
|
|
177
180
|
|
|
178
181
|
## Related
|
package/dist/analyzer/all.mjs
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
import { bayesianCtrAnalyzer } from "../analyzers/bayesian-ctr.mjs";
|
|
2
|
-
import { bipartitePagerankAnalyzer } from "../analyzers/bipartite-pagerank.mjs";
|
|
3
1
|
import { brandAnalyzer } from "../analyzers/brand.mjs";
|
|
4
2
|
import { cannibalizationAnalyzer } from "../analyzers/cannibalization.mjs";
|
|
5
|
-
import { changePointAnalyzer } from "../analyzers/change-point.mjs";
|
|
6
3
|
import { clusteringAnalyzer } from "../analyzers/clustering.mjs";
|
|
7
4
|
import { concentrationAnalyzer } from "../analyzers/concentration.mjs";
|
|
5
|
+
import { decayAnalyzer } from "../analyzers/decay.mjs";
|
|
6
|
+
import { moversAnalyzer } from "../analyzers/movers.mjs";
|
|
7
|
+
import { opportunityAnalyzer } from "../analyzers/opportunity.mjs";
|
|
8
|
+
import { seasonalityAnalyzer } from "../analyzers/seasonality.mjs";
|
|
9
|
+
import { strikingDistanceAnalyzer } from "../analyzers/striking-distance.mjs";
|
|
10
|
+
import { zeroClickAnalyzer } from "../analyzers/zero-click.mjs";
|
|
11
|
+
import { bayesianCtrAnalyzer } from "../analyzers/bayesian-ctr.mjs";
|
|
12
|
+
import { bipartitePagerankAnalyzer } from "../analyzers/bipartite-pagerank.mjs";
|
|
13
|
+
import { changePointAnalyzer } from "../analyzers/change-point.mjs";
|
|
8
14
|
import { contentVelocityAnalyzer } from "../analyzers/content-velocity.mjs";
|
|
9
15
|
import { ctrAnomalyAnalyzer } from "../analyzers/ctr-anomaly.mjs";
|
|
10
16
|
import { ctrCurveAnalyzer } from "../analyzers/ctr-curve.mjs";
|
|
11
17
|
import { darkTrafficAnalyzer } from "../analyzers/dark-traffic.mjs";
|
|
12
18
|
import { dataDetailAnalyzer } from "../analyzers/data-detail.mjs";
|
|
13
19
|
import { dataQueryAnalyzer } from "../analyzers/data-query.mjs";
|
|
14
|
-
import { decayAnalyzer } from "../analyzers/decay.mjs";
|
|
15
20
|
import { deviceGapAnalyzer } from "../analyzers/device-gap.mjs";
|
|
16
21
|
import { intentAtlasAnalyzer } from "../analyzers/intent-atlas.mjs";
|
|
17
22
|
import { keywordBreadthAnalyzer } from "../analyzers/keyword-breadth.mjs";
|
|
18
23
|
import { longTailAnalyzer } from "../analyzers/long-tail.mjs";
|
|
19
|
-
import { moversAnalyzer } from "../analyzers/movers.mjs";
|
|
20
|
-
import { opportunityAnalyzer } from "../analyzers/opportunity.mjs";
|
|
21
24
|
import { positionDistributionAnalyzer } from "../analyzers/position-distribution.mjs";
|
|
22
25
|
import { positionVolatilityAnalyzer } from "../analyzers/position-volatility.mjs";
|
|
23
26
|
import { queryMigrationAnalyzer } from "../analyzers/query-migration.mjs";
|
|
24
|
-
import { seasonalityAnalyzer } from "../analyzers/seasonality.mjs";
|
|
25
27
|
import { stlDecomposeAnalyzer } from "../analyzers/stl-decompose.mjs";
|
|
26
|
-
import { strikingDistanceAnalyzer } from "../analyzers/striking-distance.mjs";
|
|
27
28
|
import { survivalAnalyzer } from "../analyzers/survival.mjs";
|
|
28
29
|
import { trendsAnalyzer } from "../analyzers/trends.mjs";
|
|
29
|
-
import { zeroClickAnalyzer } from "../analyzers/zero-click.mjs";
|
|
30
30
|
const ALL_ANALYZERS = [
|
|
31
31
|
bayesianCtrAnalyzer,
|
|
32
32
|
bipartitePagerankAnalyzer,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
2
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
2
3
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
3
4
|
import { periodOf } from "@gscdump/engine/period";
|
|
4
5
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
5
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
6
6
|
const BIPARTITE_PAGERANK_ITERATIONS = 25;
|
|
7
7
|
const BIPARTITE_PAGERANK_DAMPING = .85;
|
|
8
8
|
const bipartitePagerankAnalyzer = defineAnalyzer({
|
package/dist/analyzers/brand.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { rowString } from "../analyzer/row-values.mjs";
|
|
2
1
|
import { queriesQueryState } from "../analyzer/adapt-rows.mjs";
|
|
2
|
+
import { rowString } from "../analyzer/row-values.mjs";
|
|
3
3
|
import { analysisErrorToException, analysisErrors } from "../errors.mjs";
|
|
4
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
4
5
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
5
6
|
import { periodOf } from "@gscdump/engine/period";
|
|
6
7
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
7
8
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
8
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
9
9
|
import { err, ok, unwrapResult } from "gscdump/result";
|
|
10
10
|
function escapeRegexAlt(s) {
|
|
11
11
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
2
1
|
import { queriesQueryState } from "../analyzer/adapt-rows.mjs";
|
|
2
|
+
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
3
3
|
import { createSorter } from "../types.mjs";
|
|
4
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
4
5
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
5
6
|
import { periodOf } from "@gscdump/engine/period";
|
|
6
7
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
7
8
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
8
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
9
9
|
const sortRowResults = createSorter((item, metric) => {
|
|
10
10
|
switch (metric) {
|
|
11
11
|
case "clicks": return item.totalClicks;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
2
1
|
import { queriesQueryState } from "../analyzer/adapt-rows.mjs";
|
|
2
|
+
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
3
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
3
4
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
4
5
|
import { periodOf } from "@gscdump/engine/period";
|
|
5
6
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
6
7
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
7
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
8
8
|
const INTENT_PREFIXES_REGEX = "^(how to|what is|what are|why is|why do|where to|when to|best|top|vs|versus|compare|review|buy|cheap|free|near me)(\\s|$)";
|
|
9
9
|
const INTENT_PREFIXES = [
|
|
10
10
|
"how to",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
2
1
|
import { pagesQueryState, queriesQueryState } from "../analyzer/adapt-rows.mjs";
|
|
2
|
+
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
3
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
3
4
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
4
5
|
import { periodOf } from "@gscdump/engine/period";
|
|
5
6
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
6
7
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
7
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
8
8
|
function analyzeConcentration(items, options = {}) {
|
|
9
9
|
const { topN = 10 } = options;
|
|
10
10
|
if (items.length === 0) return {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
2
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
2
3
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
3
4
|
import { periodOf } from "@gscdump/engine/period";
|
|
4
5
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
5
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
6
6
|
const darkTrafficAnalyzer = defineAnalyzer({
|
|
7
7
|
id: "dark-traffic",
|
|
8
8
|
buildSql(params) {
|
package/dist/analyzers/decay.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
2
1
|
import { pagesQueryState } from "../analyzer/adapt-rows.mjs";
|
|
2
|
+
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
3
3
|
import { buildPeriodMap, createMetricSorter } from "../types.mjs";
|
|
4
4
|
import { paginateInMemory } from "../analyzer/paginate.mjs";
|
|
5
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
5
6
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
6
7
|
import { comparisonOf } from "@gscdump/engine/period";
|
|
7
8
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
8
9
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
9
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
10
10
|
const sortResults = createMetricSorter("lostClicks", {
|
|
11
11
|
lostClicks: "desc",
|
|
12
12
|
declinePercent: "desc",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { rowString } from "../analyzer/row-values.mjs";
|
|
2
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
2
3
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
3
4
|
import { periodOf } from "@gscdump/engine/period";
|
|
4
5
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
5
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
6
6
|
const deviceGapAnalyzer = defineAnalyzer({
|
|
7
7
|
id: "device-gap",
|
|
8
8
|
buildSql(params) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
2
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
2
3
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
3
4
|
import { defaultEndDate } from "@gscdump/engine/period";
|
|
4
5
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
5
6
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
6
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
7
7
|
import { daysAgoUtc } from "gscdump/dates";
|
|
8
8
|
const INTENT_ATLAS_STOP_WORDS = [
|
|
9
9
|
"the",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
2
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
2
3
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
3
4
|
import { periodOf } from "@gscdump/engine/period";
|
|
4
5
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
5
6
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
6
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
7
7
|
const keywordBreadthAnalyzer = defineAnalyzer({
|
|
8
8
|
id: "keyword-breadth",
|
|
9
9
|
buildSql(params) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
2
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
2
3
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
3
4
|
import { periodOf } from "@gscdump/engine/period";
|
|
4
5
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
5
6
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
6
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
7
7
|
function downsampleLogRank(points) {
|
|
8
8
|
const toPoint = (p) => ({
|
|
9
9
|
rank: num(p.rank),
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
2
1
|
import { queriesQueryState } from "../analyzer/adapt-rows.mjs";
|
|
2
|
+
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
3
3
|
import { buildPeriodMap } from "../types.mjs";
|
|
4
4
|
import { percentDifference } from "../scoring.mjs";
|
|
5
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
5
6
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
6
7
|
import { comparisonOf } from "@gscdump/engine/period";
|
|
7
8
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
8
9
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
9
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
10
10
|
function withCanonicalFields(r) {
|
|
11
11
|
return {
|
|
12
12
|
...r,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { queriesQueryState } from "../analyzer/adapt-rows.mjs";
|
|
2
2
|
import { paginateClause, paginateSortedInMemory } from "../analyzer/paginate.mjs";
|
|
3
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
3
4
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
4
5
|
import { periodOf } from "@gscdump/engine/period";
|
|
5
6
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
6
7
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
7
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
8
8
|
const EXPECTED_CTR_BY_POSITION = {
|
|
9
9
|
1: .3,
|
|
10
10
|
2: .15,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { rowString } from "../analyzer/row-values.mjs";
|
|
2
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
2
3
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
3
4
|
import { periodOf } from "@gscdump/engine/period";
|
|
4
5
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
5
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
6
6
|
const positionDistributionAnalyzer = defineAnalyzer({
|
|
7
7
|
id: "position-distribution",
|
|
8
8
|
buildSql(params) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { rowString } from "../analyzer/row-values.mjs";
|
|
2
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
2
3
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
3
4
|
import { periodOf } from "@gscdump/engine/period";
|
|
4
5
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
5
6
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
6
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
7
7
|
const positionVolatilityAnalyzer = defineAnalyzer({
|
|
8
8
|
id: "position-volatility",
|
|
9
9
|
buildSql(params) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
2
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
2
3
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
3
4
|
import { periodOf } from "@gscdump/engine/period";
|
|
4
5
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
5
6
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
6
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
7
7
|
import { MS_PER_DAY, toIsoDate } from "gscdump/dates";
|
|
8
8
|
const queryMigrationAnalyzer = defineAnalyzer({
|
|
9
9
|
id: "query-migration",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { rowBoolean, rowString } from "../analyzer/row-values.mjs";
|
|
2
1
|
import { datesQueryState } from "../analyzer/adapt-rows.mjs";
|
|
2
|
+
import { rowBoolean, rowString } from "../analyzer/row-values.mjs";
|
|
3
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
3
4
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
4
5
|
import { periodOf } from "@gscdump/engine/period";
|
|
5
6
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
6
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
7
7
|
function calculateCV(values) {
|
|
8
8
|
if (values.length === 0) return 0;
|
|
9
9
|
const mean = values.reduce((a, b) => a + b, 0) / values.length;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { parseJsonRows, rowBoolean, rowString } from "../analyzer/row-values.mjs";
|
|
2
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
2
3
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
3
4
|
import { defaultEndDate } from "@gscdump/engine/period";
|
|
4
5
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
5
6
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
6
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
7
7
|
import { daysAgoUtc } from "gscdump/dates";
|
|
8
8
|
const stlDecomposeAnalyzer = defineAnalyzer({
|
|
9
9
|
id: "stl-decompose",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { queriesQueryState } from "../analyzer/adapt-rows.mjs";
|
|
2
2
|
import { paginateSortedInMemory } from "../analyzer/paginate.mjs";
|
|
3
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
3
4
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
4
5
|
import { periodOf } from "@gscdump/engine/period";
|
|
5
6
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
6
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
7
7
|
const DEFAULT_ROW_LIMIT = 25e3;
|
|
8
8
|
function paginateStrikingDistance(results, options) {
|
|
9
9
|
return paginateSortedInMemory(results, {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
2
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
2
3
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
3
4
|
import { defaultEndDate } from "@gscdump/engine/period";
|
|
4
5
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
5
6
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
6
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
7
7
|
import { MS_PER_DAY, daysAgoUtc } from "gscdump/dates";
|
|
8
8
|
const survivalAnalyzer = defineAnalyzer({
|
|
9
9
|
id: "survival",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { parseJsonRows, rowString } from "../analyzer/row-values.mjs";
|
|
2
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
2
3
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
3
4
|
import { defaultEndDate } from "@gscdump/engine/period";
|
|
4
5
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
5
6
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
6
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
7
7
|
import { MS_PER_DAY, toIsoDate } from "gscdump/dates";
|
|
8
8
|
const trendsAnalyzer = defineAnalyzer({
|
|
9
9
|
id: "trends",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { paginateClause, paginateSortedInMemory } from "../analyzer/paginate.mjs";
|
|
2
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
2
3
|
import { defineAnalyzer } from "@gscdump/engine/analyzer";
|
|
3
4
|
import { periodOf } from "@gscdump/engine/period";
|
|
4
5
|
import { enumeratePartitions } from "@gscdump/engine/planner";
|
|
5
6
|
import { METRIC_EXPR } from "@gscdump/engine/sql-fragments";
|
|
6
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
7
7
|
import { between, date, gsc, page, query } from "gscdump/query";
|
|
8
8
|
const DEFAULT_ROW_LIMIT = 25e3;
|
|
9
9
|
function analyzeZeroClick(rows, options = {}) {
|
package/dist/browser.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AnalyzerRegistry } from "@gscdump/engine/analyzer";
|
|
2
1
|
import { AnalysisParams, AnalysisResult } from "@gscdump/engine/analysis-types";
|
|
2
|
+
import { AnalyzerRegistry } from "@gscdump/engine/analyzer";
|
|
3
3
|
import { AttachedTableRunner, AttachedTableRunner as AnalyzerRunner, AttachedTableSourceOptions, AttachedTableSourceOptions as BrowserAnalyzeOptions } from "@gscdump/engine/source";
|
|
4
4
|
declare function analyzeInBrowser(runner: AttachedTableRunner, opts: AttachedTableSourceOptions, params: AnalysisParams, registry: AnalyzerRegistry): Promise<AnalysisResult>;
|
|
5
5
|
export { type AnalyzerRunner, type BrowserAnalyzeOptions, analyzeInBrowser };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import { ROW_ANALYZERS } from "./analyzer/row-analyzers.mjs";
|
|
2
|
-
import { SQL_ANALYZERS } from "./sql-analyzers.mjs";
|
|
3
|
-
import { defaultAnalyzerRegistry } from "./default-registry.mjs";
|
|
4
|
-
import { AnalysisError, AnalysisErrorKind, analysisErrorToException, analysisErrors, formatAnalysisError, isAnalysisError } from "./errors.mjs";
|
|
5
1
|
import { BaseMetrics, DateRow, PageRow, QueriesRow, QueryPageRow, SortOrder, createSorter } from "./types.mjs";
|
|
6
2
|
import { BrandSegmentationOptions, BrandSegmentationResult, BrandSegmentationRow, BrandSummary, analyzeBrandSegmentation } from "./analyzers/brand.mjs";
|
|
7
3
|
import { CannibalizationCompetitor, CannibalizationEvent, CannibalizationOptions, CannibalizationPage, CannibalizationResult, CannibalizationSortMetric, analyzeCannibalization } from "./analyzers/cannibalization.mjs";
|
|
@@ -16,17 +12,10 @@ import { ZeroClickOptions, ZeroClickResult, analyzeZeroClick } from "./analyzers
|
|
|
16
12
|
import { AnalyzerRunner, BrowserAnalyzeOptions, analyzeInBrowser } from "./browser.mjs";
|
|
17
13
|
import { INTENT_CLASSIFIER_VERSION, IntentClassification, SEARCH_INTENT_CODE, SearchIntent, classifyQueryIntent, encodeIntent } from "./query/intent.mjs";
|
|
18
14
|
import { NORMALIZER_VERSION, normalizeQuery } from "./query/normalize.mjs";
|
|
19
|
-
import { FormatReportOptions, formatReport } from "./report/format.mjs";
|
|
20
|
-
import { REPORTS, defaultReportRegistry } from "./report/registry.mjs";
|
|
21
|
-
import { DryRunReportResult, RunReportOptions, dryRunReport, runReport, runReportResult } from "./report/runtime.mjs";
|
|
22
|
-
import "./report/index.mjs";
|
|
23
15
|
import { CurrentSitemapScope, SITEMAP_SYNC_COLLAPSE_POLICY, SITEMAP_TRUST_COLLAPSE_POLICY, SitemapCollapsePolicy, SitemapCollapseState, SitemapDelta, SitemapHealthDiff, SitemapHealthInput, SitemapHealthRow, SitemapHealthTotals, classifySitemapCollapse, compareCurrentSitemapScope, diffSitemapHealth, sitemapHistoryHasCollapse } from "./sitemap-health.mjs";
|
|
24
|
-
import {
|
|
25
|
-
import { IN_MEMORY_DEFAULT_CAPABILITIES, InMemoryQuerySourceOptions, createInMemoryQuerySource } from "./source/in-memory.mjs";
|
|
26
|
-
import "./source/index.mjs";
|
|
16
|
+
import { AnalysisParams, AnalysisResult, AnalysisTool, num } from "@gscdump/engine/analysis-types";
|
|
27
17
|
import { Analyzer, AnalyzerCapabilityError, AnalyzerRegistry, AnalyzerRegistryInit, AnalyzerVariants, DefineAnalyzerOptions, DefinedAnalyzer, Plan, ReduceContext, ReduceCtx, Reducer, RequiredCapability, RowQueriesPlan, SqlExtraQuery, SqlPlan, SqlPlanSpec, TypedRowQuery, createAnalyzerRegistry, defineAnalyzer, runAnalyzerFromSource } from "@gscdump/engine/analyzer";
|
|
28
18
|
import { AnalysisPeriod, ComparisonMode, ComparisonPeriod, PadTimeseriesOptions, ResolveWindowOptions, ResolvedWindow, WindowPreset, comparisonOf, padTimeseries, periodOf, resolveWindow } from "@gscdump/engine/period";
|
|
29
|
-
import { AnalysisParams, AnalysisResult, AnalysisTool, num } from "@gscdump/engine/analysis-types";
|
|
30
19
|
import { AnalysisQuerySource, AnalysisSourceKind, ENGINE_QUERY_CAPABILITIES, EngineQuerySourceOptions, ExecuteSqlOptions, FileSet, QueryRow, SourceCapabilities, createEngineQuerySource, queryRows, runAnalyzerWithEngine } from "@gscdump/engine/source";
|
|
31
20
|
import { DefineReportOptions, DefinedReport, ReportContext, ReportFinding, ReportPlanStep, ReportResult, ReportSection } from "@gscdump/engine/report";
|
|
32
|
-
export { type
|
|
21
|
+
export { type AnalysisParams, type AnalysisPeriod, type AnalysisQuerySource, type AnalysisResult, type AnalysisSourceKind, type AnalysisTool, type Analyzer, AnalyzerCapabilityError, type AnalyzerRegistry, type AnalyzerRegistryInit, type AnalyzerRunner, type AnalyzerVariants, type BaseMetrics, type BrandSegmentationOptions, type BrandSegmentationResult, type BrandSegmentationRow, type BrandSummary, type BrowserAnalyzeOptions, type CannibalizationCompetitor, type CannibalizationEvent, type CannibalizationOptions, type CannibalizationPage, type CannibalizationResult, type CannibalizationSortMetric, type ClusterType, type ClusteringOptions, type ClusteringResult, type ComparisonMode, type ComparisonPeriod, type ConcentrationInput, type ConcentrationItem, type ConcentrationOptions, type ConcentrationResult, type ConcentrationRiskLevel, type CurrentSitemapScope, type DateRow, type DecayInput, type DecayOptions, type DecayResult, type DecaySeriesPoint, type DecaySortMetric, type DefineAnalyzerOptions, type DefineReportOptions, type DefinedAnalyzer, type DefinedReport, ENGINE_QUERY_CAPABILITIES, type EngineQuerySourceOptions, type ExecuteSqlOptions, type FileSet, INTENT_CLASSIFIER_VERSION, type IntentClassification, type KeywordCluster, type MonthlyData, type MoverData, type MoversInput, type MoversOptions, type MoversResult, type MoversSortMetric, NORMALIZER_VERSION, type OpportunityFactors, type OpportunityOptions, type OpportunityResult, type OpportunitySortMetric, type OpportunityWeights, type PadTimeseriesOptions, type PageRow, type Plan, type QueriesRow, type QueryPageRow, type QueryRow, type ReduceContext, type ReduceCtx, type Reducer, type ReportContext, type ReportFinding, type ReportPlanStep, type ReportResult, type ReportSection, type RequiredCapability, type ResolveWindowOptions, type ResolvedWindow, type RowQueriesPlan, SEARCH_INTENT_CODE, SITEMAP_SYNC_COLLAPSE_POLICY, SITEMAP_TRUST_COLLAPSE_POLICY, type SearchIntent, type SeasonalityMetric, type SeasonalityOptions, type SeasonalityResult, type SitemapCollapsePolicy, type SitemapCollapseState, type SitemapDelta, type SitemapHealthDiff, type SitemapHealthInput, type SitemapHealthRow, type SitemapHealthTotals, type SortOrder, type SourceCapabilities, type SqlExtraQuery, type SqlPlan, type SqlPlanSpec, type StrikingDistanceInputRow, type StrikingDistanceOptions, type StrikingDistanceResult, type TypedRowQuery, type WindowPreset, type ZeroClickOptions, type ZeroClickResult, analyzeBrandSegmentation, analyzeCannibalization, analyzeClustering, analyzeConcentration, analyzeDecay, analyzeInBrowser, analyzeKeywordConcentration, analyzeMovers, analyzeOpportunity, analyzePageConcentration, analyzeSeasonality, analyzeStrikingDistance, analyzeZeroClick, classifyQueryIntent, classifySitemapCollapse, compareCurrentSitemapScope, comparisonOf, createAnalyzerRegistry, createEngineQuerySource, createSorter, defineAnalyzer, diffSitemapHealth, encodeIntent, normalizeQuery, num, padTimeseries, periodOf, queryRows, resolveWindow, runAnalyzerFromSource, runAnalyzerWithEngine, sitemapHistoryHasCollapse };
|
package/dist/index.mjs
CHANGED
|
@@ -1,31 +1,20 @@
|
|
|
1
|
-
import { analysisErrorToException, analysisErrors, formatAnalysisError, isAnalysisError } from "./errors.mjs";
|
|
2
1
|
import { analyzeBrandSegmentation } from "./analyzers/brand.mjs";
|
|
3
2
|
import { createSorter } from "./types.mjs";
|
|
4
3
|
import { analyzeCannibalization } from "./analyzers/cannibalization.mjs";
|
|
5
4
|
import { analyzeClustering } from "./analyzers/clustering.mjs";
|
|
6
5
|
import { analyzeConcentration, analyzeKeywordConcentration, analyzePageConcentration } from "./analyzers/concentration.mjs";
|
|
7
|
-
import { INTENT_CLASSIFIER_VERSION, SEARCH_INTENT_CODE, classifyQueryIntent, encodeIntent } from "./query/intent.mjs";
|
|
8
|
-
import { NORMALIZER_VERSION, normalizeQuery } from "./query/normalize.mjs";
|
|
9
6
|
import { analyzeDecay } from "./analyzers/decay.mjs";
|
|
10
7
|
import { analyzeMovers } from "./analyzers/movers.mjs";
|
|
11
8
|
import { analyzeOpportunity } from "./analyzers/opportunity.mjs";
|
|
12
9
|
import { analyzeSeasonality } from "./analyzers/seasonality.mjs";
|
|
13
10
|
import { analyzeStrikingDistance } from "./analyzers/striking-distance.mjs";
|
|
14
11
|
import { analyzeZeroClick } from "./analyzers/zero-click.mjs";
|
|
15
|
-
import { ROW_ANALYZERS } from "./analyzer/row-analyzers.mjs";
|
|
16
12
|
import { analyzeInBrowser } from "./browser.mjs";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import { formatReport } from "./report/format.mjs";
|
|
20
|
-
import { REPORTS, defaultReportRegistry } from "./report/registry.mjs";
|
|
21
|
-
import { dryRunReport, runReport, runReportResult } from "./report/runtime.mjs";
|
|
22
|
-
import "./report/index.mjs";
|
|
13
|
+
import { INTENT_CLASSIFIER_VERSION, SEARCH_INTENT_CODE, classifyQueryIntent, encodeIntent } from "./query/intent.mjs";
|
|
14
|
+
import { NORMALIZER_VERSION, normalizeQuery } from "./query/normalize.mjs";
|
|
23
15
|
import { SITEMAP_SYNC_COLLAPSE_POLICY, SITEMAP_TRUST_COLLAPSE_POLICY, classifySitemapCollapse, compareCurrentSitemapScope, diffSitemapHealth, sitemapHistoryHasCollapse } from "./sitemap-health.mjs";
|
|
24
|
-
import {
|
|
25
|
-
import { IN_MEMORY_DEFAULT_CAPABILITIES, createInMemoryQuerySource } from "./source/in-memory.mjs";
|
|
26
|
-
import "./source/index.mjs";
|
|
16
|
+
import { num } from "@gscdump/engine/analysis-types";
|
|
27
17
|
import { AnalyzerCapabilityError, createAnalyzerRegistry, defineAnalyzer, runAnalyzerFromSource } from "@gscdump/engine/analyzer";
|
|
28
18
|
import { comparisonOf, padTimeseries, periodOf, resolveWindow } from "@gscdump/engine/period";
|
|
29
|
-
import { num } from "@gscdump/engine/analysis-types";
|
|
30
19
|
import { ENGINE_QUERY_CAPABILITIES, createEngineQuerySource, queryRows, runAnalyzerWithEngine } from "@gscdump/engine/source";
|
|
31
|
-
export { AnalyzerCapabilityError, ENGINE_QUERY_CAPABILITIES, INTENT_CLASSIFIER_VERSION,
|
|
20
|
+
export { AnalyzerCapabilityError, ENGINE_QUERY_CAPABILITIES, INTENT_CLASSIFIER_VERSION, NORMALIZER_VERSION, SEARCH_INTENT_CODE, SITEMAP_SYNC_COLLAPSE_POLICY, SITEMAP_TRUST_COLLAPSE_POLICY, analyzeBrandSegmentation, analyzeCannibalization, analyzeClustering, analyzeConcentration, analyzeDecay, analyzeInBrowser, analyzeKeywordConcentration, analyzeMovers, analyzeOpportunity, analyzePageConcentration, analyzeSeasonality, analyzeStrikingDistance, analyzeZeroClick, classifyQueryIntent, classifySitemapCollapse, compareCurrentSitemapScope, comparisonOf, createAnalyzerRegistry, createEngineQuerySource, createSorter, defineAnalyzer, diffSitemapHealth, encodeIntent, normalizeQuery, num, padTimeseries, periodOf, queryRows, resolveWindow, runAnalyzerFromSource, runAnalyzerWithEngine, sitemapHistoryHasCollapse };
|
package/dist/query/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildDataDetailPlan, buildDataDetailRows, buildDataQueryPlan, buildDataQueryRows, shapeDataDetailRowResults, shapeDataDetailRows, shapeDataQueryRowResults, shapeDataQueryRows } from "./analyzers.mjs";
|
|
2
1
|
import "./intent.mjs";
|
|
3
2
|
import "./normalize.mjs";
|
|
3
|
+
import { buildDataDetailPlan, buildDataDetailRows, buildDataQueryPlan, buildDataQueryRows, shapeDataDetailRowResults, shapeDataDetailRows, shapeDataQueryRowResults, shapeDataQueryRows } from "./analyzers.mjs";
|
|
4
4
|
export { buildDataDetailPlan, buildDataDetailRows, buildDataQueryPlan, buildDataQueryRows, shapeDataDetailRowResults, shapeDataDetailRows, shapeDataQueryRowResults, shapeDataQueryRows };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { INTENT_CLASSIFIER_VERSION, IntentClassification, SEARCH_INTENT_CODE, SearchIntent, classifyQueryIntent, encodeIntent } from "./query/intent.mjs";
|
|
2
|
+
import { NORMALIZER_VERSION, normalizeQuery } from "./query/normalize.mjs";
|
|
3
|
+
export { INTENT_CLASSIFIER_VERSION, type IntentClassification, NORMALIZER_VERSION, SEARCH_INTENT_CODE, type SearchIntent, classifyQueryIntent, encodeIntent, normalizeQuery };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { INTENT_CLASSIFIER_VERSION, SEARCH_INTENT_CODE, classifyQueryIntent, encodeIntent } from "./query/intent.mjs";
|
|
2
|
+
import { NORMALIZER_VERSION, normalizeQuery } from "./query/normalize.mjs";
|
|
3
|
+
export { INTENT_CLASSIFIER_VERSION, NORMALIZER_VERSION, SEARCH_INTENT_CODE, classifyQueryIntent, encodeIntent, normalizeQuery };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gscdump/analysis",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.2.0",
|
|
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",
|
|
@@ -36,6 +36,11 @@
|
|
|
36
36
|
"import": "./dist/errors.mjs",
|
|
37
37
|
"default": "./dist/errors.mjs"
|
|
38
38
|
},
|
|
39
|
+
"./query-dimension": {
|
|
40
|
+
"types": "./dist/query-dimension.d.mts",
|
|
41
|
+
"import": "./dist/query-dimension.mjs",
|
|
42
|
+
"default": "./dist/query-dimension.mjs"
|
|
43
|
+
},
|
|
39
44
|
"./report": {
|
|
40
45
|
"types": "./dist/report/index.d.mts",
|
|
41
46
|
"import": "./dist/report/index.mjs",
|
|
@@ -57,9 +62,9 @@
|
|
|
57
62
|
},
|
|
58
63
|
"dependencies": {
|
|
59
64
|
"pluralize": "^8.0.0",
|
|
60
|
-
"@gscdump/engine": "^3.
|
|
61
|
-
"@gscdump/engine-gsc-api": "^3.
|
|
62
|
-
"gscdump": "^3.
|
|
65
|
+
"@gscdump/engine": "^3.2.0",
|
|
66
|
+
"@gscdump/engine-gsc-api": "^3.2.0",
|
|
67
|
+
"gscdump": "^3.2.0"
|
|
63
68
|
},
|
|
64
69
|
"devDependencies": {
|
|
65
70
|
"vitest": "^4.1.10"
|