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.
- package/.env.example +37 -0
- package/README.md +486 -0
- package/alchemy.run.ts +155 -0
- package/cli/bootstrap-admin.ts +284 -0
- package/cli/deploy-staging.ts +692 -0
- package/cli/import-events.ts +628 -0
- package/cli/import-sites.ts +518 -0
- package/cli/index.ts +609 -0
- package/cli/init-db.ts +269 -0
- package/cli/migrate-to-durable-objects.ts +564 -0
- package/cli/migration-worker.ts +300 -0
- package/cli/performance-test.ts +588 -0
- package/cli/pg/client.ts +4 -0
- package/cli/pg/new-site.ts +153 -0
- package/cli/rollback-durable-objects.ts +622 -0
- package/cli/seed-data.ts +459 -0
- package/cli/setup.js +18 -0
- package/cli/setup.ts +463 -0
- package/cli/validate-migration.ts +200 -0
- package/cli/wrangler-migration.jsonc +28 -0
- package/db/adapter.ts +166 -0
- package/db/analytics_engine/client.ts +0 -0
- package/db/analytics_engine/sites.ts +0 -0
- package/db/client.ts +16 -0
- package/db/d1/client.ts +8 -0
- package/db/d1/drizzle.config.ts +35 -0
- package/db/d1/migrations/0000_true_maelstrom.sql +165 -0
- package/db/d1/migrations/0001_wonderful_bloodaxe.sql +12 -0
- package/db/d1/migrations/0002_late_frightful_four.sql +1 -0
- package/db/d1/migrations/0003_cuddly_obadiah_stane.sql +16 -0
- package/db/d1/migrations/0004_mute_stardust.sql +1 -0
- package/db/d1/migrations/0005_awesome_silvermane.sql +3 -0
- package/db/d1/migrations/0006_volatile_shriek.sql +2 -0
- package/db/d1/migrations/0007_superb_lila_cheney.sql +1 -0
- package/db/d1/migrations/0008_bitter_longshot.sql +17 -0
- package/db/d1/migrations/0009_wonderful_madame_masque.sql +28 -0
- package/db/d1/migrations/meta/0000_snapshot.json +1112 -0
- package/db/d1/migrations/meta/0001_snapshot.json +1187 -0
- package/db/d1/migrations/meta/0002_snapshot.json +1194 -0
- package/db/d1/migrations/meta/0003_snapshot.json +1296 -0
- package/db/d1/migrations/meta/0004_snapshot.json +1303 -0
- package/db/d1/migrations/meta/0005_snapshot.json +1325 -0
- package/db/d1/migrations/meta/0006_snapshot.json +1339 -0
- package/db/d1/migrations/meta/0007_snapshot.json +1347 -0
- package/db/d1/migrations/meta/0008_snapshot.json +1464 -0
- package/db/d1/migrations/meta/0009_snapshot.json +1648 -0
- package/db/d1/migrations/meta/_journal.json +76 -0
- package/db/d1/schema.ts +407 -0
- package/db/d1/sites.ts +374 -0
- package/db/d1/teamAiUsage.ts +101 -0
- package/db/d1/teams.ts +127 -0
- package/db/durable/drizzle.config.ts +8 -0
- package/db/durable/durableObjectClient.ts +480 -0
- package/db/durable/events.ts +100 -0
- package/db/durable/migrations/0000_fair_bucky.sql +38 -0
- package/db/durable/migrations/meta/0000_snapshot.json +278 -0
- package/db/durable/migrations/meta/_journal.json +13 -0
- package/db/durable/migrations/migrations.js +10 -0
- package/db/durable/schema.ts +5 -0
- package/db/durable/siteDurableObject.ts +1352 -0
- package/db/durable/types.ts +53 -0
- package/db/postgres/client.ts +13 -0
- package/db/postgres/drizzle.config.ts +12 -0
- package/db/postgres/migrations/0000_brainy_sprite.sql +116 -0
- package/db/postgres/migrations/meta/0000_snapshot.json +681 -0
- package/db/postgres/migrations/meta/_journal.json +13 -0
- package/db/postgres/schema.ts +145 -0
- package/db/postgres/sites.ts +118 -0
- package/db/tranformReports.ts +595 -0
- package/db/types.ts +55 -0
- package/endpoints/api_worker.tsx +1854 -0
- package/endpoints/site_do_worker.ts +11 -0
- package/index.d.ts +63 -0
- package/index.ts +83 -0
- package/lib/auth.ts +279 -0
- package/lib/geojson/world_countries.json +45307 -0
- package/lib/random_name.ts +41 -0
- package/lib/sendMail.ts +252 -0
- package/package.json +142 -0
- package/public/favicon.ico +0 -0
- package/public/images/android-chrome-192x192.png +0 -0
- package/public/images/android-chrome-512x512.png +0 -0
- package/public/images/apple-touch-icon.png +0 -0
- package/public/images/favicon-16x16.png +0 -0
- package/public/images/favicon-32x32.png +0 -0
- package/public/images/lytx_dark_dashboard.png +0 -0
- package/public/images/lytx_light_dashboard.png +0 -0
- package/public/images/safari-pinned-tab.svg +4 -0
- package/public/logo.png +0 -0
- package/public/site.webmanifest +26 -0
- package/public/sw.js +107 -0
- package/src/Document.tsx +86 -0
- package/src/api/ai_api.ts +1156 -0
- package/src/api/authMiddleware.ts +45 -0
- package/src/api/auth_api.ts +465 -0
- package/src/api/event_labels_api.ts +193 -0
- package/src/api/events_api.ts +210 -0
- package/src/api/queueWorker.ts +303 -0
- package/src/api/reports_api.ts +278 -0
- package/src/api/seed_api.ts +288 -0
- package/src/api/sites_api.ts +904 -0
- package/src/api/tag_api.ts +458 -0
- package/src/api/tag_api_v2.ts +289 -0
- package/src/api/team_api.ts +456 -0
- package/src/app/Dashboard.tsx +1339 -0
- package/src/app/Events.tsx +974 -0
- package/src/app/Explore.tsx +312 -0
- package/src/app/Layout.tsx +58 -0
- package/src/app/Settings.tsx +1302 -0
- package/src/app/components/DashboardCard.tsx +118 -0
- package/src/app/components/EditableCell.tsx +123 -0
- package/src/app/components/EventForm.tsx +93 -0
- package/src/app/components/MarketingFooter.tsx +49 -0
- package/src/app/components/MarketingNav.tsx +150 -0
- package/src/app/components/Nav.tsx +755 -0
- package/src/app/components/NewSiteSetup.tsx +298 -0
- package/src/app/components/SQLEditor.tsx +740 -0
- package/src/app/components/SiteSelector.tsx +126 -0
- package/src/app/components/SiteTag.tsx +42 -0
- package/src/app/components/SiteTagInstallCard.tsx +241 -0
- package/src/app/components/WorldMapCard.tsx +337 -0
- package/src/app/components/charts/ChartComponents.tsx +1481 -0
- package/src/app/components/charts/EventFunnel.tsx +45 -0
- package/src/app/components/charts/EventSummary.tsx +194 -0
- package/src/app/components/charts/SankeyFlows.tsx +72 -0
- package/src/app/components/marketing/CheckIcon.tsx +16 -0
- package/src/app/components/marketing/MarketingLayout.tsx +23 -0
- package/src/app/components/marketing/SectionHeading.tsx +35 -0
- package/src/app/components/reports/AskAiWorkspace.tsx +371 -0
- package/src/app/components/reports/CreateReportStarter.tsx +74 -0
- package/src/app/components/reports/DashboardRouteFiltersContext.tsx +14 -0
- package/src/app/components/reports/DashboardToolbar.tsx +154 -0
- package/src/app/components/reports/DashboardWorkspaceLayout.tsx +63 -0
- package/src/app/components/reports/DashboardWorkspaceShell.tsx +118 -0
- package/src/app/components/reports/ReportBuilderWorkspace.tsx +76 -0
- package/src/app/components/reports/custom/CustomReportBuilderPage.tsx +1667 -0
- package/src/app/components/reports/custom/ReportWidgetChart.tsx +297 -0
- package/src/app/components/reports/custom/buildWidgetSql.ts +151 -0
- package/src/app/components/reports/custom/chartPalettes.ts +18 -0
- package/src/app/components/reports/custom/types.ts +50 -0
- package/src/app/components/reports/reportBuilderMenuItems.ts +17 -0
- package/src/app/components/reports/useDashboardToolbarControls.tsx +235 -0
- package/src/app/components/ui/AlertBanner.tsx +101 -0
- package/src/app/components/ui/Button.tsx +55 -0
- package/src/app/components/ui/Card.tsx +80 -0
- package/src/app/components/ui/Input.tsx +72 -0
- package/src/app/components/ui/Link.tsx +23 -0
- package/src/app/components/ui/ReportBuilderMenu.tsx +246 -0
- package/src/app/components/ui/ThemeToggle.tsx +54 -0
- package/src/app/constants.ts +6 -0
- package/src/app/headers.ts +33 -0
- package/src/app/providers/AuthProvider.tsx +189 -0
- package/src/app/providers/ClientProviders.tsx +18 -0
- package/src/app/providers/QueryProvider.tsx +23 -0
- package/src/app/providers/ThemeProvider.tsx +88 -0
- package/src/app/utils/chartThemes.ts +146 -0
- package/src/app/utils/keybinds.ts +96 -0
- package/src/app/utils/media.tsx +24 -0
- package/src/client.tsx +114 -0
- package/src/config/createLytxAppConfig.ts +252 -0
- package/src/config/resourceNames.ts +88 -0
- package/src/db/index.ts +67 -0
- package/src/index.css +285 -0
- package/src/lib/featureFlags.ts +69 -0
- package/src/pages/GetStarted.tsx +290 -0
- package/src/pages/Home.tsx +268 -0
- package/src/pages/Login.tsx +283 -0
- package/src/pages/PrivacyPolicy.tsx +120 -0
- package/src/pages/Signup.tsx +267 -0
- package/src/pages/TermsOfService.tsx +126 -0
- package/src/pages/VerifyEmail.tsx +56 -0
- package/src/session/durableObject.ts +7 -0
- package/src/session/siteSchema.ts +86 -0
- package/src/session/types.ts +36 -0
- package/src/templates/README.md +80 -0
- package/src/templates/cleanFunctions.js +44 -0
- package/src/templates/embedFunctions.js +52 -0
- package/src/templates/lytx-shared.ts +662 -0
- package/src/templates/lytxpixel-core.ts +144 -0
- package/src/templates/lytxpixel.ts +267 -0
- package/src/templates/lytxpixelBrowser.js +634 -0
- package/src/templates/lytxpixelBrowser.mjs +634 -0
- package/src/templates/parseData.js +12 -0
- package/src/templates/script.ts +31 -0
- package/src/templates/template.tsx +50 -0
- package/src/templates/test.js +3 -0
- package/src/templates/trackWebEvents.ts +177 -0
- package/src/templates/vendors/clickcease.ts +8 -0
- package/src/templates/vendors/google.ts +174 -0
- package/src/templates/vendors/linkedin.ts +23 -0
- package/src/templates/vendors/meta.ts +56 -0
- package/src/templates/vendors/quantcast.ts +22 -0
- package/src/templates/vendors/simplfi.ts +7 -0
- package/src/types/app-context.ts +16 -0
- package/src/utilities/dashboardParams.ts +188 -0
- package/src/utilities/dashboardQueries.ts +537 -0
- package/src/utilities/dashboardTransforms.ts +167 -0
- package/src/utilities/dataValidation.ts +414 -0
- package/src/utilities/detector.ts +73 -0
- package/src/utilities/encrypt.ts +103 -0
- package/src/utilities/index.ts +13 -0
- package/src/utilities/parser.ts +117 -0
- package/src/utilities/performanceMonitoring.ts +570 -0
- package/src/utilities/route_interuptors.ts +24 -0
- package/src/worker.tsx +675 -0
- package/tsconfig.json +78 -0
- package/types/env.d.ts +16 -0
- package/types/rw.d.ts +7 -0
- package/types/shims.d.ts +53 -0
- package/types/vite.d.ts +19 -0
- package/vite/vite-plugin-pixel-bundle.ts +126 -0
- package/vite.config.ts +53 -0
- package/worker-configuration.d.ts +8401 -0
package/cli/init-db.ts
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { createId } from "@paralleldrive/cuid2";
|
|
3
|
+
// Import schemas for reference (not directly used but good for type checking)
|
|
4
|
+
// import { user, account, team, team_member } from "@db/d1/schema";
|
|
5
|
+
import { randomName } from "@lib/random_name";
|
|
6
|
+
import { execSync } from "child_process";
|
|
7
|
+
import { writeFileSync, unlinkSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import { scrypt, randomBytes } from "crypto";
|
|
10
|
+
|
|
11
|
+
// Hash password using scrypt with better-auth compatible parameters
|
|
12
|
+
async function hashPassword(password: string): Promise<string> {
|
|
13
|
+
const salt = randomBytes(16);
|
|
14
|
+
const saltHex = salt.toString("hex");
|
|
15
|
+
|
|
16
|
+
// Use better-auth compatible scrypt parameters
|
|
17
|
+
const config = {
|
|
18
|
+
N: 16384,
|
|
19
|
+
r: 16,
|
|
20
|
+
p: 1,
|
|
21
|
+
dkLen: 64,
|
|
22
|
+
maxmem: 128 * 16384 * 16 * 2, // 128 * N * r * 2
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
scrypt(
|
|
27
|
+
password.normalize("NFKC"),
|
|
28
|
+
saltHex,
|
|
29
|
+
config.dkLen,
|
|
30
|
+
{
|
|
31
|
+
N: config.N,
|
|
32
|
+
r: config.r,
|
|
33
|
+
p: config.p,
|
|
34
|
+
maxmem: config.maxmem,
|
|
35
|
+
},
|
|
36
|
+
(err, derivedKey) => {
|
|
37
|
+
if (err) reject(err);
|
|
38
|
+
else resolve(`${saltHex}:${derivedKey.toString("hex")}`);
|
|
39
|
+
},
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Parse CLI arguments
|
|
45
|
+
const args = process.argv.slice(2);
|
|
46
|
+
const getArg = (flag: string, defaultValue?: string): string => {
|
|
47
|
+
const index = args.indexOf(flag);
|
|
48
|
+
if (index === -1) {
|
|
49
|
+
if (defaultValue !== undefined) return defaultValue;
|
|
50
|
+
throw new Error(`Missing required argument: ${flag}`);
|
|
51
|
+
}
|
|
52
|
+
const value = args[index + 1];
|
|
53
|
+
if (!value || value.startsWith("-")) {
|
|
54
|
+
throw new Error(`Invalid value for ${flag}`);
|
|
55
|
+
}
|
|
56
|
+
return value;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const hasFlag = (flag: string): boolean => args.includes(flag);
|
|
60
|
+
|
|
61
|
+
// Check for help flag first
|
|
62
|
+
if (hasFlag("--help") || hasFlag("-h")) {
|
|
63
|
+
console.log(`
|
|
64
|
+
Usage: bun run db/init-db.ts [options]
|
|
65
|
+
|
|
66
|
+
Options:
|
|
67
|
+
-e, --email <email> User email (required)
|
|
68
|
+
-p, --password <password> User password (required)
|
|
69
|
+
-n, --name <name> User name (default: "Admin User")
|
|
70
|
+
-d, --database <name> Database name (default: "lytx_core_db")
|
|
71
|
+
--local Use local database (default: true)
|
|
72
|
+
--remote Use remote database (default: false)
|
|
73
|
+
-h, --help Show this help message
|
|
74
|
+
|
|
75
|
+
Example:
|
|
76
|
+
bun run db/init-db.ts --email admin@example.com --password mypassword --name "John Doe"
|
|
77
|
+
bun run db/init-db.ts --email admin@example.com --password mypassword --remote
|
|
78
|
+
`);
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// CLI argument parsing
|
|
83
|
+
const getEmailArg = () => {
|
|
84
|
+
try {
|
|
85
|
+
return getArg("--email");
|
|
86
|
+
} catch {
|
|
87
|
+
return getArg("-e");
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const getPasswordArg = () => {
|
|
92
|
+
try {
|
|
93
|
+
return getArg("--password");
|
|
94
|
+
} catch {
|
|
95
|
+
return getArg("-p");
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const getNameArg = () => {
|
|
100
|
+
try {
|
|
101
|
+
return getArg("--name");
|
|
102
|
+
} catch {
|
|
103
|
+
try {
|
|
104
|
+
return getArg("-n");
|
|
105
|
+
} catch {
|
|
106
|
+
return "Admin User";
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const getDatabaseArg = () => {
|
|
112
|
+
try {
|
|
113
|
+
return getArg("--database");
|
|
114
|
+
} catch {
|
|
115
|
+
try {
|
|
116
|
+
return getArg("-d");
|
|
117
|
+
} catch {
|
|
118
|
+
return "lytx_core_db";
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const email = getEmailArg();
|
|
124
|
+
const password = getPasswordArg();
|
|
125
|
+
const name = getNameArg();
|
|
126
|
+
const database = getDatabaseArg();
|
|
127
|
+
const isRemote = hasFlag("--remote");
|
|
128
|
+
const isLocal = hasFlag("--local") || !isRemote; // Default to local
|
|
129
|
+
|
|
130
|
+
// Helper function to execute SQL via wrangler
|
|
131
|
+
function executeSQL(sql: string, description: string) {
|
|
132
|
+
console.log(`📝 ${description}...`);
|
|
133
|
+
|
|
134
|
+
// Create temporary SQL file
|
|
135
|
+
const tempFile = join(process.cwd(), `temp_${Date.now()}.sql`);
|
|
136
|
+
writeFileSync(tempFile, sql);
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
const command = `bunx wrangler d1 execute ${database} --file ${tempFile} ${isLocal ? "--local" : "--remote"} --yes`;
|
|
140
|
+
const result = execSync(command, { encoding: "utf8", stdio: "pipe" });
|
|
141
|
+
console.log(`✅ ${description} completed`);
|
|
142
|
+
return result;
|
|
143
|
+
} catch (error: any) {
|
|
144
|
+
console.error(`❌ Error during ${description}:`, error.message);
|
|
145
|
+
throw error;
|
|
146
|
+
} finally {
|
|
147
|
+
// Clean up temp file
|
|
148
|
+
try {
|
|
149
|
+
unlinkSync(tempFile);
|
|
150
|
+
} catch (e) {
|
|
151
|
+
// Ignore cleanup errors
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async function initDatabase() {
|
|
157
|
+
try {
|
|
158
|
+
console.log("🚀 Initializing database with default user...");
|
|
159
|
+
console.log(`📊 Target: ${database} (${isLocal ? "local" : "remote"})`);
|
|
160
|
+
|
|
161
|
+
// Generate IDs and timestamp
|
|
162
|
+
const userId = createId();
|
|
163
|
+
const teamUuid = createId();
|
|
164
|
+
const accountId = createId();
|
|
165
|
+
const now = new Date();
|
|
166
|
+
const timestamp = Math.floor(now.getTime() / 1000); // Convert to Unix timestamp (seconds)
|
|
167
|
+
|
|
168
|
+
// Hash the password using scrypt (same as better-auth)
|
|
169
|
+
console.log("🔐 Hashing password...");
|
|
170
|
+
const hashedPassword = await hashPassword(password);
|
|
171
|
+
|
|
172
|
+
// 1. Create user
|
|
173
|
+
const userSQL = `
|
|
174
|
+
INSERT INTO user (id, name, email, email_verified, created_at, updated_at)
|
|
175
|
+
VALUES ('${userId}', '${name.replace(/'/g, "''")}', '${email}', 1, ${timestamp}, ${timestamp});
|
|
176
|
+
`;
|
|
177
|
+
executeSQL(userSQL, "Creating user");
|
|
178
|
+
|
|
179
|
+
// 2. Create account with hashed password (for better-auth email/password provider)
|
|
180
|
+
const accountSQL = `
|
|
181
|
+
INSERT INTO account (id, account_id, provider_id, user_id, password, created_at, updated_at)
|
|
182
|
+
VALUES ('${accountId}', '${userId}', 'credential', '${userId}', '${hashedPassword}', ${timestamp}, ${timestamp});
|
|
183
|
+
`;
|
|
184
|
+
executeSQL(accountSQL, "Creating account with hashed password");
|
|
185
|
+
|
|
186
|
+
// 3. Create team for the user
|
|
187
|
+
const teamName = randomName();
|
|
188
|
+
const teamSQL = `
|
|
189
|
+
INSERT INTO team (created_by, name, uuid, db_adapter, created_at, updated_at)
|
|
190
|
+
VALUES ('${userId}', '${teamName}', '${teamUuid}', 'sqlite', ${timestamp}, ${timestamp});
|
|
191
|
+
`;
|
|
192
|
+
executeSQL(teamSQL, "Creating default team");
|
|
193
|
+
|
|
194
|
+
// 4. Get the team ID (we need to query it since it's auto-increment)
|
|
195
|
+
const getTeamIdSQL = `SELECT id FROM team WHERE uuid = '${teamUuid}';`;
|
|
196
|
+
const tempFile = join(process.cwd(), `temp_query_${Date.now()}.sql`);
|
|
197
|
+
writeFileSync(tempFile, getTeamIdSQL);
|
|
198
|
+
|
|
199
|
+
let teamId: number;
|
|
200
|
+
try {
|
|
201
|
+
const command = `bunx wrangler d1 execute ${database} --file ${tempFile} ${isLocal ? "--local" : "--remote"} --json --yes`;
|
|
202
|
+
const result = execSync(command, { encoding: "utf8", stdio: "pipe" });
|
|
203
|
+
const jsonResult = JSON.parse(result);
|
|
204
|
+
teamId = jsonResult[0].results[0].id;
|
|
205
|
+
console.log(`🔍 Found team ID: ${teamId}`);
|
|
206
|
+
} catch (error: any) {
|
|
207
|
+
console.error("❌ Error getting team ID:", error.message);
|
|
208
|
+
throw error;
|
|
209
|
+
} finally {
|
|
210
|
+
try {
|
|
211
|
+
unlinkSync(tempFile);
|
|
212
|
+
} catch (e) {
|
|
213
|
+
// Ignore cleanup errors
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// 5. Add user to team
|
|
218
|
+
const teamMemberSQL = `
|
|
219
|
+
INSERT INTO team_member (team_id, user_id, created_at, updated_at)
|
|
220
|
+
VALUES (${teamId}, '${userId}', ${timestamp}, ${timestamp});
|
|
221
|
+
`;
|
|
222
|
+
executeSQL(teamMemberSQL, "Adding user to team");
|
|
223
|
+
|
|
224
|
+
console.log("✅ Database initialization complete!");
|
|
225
|
+
console.log(`
|
|
226
|
+
📊 Summary:
|
|
227
|
+
User ID: ${userId}
|
|
228
|
+
Email: ${email}
|
|
229
|
+
Name: ${name}
|
|
230
|
+
Team ID: ${teamId}
|
|
231
|
+
Team Name: ${teamName}
|
|
232
|
+
Team UUID: ${teamUuid}
|
|
233
|
+
Database: ${database} (${isLocal ? "local" : "remote"})
|
|
234
|
+
`);
|
|
235
|
+
|
|
236
|
+
console.log(`
|
|
237
|
+
🔑 Login credentials:
|
|
238
|
+
Email: ${email}
|
|
239
|
+
Password: ${password}
|
|
240
|
+
`);
|
|
241
|
+
|
|
242
|
+
console.log(`
|
|
243
|
+
🚀 Next steps:
|
|
244
|
+
1. Start the dev server: bun run dev
|
|
245
|
+
2. Visit the login page and use the credentials above
|
|
246
|
+
3. The user will automatically have a team and can create sites
|
|
247
|
+
`);
|
|
248
|
+
} catch (error) {
|
|
249
|
+
console.error("❌ Error initializing database:", error);
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Validate required arguments
|
|
255
|
+
if (!email || !password) {
|
|
256
|
+
console.error("❌ Error: --email and --password are required");
|
|
257
|
+
console.log("Use --help for usage information");
|
|
258
|
+
process.exit(1);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Validate email format
|
|
262
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
263
|
+
if (!emailRegex.test(email)) {
|
|
264
|
+
console.error("❌ Error: Invalid email format");
|
|
265
|
+
process.exit(1);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Run the initialization
|
|
269
|
+
initDatabase();
|