@gscdump/engine-sqlite 0.4.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/LICENSE +21 -0
- package/dist/index.d.mts +2303 -0
- package/dist/index.mjs +141 -0
- package/package.json +55 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { assertSchemaInSync, compileSqlite, compileSqlite as compileSqlite$1, createResolverAdapter, createSqlQuerySource } from "@gscdump/engine/resolver";
|
|
2
|
+
import { and, eq, gte, lte, sql, sql as sql$1 } from "drizzle-orm";
|
|
3
|
+
import { integer, real, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
4
|
+
import { createScopedHelpers } from "@gscdump/engine/scope";
|
|
5
|
+
import { drizzle } from "drizzle-orm/sqlite-proxy";
|
|
6
|
+
import { resolveWindow } from "@gscdump/analysis/period";
|
|
7
|
+
function metricCols() {
|
|
8
|
+
return {
|
|
9
|
+
clicks: integer("clicks").notNull().default(0),
|
|
10
|
+
impressions: integer("impressions").notNull().default(0),
|
|
11
|
+
ctr: real("ctr").notNull().default(0),
|
|
12
|
+
position: real("position").notNull().default(0),
|
|
13
|
+
sum_position: real("sum_position").notNull().default(0)
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function baseCols() {
|
|
17
|
+
return {
|
|
18
|
+
id: text("id").primaryKey(),
|
|
19
|
+
site_id: text("site_id").notNull(),
|
|
20
|
+
date: text("date").notNull(),
|
|
21
|
+
created_at: integer("created_at").default(sql$1`(unixepoch())`)
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const gsc_pages = sqliteTable("gsc_pages", {
|
|
25
|
+
...baseCols(),
|
|
26
|
+
url: text("url").notNull(),
|
|
27
|
+
...metricCols()
|
|
28
|
+
});
|
|
29
|
+
const gsc_keywords = sqliteTable("gsc_keywords", {
|
|
30
|
+
...baseCols(),
|
|
31
|
+
query: text("query").notNull(),
|
|
32
|
+
query_canonical: text("query_canonical"),
|
|
33
|
+
...metricCols()
|
|
34
|
+
});
|
|
35
|
+
const gsc_countries = sqliteTable("gsc_countries", {
|
|
36
|
+
...baseCols(),
|
|
37
|
+
country: text("country").notNull(),
|
|
38
|
+
...metricCols()
|
|
39
|
+
});
|
|
40
|
+
const gsc_devices = sqliteTable("gsc_devices", {
|
|
41
|
+
...baseCols(),
|
|
42
|
+
device: text("device").notNull(),
|
|
43
|
+
...metricCols()
|
|
44
|
+
});
|
|
45
|
+
const gsc_page_keywords = sqliteTable("gsc_page_keywords", {
|
|
46
|
+
...baseCols(),
|
|
47
|
+
url: text("url").notNull(),
|
|
48
|
+
query: text("query").notNull(),
|
|
49
|
+
query_canonical: text("query_canonical"),
|
|
50
|
+
...metricCols()
|
|
51
|
+
});
|
|
52
|
+
const schema = {
|
|
53
|
+
gsc_pages,
|
|
54
|
+
gsc_keywords,
|
|
55
|
+
gsc_countries,
|
|
56
|
+
gsc_devices,
|
|
57
|
+
gsc_page_keywords,
|
|
58
|
+
gsc_search_appearance: sqliteTable("gsc_search_appearance", {
|
|
59
|
+
...baseCols(),
|
|
60
|
+
searchAppearance: text("searchAppearance").notNull(),
|
|
61
|
+
...metricCols()
|
|
62
|
+
})
|
|
63
|
+
};
|
|
64
|
+
const GSC_PREFIX_RE = /^gsc_/;
|
|
65
|
+
assertSchemaInSync({
|
|
66
|
+
label: "sqlite",
|
|
67
|
+
schema,
|
|
68
|
+
tableKeyToName: (key) => key.replace(GSC_PREFIX_RE, ""),
|
|
69
|
+
mode: "superset"
|
|
70
|
+
});
|
|
71
|
+
function createSqliteResolverAdapter(options = {}) {
|
|
72
|
+
return createResolverAdapter({
|
|
73
|
+
schema,
|
|
74
|
+
datasetToTableKey: {
|
|
75
|
+
pages: "gsc_pages",
|
|
76
|
+
keywords: "gsc_keywords",
|
|
77
|
+
page_keywords: "gsc_page_keywords",
|
|
78
|
+
countries: "gsc_countries",
|
|
79
|
+
devices: "gsc_devices",
|
|
80
|
+
search_appearance: "gsc_search_appearance"
|
|
81
|
+
},
|
|
82
|
+
metricCast: "REAL",
|
|
83
|
+
regexPredicate: (expr, pattern, negate) => negate ? sql$1`NOT (${expr} REGEXP ${pattern})` : sql$1`${expr} REGEXP ${pattern}`,
|
|
84
|
+
tableLabel: "sqlite/resolver-adapter",
|
|
85
|
+
includeSiteId: true,
|
|
86
|
+
compile: compileSqlite$1,
|
|
87
|
+
capabilities: {
|
|
88
|
+
regex: options.regex ?? false,
|
|
89
|
+
comparisonJoin: true,
|
|
90
|
+
windowTotals: true
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
const sqliteResolverAdapter = createSqliteResolverAdapter();
|
|
95
|
+
async function probeSqliteRegex(executor) {
|
|
96
|
+
return executor(`SELECT 'a' REGEXP 'a' AS r`, [], "all").then(({ rows }) => rows.length > 0).catch(() => false);
|
|
97
|
+
}
|
|
98
|
+
async function createSqliteResolverAdapterFromExecutor(options) {
|
|
99
|
+
return createSqliteResolverAdapter({ regex: await probeSqliteRegex(options.executor) });
|
|
100
|
+
}
|
|
101
|
+
function createEngine(config) {
|
|
102
|
+
const { executor, siteId, regex } = config;
|
|
103
|
+
return createSqlQuerySource({
|
|
104
|
+
name: "sqlite",
|
|
105
|
+
adapter: regex === void 0 ? sqliteResolverAdapter : createSqliteResolverAdapter({ regex }),
|
|
106
|
+
execute: async (sql, params) => {
|
|
107
|
+
return (await executor(sql, params, "all")).rows;
|
|
108
|
+
},
|
|
109
|
+
siteId
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function aggClicks(t) {
|
|
113
|
+
return sql$1`SUM(${t.clicks})`;
|
|
114
|
+
}
|
|
115
|
+
function aggImpressions(t) {
|
|
116
|
+
return sql$1`SUM(${t.impressions})`;
|
|
117
|
+
}
|
|
118
|
+
function aggCtr(t) {
|
|
119
|
+
return sql$1`CAST(SUM(${t.clicks}) AS REAL) / NULLIF(SUM(${t.impressions}), 0)`;
|
|
120
|
+
}
|
|
121
|
+
function aggPosition(t) {
|
|
122
|
+
return sql$1`SUM(${t.sum_position}) / NULLIF(SUM(${t.impressions}), 0) + 1`;
|
|
123
|
+
}
|
|
124
|
+
function createSqliteInsightRunner(opts) {
|
|
125
|
+
const { executor, logger, rowsAsArrays, schema: schemaOverride } = opts;
|
|
126
|
+
const callback = async (sql, params, method) => {
|
|
127
|
+
const result = await executor(sql, params, method);
|
|
128
|
+
if (!rowsAsArrays) return { rows: result.rows };
|
|
129
|
+
return { rows: result.rows.map((r) => {
|
|
130
|
+
if (Array.isArray(r)) return r;
|
|
131
|
+
if (r && typeof r === "object") return Object.values(r);
|
|
132
|
+
return r;
|
|
133
|
+
}) };
|
|
134
|
+
};
|
|
135
|
+
return { db: drizzle(callback, {
|
|
136
|
+
schema: schemaOverride ?? schema,
|
|
137
|
+
logger
|
|
138
|
+
}) };
|
|
139
|
+
}
|
|
140
|
+
const { scopeFor, mergeScope } = createScopedHelpers(schema);
|
|
141
|
+
export { aggClicks, aggCtr, aggImpressions, aggPosition, and, compileSqlite, createEngine, createSqliteInsightRunner, createSqliteResolverAdapter, createSqliteResolverAdapterFromExecutor, eq, gsc_countries, gsc_devices, gsc_keywords, gsc_page_keywords, gsc_pages, gte, lte, mergeScope, probeSqliteRegex, resolveWindow, schema, scopeFor, sql, sqliteResolverAdapter };
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gscdump/engine-sqlite",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.4.0",
|
|
5
|
+
"description": "SQLite / D1 engine adapter for @gscdump/analysis — typed analytics over sqlite-proxy executors (Cloudflare D1, libsql).",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Harlan Wilton",
|
|
8
|
+
"email": "harlan@harlanzw.com",
|
|
9
|
+
"url": "https://harlanzw.com/"
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"funding": "https://github.com/sponsors/harlan-zw",
|
|
13
|
+
"homepage": "https://github.com/harlan-zw/gscdump/tree/main/packages/engine-sqlite#readme",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/harlan-zw/gscdump.git",
|
|
17
|
+
"directory": "packages/engine-sqlite"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/harlan-zw/gscdump/issues"
|
|
21
|
+
},
|
|
22
|
+
"sideEffects": false,
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.mts",
|
|
26
|
+
"import": "./dist/index.mjs"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"main": "./dist/index.mjs",
|
|
30
|
+
"types": "./dist/index.d.mts",
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=18"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"drizzle-orm": "^0.45.2"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@gscdump/analysis": "0.4.0",
|
|
42
|
+
"@gscdump/engine": "0.4.0",
|
|
43
|
+
"gscdump": "0.4.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"drizzle-orm": "^0.45.2",
|
|
47
|
+
"vitest": "^4.1.5"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "obuild",
|
|
51
|
+
"dev": "obuild --stub",
|
|
52
|
+
"typecheck": "tsc --noEmit",
|
|
53
|
+
"test": "vitest"
|
|
54
|
+
}
|
|
55
|
+
}
|