lytx 0.3.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.
Files changed (213) hide show
  1. package/.env.example +37 -0
  2. package/README.md +486 -0
  3. package/alchemy.run.ts +155 -0
  4. package/cli/bootstrap-admin.ts +284 -0
  5. package/cli/deploy-staging.ts +692 -0
  6. package/cli/import-events.ts +628 -0
  7. package/cli/import-sites.ts +518 -0
  8. package/cli/index.ts +609 -0
  9. package/cli/init-db.ts +269 -0
  10. package/cli/migrate-to-durable-objects.ts +564 -0
  11. package/cli/migration-worker.ts +300 -0
  12. package/cli/performance-test.ts +588 -0
  13. package/cli/pg/client.ts +4 -0
  14. package/cli/pg/new-site.ts +153 -0
  15. package/cli/rollback-durable-objects.ts +622 -0
  16. package/cli/seed-data.ts +459 -0
  17. package/cli/setup.js +18 -0
  18. package/cli/setup.ts +463 -0
  19. package/cli/validate-migration.ts +200 -0
  20. package/cli/wrangler-migration.jsonc +28 -0
  21. package/db/adapter.ts +166 -0
  22. package/db/analytics_engine/client.ts +0 -0
  23. package/db/analytics_engine/sites.ts +0 -0
  24. package/db/client.ts +16 -0
  25. package/db/d1/client.ts +8 -0
  26. package/db/d1/drizzle.config.ts +35 -0
  27. package/db/d1/migrations/0000_true_maelstrom.sql +165 -0
  28. package/db/d1/migrations/0001_wonderful_bloodaxe.sql +12 -0
  29. package/db/d1/migrations/0002_late_frightful_four.sql +1 -0
  30. package/db/d1/migrations/0003_cuddly_obadiah_stane.sql +16 -0
  31. package/db/d1/migrations/0004_mute_stardust.sql +1 -0
  32. package/db/d1/migrations/0005_awesome_silvermane.sql +3 -0
  33. package/db/d1/migrations/0006_volatile_shriek.sql +2 -0
  34. package/db/d1/migrations/0007_superb_lila_cheney.sql +1 -0
  35. package/db/d1/migrations/0008_bitter_longshot.sql +17 -0
  36. package/db/d1/migrations/0009_wonderful_madame_masque.sql +28 -0
  37. package/db/d1/migrations/meta/0000_snapshot.json +1112 -0
  38. package/db/d1/migrations/meta/0001_snapshot.json +1187 -0
  39. package/db/d1/migrations/meta/0002_snapshot.json +1194 -0
  40. package/db/d1/migrations/meta/0003_snapshot.json +1296 -0
  41. package/db/d1/migrations/meta/0004_snapshot.json +1303 -0
  42. package/db/d1/migrations/meta/0005_snapshot.json +1325 -0
  43. package/db/d1/migrations/meta/0006_snapshot.json +1339 -0
  44. package/db/d1/migrations/meta/0007_snapshot.json +1347 -0
  45. package/db/d1/migrations/meta/0008_snapshot.json +1464 -0
  46. package/db/d1/migrations/meta/0009_snapshot.json +1648 -0
  47. package/db/d1/migrations/meta/_journal.json +76 -0
  48. package/db/d1/schema.ts +407 -0
  49. package/db/d1/sites.ts +374 -0
  50. package/db/d1/teamAiUsage.ts +101 -0
  51. package/db/d1/teams.ts +127 -0
  52. package/db/durable/drizzle.config.ts +8 -0
  53. package/db/durable/durableObjectClient.ts +480 -0
  54. package/db/durable/events.ts +100 -0
  55. package/db/durable/migrations/0000_fair_bucky.sql +38 -0
  56. package/db/durable/migrations/meta/0000_snapshot.json +278 -0
  57. package/db/durable/migrations/meta/_journal.json +13 -0
  58. package/db/durable/migrations/migrations.js +10 -0
  59. package/db/durable/schema.ts +5 -0
  60. package/db/durable/siteDurableObject.ts +1352 -0
  61. package/db/durable/types.ts +53 -0
  62. package/db/postgres/client.ts +13 -0
  63. package/db/postgres/drizzle.config.ts +12 -0
  64. package/db/postgres/migrations/0000_brainy_sprite.sql +116 -0
  65. package/db/postgres/migrations/meta/0000_snapshot.json +681 -0
  66. package/db/postgres/migrations/meta/_journal.json +13 -0
  67. package/db/postgres/schema.ts +145 -0
  68. package/db/postgres/sites.ts +118 -0
  69. package/db/tranformReports.ts +595 -0
  70. package/db/types.ts +55 -0
  71. package/endpoints/api_worker.tsx +1854 -0
  72. package/endpoints/site_do_worker.ts +11 -0
  73. package/index.d.ts +63 -0
  74. package/index.ts +83 -0
  75. package/lib/auth.ts +279 -0
  76. package/lib/geojson/world_countries.json +45307 -0
  77. package/lib/random_name.ts +41 -0
  78. package/lib/sendMail.ts +252 -0
  79. package/package.json +142 -0
  80. package/public/favicon.ico +0 -0
  81. package/public/images/android-chrome-192x192.png +0 -0
  82. package/public/images/android-chrome-512x512.png +0 -0
  83. package/public/images/apple-touch-icon.png +0 -0
  84. package/public/images/favicon-16x16.png +0 -0
  85. package/public/images/favicon-32x32.png +0 -0
  86. package/public/images/lytx_dark_dashboard.png +0 -0
  87. package/public/images/lytx_light_dashboard.png +0 -0
  88. package/public/images/safari-pinned-tab.svg +4 -0
  89. package/public/logo.png +0 -0
  90. package/public/site.webmanifest +26 -0
  91. package/public/sw.js +107 -0
  92. package/src/Document.tsx +86 -0
  93. package/src/api/ai_api.ts +1156 -0
  94. package/src/api/authMiddleware.ts +45 -0
  95. package/src/api/auth_api.ts +465 -0
  96. package/src/api/event_labels_api.ts +193 -0
  97. package/src/api/events_api.ts +210 -0
  98. package/src/api/queueWorker.ts +303 -0
  99. package/src/api/reports_api.ts +278 -0
  100. package/src/api/seed_api.ts +288 -0
  101. package/src/api/sites_api.ts +904 -0
  102. package/src/api/tag_api.ts +458 -0
  103. package/src/api/tag_api_v2.ts +289 -0
  104. package/src/api/team_api.ts +456 -0
  105. package/src/app/Dashboard.tsx +1339 -0
  106. package/src/app/Events.tsx +974 -0
  107. package/src/app/Explore.tsx +312 -0
  108. package/src/app/Layout.tsx +58 -0
  109. package/src/app/Settings.tsx +1302 -0
  110. package/src/app/components/DashboardCard.tsx +118 -0
  111. package/src/app/components/EditableCell.tsx +123 -0
  112. package/src/app/components/EventForm.tsx +93 -0
  113. package/src/app/components/MarketingFooter.tsx +49 -0
  114. package/src/app/components/MarketingNav.tsx +150 -0
  115. package/src/app/components/Nav.tsx +755 -0
  116. package/src/app/components/NewSiteSetup.tsx +298 -0
  117. package/src/app/components/SQLEditor.tsx +740 -0
  118. package/src/app/components/SiteSelector.tsx +126 -0
  119. package/src/app/components/SiteTag.tsx +42 -0
  120. package/src/app/components/SiteTagInstallCard.tsx +241 -0
  121. package/src/app/components/WorldMapCard.tsx +337 -0
  122. package/src/app/components/charts/ChartComponents.tsx +1481 -0
  123. package/src/app/components/charts/EventFunnel.tsx +45 -0
  124. package/src/app/components/charts/EventSummary.tsx +194 -0
  125. package/src/app/components/charts/SankeyFlows.tsx +72 -0
  126. package/src/app/components/marketing/CheckIcon.tsx +16 -0
  127. package/src/app/components/marketing/MarketingLayout.tsx +23 -0
  128. package/src/app/components/marketing/SectionHeading.tsx +35 -0
  129. package/src/app/components/reports/AskAiWorkspace.tsx +371 -0
  130. package/src/app/components/reports/CreateReportStarter.tsx +74 -0
  131. package/src/app/components/reports/DashboardRouteFiltersContext.tsx +14 -0
  132. package/src/app/components/reports/DashboardToolbar.tsx +154 -0
  133. package/src/app/components/reports/DashboardWorkspaceLayout.tsx +63 -0
  134. package/src/app/components/reports/DashboardWorkspaceShell.tsx +118 -0
  135. package/src/app/components/reports/ReportBuilderWorkspace.tsx +76 -0
  136. package/src/app/components/reports/custom/CustomReportBuilderPage.tsx +1667 -0
  137. package/src/app/components/reports/custom/ReportWidgetChart.tsx +297 -0
  138. package/src/app/components/reports/custom/buildWidgetSql.ts +151 -0
  139. package/src/app/components/reports/custom/chartPalettes.ts +18 -0
  140. package/src/app/components/reports/custom/types.ts +50 -0
  141. package/src/app/components/reports/reportBuilderMenuItems.ts +17 -0
  142. package/src/app/components/reports/useDashboardToolbarControls.tsx +235 -0
  143. package/src/app/components/ui/AlertBanner.tsx +101 -0
  144. package/src/app/components/ui/Button.tsx +55 -0
  145. package/src/app/components/ui/Card.tsx +80 -0
  146. package/src/app/components/ui/Input.tsx +72 -0
  147. package/src/app/components/ui/Link.tsx +23 -0
  148. package/src/app/components/ui/ReportBuilderMenu.tsx +246 -0
  149. package/src/app/components/ui/ThemeToggle.tsx +54 -0
  150. package/src/app/constants.ts +6 -0
  151. package/src/app/headers.ts +33 -0
  152. package/src/app/providers/AuthProvider.tsx +189 -0
  153. package/src/app/providers/ClientProviders.tsx +18 -0
  154. package/src/app/providers/QueryProvider.tsx +23 -0
  155. package/src/app/providers/ThemeProvider.tsx +88 -0
  156. package/src/app/utils/chartThemes.ts +146 -0
  157. package/src/app/utils/keybinds.ts +96 -0
  158. package/src/app/utils/media.tsx +24 -0
  159. package/src/client.tsx +114 -0
  160. package/src/config/createLytxAppConfig.ts +252 -0
  161. package/src/config/resourceNames.ts +88 -0
  162. package/src/db/index.ts +67 -0
  163. package/src/index.css +285 -0
  164. package/src/lib/featureFlags.ts +69 -0
  165. package/src/pages/GetStarted.tsx +290 -0
  166. package/src/pages/Home.tsx +268 -0
  167. package/src/pages/Login.tsx +283 -0
  168. package/src/pages/PrivacyPolicy.tsx +120 -0
  169. package/src/pages/Signup.tsx +267 -0
  170. package/src/pages/TermsOfService.tsx +126 -0
  171. package/src/pages/VerifyEmail.tsx +56 -0
  172. package/src/session/durableObject.ts +7 -0
  173. package/src/session/siteSchema.ts +86 -0
  174. package/src/session/types.ts +36 -0
  175. package/src/templates/README.md +80 -0
  176. package/src/templates/cleanFunctions.js +44 -0
  177. package/src/templates/embedFunctions.js +52 -0
  178. package/src/templates/lytx-shared.ts +662 -0
  179. package/src/templates/lytxpixel-core.ts +144 -0
  180. package/src/templates/lytxpixel.ts +267 -0
  181. package/src/templates/lytxpixelBrowser.js +634 -0
  182. package/src/templates/lytxpixelBrowser.mjs +634 -0
  183. package/src/templates/parseData.js +12 -0
  184. package/src/templates/script.ts +31 -0
  185. package/src/templates/template.tsx +50 -0
  186. package/src/templates/test.js +3 -0
  187. package/src/templates/trackWebEvents.ts +177 -0
  188. package/src/templates/vendors/clickcease.ts +8 -0
  189. package/src/templates/vendors/google.ts +174 -0
  190. package/src/templates/vendors/linkedin.ts +23 -0
  191. package/src/templates/vendors/meta.ts +56 -0
  192. package/src/templates/vendors/quantcast.ts +22 -0
  193. package/src/templates/vendors/simplfi.ts +7 -0
  194. package/src/types/app-context.ts +16 -0
  195. package/src/utilities/dashboardParams.ts +188 -0
  196. package/src/utilities/dashboardQueries.ts +537 -0
  197. package/src/utilities/dashboardTransforms.ts +167 -0
  198. package/src/utilities/dataValidation.ts +414 -0
  199. package/src/utilities/detector.ts +73 -0
  200. package/src/utilities/encrypt.ts +103 -0
  201. package/src/utilities/index.ts +13 -0
  202. package/src/utilities/parser.ts +117 -0
  203. package/src/utilities/performanceMonitoring.ts +570 -0
  204. package/src/utilities/route_interuptors.ts +24 -0
  205. package/src/worker.tsx +675 -0
  206. package/tsconfig.json +78 -0
  207. package/types/env.d.ts +16 -0
  208. package/types/rw.d.ts +7 -0
  209. package/types/shims.d.ts +53 -0
  210. package/types/vite.d.ts +19 -0
  211. package/vite/vite-plugin-pixel-bundle.ts +126 -0
  212. package/vite.config.ts +53 -0
  213. package/worker-configuration.d.ts +8401 -0
