├── Images
├── example1.png
├── example2.png
└── tauri-sveltekit-sqlite.png
├── README.md
├── src-tauri
├── Cargo.toml
├── build.rs
├── icons
│ ├── 128x128.png
│ ├── 128x128@2x.png
│ ├── 32x32.png
│ ├── Square107x107Logo.png
│ ├── Square142x142Logo.png
│ ├── Square150x150Logo.png
│ ├── Square284x284Logo.png
│ ├── Square30x30Logo.png
│ ├── Square310x310Logo.png
│ ├── Square44x44Logo.png
│ ├── Square71x71Logo.png
│ ├── Square89x89Logo.png
│ ├── StoreLogo.png
│ ├── icon.icns
│ ├── icon.ico
│ └── icon.png
├── sqlite.db
├── src
│ ├── commands.rs
│ ├── db.rs
│ └── main.rs
└── tauri.conf.json
├── src
├── app.d.ts
├── app.html
├── lib
│ ├── index.ts
│ └── table.svelte
└── routes
│ ├── +layout.ts
│ └── +page.svelte
├── static
└── favicon.png
├── svelte.config.js
├── tsconfig.json
└── vite.config.ts
/Images/example1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/Images/example1.png
--------------------------------------------------------------------------------
/Images/example2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/Images/example2.png
--------------------------------------------------------------------------------
/Images/tauri-sveltekit-sqlite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/Images/tauri-sveltekit-sqlite.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Overview
4 | This guide will walk you through the process of integrating the primary components of a modern full stack desktop application — Frontend, Backend, and Database. Tauri which is implemented in Rust will serve as our Backend, while SvelteKit will serve as our Frontend. The database we will use is SQLite and to do this we will be using SQLx; a Rust toolkit for communicating asynchronously with a number of different databases (MySQL, MSSQL, PostgreSQL, and SQLite). We will use Tauri’s built-in capabilities to then pass information back and forth between the front and backend. The purpose of this guide is simply to share what I have learned in my journey to create cross platform applications for a number of personal and professional projects. As I continue to grow my understanding and refine techniques to build applications on top of this core architecture, I will be sure to update the project’s GitHub repository along with this guide to reflect my methodology (See the ‘Additional Enhancements’ section). I will also include this [link to my Notion page for this project](https://leafdeveloper.notion.site/Tauri-SvelteKit-SQLite-e520a1051f5c47c29f919fbf6bc02015?pvs=4) which includes helpful links to articles, documentation, examples, and eventually links to my own applications once I have gotten them ready enough to be seen and taken seriously haha. With all that said, let’s get coding!!
5 |
6 | ---
7 |
8 |
9 |
10 |
11 | Step 1: Set up environment and Install prerequisites
12 |
13 |
14 |
15 |
Windows
16 |
17 | - [ ] Install **MS Visual Studio C++ build tools** and **Windows 10 SDK**
18 | - [ ] WebView2 (Most likely already installed as it is part of Win10 and Win11 by default)
19 | - [ ] Install Rust from the [website](https://www.rust-lang.org/tools/install) or by running the following command
20 | ```powershell
21 | winget install --id Rustlang.Rustup
22 | ```
23 |
24 |
macOS
25 |
26 | - [ ] Install CLang and macOS Dev Dependencies using the following command
27 | ```shell
28 | xcode-select --install
29 | ```
30 | - [ ] Install Rust with the following command then restart your Terminal for changes to take effect
31 | ```shell
32 | curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
33 | ```
34 |
35 |
Linux
36 |
37 | Use this link to [the official Tauri website](https://tauri.app/v1/guides/getting-started/prerequisites#installing) to find instructions on how to install system dependencies for your specific distro
38 |
39 |
40 |
41 | ---
42 |
43 |
44 |
45 |
46 | Step 2: Create the SvelteKit Frontend
47 |
48 |
49 |
50 | - [ ] Using the tool of your choice, run one of the following commands
51 | ```shell
52 | npm create svelte@latest
53 | ```
54 | ```shell
55 | pnpm create svelte
56 | ```
57 | - [ ] Select the following options:
58 | - Current directory
59 | - Yes (to Continue)
60 | - Skeleton project
61 | - TypeScript
62 | - Additions: ESLint, Prettier
63 | - [ ] Using the tool of your choice, run one of the following commands
64 | ```shell
65 | npm install
66 | ```
67 | ```shell
68 | pnpm install
69 | ```
70 | - [ ] Add static adapter for Static Site Generation
71 | ```shell
72 | npm install --save-dev @sveltejs/adapter-static
73 | ```
74 | ```shell
75 | pnpm add -D @sveltejs/adapter-static
76 | ```
77 | - [ ] Open the `svelte.config.js` file and edit the adapter import line:
78 | ```jsx
79 | import adapter from '@sveltejs/adapter-static'; // <-- This was changed from 'adapter-auto' to 'adapter-static'
80 | import { vitePreprocess } from '@sveltejs/kit/vite';
81 |
82 | /** @type {import('@sveltejs/kit').Config} */
83 | const config = {
84 | // Consult https://kit.svelte.dev/docs/integrations#preprocessors
85 | // for more information about preprocessors
86 | preprocess: vitePreprocess(),
87 |
88 | kit: {
89 | // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
90 | // If your environment is not supported or you settled on a specific environment, switch out the adapter.
91 | // See https://kit.svelte.dev/docs/adapters for more information about adapters.
92 | adapter: adapter()
93 | }
94 | };
95 |
96 | export default config;
97 | ```
98 | - [ ] Create a `+layout.ts` file inside the `/*app_name*/src/routes` directory. Insert the following 2 lines of code to disable Server Side Rendering (SSR):
99 | ```tsx
100 | export const prerender = true
101 | export const ssr = false
102 | ```
103 |
104 |
105 | ---
106 |
107 |
108 |
109 |
110 | Step 3: Add and Configure Tauri
111 |
112 |
113 |
114 | - [ ] Install the Tauri CLI with the following command:
115 | ```shell
116 | pnpm add -D @tauri-apps/cli
117 | ```
118 | ```shell
119 | npm install --save-dev @tauri-apps/cli
120 | ```
121 | > Note:
122 | > For **npm** to detect Tauri correctly you need to add it to the "scripts" section in your package.json file:
123 | > ```json
124 | > "scripts": {
125 | > "tauri": "tauri"
126 | > }
127 | > ```
128 | - [ ] Run the Tauri scaffolding utility and use the options below. Use the following command to run the utility:
129 | ```shell
130 | npm run tauri init
131 | ```
132 | - App Name: *Any*
133 | - Window Title: *Any*
134 | - Web Asset Path: `../build` (*located relative to the `/src-tauri/tauri.conf.json` file that will be created)*
135 | - Dev Server URL: `http://localhost:5173`
136 | - Frontend dev command: `npm run dev` or `pnpm run dev`
137 | - Frontend build command: `npm run build` or `pnpm run build`
138 |
139 | The result is a folder called `src-tauri` that should contain files such as `Cargo.toml`, `tauri.conf.json`, *icons* and `src/main.rs`. Each is used for tauri to work. To learn more about how to use these files visit the [tauri docs site](https://tauri.app/v1/guides/getting-started/setup/sveltekit).
140 |
141 | - [ ] Add the tauri-apps/api JavaScript library
142 | ```shell
143 | pnpm add @tauri-apps/api
144 | ```
145 | ```shell
146 | npm install @tauri-apps/api
147 | ```
148 |
149 |
150 |
151 | ---
152 |
153 |
154 |
155 |
156 | Step 4: SQLite and SQLx
157 |
158 |
159 |
160 | - [ ] Open `Cargo.toml` and add the following dependencies for **SQLx** and the **async-std** runtime
161 | ```toml
162 | [dependencies]
163 | serde_json = "1.0"
164 | serde = { version = "1.0", features = ["derive"] }
165 | tauri = { version = "1.4.0", features = [] }
166 | sqlx = { version = "0.7", features = [ "runtime-async-std", "tls-native-tls", "sqlite", "macros" ] }
167 | async-std = { version = "1.7.0", features = [ "attributes" ] }
168 | ```
169 | - [ ] Open `main.rs` and add **async_std** to `main()` function. Save changes
170 | ```rust
171 | // Prevents additional console window on Windows in release, DO NOT REMOVE!!
172 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
173 |
174 | #[async_std::main]
175 | async fn main() {
176 | tauri::Builder::default()
177 | .run(tauri::generate_context!())
178 | .expect("error while running tauri application");
179 | }
180 | ```
181 | - [ ] Create `db.rs` file in `src-tauri/src` directory and add the following
182 | ```rust
183 | use sqlx::{ migrate::MigrateDatabase, Sqlite, SqlitePool };
184 |
185 | const DB_URL: &str = "sqlite://sqlite.db";
186 |
187 | // Check for DB, create if non existent
188 | pub async fn init() {
189 | if !Sqlite::database_exists(DB_URL).await.unwrap_or(false) {
190 | match Sqlite::create_database(DB_URL).await {
191 | Ok(_) => println!("Create db success"),
192 | Err(error) => panic!("error: {}", error),
193 | }
194 | } else {
195 | println!("Database already exists");
196 | }
197 |
198 | create_schema().await;
199 | }
200 |
201 | // Create Schema
202 | async fn create_schema() {
203 | let pool = SqlitePool::connect(DB_URL).await.expect("unable to connect");
204 | let sql = "
205 | PRAGMA foreign_keys = ON ;
206 | CREATE TABLE IF NOT EXISTS projects
207 | (
208 | id INTEGER PRIMARY KEY NOT NULL,
209 | name TEXT NOT NULL
210 | );
211 |
212 | CREATE TABLE IF NOT EXISTS tasks
213 | (
214 | id INTEGER PRIMARY KEY NOT NULL,
215 | value TEXT NOT NULL,
216 | completed INTEGER NOT NULL,
217 | date_completed TEXT,
218 | project_id INTEGER NOT NULL,
219 | FOREIGN KEY (project_id) REFERENCES projects (id) ON UPDATE SET NULL ON DELETE SET NULL
220 | );
221 | ";
222 |
223 | let query = sqlx::query(&sql);
224 | let result = query.execute(&pool).await.unwrap();
225 | println!("Create Schema result: {:?}", result);
226 | pool.close().await;
227 | }
228 | ```
229 | - [ ] Add `db.rs` to `main.rs` as a module and call the `init()` function within the `main()`
230 | ```rust
231 | // Prevents additional console window on Windows in release, DO NOT REMOVE!!
232 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
233 |
234 | mod db;
235 |
236 | #[async_std::main]
237 | async fn main() {
238 | db::init().await;
239 |
240 | tauri::Builder::default()
241 | .run(tauri::generate_context!())
242 | .expect("error while running tauri application");
243 | }
244 | ```
245 | - [ ] Create `commands.rs` file in the `src-tauri/src` directory and add the following
246 | ```rust
247 | use sqlx::FromRow;
248 | use serde::{Deserialize, Serialize};
249 |
250 | #[derive(Debug,FromRow,Deserialize,Serialize)]
251 | pub struct Task {
252 | pub id: i64,
253 | pub value: String,
254 | pub completed: i8,
255 | pub date_completed: String,
256 | pub project_id: i64,
257 | }
258 |
259 | #[tauri::command(rename_all = "snake_case")]
260 | pub async fn get_tasks() -> Result, String>{
261 | let url = "sqlite://sqlite.db";
262 |
263 | let pool = sqlx::sqlite::SqlitePool::connect(url).await.expect("unable to connect");
264 |
265 | let sql = "SELECT * FROM tasks";
266 |
267 | let query = sqlx::query_as::<_, Task>(sql);
268 |
269 | let response = query.fetch_all(&pool).await.expect("unable to list tasks");
270 |
271 | pool.close().await;
272 |
273 | Ok(response)
274 | }
275 | ```
276 | - [ ] Add `commands.rs` to `main.rs` as a module and add the following to `tauri::Builder::default()`
277 | ```rust
278 | // Prevents additional console window on Windows in release, DO NOT REMOVE!!
279 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
280 |
281 | mod db;
282 | mod commands;
283 |
284 | #[async_std::main]
285 | async fn main() {
286 | db::init().await;
287 |
288 | tauri::Builder::default()
289 | .invoke_handler(tauri::generate_handler![
290 | commands::get_tasks,
291 | ])
292 | .run(tauri::generate_context!())
293 | .expect("error while running tauri application");
294 | }
295 | ```
296 | - [ ] Create a set of records in each table to test the functionality of the application. There are a number of different ways to achieve this, I chose to create a function that will perform this operation as part of the `db::init()` fn, and by commenting it out or uncommenting it when necessary *(This fn would need to be deleted before building and deploying)*
297 | ```rust
298 | // Check for DB, create if non existent
299 | pub async fn init() {
300 | if !Sqlite::database_exists(DB_URL).await.unwrap_or(false) {
301 | match Sqlite::create_database(DB_URL).await {
302 | Ok(_) => println!("Create db success"),
303 | Err(error) => panic!("error: {}", error),
304 | }
305 | } else {
306 | println!("Database already exists");
307 | }
308 |
309 | create_schema().await;
310 |
311 | // Uncomment the fn below and run to make some records for testing
312 | insert_dev_records().await;
313 | }
314 |
315 | // Create schema
316 | // ...
317 |
318 | // Create some test records in each table
319 | async fn insert_dev_records() {
320 | let pool = SqlitePool::connect(DB_URL).await.expect("unable to connect");
321 | let sql = "
322 | INSERT INTO projects (name)
323 | VALUES ('Awesome Current Product'), ('Top Secret Product'), ('Super Top Secret Product');
324 |
325 | INSERT INTO tasks (value, completed, date_completed, project_id)
326 | VALUES ('Design the UI', 0, NULL, 3),
327 | ('Design DB Schema', 0, NULL, 3),
328 | ('Build prototype app', 0, NULL, 3),
329 | ('Design a cool logo', 1, DATE('2023-04-22'), 3),
330 | ('Refactor component lib', 0, NULL, 2),
331 | ('Add input sanitization to ipc', 0, NULL, 2),
332 | ('Security audit testing for v1.5', 0, NULL, 1),
333 | ('Add Dark Mode', 1, DATE('2023-04-20'), 1),
334 | ('Fix UI glitch', 1, DATE('2023-04-20'), 1);
335 | ";
336 |
337 | let query = sqlx::query(&sql);
338 | let result = query.execute(&pool).await.unwrap();
339 | println!("Create Records result: {:?}", result);
340 | pool.close().await;
341 | }
342 | ```
343 |
344 |
345 | ---
346 |
347 |
348 |
Step 5: Build Frontend
349 |
350 | - [ ] Within `/src/lib` folder, create 2 new files called `table.svelte` and `index.ts` with the following contents
351 | ```tsx
352 |
377 |
378 |
379 |
Tasks
380 |
381 |
382 |
383 |
384 | {#each fields as field}
385 |
{field}
386 | {/each}
387 |
388 |
389 |
390 |
391 |
392 |
393 | {#each records as record}
394 |
395 |
396 | {#each Object.values(record) as value}
397 |
{value}
398 | {/each}
399 |
400 |
401 | {/each}
402 |
403 |
404 |
405 |
406 | ```
407 | ```tsx
408 | // place files you want to import through the `$lib` alias in this folder.
409 | export { default } from "./table.svelte";
410 | ```
411 |
476 |
477 |
478 | - [ ] Make sure everything is saved then run the following command in the terminal
479 | ```shell
480 | pnpm tauri dev
481 | ```
482 | 
483 |
484 | > **🎉 Congrats!**
485 | > You have built a very basic full-stack desktop app with an embedded database. There’s a lot of potential with how this template can be applied and there are plenty of concepts, best practices, and steps that you should be aware of that are not discussed/included in this basic example, so do your own research regarding the technologies used here, experiment with new things, and most importantly have fun — coding is cool😎
486 | > PS: If you like this or have suggestions let me know!! I’m still pretty new to Rust and backend web development, and I’m always looking for ways to improve my skills as a developer (Rust, Svelte, SQLite/DBs, etc.). Furthermore, I like knowing when I do a good job so that I can flex or if my code is trash so I can fix it and then flex (Just kidding, maybe).
487 |
488 |
489 |
--------------------------------------------------------------------------------
/src-tauri/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "app"
3 | version = "0.1.0"
4 | description = "A Tauri App"
5 | authors = ["you"]
6 | license = ""
7 | repository = ""
8 | default-run = "app"
9 | edition = "2021"
10 | rust-version = "1.60"
11 |
12 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
13 |
14 | [build-dependencies]
15 | tauri-build = { version = "1.4.0", features = [] }
16 |
17 | [dependencies]
18 | serde_json = "1.0"
19 | serde = { version = "1.0", features = ["derive"] }
20 | tauri = { version = "1.4.0", features = [] }
21 | sqlx = { version = "0.7", features = [ "runtime-async-std", "tls-native-tls", "sqlite", "macros" ] }
22 | async-std = { version = "1.7.0", features = [ "attributes" ] }
23 |
24 | [features]
25 | # this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
26 | # If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
27 | # DO NOT REMOVE!!
28 | custom-protocol = [ "tauri/custom-protocol" ]
29 |
--------------------------------------------------------------------------------
/src-tauri/build.rs:
--------------------------------------------------------------------------------
1 | fn main() {
2 | tauri_build::build()
3 | }
4 |
--------------------------------------------------------------------------------
/src-tauri/icons/128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/128x128.png
--------------------------------------------------------------------------------
/src-tauri/icons/128x128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/128x128@2x.png
--------------------------------------------------------------------------------
/src-tauri/icons/32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/32x32.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square107x107Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/Square107x107Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square142x142Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/Square142x142Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square150x150Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/Square150x150Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square284x284Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/Square284x284Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square30x30Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/Square30x30Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square310x310Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/Square310x310Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square44x44Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/Square44x44Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square71x71Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/Square71x71Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square89x89Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/Square89x89Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/StoreLogo.png
--------------------------------------------------------------------------------
/src-tauri/icons/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/icon.icns
--------------------------------------------------------------------------------
/src-tauri/icons/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/icon.ico
--------------------------------------------------------------------------------
/src-tauri/icons/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/icons/icon.png
--------------------------------------------------------------------------------
/src-tauri/sqlite.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lmedmo/Tauri-SvelteKit-SQLite/6607eb7132879afcc6038f35717374a542cbb8d9/src-tauri/sqlite.db
--------------------------------------------------------------------------------
/src-tauri/src/commands.rs:
--------------------------------------------------------------------------------
1 | use sqlx::FromRow;
2 | use serde::{Deserialize, Serialize};
3 |
4 | #[derive(Debug,FromRow,Deserialize,Serialize)]
5 | pub struct Task {
6 | pub id: i64,
7 | pub value: String,
8 | pub completed: i8,
9 | pub date_completed: String,
10 | pub project_id: i64,
11 | }
12 |
13 | #[tauri::command(rename_all = "snake_case")]
14 | pub async fn get_tasks() -> Result, String>{
15 | let url = "sqlite://sqlite.db";
16 |
17 | let pool = sqlx::sqlite::SqlitePool::connect(url).await.expect("unable to connect");
18 |
19 | let sql = "SELECT * FROM tasks";
20 |
21 | let query = sqlx::query_as::<_, Task>(sql);
22 |
23 | let response = query.fetch_all(&pool).await.expect("unable to list tasks");
24 |
25 | pool.close().await;
26 |
27 | Ok(response)
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/src-tauri/src/db.rs:
--------------------------------------------------------------------------------
1 | use sqlx::{ migrate::MigrateDatabase, Sqlite, SqlitePool };
2 |
3 | const DB_URL: &str = "sqlite://sqlite.db";
4 |
5 | // Check for DB, create if non existent
6 | pub async fn init() {
7 | if !Sqlite::database_exists(DB_URL).await.unwrap_or(false) {
8 | match Sqlite::create_database(DB_URL).await {
9 | Ok(_) => println!("Create db success"),
10 | Err(error) => panic!("error: {}", error),
11 | }
12 | } else {
13 | println!("Database already exists");
14 | }
15 |
16 | create_schema().await;
17 |
18 | // Uncomment the fn below and run to make some records for testing
19 | // insert_dev_records().await;
20 | }
21 |
22 | // Create Schema
23 | async fn create_schema() {
24 | let pool = SqlitePool::connect(DB_URL).await.expect("unable to connect");
25 | let sql = "
26 | PRAGMA foreign_keys = ON ;
27 | CREATE TABLE IF NOT EXISTS projects
28 | (
29 | id INTEGER PRIMARY KEY NOT NULL,
30 | name TEXT NOT NULL
31 | );
32 |
33 | CREATE TABLE IF NOT EXISTS tasks
34 | (
35 | id INTEGER PRIMARY KEY NOT NULL,
36 | value TEXT NOT NULL,
37 | completed INTEGER NOT NULL,
38 | date_completed TEXT,
39 | project_id INTEGER NOT NULL,
40 | FOREIGN KEY (project_id) REFERENCES projects (id) ON UPDATE SET NULL ON DELETE SET NULL
41 | );
42 | ";
43 |
44 | let query = sqlx::query(&sql);
45 | let result = query.execute(&pool).await.unwrap();
46 | println!("Create Schema result: {:?}", result);
47 | pool.close().await;
48 | }
49 |
50 | // Create some test records in each table
51 | #[allow(dead_code)]
52 | async fn insert_dev_records() {
53 | let pool = SqlitePool::connect(DB_URL).await.expect("unable to connect");
54 | let sql = "
55 | INSERT INTO projects (name)
56 | VALUES ('Awesome Current Product'), ('Top Secret Product'), ('Super Top Secret Product');
57 |
58 | INSERT INTO tasks (value, completed, date_completed, project_id)
59 | VALUES ('Design the UI', 0, NULL, 3),
60 | ('Design DB Schema', 0, NULL, 3),
61 | ('Build prototype app', 0, NULL, 3),
62 | ('Design a cool logo', 1, DATE('2023-04-22'), 3),
63 | ('Refactor component lib', 0, NULL, 2),
64 | ('Add input sanitization to ipc', 0, NULL, 2),
65 | ('Security audit testing for v1.5', 0, NULL, 1),
66 | ('Add Dark Mode', 1, DATE('2023-04-20'), 1),
67 | ('Fix UI glitch', 1, DATE('2023-04-20'), 1);
68 | ";
69 |
70 | let query = sqlx::query(&sql);
71 | let result = query.execute(&pool).await.unwrap();
72 | println!("Create Records result: {:?}", result);
73 | pool.close().await;
74 | }
--------------------------------------------------------------------------------
/src-tauri/src/main.rs:
--------------------------------------------------------------------------------
1 | // Prevents additional console window on Windows in release, DO NOT REMOVE!!
2 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
3 |
4 | mod db;
5 | mod commands;
6 |
7 | #[async_std::main]
8 | async fn main() {
9 | db::init().await;
10 |
11 | tauri::Builder::default()
12 | .invoke_handler(tauri::generate_handler![
13 | commands::get_tasks
14 | ])
15 | .run(tauri::generate_context!())
16 | .expect("error while running tauri application");
17 | }
18 |
--------------------------------------------------------------------------------
/src-tauri/tauri.conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../node_modules/@tauri-apps/cli/schema.json",
3 | "build": {
4 | "beforeBuildCommand": "pnpm run build",
5 | "beforeDevCommand": "pnpm run dev",
6 | "devPath": "http://localhost:5173",
7 | "distDir": "../build"
8 | },
9 | "package": {
10 | "productName": "tauri-sveltekit-sqlite",
11 | "version": "0.1.0"
12 | },
13 | "tauri": {
14 | "allowlist": {
15 | "all": false
16 | },
17 | "bundle": {
18 | "active": true,
19 | "category": "DeveloperTool",
20 | "copyright": "",
21 | "deb": {
22 | "depends": []
23 | },
24 | "externalBin": [],
25 | "icon": [
26 | "icons/32x32.png",
27 | "icons/128x128.png",
28 | "icons/128x128@2x.png",
29 | "icons/icon.icns",
30 | "icons/icon.ico"
31 | ],
32 | "identifier": "com.tauri.dev",
33 | "longDescription": "",
34 | "macOS": {
35 | "entitlements": null,
36 | "exceptionDomain": "",
37 | "frameworks": [],
38 | "providerShortName": null,
39 | "signingIdentity": null
40 | },
41 | "resources": [],
42 | "shortDescription": "",
43 | "targets": "all",
44 | "windows": {
45 | "certificateThumbprint": null,
46 | "digestAlgorithm": "sha256",
47 | "timestampUrl": ""
48 | }
49 | },
50 | "security": {
51 | "csp": null
52 | },
53 | "updater": {
54 | "active": false
55 | },
56 | "windows": [
57 | {
58 | "fullscreen": false,
59 | "height": 600,
60 | "resizable": true,
61 | "title": "Tauri-Notes",
62 | "width": 800
63 | }
64 | ]
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/app.d.ts:
--------------------------------------------------------------------------------
1 | // See https://kit.svelte.dev/docs/types#app
2 | // for information about these interfaces
3 | declare global {
4 | namespace App {
5 | // interface Error {}
6 | // interface Locals {}
7 | // interface PageData {}
8 | // interface Platform {}
9 | }
10 | }
11 |
12 | export {};
13 |
14 |
--------------------------------------------------------------------------------
/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | %sveltekit.head%
8 |
9 |
10 |
%sveltekit.body%
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | // place files you want to import through the `$lib` alias in this folder.
2 | export { default } from "./table.svelte";
--------------------------------------------------------------------------------
/src/lib/table.svelte:
--------------------------------------------------------------------------------
1 |
26 |
27 |
28 |
Tasks
29 |
30 |
31 |
32 |
33 | {#each fields as field}
34 |
{field}
35 | {/each}
36 |
37 |
38 |
39 |
40 |
41 |
42 | {#each records as record}
43 |
44 |
45 | {#each Object.values(record) as value}
46 |