Skip to content

Commit 2f7c4b0

Browse files
committed
i... broke a lot
1 parent 9291b84 commit 2f7c4b0

File tree

6 files changed

+112
-116
lines changed

6 files changed

+112
-116
lines changed

.gitattributes

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
* text=auto eol=lf
2-
*.lockb binary diff=lockb
2+
*.wasm binary diff=wasm

.prettierrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"tabWidth": 4
3+
}

next.config.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ const nextConfig: NextConfig = {
66
/* config options here */
77
reactStrictMode: true,
88
webpack: (config) => {
9-
config.externals.push("bun:sqlite");
9+
config.resolve.fallback = {
10+
fs: false,
11+
};
1012

1113
return config;
1214
},

pages/convert.tsx

Lines changed: 49 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
// yes i know the page is the exact same as index.tsx, it's just temporary lol
2+
13
"use client";
24

35
import React, { useState, useEffect } from "react";
46
import { FaCloudUploadAlt, FaDatabase } from "react-icons/fa";
5-
import initSqlJs, { Database } from "sql.js";
7+
import initSqlJs from "sql.js";
68

79
import Navbar from "@/components/Navbar";
810

@@ -30,30 +32,13 @@ const Tabs = React.memo(({ tabs, activeTab, onTabChange }: TabsProps) => (
3032
</div>
3133
));
3234

33-
// Everything will die if i remove this
3435
Tabs.displayName = "Tabs";
3536

3637
export default function Home() {
3738
const [file, setFile] = useState<File | null>(null);
38-
const [db, setDb] = useState<Database | null>(null);
39-
const [queryResult, setQueryResult] = useState<any>(null);
4039
const [data, setData] = useState<{ [key: string]: any[] } | null>(null);
4140
const [activeTab, setActiveTab] = useState<string>("");
4241
const [isDarkMode, setIsDarkMode] = useState<boolean>(false);
43-
const [isLoading, setIsLoading] = useState<boolean>(false);
44-
45-
useEffect(() => {
46-
const loadDb = async () => {
47-
const SQL = await initSqlJs({
48-
locateFile: () => "/sql-wasm.wasm", // Ensure the correct path
49-
});
50-
const database = new SQL.Database();
51-
52-
setDb(database);
53-
};
54-
55-
loadDb();
56-
}, []);
5742

5843
useEffect(() => {
5944
const systemPrefersDark = window.matchMedia(
@@ -73,50 +58,63 @@ export default function Home() {
7358
}
7459
};
7560

76-
const handleUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
77-
const file = event.target.files?.[0];
61+
const handleUpload = async () => {
62+
if (!file) return alert("Please select a file first.");
63+
64+
if (file.size > 50 * 1024 * 1024) {
65+
return alert(
66+
"File size exceeds the 50MB limit. That's a good thing though because unless you're NASA, your pc would probably explode.",
67+
);
68+
}
69+
7870
if (!file) return;
79-
71+
8072
const reader = new FileReader();
73+
8174
reader.onload = async (e) => {
8275
const arrayBuffer = e.target?.result as ArrayBuffer;
76+
8377
if (!arrayBuffer) return;
84-
78+
8579
const SQL = await initSqlJs();
8680
const database = new SQL.Database(new Uint8Array(arrayBuffer));
87-
setDb(database);
88-
81+
8982
// Get all table names
9083
const tablesResult = database.exec(
91-
"SELECT name FROM sqlite_master WHERE type='table'"
84+
"SELECT name FROM sqlite_master WHERE type='table'",
9285
);
93-
86+
9487
if (tablesResult.length === 0) return;
95-
88+
9689
const tableNames = tablesResult[0].values.flat() as string[];
90+
9791
setActiveTab(tableNames[0]); // Set the first table as active
98-
92+
9993
// Fetch data for each table
10094
const dbData: { [key: string]: any[] } = {};
95+
10196
for (const table of tableNames) {
10297
const result = database.exec(`SELECT * FROM ${table}`);
98+
10399
if (result.length > 0) {
104100
const columns = result[0].columns;
105101
const rows = result[0].values.map((row) =>
106-
Object.fromEntries(columns.map((col, i) => [col, row[i]]))
102+
Object.fromEntries(
103+
columns.map((col, i) => [col, row[i]]),
104+
),
107105
);
106+
108107
dbData[table] = rows;
109108
} else {
110109
dbData[table] = [];
111110
}
112111
}
113-
112+
114113
setData(dbData);
115114
};
116-
115+
117116
reader.readAsArrayBuffer(file);
118117
};
119-
120118

121119
const renderTable = (tableData: any[]) => {
122120
if (!tableData || tableData.length === 0)
@@ -128,6 +126,9 @@ export default function Home() {
128126
<table className="w-full text-left border-collapse border border-gray-200 dark:border-gray-700">
129127
<thead>
130128
<tr className="bg-gray-200 dark:bg-gray-800">
129+
<th className="p-3 border border-gray-300 font-medium text-gray-700 dark:text-gray-300">
130+
#
131+
</th>
131132
{columns.map((col, index) => (
132133
<th
133134
key={index}
@@ -148,6 +149,9 @@ export default function Home() {
148149
: "bg-gray-50 dark:bg-gray-800"
149150
} hover:bg-gray-100 dark:hover:bg-gray-700`}
150151
>
152+
<td className="p-3 border border-gray-300 dark:border-gray-700">
153+
{rowIndex + 1}
154+
</td>
151155
{columns.map((col, colIndex) => (
152156
<td
153157
key={colIndex}
@@ -163,22 +167,14 @@ export default function Home() {
163167
);
164168
};
165169

166-
const Spinner = () => (
167-
<div className="flex justify-center items-center mb-4">
168-
<div className="animate-spin rounded-full h-8 w-8 border-t-2 border-blue-500" />
169-
</div>
170-
);
171-
172170
return (
173171
<div style={{ color: "var(--text-color)" }}>
174172
<Navbar />
175173

176174
<div className="flex justify-center mb-12">
177175
<div
178176
className="w-full max-w-3xl p-6 shadow rounded-lg"
179-
style={{
180-
backgroundColor: "var(--upload-box-bg)",
181-
}}
177+
style={{ backgroundColor: "var(--upload-box-bg)" }}
182178
>
183179
<h2 className="text-lg text-center font-semibold mb-4">
184180
Upload SQLite File
@@ -191,7 +187,6 @@ export default function Home() {
191187
type="file"
192188
onChange={handleFileChange}
193189
/>
194-
195190
<label
196191
className="px-6 py-2 rounded hover:bg-blue-600 transition inline-flex items-center gap-2"
197192
htmlFor="file-upload"
@@ -224,15 +219,14 @@ export default function Home() {
224219
</button>
225220
</div>
226221

227-
<h2 className="text-lg font-semibold mb-4 text-center">
228-
btw, there&apos;s a maximum upload limit of 50MB
229-
</h2>
222+
<p className="text-lg font-semibold mb-4 text-center bg-gradient-to-r from-purple-400 via-pink-500 to-red-500 bg-clip-text text-transparent">
223+
Update: There is no upload limit anymore, it&apos;s all
224+
done in your browser! Better for security and privacy.
225+
</p>
230226
</div>
231227
</div>
232228

233-
{isLoading ? (
234-
<Spinner />
235-
) : data ? (
229+
{data ? (
236230
<div className="mb-8">
237231
<Tabs
238232
activeTab={activeTab}
@@ -260,23 +254,20 @@ export default function Home() {
260254
How does it work?
261255
</h2>
262256
<p className="mb-4">
263-
Whenever you upload a SQLite file, it gets sent to the
264-
server where the entire contents gets read and returned
265-
in a massive JSON object, which is parsed into multiple
266-
tables.
257+
When you upload your SQLite file, it gets processed
258+
locally on your device and is stored in RAM. It then
259+
reads the data of the database and visualizes it in the
260+
browser.
267261
</p>
268262

269263
<h2 className="text-lg font-semibold mb-4">
270264
Do my files get saved?
271265
</h2>
272-
<p className="mb-4">
273-
Only when it&apos;s being processed. Once it&apos;s
274-
done, the file is immediately deleted, so no worries
275-
about your data being stored.
276-
</p>
266+
<p className="mb-4">Nope, it&apos;s all locally done!</p>
277267
<p className="mb-4">
278268
A reminder that the site is open source, so you can view
279-
the code! Check the first link at the top of the page.
269+
the code! Click the &quot;View on GitHub&quot; button to
270+
see more.
280271
</p>
281272

282273
<h2 className="text-lg font-semibold mb-4">

0 commit comments

Comments
 (0)