@kaeawc/auto-mobile 0.0.85 → 0.0.87

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.
Files changed (87) hide show
  1. package/README.md +3 -3
  2. package/README.md.backup +3 -3
  3. package/dist/build-info.json +10 -10
  4. package/dist/src/index.js +1173 -840
  5. package/dist/src/utils/workers/iosBundleExtractWorker.js +3 -3
  6. package/node_modules/strtok3/lib/stream/StreamReader.js +6 -1
  7. package/node_modules/strtok3/package.json +1 -1
  8. package/package.json +21 -17
  9. package/dist/schemas/managed-slot-contract.json +0 -142
  10. package/dist/src/db/eventTables.ts +0 -8
  11. package/dist/src/db/migrations/2025_12_28_000_initial_schema.ts +0 -28
  12. package/dist/src/db/migrations/2025_12_30_000_performance_thresholds.ts +0 -85
  13. package/dist/src/db/migrations/2025_12_30_001_navigation_graph.ts +0 -223
  14. package/dist/src/db/migrations/2025_12_31_000_accessibility_baselines.ts +0 -34
  15. package/dist/src/db/migrations/2025_12_31_001_memory_audit.ts +0 -120
  16. package/dist/src/db/migrations/2026_01_01_000_recomposition_metrics.ts +0 -44
  17. package/dist/src/db/migrations/2026_01_02_000_prediction_history.ts +0 -87
  18. package/dist/src/db/migrations/2026_01_03_000_feature_flags.ts +0 -17
  19. package/dist/src/db/migrations/2026_01_03_000_test_executions.ts +0 -45
  20. package/dist/src/db/migrations/2026_01_05_000_tool_calls.ts +0 -31
  21. package/dist/src/db/migrations/2026_01_08_000_test_coverage.ts +0 -109
  22. package/dist/src/db/migrations/2026_01_09_000_video_recordings.ts +0 -66
  23. package/dist/src/db/migrations/2026_01_10_000_device_snapshots.ts +0 -54
  24. package/dist/src/db/migrations/2026_01_11_000_installed_apps.ts +0 -33
  25. package/dist/src/db/migrations/2026_01_11_000_video_recording_highlights.ts +0 -24
  26. package/dist/src/db/migrations/2026_01_13_000_installed_apps_session_tracking.ts +0 -27
  27. package/dist/src/db/migrations/2026_01_14_000_appearance_config.ts +0 -16
  28. package/dist/src/db/migrations/2026_01_25_000_navigation_screenshots.ts +0 -27
  29. package/dist/src/db/migrations/2026_01_25_001_test_run_details.ts +0 -97
  30. package/dist/src/db/migrations/2026_01_27_000_crash_anr_monitoring.ts +0 -204
  31. package/dist/src/db/migrations/2026_01_27_000_failures.ts +0 -217
  32. package/dist/src/db/migrations/2026_01_29_000_named_nodes.ts +0 -88
  33. package/dist/src/db/migrations/2026_01_30_000_performance_live_metrics.ts +0 -108
  34. package/dist/src/db/migrations/2026_03_15_000_telemetry_events.ts +0 -184
  35. package/dist/src/db/migrations/2026_03_18_000_navigation_events.ts +0 -36
  36. package/dist/src/db/migrations/2026_03_19_000_storage_events.ts +0 -37
  37. package/dist/src/db/migrations/2026_03_19_001_layout_events.ts +0 -39
  38. package/dist/src/db/migrations/2026_03_19_002_storage_events_previous_value.ts +0 -23
  39. package/dist/src/db/migrations/2026_03_19_003_layout_events_screen_name.ts +0 -23
  40. package/dist/src/db/migrations/2026_03_20_000_network_event_details.ts +0 -32
  41. package/dist/src/db/migrations/2026_04_01_000_drop_custom_events.ts +0 -41
  42. package/dist/src/db/migrations/2026_04_02_000_device_sessions.ts +0 -51
  43. package/dist/src/db/migrations/2026_07_01_000_failure_groups_signature_unique.ts +0 -162
  44. package/dist/src/db/migrations/2026_07_02_000_event_composite_indexes.ts +0 -62
  45. package/dist/src/db/migrations/2026_07_03_000_drop_redundant_device_indexes.ts +0 -66
  46. package/dist/src/db/migrations/2026_07_03_000_repair_datetime_now_defaults.ts +0 -278
  47. package/dist/src/db/migrations/2026_07_04_000_storage_events_key_lookup.ts +0 -60
  48. package/dist/src/db/migrations/2026_07_05_000_repair_updated_at_defaults.ts +0 -239
  49. package/dist/src/db/migrations/2026_07_24_000_device_locks.ts +0 -27
  50. package/dist/src/db/migrations/2026_07_27_000_session_tool_capabilities.ts +0 -17
  51. package/dist/src/db/migrations/2026_07_31_000_video_recordings_owner_session.ts +0 -39
  52. package/dist/src/db/migrations/2026_08_02_000_navigation_provenance.ts +0 -159
  53. package/dist/src/db/migrations/2026_08_17_000_emulator_loss_incidents.ts +0 -39
  54. package/dist/src/db/migrations/2026_08_22_000_provision_device_operations.ts +0 -21
  55. package/dist/src/db/migrations/2026_08_22_001_session_tool_overrides.ts +0 -106
  56. package/dist/src/db/migrations/2026_08_22_002_navigation_observation_eviction_index.ts +0 -67
  57. package/dist/src/db/migrations/2026_08_22_003_device_teardown_operations.ts +0 -19
  58. package/dist/src/db/migrations/2026_08_23_000_device_teardown_operation_owner.ts +0 -19
  59. package/dist/src/db/migrations/2026_08_23_001_default_existing_delete_device_disabled.ts +0 -26
  60. package/dist/src/db/migrations/2026_08_24_000_installed_apps_profile_type.ts +0 -15
  61. package/dist/src/db/migrations/2026_09_06_000_tool_selection_profile_provenance.ts +0 -36
  62. package/dist/src/db/migrations/2026_09_08_000_provision_device_operations_expiry.ts +0 -25
  63. package/dist/src/db/migrations/2026_09_10_000_provision_device_operation_attempt.ts +0 -25
  64. package/dist/src/db/migrations/2026_09_10_001_device_session_retention_index.ts +0 -14
  65. package/dist/src/db/migrations/2026_09_13_000_device_snapshot_vm_reclaim.ts +0 -63
  66. package/dist/src/db/migrations/2026_09_14_000_device_session_stable_identity.ts +0 -9
  67. package/dist/src/db/migrations/2026_09_14_001_device_session_identity_writer_fence.ts +0 -45
  68. package/dist/src/db/migrations/2026_09_16_000_device_session_liveness_owner.ts +0 -9
  69. package/dist/src/db/migrations/2026_09_16_001_device_session_liveness_contract.ts +0 -37
  70. package/dist/src/db/migrations/2026_09_17_000_device_session_liveness_writer_fence.ts +0 -48
  71. package/dist/src/db/migrations/2026_09_17_001_device_session_identity_fence_same_serial.ts +0 -53
  72. package/dist/src/db/migrations/2026_09_20_000_provision_device_lifecycle_outcome.ts +0 -32
  73. package/dist/src/db/migrations/2026_09_29_000_navigation_suggestion_provenance.ts +0 -41
  74. package/dist/src/db/migrations/2026_09_30_000_video_recording_display.ts +0 -17
  75. package/dist/src/db/migrations/2026_09_30_001_network_capture_fields.ts +0 -30
  76. package/dist/src/db/migrations/2026_10_05_000_device_locks_device_identity.ts +0 -28
  77. package/dist/src/db/migrations/2026_10_05_001_storage_events_key_lookup_insertion_order.ts +0 -38
  78. package/dist/src/db/migrations/2026_10_05_002_test_edge_coverage_edge_id_index.ts +0 -19
  79. package/dist/src/db/migrations/2026_10_09_000_device_resource_applications.ts +0 -22
  80. package/dist/src/db/migrations/2026_10_09_001_drop_provision_device_operations.ts +0 -32
  81. package/dist/src/db/migrations/2026_10_09_002_drop_device_teardown_operations.ts +0 -28
  82. package/dist/src/db/migrations/2026_10_12_000_rename_recording_tool_names.ts +0 -44
  83. package/dist/src/db/migrations/2026_10_12_001_video_recording_capture_teardown.ts +0 -17
  84. package/dist/src/db/migrations/2026_10_13_000_video_recording_recorder_daemon.ts +0 -17
  85. package/dist/src/index.js.map +0 -1
  86. package/dist/src/utils/workers/iosBundleExtractWorker.js.map +0 -1
  87. package/schemas/managed-slot-contract.json +0 -142