package/db/adapter.ts ADDED
@@ -0,0 +1,166 @@
1
+ import { getDashboardDataFromDurableObject, getSiteInfo } from "@db/durable/durableObjectClient";
2
+ import { processDirectSiteEvents, batchProcessSiteEvents } from "@/api/queueWorker";
3
+
4
+ import type { DashboardOptions, DBAdapter } from "@db/types";
5
+ import type { SiteEventInput } from "@/session/siteSchema";
6
+ import { IS_DEV } from "rwsdk/constants";
7
+
8
+ /**
9
+ * Updated Site Adapter - All dashboard reads now go to durable objects for performance
10
+ */
11
+ const SiteAdapter = {
12
+ //NOTE: The sites are from durable objects, but all account admin is d1
13
+ "sqlite": getDashboardDataFromDurableObject,
14
+ "postgres": getDashboardDataFromDurableObject, // Fast reads from durable object
15
+ "singlestore": getDashboardDataFromDurableObject,
16
+ "analytics_engine": getDashboardDataFromDurableObject
17
+ } as const;
18
+
19
+ /**
20
+ * Get dashboard data from site-specific durable objects
21
+ * All adapters now use durable objects for fast dashboard access
22
+ */
23
+ export async function getDashboardData<T extends DBAdapter>(
24
+ adapter: T,
25
+ options: DashboardOptions,
26
+ ) {
27
+ if (IS_DEV) {
28
+ console.log(`Adapter set to : ${adapter} with options:`);
29
+ console.dir(options);
30
+ }
31
+ return SiteAdapter[adapter](options);
32
+ }
33
+
34
+ /**
35
+ * Insert site events with intelligent routing based on site adapter
36
+ * - sqlite sites: Direct write to durable object
37
+ * - postgres/singlestore sites: Queue for dual-write (original DB + durable object)
38
+ */
39
+ export async function insertSiteEvents(
40
+ site_id: number,
41
+ site_uuid: string,
42
+ events: SiteEventInput[],
43
+ db_adapter: DBAdapter
44
+ ): Promise<{ success: boolean; inserted?: number; error?: string }> {
45
+ try {
46
+ // Get site information to determine routing strategy
47
+ if (db_adapter === 'sqlite') {
48
+ // Direct write to durable object for sqlite sites
49
+ return await processDirectSiteEvents(site_id, site_uuid, events);
50
+
51
+ } else if (db_adapter === 'postgres' || db_adapter === 'singlestore') {
52
+ // Queue for dual-write (postgres/singlestore + durable object)
53
+ const eventsBySite = new Map();
54
+ eventsBySite.set(site_id, {
55
+ siteUuid: site_uuid,
56
+ teamId: 1, // TODO: Get actual team_id from site info
57
+ adapter: db_adapter,
58
+ events
59
+ });
60
+
61
+ await batchProcessSiteEvents(eventsBySite);
62
+
63
+ return {
64
+ success: true,
65
+ inserted: events.length
66
+ };
67
+
68
+ } else {
69
+ return {
70
+ success: false,
71
+ error: `Unsupported adapter: ${db_adapter}`
72
+ };
73
+ }
74
+
75
+ } catch (error) {
76
+ console.error(`Error inserting site events for site ${site_uuid}:`, error);
77
+ return {
78
+ success: false,
79
+ error: error instanceof Error ? error.message : 'Unknown error'
80
+ };
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Batch insert events for multiple sites
86
+ */
87
+ export async function batchInsertSiteEvents(
88
+ eventsBySite: Map<number, SiteEventInput[]>,
89
+ env: Env
90
+ ): Promise<Map<number, { success: boolean; inserted?: number; error?: string }>> {
91
+ const results = new Map();
92
+
93
+ // Group sites by adapter type for efficient processing
94
+ const sqliteSites = new Map<number, SiteEventInput[]>();
95
+ const queueSites = new Map<number, { teamId: number; adapter: string; events: SiteEventInput[] }>();
96
+
97
+ // Categorize sites by adapter
98
+ for (const [siteId, events] of eventsBySite) {
99
+ const siteInfo = await getSiteInfo(siteId, env);
100
+
101
+ if (!siteInfo) {
102
+ results.set(siteId, { success: false, error: `Site ${siteId} not found` });
103
+ continue;
104
+ }
105
+
106
+ if (siteInfo.site_db_adapter === 'sqlite') {
107
+ sqliteSites.set(siteId, events);
108
+ } else {
109
+ queueSites.set(siteId, {
110
+ teamId: 1, // TODO: Get actual team_id
111
+ adapter: siteInfo.site_db_adapter,
112
+ events
113
+ });
114
+ }
115
+ }
116
+
117
+ // Process sqlite sites directly (parallel)
118
+ const sqlitePromises = Array.from(sqliteSites.entries()).map(async ([siteId, events]) => {
119
+ const siteInfo = await getSiteInfo(siteId, env);
120
+ if (!siteInfo) {
121
+ return [siteId, { success: false, error: `Site ${siteId} not found` }] as const;
122
+ }
123
+
124
+ const result = await processDirectSiteEvents(siteId, siteInfo.tag_id, events);
125
+ return [siteId, result] as const;
126
+ });
127
+
128
+ const sqliteResults = await Promise.allSettled(sqlitePromises);
129
+ sqliteResults.forEach((result, index) => {
130
+ const siteId = Array.from(sqliteSites.keys())[index];
131
+ if (result.status === 'fulfilled') {
132
+ results.set(result.value[0], result.value[1]);
133
+ } else {
134
+ results.set(siteId, { success: false, error: `Batch processing failed: ${result.reason}` });
135
+ }
136
+ });
137
+
138
+ // Process queue sites in batch
139
+ if (queueSites.size > 0) {
140
+ try {
141
+ await batchProcessSiteEvents(queueSites);
142
+ // Mark all queue sites as successful
143
+ for (const [siteId, { events }] of queueSites) {
144
+ results.set(siteId, { success: true, inserted: events.length });
145
+ }
146
+ } catch (error) {
147
+ // Mark all queue sites as failed
148
+ for (const siteId of queueSites.keys()) {
149
+ results.set(siteId, {
150
+ success: false,
151
+ error: error instanceof Error ? error.message : 'Queue processing failed'
152
+ });
153
+ }
154
+ }
155
+ }
156
+
157
+ return results;
158
+ }
159
+
160
+ /**
161
+ * Get site adapter type for routing decisions
162
+ */
163
+ export async function getSiteAdapter(siteId: number, env: Env): Promise<DBAdapter | null> {
164
+ const siteInfo = await getSiteInfo(siteId, env);
165
+ return siteInfo ? (siteInfo.site_db_adapter as DBAdapter) : null;
166
+ }
File without changes
File without changes
package/db/client.ts ADDED
@@ -0,0 +1,16 @@
1
+ import { d1_client } from "@db/d1/client";
2
+ import { pg_client } from "@db/postgres/client";
3
+ import type { AdapterToClient, DBAdapter } from "@db/types";
4
+
5
+ export function getClient<T extends DBAdapter>(adapter: T, connectionString?: string): AdapterToClient[T] {
6
+ switch (adapter) {
7
+ case "sqlite":
8
+ return d1_client as AdapterToClient[T]
9
+ case "postgres":
10
+ if (!connectionString) throw new Error("connectionString is required for postgres");
11
+ return pg_client(connectionString) as AdapterToClient[T];
12
+ default:
13
+ return d1_client as AdapterToClient[T];
14
+ }
15
+ }
16
+
@@ -0,0 +1,8 @@
1
+ import { drizzle } from 'drizzle-orm/d1';
2
+ import { env } from 'cloudflare:workers';
3
+
4
+ export const d1_client = drizzle(env.lytx_core_db);
5
+
6
+
7
+
8
+
@@ -0,0 +1,35 @@
1
+ // import * as dotenv from 'dotenv';
2
+ import { defineConfig, type Config } from 'drizzle-kit';
3
+ // dotenv.config();
4
+ // const mode = process.env.MODE;
5
+
6
+
7
+ export default defineConfig({
8
+ schema: './db/d1/schema.ts',
9
+ out: './db/d1/migrations',
10
+ dialect: 'sqlite',
11
+ });
12
+
13
+ // const config: Config = {
14
+ // out: './db/d1/migrations',
15
+ // schema: './db/d1/schema.ts',
16
+ // dialect: 'sqlite',
17
+ //
18
+ //
19
+ // }
20
+ // if (mode == "DEV") {
21
+ // //@ts-ignore
22
+ // config.dbCredentials = {
23
+ // url: process.env.LOCAL_D1!
24
+ // }
25
+ // } else {
26
+ // //@ts-ignore
27
+ // config.driver = "d1-http";
28
+ // //@ts-ignore
29
+ // config.dbCredentials = {
30
+ // accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
31
+ // databaseId: process.env.CLOUDFLARE_DATABASE_ID!,
32
+ // token: process.env.CLOUDFLARE_D1_TOKEN!,
33
+ // }
34
+ // }
35
+ // export default defineConfig(config);
@@ -0,0 +1,165 @@
1
+ CREATE TABLE `account` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `account_id` text NOT NULL,
4
+ `provider_id` text NOT NULL,
5
+ `user_id` text NOT NULL,
6
+ `access_token` text,
7
+ `refresh_token` text,
8
+ `id_token` text,
9
+ `access_token_expires_at` integer,
10
+ `refresh_token_expires_at` integer,
11
+ `scope` text,
12
+ `password` text,
13
+ `created_at` integer NOT NULL,
14
+ `updated_at` integer NOT NULL,
15
+ FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
16
+ );
17
+ --> statement-breakpoint
18
+ CREATE INDEX `account_user_id_idx` ON `account` (`user_id`);--> statement-breakpoint
19
+ CREATE TABLE `api_key` (
20
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
21
+ `key` text,
22
+ `team_id` integer NOT NULL,
23
+ `enabled` integer DEFAULT true,
24
+ `permissions` text DEFAULT '{"read":true,"write":true}' NOT NULL,
25
+ `allowed_team_members` text DEFAULT '[]',
26
+ `created_at` integer NOT NULL,
27
+ `updated_at` integer NOT NULL
28
+ );
29
+ --> statement-breakpoint
30
+ CREATE INDEX `api_key_team_id_idx` ON `api_key` (`team_id`);--> statement-breakpoint
31
+ CREATE TABLE `invited_user` (
32
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
33
+ `team_id` integer NOT NULL,
34
+ `accepted` integer NOT NULL,
35
+ `email` text NOT NULL,
36
+ `role` text DEFAULT 'editor' NOT NULL,
37
+ `name` text,
38
+ `created_at` integer NOT NULL,
39
+ `updated_at` integer NOT NULL
40
+ );
41
+ --> statement-breakpoint
42
+ CREATE UNIQUE INDEX `invited_user_email_unique` ON `invited_user` (`email`);--> statement-breakpoint
43
+ CREATE INDEX `invited_user_team_id_idx` ON `invited_user` (`team_id`);--> statement-breakpoint
44
+ CREATE INDEX `invited_user_email_idx` ON `invited_user` (`email`);--> statement-breakpoint
45
+ CREATE TABLE `session` (
46
+ `id` text PRIMARY KEY NOT NULL,
47
+ `expires_at` integer NOT NULL,
48
+ `token` text NOT NULL,
49
+ `created_at` integer NOT NULL,
50
+ `updated_at` integer NOT NULL,
51
+ `ip_address` text,
52
+ `user_agent` text,
53
+ `user_id` text NOT NULL,
54
+ FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
55
+ );
56
+ --> statement-breakpoint
57
+ CREATE UNIQUE INDEX `session_token_unique` ON `session` (`token`);--> statement-breakpoint
58
+ CREATE INDEX `session_user_id_idx` ON `session` (`user_id`);--> statement-breakpoint
59
+ CREATE INDEX `session_token_idx` ON `session` (`token`);--> statement-breakpoint
60
+ CREATE TABLE `site_events` (
61
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
62
+ `team_id` integer,
63
+ `bot_data` text,
64
+ `browser` text,
65
+ `city` text,
66
+ `client_page_url` text,
67
+ `country` text,
68
+ `created_at` integer NOT NULL,
69
+ `updated_at` integer NOT NULL,
70
+ `custom_data` text,
71
+ `device_type` text,
72
+ `event` text NOT NULL,
73
+ `operating_system` text,
74
+ `page_url` text,
75
+ `postal` text,
76
+ `query_params` text,
77
+ `referer` text,
78
+ `region` text,
79
+ `rid` text,
80
+ `screen_height` integer,
81
+ `screen_width` integer,
82
+ `site_id` integer NOT NULL,
83
+ `tag_id` text NOT NULL
84
+ );
85
+ --> statement-breakpoint
86
+ CREATE INDEX `site_events_team_id_idx` ON `site_events` (`team_id`);--> statement-breakpoint
87
+ CREATE INDEX `site_events_site_id_idx` ON `site_events` (`site_id`);--> statement-breakpoint
88
+ CREATE INDEX `site_events_tag_id_idx` ON `site_events` (`tag_id`);--> statement-breakpoint
89
+ CREATE INDEX `site_events_created_at_idx` ON `site_events` (`created_at`);--> statement-breakpoint
90
+ CREATE INDEX `site_events_team_site_idx` ON `site_events` (`team_id`,`site_id`);--> statement-breakpoint
91
+ CREATE INDEX `site_events_team_tag_idx` ON `site_events` (`team_id`,`tag_id`);--> statement-breakpoint
92
+ CREATE INDEX `site_events_site_created_idx` ON `site_events` (`site_id`,`created_at`);--> statement-breakpoint
93
+ CREATE INDEX `site_events_team_created_idx` ON `site_events` (`team_id`,`created_at`);--> statement-breakpoint
94
+ CREATE INDEX `site_events_country_idx` ON `site_events` (`country`);--> statement-breakpoint
95
+ CREATE INDEX `site_events_device_type_idx` ON `site_events` (`device_type`);--> statement-breakpoint
96
+ CREATE INDEX `site_events_event_idx` ON `site_events` (`event`);--> statement-breakpoint
97
+ CREATE INDEX `site_events_referer_idx` ON `site_events` (`referer`);--> statement-breakpoint
98
+ CREATE TABLE `sites` (
99
+ `site_id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
100
+ `uuid` text NOT NULL,
101
+ `tag_id` text NOT NULL,
102
+ `track_web_events` integer DEFAULT false NOT NULL,
103
+ `gdpr` integer DEFAULT false,
104
+ `event_load_strategy` text DEFAULT 'sdk' NOT NULL,
105
+ `external_id` integer DEFAULT 0 NOT NULL,
106
+ `site_db_adapter` text DEFAULT 'sqlite' NOT NULL,
107
+ `team_id` integer NOT NULL,
108
+ `name` text,
109
+ `created_at` integer NOT NULL,
110
+ `updated_at` integer NOT NULL,
111
+ `domain` text,
112
+ `tag_manager` integer DEFAULT false,
113
+ `autocapture` integer DEFAULT true,
114
+ `rid_salt` text,
115
+ `rid_salt_expire` integer,
116
+ `tag_id_override` text
117
+ );
118
+ --> statement-breakpoint
119
+ CREATE INDEX `sites_team_id_idx` ON `sites` (`team_id`);--> statement-breakpoint
120
+ CREATE INDEX `sites_tag_id_idx` ON `sites` (`tag_id`);--> statement-breakpoint
121
+ CREATE INDEX `sites_domain_idx` ON `sites` (`domain`);--> statement-breakpoint
122
+ CREATE TABLE `team` (
123
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
124
+ `external_id` integer DEFAULT 0 NOT NULL,
125
+ `created_at` integer,
126
+ `updated_at` integer NOT NULL,
127
+ `created_by` text NOT NULL,
128
+ `name` text,
129
+ `uuid` text,
130
+ `db_adapter` text DEFAULT 'sqlite' NOT NULL
131
+ );
132
+ --> statement-breakpoint
133
+ CREATE TABLE `team_member` (
134
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
135
+ `team_id` integer NOT NULL,
136
+ `role` text DEFAULT 'editor' NOT NULL,
137
+ `user_id` text NOT NULL,
138
+ `allowed_site_ids` text DEFAULT '["all"]',
139
+ `created_at` integer NOT NULL,
140
+ `updated_at` integer NOT NULL
141
+ );
142
+ --> statement-breakpoint
143
+ CREATE INDEX `team_member_team_id_idx` ON `team_member` (`team_id`);--> statement-breakpoint
144
+ CREATE INDEX `team_member_user_id_idx` ON `team_member` (`user_id`);--> statement-breakpoint
145
+ CREATE INDEX `team_member_team_user_idx` ON `team_member` (`team_id`,`user_id`);--> statement-breakpoint
146
+ CREATE TABLE `user` (
147
+ `id` text PRIMARY KEY NOT NULL,
148
+ `name` text NOT NULL,
149
+ `email` text NOT NULL,
150
+ `email_verified` integer NOT NULL,
151
+ `image` text,
152
+ `timezone` text,
153
+ `created_at` integer NOT NULL,
154
+ `updated_at` integer NOT NULL
155
+ );
156
+ --> statement-breakpoint
157
+ CREATE UNIQUE INDEX `user_email_unique` ON `user` (`email`);--> statement-breakpoint
158
+ CREATE TABLE `verification` (
159
+ `id` text PRIMARY KEY NOT NULL,
160
+ `identifier` text NOT NULL,
161
+ `value` text NOT NULL,
162
+ `expires_at` integer NOT NULL,
163
+ `created_at` integer,
164
+ `updated_at` integer NOT NULL
165
+ );
@@ -0,0 +1,12 @@
1
+ CREATE TABLE `event_labels` (
2
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
3
+ `site_id` integer NOT NULL,
4
+ `event_name` text NOT NULL,
5
+ `label` text NOT NULL,
6
+ `description` text,
7
+ `created_at` integer NOT NULL,
8
+ `updated_at` integer NOT NULL
9
+ );
10
+ --> statement-breakpoint
11
+ CREATE INDEX `event_labels_site_id_idx` ON `event_labels` (`site_id`);--> statement-breakpoint
12
+ CREATE INDEX `event_labels_site_event_idx` ON `event_labels` (`site_id`,`event_name`);
@@ -0,0 +1 @@
1
+ ALTER TABLE `user` ADD `last_site_id` integer;
@@ -0,0 +1,16 @@
1
+ CREATE TABLE `team_billing` (
2
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
3
+ `team_id` integer NOT NULL,
4
+ `stripe_customer_id` text,
5
+ `stripe_subscription_id` text,
6
+ `stripe_price_id` text,
7
+ `plan_name` text,
8
+ `status` text,
9
+ `current_period_end` integer,
10
+ `created_at` integer NOT NULL,
11
+ `updated_at` integer NOT NULL
12
+ );
13
+ --> statement-breakpoint
14
+ CREATE INDEX `team_billing_team_id_idx` ON `team_billing` (`team_id`);--> statement-breakpoint
15
+ CREATE INDEX `team_billing_customer_idx` ON `team_billing` (`stripe_customer_id`);--> statement-breakpoint
16
+ CREATE INDEX `team_billing_subscription_idx` ON `team_billing` (`stripe_subscription_id`);
@@ -0,0 +1 @@
1
+ ALTER TABLE `user` ADD `last_team_id` integer;
@@ -0,0 +1,3 @@
1
+ ALTER TABLE `team_billing` ADD `current_period_start` integer;--> statement-breakpoint
2
+ ALTER TABLE `team_billing` ADD `usage_mode` text DEFAULT 'metered' NOT NULL;--> statement-breakpoint
3
+ ALTER TABLE `team_billing` ADD `usage_cap` integer;
@@ -0,0 +1,2 @@
1
+ ALTER TABLE `api_key` ADD `site_id` integer;--> statement-breakpoint
2
+ CREATE INDEX `api_key_site_id_idx` ON `api_key` (`site_id`);
@@ -0,0 +1 @@
1
+ ALTER TABLE `team_billing` ADD `billing_method` text DEFAULT 'stripe_subscription' NOT NULL;
@@ -0,0 +1,17 @@
1
+ CREATE TABLE `custom_reports` (
2
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
3
+ `uuid` text NOT NULL,
4
+ `team_id` integer NOT NULL,
5
+ `site_id` integer NOT NULL,
6
+ `name` text NOT NULL,
7
+ `description` text,
8
+ `config` text NOT NULL,
9
+ `created_by` text NOT NULL,
10
+ `created_at` integer NOT NULL,
11
+ `updated_at` integer NOT NULL
12
+ );
13
+ --> statement-breakpoint
14
+ CREATE UNIQUE INDEX `custom_reports_uuid_unique` ON `custom_reports` (`uuid`);--> statement-breakpoint
15
+ CREATE INDEX `custom_reports_team_id_idx` ON `custom_reports` (`team_id`);--> statement-breakpoint
16
+ CREATE INDEX `custom_reports_site_id_idx` ON `custom_reports` (`site_id`);--> statement-breakpoint
17
+ CREATE INDEX `custom_reports_team_site_idx` ON `custom_reports` (`team_id`,`site_id`);
@@ -0,0 +1,28 @@
1
+ CREATE TABLE `team_ai_usage` (
2
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
3
+ `team_id` integer NOT NULL,
4
+ `user_id` text,
5
+ `site_id` integer,
6
+ `request_id` text,
7
+ `request_type` text NOT NULL,
8
+ `provider` text,
9
+ `model` text,
10
+ `status` text DEFAULT 'success' NOT NULL,
11
+ `error_code` text,
12
+ `error_message` text,
13
+ `input_tokens` integer,
14
+ `output_tokens` integer,
15
+ `total_tokens` integer,
16
+ `tool_calls` integer,
17
+ `message_count` integer,
18
+ `prompt_chars` integer,
19
+ `completion_chars` integer,
20
+ `duration_ms` integer,
21
+ `created_at` integer NOT NULL
22
+ );
23
+ --> statement-breakpoint
24
+ CREATE INDEX `team_ai_usage_team_id_idx` ON `team_ai_usage` (`team_id`);--> statement-breakpoint
25
+ CREATE INDEX `team_ai_usage_team_created_idx` ON `team_ai_usage` (`team_id`,`created_at`);--> statement-breakpoint
26
+ CREATE INDEX `team_ai_usage_team_type_created_idx` ON `team_ai_usage` (`team_id`,`request_type`,`created_at`);--> statement-breakpoint
27
+ CREATE INDEX `team_ai_usage_request_id_idx` ON `team_ai_usage` (`request_id`);--> statement-breakpoint
28
+ CREATE INDEX `team_ai_usage_user_created_idx` ON `team_ai_usage` (`user_id`,`created_at`);