@kaeawc/auto-mobile 0.0.14 → 0.0.16
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 +3 -4
- package/README.md.backup +3 -4
- package/dist/schemas/tool-definitions.json +319 -39
- package/dist/src/db/migrations/2026_03_15_000_telemetry_events.ts +182 -0
- package/dist/src/db/migrations/2026_03_18_000_navigation_events.ts +36 -0
- package/dist/src/db/migrations/2026_03_19_000_storage_events.ts +37 -0
- package/dist/src/db/migrations/2026_03_19_001_layout_events.ts +39 -0
- package/dist/src/db/migrations/2026_03_19_002_storage_events_previous_value.ts +25 -0
- package/dist/src/db/migrations/2026_03_19_003_layout_events_screen_name.ts +25 -0
- package/dist/src/db/migrations/2026_03_20_000_network_event_details.ts +25 -0
- package/dist/src/db/migrations/2026_04_01_000_drop_custom_events.ts +41 -0
- package/dist/src/index.js +294 -271
- package/dist/src/index.js.map +1 -1
- package/package.json +2 -2
- package/schemas/tool-definitions.json +209 -37
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
|
|
3
|
+
async function tableExists(
|
|
4
|
+
db: Kysely<unknown>,
|
|
5
|
+
tableName: string
|
|
6
|
+
): Promise<boolean> {
|
|
7
|
+
const result = await db
|
|
8
|
+
.selectFrom("sqlite_master" as never)
|
|
9
|
+
.select("name")
|
|
10
|
+
.where("type", "=", "table")
|
|
11
|
+
.where("name", "=", tableName)
|
|
12
|
+
.execute();
|
|
13
|
+
return result.length > 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
17
|
+
// Network events table
|
|
18
|
+
if (!(await tableExists(db, "network_events"))) {
|
|
19
|
+
await db.schema
|
|
20
|
+
.createTable("network_events")
|
|
21
|
+
.ifNotExists()
|
|
22
|
+
.addColumn("id", "integer", col => col.primaryKey().autoIncrement())
|
|
23
|
+
.addColumn("device_id", "text")
|
|
24
|
+
.addColumn("timestamp", "integer", col => col.notNull())
|
|
25
|
+
.addColumn("application_id", "text")
|
|
26
|
+
.addColumn("session_id", "text")
|
|
27
|
+
.addColumn("url", "text", col => col.notNull())
|
|
28
|
+
.addColumn("method", "text", col => col.notNull())
|
|
29
|
+
.addColumn("status_code", "integer", col => col.notNull().defaultTo(0))
|
|
30
|
+
.addColumn("duration_ms", "integer", col => col.notNull().defaultTo(0))
|
|
31
|
+
.addColumn("request_body_size", "integer", col => col.defaultTo(-1))
|
|
32
|
+
.addColumn("response_body_size", "integer", col => col.defaultTo(-1))
|
|
33
|
+
.addColumn("protocol", "text")
|
|
34
|
+
.addColumn("host", "text")
|
|
35
|
+
.addColumn("path", "text")
|
|
36
|
+
.addColumn("error", "text")
|
|
37
|
+
.addColumn("created_at", "text", col => col.notNull().defaultTo("datetime('now')"))
|
|
38
|
+
.execute();
|
|
39
|
+
|
|
40
|
+
await db.schema
|
|
41
|
+
.createIndex("idx_network_events_timestamp")
|
|
42
|
+
.ifNotExists()
|
|
43
|
+
.on("network_events")
|
|
44
|
+
.column("timestamp")
|
|
45
|
+
.execute();
|
|
46
|
+
|
|
47
|
+
await db.schema
|
|
48
|
+
.createIndex("idx_network_events_host")
|
|
49
|
+
.ifNotExists()
|
|
50
|
+
.on("network_events")
|
|
51
|
+
.column("host")
|
|
52
|
+
.execute();
|
|
53
|
+
|
|
54
|
+
await db.schema
|
|
55
|
+
.createIndex("idx_network_events_device")
|
|
56
|
+
.ifNotExists()
|
|
57
|
+
.on("network_events")
|
|
58
|
+
.column("device_id")
|
|
59
|
+
.execute();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Log events table
|
|
63
|
+
if (!(await tableExists(db, "log_events"))) {
|
|
64
|
+
await db.schema
|
|
65
|
+
.createTable("log_events")
|
|
66
|
+
.ifNotExists()
|
|
67
|
+
.addColumn("id", "integer", col => col.primaryKey().autoIncrement())
|
|
68
|
+
.addColumn("device_id", "text")
|
|
69
|
+
.addColumn("timestamp", "integer", col => col.notNull())
|
|
70
|
+
.addColumn("application_id", "text")
|
|
71
|
+
.addColumn("session_id", "text")
|
|
72
|
+
.addColumn("level", "integer", col => col.notNull())
|
|
73
|
+
.addColumn("tag", "text", col => col.notNull())
|
|
74
|
+
.addColumn("message", "text", col => col.notNull())
|
|
75
|
+
.addColumn("filter_name", "text", col => col.notNull())
|
|
76
|
+
.addColumn("created_at", "text", col => col.notNull().defaultTo("datetime('now')"))
|
|
77
|
+
.execute();
|
|
78
|
+
|
|
79
|
+
await db.schema
|
|
80
|
+
.createIndex("idx_log_events_timestamp")
|
|
81
|
+
.ifNotExists()
|
|
82
|
+
.on("log_events")
|
|
83
|
+
.column("timestamp")
|
|
84
|
+
.execute();
|
|
85
|
+
|
|
86
|
+
await db.schema
|
|
87
|
+
.createIndex("idx_log_events_tag")
|
|
88
|
+
.ifNotExists()
|
|
89
|
+
.on("log_events")
|
|
90
|
+
.column("tag")
|
|
91
|
+
.execute();
|
|
92
|
+
|
|
93
|
+
await db.schema
|
|
94
|
+
.createIndex("idx_log_events_device")
|
|
95
|
+
.ifNotExists()
|
|
96
|
+
.on("log_events")
|
|
97
|
+
.column("device_id")
|
|
98
|
+
.execute();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Custom events table
|
|
102
|
+
if (!(await tableExists(db, "custom_events"))) {
|
|
103
|
+
await db.schema
|
|
104
|
+
.createTable("custom_events")
|
|
105
|
+
.ifNotExists()
|
|
106
|
+
.addColumn("id", "integer", col => col.primaryKey().autoIncrement())
|
|
107
|
+
.addColumn("device_id", "text")
|
|
108
|
+
.addColumn("timestamp", "integer", col => col.notNull())
|
|
109
|
+
.addColumn("application_id", "text")
|
|
110
|
+
.addColumn("session_id", "text")
|
|
111
|
+
.addColumn("name", "text", col => col.notNull())
|
|
112
|
+
.addColumn("properties_json", "text") // JSON of string key-value pairs
|
|
113
|
+
.addColumn("created_at", "text", col => col.notNull().defaultTo("datetime('now')"))
|
|
114
|
+
.execute();
|
|
115
|
+
|
|
116
|
+
await db.schema
|
|
117
|
+
.createIndex("idx_custom_events_timestamp")
|
|
118
|
+
.ifNotExists()
|
|
119
|
+
.on("custom_events")
|
|
120
|
+
.column("timestamp")
|
|
121
|
+
.execute();
|
|
122
|
+
|
|
123
|
+
await db.schema
|
|
124
|
+
.createIndex("idx_custom_events_name")
|
|
125
|
+
.ifNotExists()
|
|
126
|
+
.on("custom_events")
|
|
127
|
+
.column("name")
|
|
128
|
+
.execute();
|
|
129
|
+
|
|
130
|
+
await db.schema
|
|
131
|
+
.createIndex("idx_custom_events_device")
|
|
132
|
+
.ifNotExists()
|
|
133
|
+
.on("custom_events")
|
|
134
|
+
.column("device_id")
|
|
135
|
+
.execute();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// OS events table (lifecycle, broadcast, websocket_frame)
|
|
139
|
+
if (!(await tableExists(db, "os_events"))) {
|
|
140
|
+
await db.schema
|
|
141
|
+
.createTable("os_events")
|
|
142
|
+
.ifNotExists()
|
|
143
|
+
.addColumn("id", "integer", col => col.primaryKey().autoIncrement())
|
|
144
|
+
.addColumn("device_id", "text")
|
|
145
|
+
.addColumn("timestamp", "integer", col => col.notNull())
|
|
146
|
+
.addColumn("application_id", "text")
|
|
147
|
+
.addColumn("session_id", "text")
|
|
148
|
+
.addColumn("category", "text", col => col.notNull()) // lifecycle, broadcast, websocket_frame
|
|
149
|
+
.addColumn("kind", "text", col => col.notNull()) // e.g., foreground, screen_on, connectivity_change
|
|
150
|
+
.addColumn("details_json", "text") // JSON of additional details
|
|
151
|
+
.addColumn("created_at", "text", col => col.notNull().defaultTo("datetime('now')"))
|
|
152
|
+
.execute();
|
|
153
|
+
|
|
154
|
+
await db.schema
|
|
155
|
+
.createIndex("idx_os_events_timestamp")
|
|
156
|
+
.ifNotExists()
|
|
157
|
+
.on("os_events")
|
|
158
|
+
.column("timestamp")
|
|
159
|
+
.execute();
|
|
160
|
+
|
|
161
|
+
await db.schema
|
|
162
|
+
.createIndex("idx_os_events_category")
|
|
163
|
+
.ifNotExists()
|
|
164
|
+
.on("os_events")
|
|
165
|
+
.column("category")
|
|
166
|
+
.execute();
|
|
167
|
+
|
|
168
|
+
await db.schema
|
|
169
|
+
.createIndex("idx_os_events_device")
|
|
170
|
+
.ifNotExists()
|
|
171
|
+
.on("os_events")
|
|
172
|
+
.column("device_id")
|
|
173
|
+
.execute();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
178
|
+
await db.schema.dropTable("os_events").ifExists().execute();
|
|
179
|
+
await db.schema.dropTable("custom_events").ifExists().execute();
|
|
180
|
+
await db.schema.dropTable("log_events").ifExists().execute();
|
|
181
|
+
await db.schema.dropTable("network_events").ifExists().execute();
|
|
182
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
|
|
3
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
4
|
+
await db.schema
|
|
5
|
+
.createTable("navigation_events")
|
|
6
|
+
.ifNotExists()
|
|
7
|
+
.addColumn("id", "integer", col => col.primaryKey().autoIncrement())
|
|
8
|
+
.addColumn("device_id", "text")
|
|
9
|
+
.addColumn("timestamp", "integer", col => col.notNull())
|
|
10
|
+
.addColumn("application_id", "text")
|
|
11
|
+
.addColumn("session_id", "text")
|
|
12
|
+
.addColumn("destination", "text", col => col.notNull())
|
|
13
|
+
.addColumn("source", "text")
|
|
14
|
+
.addColumn("arguments_json", "text")
|
|
15
|
+
.addColumn("metadata_json", "text")
|
|
16
|
+
.addColumn("created_at", "text", col => col.notNull().defaultTo("datetime('now')"))
|
|
17
|
+
.execute();
|
|
18
|
+
|
|
19
|
+
await db.schema
|
|
20
|
+
.createIndex("idx_navigation_events_timestamp")
|
|
21
|
+
.ifNotExists()
|
|
22
|
+
.on("navigation_events")
|
|
23
|
+
.column("timestamp")
|
|
24
|
+
.execute();
|
|
25
|
+
|
|
26
|
+
await db.schema
|
|
27
|
+
.createIndex("idx_navigation_events_device")
|
|
28
|
+
.ifNotExists()
|
|
29
|
+
.on("navigation_events")
|
|
30
|
+
.column("device_id")
|
|
31
|
+
.execute();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
35
|
+
await db.schema.dropTable("navigation_events").ifExists().execute();
|
|
36
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
|
|
3
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
4
|
+
await db.schema
|
|
5
|
+
.createTable("storage_events")
|
|
6
|
+
.ifNotExists()
|
|
7
|
+
.addColumn("id", "integer", col => col.primaryKey().autoIncrement())
|
|
8
|
+
.addColumn("device_id", "text")
|
|
9
|
+
.addColumn("timestamp", "integer", col => col.notNull())
|
|
10
|
+
.addColumn("application_id", "text")
|
|
11
|
+
.addColumn("session_id", "text")
|
|
12
|
+
.addColumn("file_name", "text", col => col.notNull())
|
|
13
|
+
.addColumn("key", "text")
|
|
14
|
+
.addColumn("value", "text")
|
|
15
|
+
.addColumn("value_type", "text")
|
|
16
|
+
.addColumn("change_type", "text", col => col.notNull())
|
|
17
|
+
.addColumn("created_at", "text", col => col.notNull().defaultTo("datetime('now')"))
|
|
18
|
+
.execute();
|
|
19
|
+
|
|
20
|
+
await db.schema
|
|
21
|
+
.createIndex("idx_storage_events_timestamp")
|
|
22
|
+
.ifNotExists()
|
|
23
|
+
.on("storage_events")
|
|
24
|
+
.column("timestamp")
|
|
25
|
+
.execute();
|
|
26
|
+
|
|
27
|
+
await db.schema
|
|
28
|
+
.createIndex("idx_storage_events_device")
|
|
29
|
+
.ifNotExists()
|
|
30
|
+
.on("storage_events")
|
|
31
|
+
.column("device_id")
|
|
32
|
+
.execute();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
36
|
+
await db.schema.dropTable("storage_events").ifExists().execute();
|
|
37
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
|
|
3
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
4
|
+
await db.schema
|
|
5
|
+
.createTable("layout_events")
|
|
6
|
+
.ifNotExists()
|
|
7
|
+
.addColumn("id", "integer", col => col.primaryKey().autoIncrement())
|
|
8
|
+
.addColumn("device_id", "text")
|
|
9
|
+
.addColumn("timestamp", "integer", col => col.notNull())
|
|
10
|
+
.addColumn("application_id", "text")
|
|
11
|
+
.addColumn("session_id", "text")
|
|
12
|
+
.addColumn("sub_type", "text", col => col.notNull())
|
|
13
|
+
.addColumn("composable_name", "text")
|
|
14
|
+
.addColumn("composable_id", "text")
|
|
15
|
+
.addColumn("recomposition_count", "integer")
|
|
16
|
+
.addColumn("duration_ms", "integer")
|
|
17
|
+
.addColumn("likely_cause", "text")
|
|
18
|
+
.addColumn("details_json", "text")
|
|
19
|
+
.addColumn("created_at", "text", col => col.notNull().defaultTo("datetime('now')"))
|
|
20
|
+
.execute();
|
|
21
|
+
|
|
22
|
+
await db.schema
|
|
23
|
+
.createIndex("idx_layout_events_timestamp")
|
|
24
|
+
.ifNotExists()
|
|
25
|
+
.on("layout_events")
|
|
26
|
+
.column("timestamp")
|
|
27
|
+
.execute();
|
|
28
|
+
|
|
29
|
+
await db.schema
|
|
30
|
+
.createIndex("idx_layout_events_device")
|
|
31
|
+
.ifNotExists()
|
|
32
|
+
.on("layout_events")
|
|
33
|
+
.column("device_id")
|
|
34
|
+
.execute();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
38
|
+
await db.schema.dropTable("layout_events").ifExists().execute();
|
|
39
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
import { sql } from "kysely";
|
|
3
|
+
|
|
4
|
+
async function columnExists(db: Kysely<unknown>, tableName: string, columnName: string): Promise<boolean> {
|
|
5
|
+
const result = await sql<{ name: string }>`
|
|
6
|
+
SELECT name FROM pragma_table_info(${tableName}) WHERE name = ${columnName}
|
|
7
|
+
`.execute(db);
|
|
8
|
+
return result.rows.length > 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
12
|
+
if (!(await columnExists(db, "storage_events", "previous_value"))) {
|
|
13
|
+
await db.schema
|
|
14
|
+
.alterTable("storage_events")
|
|
15
|
+
.addColumn("previous_value", "text")
|
|
16
|
+
.execute();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
21
|
+
await db.schema
|
|
22
|
+
.alterTable("storage_events")
|
|
23
|
+
.dropColumn("previous_value")
|
|
24
|
+
.execute();
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
import { sql } from "kysely";
|
|
3
|
+
|
|
4
|
+
async function columnExists(db: Kysely<unknown>, tableName: string, columnName: string): Promise<boolean> {
|
|
5
|
+
const result = await sql<{ name: string }>`
|
|
6
|
+
SELECT name FROM pragma_table_info(${tableName}) WHERE name = ${columnName}
|
|
7
|
+
`.execute(db);
|
|
8
|
+
return result.rows.length > 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
12
|
+
if (!(await columnExists(db, "layout_events", "screen_name"))) {
|
|
13
|
+
await db.schema
|
|
14
|
+
.alterTable("layout_events")
|
|
15
|
+
.addColumn("screen_name", "text")
|
|
16
|
+
.execute();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
21
|
+
await db.schema
|
|
22
|
+
.alterTable("layout_events")
|
|
23
|
+
.dropColumn("screen_name")
|
|
24
|
+
.execute();
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
import { sql } from "kysely";
|
|
3
|
+
|
|
4
|
+
async function columnExists(db: Kysely<unknown>, tableName: string, columnName: string): Promise<boolean> {
|
|
5
|
+
const result = await sql<{ name: string }>`
|
|
6
|
+
SELECT name FROM pragma_table_info(${tableName}) WHERE name = ${columnName}
|
|
7
|
+
`.execute(db);
|
|
8
|
+
return result.rows.length > 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
12
|
+
const columns = ["request_headers_json", "response_headers_json", "request_body", "response_body", "content_type"];
|
|
13
|
+
for (const col of columns) {
|
|
14
|
+
if (!(await columnExists(db, "network_events", col))) {
|
|
15
|
+
await db.schema
|
|
16
|
+
.alterTable("network_events")
|
|
17
|
+
.addColumn(col, "text")
|
|
18
|
+
.execute();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
24
|
+
// SQLite doesn't support DROP COLUMN easily; these columns are nullable and safe to leave
|
|
25
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
|
|
3
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
4
|
+
await db.schema.dropTable("custom_events").ifExists().execute();
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
8
|
+
await db.schema
|
|
9
|
+
.createTable("custom_events")
|
|
10
|
+
.ifNotExists()
|
|
11
|
+
.addColumn("id", "integer", col => col.primaryKey().autoIncrement())
|
|
12
|
+
.addColumn("device_id", "text")
|
|
13
|
+
.addColumn("timestamp", "integer", col => col.notNull())
|
|
14
|
+
.addColumn("application_id", "text")
|
|
15
|
+
.addColumn("session_id", "text")
|
|
16
|
+
.addColumn("name", "text", col => col.notNull())
|
|
17
|
+
.addColumn("properties_json", "text")
|
|
18
|
+
.addColumn("created_at", "text", col => col.notNull().defaultTo("datetime('now')"))
|
|
19
|
+
.execute();
|
|
20
|
+
|
|
21
|
+
await db.schema
|
|
22
|
+
.createIndex("idx_custom_events_timestamp")
|
|
23
|
+
.ifNotExists()
|
|
24
|
+
.on("custom_events")
|
|
25
|
+
.column("timestamp")
|
|
26
|
+
.execute();
|
|
27
|
+
|
|
28
|
+
await db.schema
|
|
29
|
+
.createIndex("idx_custom_events_name")
|
|
30
|
+
.ifNotExists()
|
|
31
|
+
.on("custom_events")
|
|
32
|
+
.column("name")
|
|
33
|
+
.execute();
|
|
34
|
+
|
|
35
|
+
await db.schema
|
|
36
|
+
.createIndex("idx_custom_events_device")
|
|
37
|
+
.ifNotExists()
|
|
38
|
+
.on("custom_events")
|
|
39
|
+
.column("device_id")
|
|
40
|
+
.execute();
|
|
41
|
+
}
|