@@ -1,217 +0,0 @@
1
- import { type Kysely, sql } from "kysely";
2
-
3
- // Keep raw migrations independent of app modules that are not shipped beside them.
4
- interface SqliteCatalogSchema {
5
- sqlite_master: { type: string; name: string };
6
- }
7
-
8
- async function tableExists(db: Kysely<unknown>, tableName: string): Promise<boolean> {
9
- const result = await (db as Kysely<SqliteCatalogSchema>)
10
- .selectFrom("sqlite_master")
11
- .select("name")
12
- .where("type", "=", "table")
13
- .where("name", "=", tableName)
14
- .execute();
15
- return result.length > 0;
16
- }
17
-
18
- export async function up(db: Kysely<unknown>): Promise<void> {
19
- await createFailureGroups(db);
20
- await createFailureOccurrences(db);
21
- await createFailureOccurrenceScreens(db);
22
- await createFailureCaptures(db);
23
- await createFailureNotifications(db);
24
- }
25
-
26
- async function createFailureGroups(db: Kysely<unknown>): Promise<void> {
27
- // Main failure groups table - groups similar failures by signature
28
- if (!(await tableExists(db, "failure_groups"))) {
29
- await db.schema
30
- .createTable("failure_groups")
31
- .ifNotExists()
32
- .addColumn("id", "text", (col) => col.primaryKey())
33
- .addColumn("type", "text", (col) => col.notNull()) // crash, anr, tool_failure
34
- .addColumn("signature", "text", (col) => col.notNull()) // Stack trace hash or tool+error
35
- .addColumn("title", "text", (col) => col.notNull())
36
- .addColumn("message", "text", (col) => col.notNull())
37
- .addColumn("severity", "text", (col) => col.notNull()) // critical, high, medium, low
38
- .addColumn("first_occurrence", "integer", (col) => col.notNull())
39
- .addColumn("last_occurrence", "integer", (col) => col.notNull())
40
- .addColumn("total_count", "integer", (col) => col.notNull().defaultTo(0))
41
- .addColumn("unique_sessions", "integer", (col) => col.notNull().defaultTo(0))
42
- .addColumn("stack_trace_json", "text") // JSON array of StackTraceElement
43
- .addColumn("tool_call_info_json", "text") // JSON of AggregatedToolCallInfo
44
- .addColumn("created_at", "text", (col) => col.notNull().defaultTo(sql`(datetime('now'))`))
45
- .addColumn("updated_at", "text", (col) => col.notNull().defaultTo(sql`(datetime('now'))`))
46
- .execute();
47
-
48
- await db.schema
49
- .createIndex("idx_failure_groups_type")
50
- .ifNotExists()
51
- .on("failure_groups")
52
- .column("type")
53
- .execute();
54
-
55
- await db.schema
56
- .createIndex("idx_failure_groups_signature")
57
- .ifNotExists()
58
- .on("failure_groups")
59
- .column("signature")
60
- .execute();
61
-
62
- await db.schema
63
- .createIndex("idx_failure_groups_last_occurrence")
64
- .ifNotExists()
65
- .on("failure_groups")
66
- .column("last_occurrence")
67
- .execute();
68
- }
69
- }
70
-
71
- async function createFailureOccurrences(db: Kysely<unknown>): Promise<void> {
72
- // Individual failure occurrences
73
- if (!(await tableExists(db, "failure_occurrences"))) {
74
- await db.schema
75
- .createTable("failure_occurrences")
76
- .ifNotExists()
77
- .addColumn("id", "text", (col) => col.primaryKey())
78
- .addColumn("group_id", "text", (col) =>
79
- col.notNull().references("failure_groups.id").onDelete("cascade"),
80
- )
81
- .addColumn("timestamp", "integer", (col) => col.notNull())
82
- .addColumn("device_id", "text")
83
- .addColumn("device_model", "text", (col) => col.notNull())
84
- .addColumn("os", "text", (col) => col.notNull())
85
- .addColumn("app_version", "text", (col) => col.notNull())
86
- .addColumn("session_id", "text", (col) => col.notNull())
87
- .addColumn("screen_at_failure", "text")
88
- .addColumn("test_name", "text")
89
- .addColumn("test_execution_id", "integer") // FK to test_executions if from a test
90
- .addColumn("error_code", "text") // For tool failures
91
- .addColumn("duration_ms", "integer") // For tool failures
92
- .addColumn("tool_args_json", "text") // For tool failures - JSON of parameters
93
- .addColumn("created_at", "text", (col) => col.notNull().defaultTo(sql`(datetime('now'))`))
94
- .execute();
95
-
96
- await db.schema
97
- .createIndex("idx_failure_occurrences_group")
98
- .ifNotExists()
99
- .on("failure_occurrences")
100
- .column("group_id")
101
- .execute();
102
-
103
- await db.schema
104
- .createIndex("idx_failure_occurrences_timestamp")
105
- .ifNotExists()
106
- .on("failure_occurrences")
107
- .column("timestamp")
108
- .execute();
109
-
110
- await db.schema
111
- .createIndex("idx_failure_occurrences_session")
112
- .ifNotExists()
113
- .on("failure_occurrences")
114
- .column("session_id")
115
- .execute();
116
-
117
- await db.schema
118
- .createIndex("idx_failure_occurrences_device")
119
- .ifNotExists()
120
- .on("failure_occurrences")
121
- .column("device_id")
122
- .execute();
123
- }
124
- }
125
-
126
- async function createFailureOccurrenceScreens(db: Kysely<unknown>): Promise<void> {
127
- // Screens visited during a failure occurrence
128
- if (!(await tableExists(db, "failure_occurrence_screens"))) {
129
- await db.schema
130
- .createTable("failure_occurrence_screens")
131
- .ifNotExists()
132
- .addColumn("id", "integer", (col) => col.primaryKey().autoIncrement())
133
- .addColumn("occurrence_id", "text", (col) =>
134
- col.notNull().references("failure_occurrences.id").onDelete("cascade"),
135
- )
136
- .addColumn("screen_name", "text", (col) => col.notNull())
137
- .addColumn("visit_order", "integer", (col) => col.notNull())
138
- .addColumn("created_at", "text", (col) => col.notNull().defaultTo(sql`(datetime('now'))`))
139
- .execute();
140
-
141
- await db.schema
142
- .createIndex("idx_failure_occurrence_screens_occurrence")
143
- .ifNotExists()
144
- .on("failure_occurrence_screens")
145
- .column("occurrence_id")
146
- .execute();
147
- }
148
- }
149
-
150
- async function createFailureCaptures(db: Kysely<unknown>): Promise<void> {
151
- // Captures (screenshots/videos) associated with failures
152
- if (!(await tableExists(db, "failure_captures"))) {
153
- await db.schema
154
- .createTable("failure_captures")
155
- .ifNotExists()
156
- .addColumn("id", "text", (col) => col.primaryKey())
157
- .addColumn("occurrence_id", "text", (col) =>
158
- col.notNull().references("failure_occurrences.id").onDelete("cascade"),
159
- )
160
- .addColumn("type", "text", (col) => col.notNull()) // screenshot, video
161
- .addColumn("path", "text", (col) => col.notNull())
162
- .addColumn("timestamp", "integer", (col) => col.notNull())
163
- .addColumn("device_model", "text", (col) => col.notNull())
164
- .addColumn("created_at", "text", (col) => col.notNull().defaultTo(sql`(datetime('now'))`))
165
- .execute();
166
-
167
- await db.schema
168
- .createIndex("idx_failure_captures_occurrence")
169
- .ifNotExists()
170
- .on("failure_captures")
171
- .column("occurrence_id")
172
- .execute();
173
- }
174
- }
175
-
176
- async function createFailureNotifications(db: Kysely<unknown>): Promise<void> {
177
- // Notifications for real-time streaming - tracks which occurrences are new
178
- if (!(await tableExists(db, "failure_notifications"))) {
179
- await db.schema
180
- .createTable("failure_notifications")
181
- .ifNotExists()
182
- .addColumn("id", "integer", (col) => col.primaryKey().autoIncrement())
183
- .addColumn("occurrence_id", "text", (col) =>
184
- col.notNull().references("failure_occurrences.id").onDelete("cascade"),
185
- )
186
- .addColumn("group_id", "text", (col) => col.notNull())
187
- .addColumn("type", "text", (col) => col.notNull()) // crash, anr, tool_failure
188
- .addColumn("severity", "text", (col) => col.notNull())
189
- .addColumn("title", "text", (col) => col.notNull())
190
- .addColumn("timestamp", "integer", (col) => col.notNull())
191
- .addColumn("acknowledged", "integer", (col) => col.notNull().defaultTo(0)) // SQLite boolean
192
- .addColumn("created_at", "text", (col) => col.notNull().defaultTo(sql`(datetime('now'))`))
193
- .execute();
194
-
195
- await db.schema
196
- .createIndex("idx_failure_notifications_timestamp")
197
- .ifNotExists()
198
- .on("failure_notifications")
199
- .column("timestamp")
200
- .execute();
201
-
202
- await db.schema
203
- .createIndex("idx_failure_notifications_acknowledged")
204
- .ifNotExists()
205
- .on("failure_notifications")
206
- .column("acknowledged")
207
- .execute();
208
- }
209
- }
210
-
211
- export async function down(db: Kysely<unknown>): Promise<void> {
212
- await db.schema.dropTable("failure_notifications").ifExists().execute();
213
- await db.schema.dropTable("failure_captures").ifExists().execute();
214
- await db.schema.dropTable("failure_occurrence_screens").ifExists().execute();
215
- await db.schema.dropTable("failure_occurrences").ifExists().execute();
216
- await db.schema.dropTable("failure_groups").ifExists().execute();
217
- }
@@ -1,88 +0,0 @@
1
- import { type Kysely, sql } from "kysely";
2
-
3
- export async function up(db: Kysely<unknown>): Promise<void> {
4
- // 1. Clear all existing navigation data (cascade handles related tables)
5
- // This is a breaking change - navigation graphs will need to be rebuilt
6
- await db.deleteFrom("navigation_edges" as never).execute();
7
- await db.deleteFrom("navigation_nodes" as never).execute();
8
-
9
- // 2. Create navigation_node_fingerprints table
10
- // Tracks view hierarchy fingerprints associated with named navigation nodes
11
- // Fingerprints are scoped per app to prevent cross-app collisions
12
- await db.schema
13
- .createTable("navigation_node_fingerprints")
14
- .ifNotExists()
15
- .addColumn("id", "integer", (col) => col.primaryKey().autoIncrement())
16
- .addColumn("app_id", "text", (col) =>
17
- col.notNull().references("navigation_apps.app_id").onDelete("cascade"),
18
- )
19
- .addColumn("node_id", "integer", (col) =>
20
- col.notNull().references("navigation_nodes.id").onDelete("cascade"),
21
- )
22
- .addColumn("fingerprint_hash", "text", (col) => col.notNull())
23
- .addColumn("fingerprint_data", "text", (col) => col.notNull())
24
- .addColumn("first_seen_at", "integer", (col) => col.notNull())
25
- .addColumn("last_seen_at", "integer", (col) => col.notNull())
26
- .addColumn("occurrence_count", "integer", (col) => col.notNull().defaultTo(1))
27
- .addColumn("created_at", "text", (col) => col.notNull().defaultTo(sql`(datetime('now'))`))
28
- .execute();
29
-
30
- // Create unique index on (app_id, fingerprint_hash) - fingerprints are unique per app
31
- await db.schema
32
- .createIndex("idx_navigation_node_fingerprints_app_hash")
33
- .ifNotExists()
34
- .on("navigation_node_fingerprints")
35
- .columns(["app_id", "fingerprint_hash"])
36
- .unique()
37
- .execute();
38
-
39
- // Create index on node_id for efficient lookups
40
- await db.schema
41
- .createIndex("idx_navigation_node_fingerprints_node")
42
- .ifNotExists()
43
- .on("navigation_node_fingerprints")
44
- .column("node_id")
45
- .execute();
46
-
47
- // 3. Create navigation_suggestions table
48
- // Stores uncorrelated fingerprints for apps that have named nodes
49
- await db.schema
50
- .createTable("navigation_suggestions")
51
- .ifNotExists()
52
- .addColumn("id", "integer", (col) => col.primaryKey().autoIncrement())
53
- .addColumn("app_id", "text", (col) =>
54
- col.notNull().references("navigation_apps.app_id").onDelete("cascade"),
55
- )
56
- .addColumn("fingerprint_hash", "text", (col) => col.notNull())
57
- .addColumn("fingerprint_data", "text", (col) => col.notNull())
58
- .addColumn("first_seen_at", "integer", (col) => col.notNull())
59
- .addColumn("last_seen_at", "integer", (col) => col.notNull())
60
- .addColumn("occurrence_count", "integer", (col) => col.notNull().defaultTo(1))
61
- .addColumn("promoted_to_fingerprint_id", "integer", (col) =>
62
- col.references("navigation_node_fingerprints.id").onDelete("set null"),
63
- )
64
- .addColumn("created_at", "text", (col) => col.notNull().defaultTo(sql`(datetime('now'))`))
65
- .execute();
66
-
67
- // Create unique index on (app_id, fingerprint_hash) for deduplication
68
- await db.schema
69
- .createIndex("idx_navigation_suggestions_app_hash")
70
- .ifNotExists()
71
- .on("navigation_suggestions")
72
- .columns(["app_id", "fingerprint_hash"])
73
- .unique()
74
- .execute();
75
-
76
- // Create index on app_id for efficient queries
77
- await db.schema
78
- .createIndex("idx_navigation_suggestions_app")
79
- .ifNotExists()
80
- .on("navigation_suggestions")
81
- .column("app_id")
82
- .execute();
83
- }
84
-
85
- export async function down(db: Kysely<unknown>): Promise<void> {
86
- await db.schema.dropTable("navigation_suggestions").execute();
87
- await db.schema.dropTable("navigation_node_fingerprints").execute();
88
- }
@@ -1,108 +0,0 @@
1
- import type { Kysely } from "kysely";
2
- import { sql } from "kysely";
3
-
4
- async function columnExists(
5
- db: Kysely<unknown>,
6
- tableName: string,
7
- columnName: string,
8
- ): Promise<boolean> {
9
- const result = await sql<{ name: string }>`
10
- SELECT name FROM pragma_table_info(${tableName}) WHERE name = ${columnName}
11
- `.execute(db);
12
- return result.rows.length > 0;
13
- }
14
-
15
- async function addColumnIfNotExists(
16
- db: Kysely<unknown>,
17
- tableName: string,
18
- columnName: string,
19
- columnType: "real" | "integer",
20
- ): Promise<void> {
21
- if (await columnExists(db, tableName, columnName)) {
22
- return;
23
- }
24
- await db.schema.alterTable(tableName).addColumn(columnName, columnType).execute();
25
- }
26
-
27
- export async function up(db: Kysely<unknown>): Promise<void> {
28
- // Add new columns to performance_audit_results table for live metrics
29
- await addColumnIfNotExists(db, "performance_audit_results", "time_to_first_frame_ms", "real");
30
- await addColumnIfNotExists(db, "performance_audit_results", "time_to_interactive_ms", "real");
31
- await addColumnIfNotExists(db, "performance_audit_results", "frame_rate_fps", "real");
32
- await addColumnIfNotExists(db, "performance_audit_results", "node_id", "integer");
33
-
34
- // Create index on node_id for navigation node lookups
35
- await db.schema
36
- .createIndex("idx_performance_audit_results_node_id")
37
- .ifNotExists()
38
- .on("performance_audit_results")
39
- .column("node_id")
40
- .execute();
41
-
42
- // Create composite index on (package_name, timestamp) for efficient pruning
43
- await db.schema
44
- .createIndex("idx_performance_audit_results_package_timestamp")
45
- .ifNotExists()
46
- .on("performance_audit_results")
47
- .columns(["package_name", "timestamp"])
48
- .execute();
49
- }
50
-
51
- export async function down(db: Kysely<unknown>): Promise<void> {
52
- // Drop indexes first
53
- await db.schema.dropIndex("idx_performance_audit_results_package_timestamp").execute();
54
-
55
- await db.schema.dropIndex("idx_performance_audit_results_node_id").execute();
56
-
57
- // SQLite doesn't support DROP COLUMN directly, so we need to recreate the table
58
- // For simplicity in migration rollback, we'll just drop and recreate the table
59
- // This is acceptable for development but should be handled more carefully in production
60
-
61
- // Create a backup table with original schema
62
- await db.schema
63
- .createTable("performance_audit_results_backup")
64
- .addColumn("id", "integer", (col) => col.primaryKey().autoIncrement())
65
- .addColumn("device_id", "text", (col) => col.notNull())
66
- .addColumn("session_id", "text", (col) => col.notNull())
67
- .addColumn("package_name", "text", (col) => col.notNull())
68
- .addColumn("timestamp", "text", (col) => col.notNull())
69
- .addColumn("passed", "integer", (col) => col.notNull())
70
- .addColumn("p50_ms", "real")
71
- .addColumn("p90_ms", "real")
72
- .addColumn("p95_ms", "real")
73
- .addColumn("p99_ms", "real")
74
- .addColumn("jank_count", "integer")
75
- .addColumn("missed_vsync_count", "integer")
76
- .addColumn("slow_ui_thread_count", "integer")
77
- .addColumn("frame_deadline_missed_count", "integer")
78
- .addColumn("cpu_usage_percent", "real")
79
- .addColumn("touch_latency_ms", "real")
80
- .addColumn("diagnostics_json", "text")
81
- .addColumn("created_at", "text", (col) => col.notNull().defaultTo(sql`(datetime('now'))`))
82
- .execute();
83
-
84
- // Copy data to backup
85
- await sql`
86
- INSERT INTO performance_audit_results_backup
87
- SELECT id, device_id, session_id, package_name, timestamp, passed,
88
- p50_ms, p90_ms, p95_ms, p99_ms, jank_count, missed_vsync_count,
89
- slow_ui_thread_count, frame_deadline_missed_count, cpu_usage_percent,
90
- touch_latency_ms, diagnostics_json, created_at
91
- FROM performance_audit_results
92
- `.execute(db);
93
-
94
- // Drop original table
95
- await db.schema.dropTable("performance_audit_results").execute();
96
-
97
- // Rename backup to original
98
- await sql`ALTER TABLE performance_audit_results_backup RENAME TO performance_audit_results`.execute(
99
- db,
100
- );
101
-
102
- // Recreate original index
103
- await db.schema
104
- .createIndex("idx_performance_audit_results_device_timestamp")
105
- .on("performance_audit_results")
106
- .columns(["device_id", "timestamp"])
107
- .execute();
108
- }
@@ -1,184 +0,0 @@
1
- import { type Kysely, sql } from "kysely";
2
-
3
- // Keep raw migrations independent of app modules that are not shipped beside them.
4
- interface SqliteCatalogSchema {
5
- sqlite_master: { type: string; name: string };
6
- }
7
-
8
- async function tableExists(db: Kysely<unknown>, tableName: string): Promise<boolean> {
9
- const result = await (db as Kysely<SqliteCatalogSchema>)
10
- .selectFrom("sqlite_master")
11
- .select("name")
12
- .where("type", "=", "table")
13
- .where("name", "=", tableName)
14
- .execute();
15
- return result.length > 0;
16
- }
17
-
18
- export async function up(db: Kysely<unknown>): Promise<void> {
19
- // Network events table
20
- if (!(await tableExists(db, "network_events"))) {
21
- await db.schema
22
- .createTable("network_events")
23
- .ifNotExists()
24
- .addColumn("id", "integer", (col) => col.primaryKey().autoIncrement())
25
- .addColumn("device_id", "text")
26
- .addColumn("timestamp", "integer", (col) => col.notNull())
27
- .addColumn("application_id", "text")
28
- .addColumn("session_id", "text")
29
- .addColumn("url", "text", (col) => col.notNull())
30
- .addColumn("method", "text", (col) => col.notNull())
31
- .addColumn("status_code", "integer", (col) => col.notNull().defaultTo(0))
32
- .addColumn("duration_ms", "integer", (col) => col.notNull().defaultTo(0))
33
- .addColumn("request_body_size", "integer", (col) => col.defaultTo(-1))
34
- .addColumn("response_body_size", "integer", (col) => col.defaultTo(-1))
35
- .addColumn("protocol", "text")
36
- .addColumn("host", "text")
37
- .addColumn("path", "text")
38
- .addColumn("error", "text")
39
- .addColumn("created_at", "text", (col) => col.notNull().defaultTo(sql`(datetime('now'))`))
40
- .execute();
41
-
42
- await db.schema
43
- .createIndex("idx_network_events_timestamp")
44
- .ifNotExists()
45
- .on("network_events")
46
- .column("timestamp")
47
- .execute();
48
-
49
- await db.schema
50
- .createIndex("idx_network_events_host")
51
- .ifNotExists()
52
- .on("network_events")
53
- .column("host")
54
- .execute();
55
-
56
- await db.schema
57
- .createIndex("idx_network_events_device")
58
- .ifNotExists()
59
- .on("network_events")
60
- .column("device_id")
61
- .execute();
62
- }
63
-
64
- // Log events table
65
- if (!(await tableExists(db, "log_events"))) {
66
- await db.schema
67
- .createTable("log_events")
68
- .ifNotExists()
69
- .addColumn("id", "integer", (col) => col.primaryKey().autoIncrement())
70
- .addColumn("device_id", "text")
71
- .addColumn("timestamp", "integer", (col) => col.notNull())
72
- .addColumn("application_id", "text")
73
- .addColumn("session_id", "text")
74
- .addColumn("level", "integer", (col) => col.notNull())
75
- .addColumn("tag", "text", (col) => col.notNull())
76
- .addColumn("message", "text", (col) => col.notNull())
77
- .addColumn("filter_name", "text", (col) => col.notNull())
78
- .addColumn("created_at", "text", (col) => col.notNull().defaultTo(sql`(datetime('now'))`))
79
- .execute();
80
-
81
- await db.schema
82
- .createIndex("idx_log_events_timestamp")
83
- .ifNotExists()
84
- .on("log_events")
85
- .column("timestamp")
86
- .execute();
87
-
88
- await db.schema
89
- .createIndex("idx_log_events_tag")
90
- .ifNotExists()
91
- .on("log_events")
92
- .column("tag")
93
- .execute();
94
-
95
- await db.schema
96
- .createIndex("idx_log_events_device")
97
- .ifNotExists()
98
- .on("log_events")
99
- .column("device_id")
100
- .execute();
101
- }
102
-
103
- // Custom events table
104
- if (!(await tableExists(db, "custom_events"))) {
105
- await db.schema
106
- .createTable("custom_events")
107
- .ifNotExists()
108
- .addColumn("id", "integer", (col) => col.primaryKey().autoIncrement())
109
- .addColumn("device_id", "text")
110
- .addColumn("timestamp", "integer", (col) => col.notNull())
111
- .addColumn("application_id", "text")
112
- .addColumn("session_id", "text")
113
- .addColumn("name", "text", (col) => col.notNull())
114
- .addColumn("properties_json", "text") // JSON of string key-value pairs
115
- .addColumn("created_at", "text", (col) => col.notNull().defaultTo(sql`(datetime('now'))`))
116
- .execute();
117
-
118
- await db.schema
119
- .createIndex("idx_custom_events_timestamp")
120
- .ifNotExists()
121
- .on("custom_events")
122
- .column("timestamp")
123
- .execute();
124
-
125
- await db.schema
126
- .createIndex("idx_custom_events_name")
127
- .ifNotExists()
128
- .on("custom_events")
129
- .column("name")
130
- .execute();
131
-
132
- await db.schema
133
- .createIndex("idx_custom_events_device")
134
- .ifNotExists()
135
- .on("custom_events")
136
- .column("device_id")
137
- .execute();
138
- }
139
-
140
- // OS events table (lifecycle, broadcast, websocket_frame)
141
- if (!(await tableExists(db, "os_events"))) {
142
- await db.schema
143
- .createTable("os_events")
144
- .ifNotExists()
145
- .addColumn("id", "integer", (col) => col.primaryKey().autoIncrement())
146
- .addColumn("device_id", "text")
147
- .addColumn("timestamp", "integer", (col) => col.notNull())
148
- .addColumn("application_id", "text")
149
- .addColumn("session_id", "text")
150
- .addColumn("category", "text", (col) => col.notNull()) // lifecycle, broadcast, websocket_frame
151
- .addColumn("kind", "text", (col) => col.notNull()) // e.g., foreground, screen_on, connectivity_change
152
- .addColumn("details_json", "text") // JSON of additional details
153
- .addColumn("created_at", "text", (col) => col.notNull().defaultTo(sql`(datetime('now'))`))
154
- .execute();
155
-
156
- await db.schema
157
- .createIndex("idx_os_events_timestamp")
158
- .ifNotExists()
159
- .on("os_events")
160
- .column("timestamp")
161
- .execute();
162
-
163
- await db.schema
164
- .createIndex("idx_os_events_category")
165
- .ifNotExists()
166
- .on("os_events")
167
- .column("category")
168
- .execute();
169
-
170
- await db.schema
171
- .createIndex("idx_os_events_device")
172
- .ifNotExists()
173
- .on("os_events")
174
- .column("device_id")
175
- .execute();
176
- }
177
- }
178
-
179
- export async function down(db: Kysely<unknown>): Promise<void> {
180
- await db.schema.dropTable("os_events").ifExists().execute();
181
- await db.schema.dropTable("custom_events").ifExists().execute();
182
- await db.schema.dropTable("log_events").ifExists().execute();
183
- await db.schema.dropTable("network_events").ifExists().execute();
184
- }
@@ -1,36 +0,0 @@
1
- import { type Kysely, sql } 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(sql`(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
- }
@@ -1,37 +0,0 @@
1
- import { type Kysely, sql } 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(sql`(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
- }