Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| reinforcedlearningwithaisupport:start [2025/03/07 02:56] – [Loading WASM from a Base64 encoded string] gedbadmin | reinforcedlearningwithaisupport:start [2025/03/08 17:14] (current) – gedbadmin | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Learning | + | ====== |
| + | |||
| + | ===== Learning Required | ||
| I love playing with [[https:// | I love playing with [[https:// | ||
| Line 11: | Line 13: | ||
| I've always put the task of because it would require me to create a long term plan for all the the requisite learning, and that is too much like my day job. In my free time I like to take a more exploratory roles. | I've always put the task of because it would require me to create a long term plan for all the the requisite learning, and that is too much like my day job. In my free time I like to take a more exploratory roles. | ||
| - | ====== Support Offered by AI | + | ===== Support Offered by AI ===== |
| I've tried working with AI as a co-pilot, and I don't like it much. I don't like adding code I don't understand. | I've tried working with AI as a co-pilot, and I don't like it much. I don't like adding code I don't understand. | ||
| Line 19: | Line 21: | ||
| So I've decided to jump in and explore, and keep a journal along the way. This is because I only a few hours here and there to do this, so I want to be able to read back on what I did last time before moving forward. | So I've decided to jump in and explore, and keep a journal along the way. This is because I only a few hours here and there to do this, so I want to be able to read back on what I did last time before moving forward. | ||
| - | ====== Proof of Concept: Can I run SQLite in the browser without a server? ====== | + | ===== A personal experiment |
| - | + | ||
| - | Last time I looked into this I tried taking the [[https:// | + | |
| - | + | ||
| - | If I'm to embed SQLite within TiddlyWiki I need to run it locally as a standalone, so I ask ChatGPT if it can be done: | + | |
| - | + | ||
| - | >Is it possible to run SqlIte in the browser from a file, without any web server? | + | |
| - | + | ||
| - | >> | + | |
| - | >> | + | |
| - | >> | + | |
| - | >>* **Download SQLite Wasm** | + | |
| - | >>* **Create an HTML file** | + | |
| - | <code html> | + | |
| - | < | + | |
| - | <html lang=" | + | |
| - | < | + | |
| - | <meta charset=" | + | |
| - | <meta name=" | + | |
| - | < | + | |
| - | </ | + | |
| - | < | + | |
| - | < | + | |
| - | <input type=" | + | |
| - | <pre id=" | + | |
| - | + | ||
| - | <script src=" | + | |
| - | < | + | |
| - | let db; | + | |
| - | + | ||
| - | document.getElementById(' | + | |
| - | const file = event.target.files[0]; | + | |
| - | if (file) { | + | |
| - | const buffer = await file.arrayBuffer(); | + | |
| - | const SQL = await initSqlJs({ locateFile: filename => `https:// | + | |
| - | db = new SQL.Database(new Uint8Array(buffer)); | + | |
| - | + | ||
| - | const result = db.exec(" | + | |
| - | document.getElementById(' | + | |
| - | } | + | |
| - | }); | + | |
| - | </ | + | |
| - | </ | + | |
| - | </ | + | |
| - | </ | + | |
| - | >>* **Open the file in a browser** | + | |
| - | >> | + | |
| - | >>// | + | |
| - | >>* The SQLite Wasm engine processes the .sqlite file. | + | |
| - | >>* Queries run directly in the browser. | + | |
| - | >>* The output shows available tables — you can expand this to support custom queries. | + | |
| - | + | ||
| - | I follow the instructions but I hit a problem. | + | |
| - | + | ||
| - | > Is a file necessary? | + | |
| - | >> Yes! You can create a purely in-memory SQLite database in the browser — no file needed. Here’s a simple example using sql.js: | + | |
| - | <code html> | + | |
| - | < | + | |
| - | <html lang=" | + | |
| - | < | + | |
| - | <meta charset=" | + | |
| - | <meta name=" | + | |
| - | < | + | |
| - | </ | + | |
| - | < | + | |
| - | < | + | |
| - | <button id=" | + | |
| - | <pre id=" | + | |
| - | + | ||
| - | <script src=" | + | |
| - | < | + | |
| - | (async () => { | + | |
| - | const SQL = await initSqlJs({ locateFile: file => `https:// | + | |
| - | const db = new SQL.Database(); | + | |
| - | + | ||
| - | document.getElementById(' | + | |
| - | db.run(" | + | |
| - | db.run(" | + | |
| - | + | ||
| - | const result = db.exec(" | + | |
| - | document.getElementById(' | + | |
| - | }); | + | |
| - | })(); | + | |
| - | </ | + | |
| - | </ | + | |
| - | </ | + | |
| - | </ | + | |
| - | + | ||
| - | I run this and it works, giving me the following result set in a JSON format: | + | |
| - | <code javascript> | + | |
| - | [ | + | |
| - | { | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | ], | + | |
| - | " | + | |
| - | [ | + | |
| - | 1, | + | |
| - | " | + | |
| - | ], | + | |
| - | [ | + | |
| - | 2, | + | |
| - | " | + | |
| - | ] | + | |
| - | ] | + | |
| - | } | + | |
| - | ] | + | |
| - | </ | + | |
| - | + | ||
| - | ===== Loading WASM from a Base64 encoded string ===== | + | |
| - | + | ||
| - | It's still loading code and WASM from a server. | + | |
| - | + | ||
| - | > I'd like to run this offline. | + | |
| - | >> Yes! You can absolutely run SQLite (with sql.js) offline by downloading the necessary files. Let’s set this up step by step. | + | |
| - | + | ||
| - | The instructions a straight forward. | + | |
| - | + | ||
| - | <code javascript> | + | |
| - | // Initialize sql.js with local wasm file | + | |
| - | initSqlJs({ | + | |
| - | locateFile: file => `lib/ | + | |
| - | }).then(SQL => { ... } | + | |
| - | </ | + | |
| - | + | ||
| - | This is when I run into the same CORS Policy problems that blocked me in the past: | + | |
| - | + | ||
| - | < | + | |
| - | Access to fetch at ' | + | |
| - | + | ||
| - | Failed to load resource: net:: | + | |
| - | + | ||
| - | Uncaught (in promise) TypeError: Failed to fetch (sql-wasm.js: | + | |
| - | at sql-wasm.js: | + | |
| - | at sql-wasm.js: | + | |
| - | at sql-wasm.js: | + | |
| - | at new Promise (< | + | |
| - | at initSqlJs (sql-wasm.js: | + | |
| - | at Test.html: | + | |
| - | at Test.html: | + | |
| - | </ | + | |
| - | + | ||
| - | I tell ChatGPT about the error, and it confidently provides me with a fix. | + | |
| - | + | ||
| - | >> Ah, yes — this happens because modern browsers block fetch requests for local files due to CORS restrictions. Even though you’re running things locally, loading '' | + | |
| - | >> Let’s fix it! 🚀 | + | |
| - | + | ||
| - | It then gives me three possible options: | + | |
| - | 1. Run a simple local server (Recommended) | + | |
| - | 1. Use a VS Code extension (even simpler) | + | |
| - | 1. Not recommended) Disable CORS checks temporarily | + | |
| - | + | ||
| - | None of these really work for me. For the WASM to work in TiddlyWiki | + | |
| - | + | ||
| - | I explain my problem to ChatGPT, and it confidently provides the answer: | + | |
| - | + | ||
| - | > I don't really like any of these options. | + | |
| - | > Is there anyway of loading WASM from data embedded in my HTML file, perhaps BASE64 encoded? | + | |
| - | >> Yes! You can absolutely embed the WebAssembly (WASM) directly into your TiddlyWiki without needing any external files or servers. Let’s tackle this step by step. 🚀 | + | |
| - | + | ||
| - | I am loving this AI's can do attitude, so I follow the steps provided. | + | |
| - | + | ||
| - | First of all I convert my WASM file to Base64. | + | |
| - | <code powershell> | + | |
| - | [convert]:: | + | |
| - | </ | + | |
| - | + | ||
| - | Then I copy the Base64 text into a string so that I can loading it into a binary array. | + | |
| - | + | ||
| - | One thing I like at this point is that ChatGPT doesn' | + | |
| - | + | ||
| - | <code javascript> | + | |
| - | < | + | |
| - | <html lang=" | + | |
| - | < | + | |
| - | <meta charset=" | + | |
| - | < | + | |
| - | </ | + | |
| - | < | + | |
| - | < | + | |
| - | <script src=" | + | |
| - | < | + | |
| - | // Paste the long Base64-encoded WASM here | + | |
| - | const wasmBase64 = " | + | |
| - | + | ||
| - | // Convert Base64 to binary | + | |
| - | const binaryString = atob(wasmBase64); | + | |
| - | const bytes = new Uint8Array(binaryString.length); | + | |
| - | for (let i = 0; i < binaryString.length; | + | |
| - | bytes[i] = binaryString.charCodeAt(i); | + | |
| - | } | + | |
| - | const wasmBinary = bytes.buffer; | + | |
| - | + | ||
| - | // Initialize sql.js using the in-memory WASM binary | + | |
| - | initSqlJs({ | + | |
| - | locateFile: () => URL.createObjectURL(new Blob([wasmBinary], | + | |
| - | }).then(SQL => { | + | |
| - | const db = new SQL.Database(); | + | |
| - | db.run(" | + | |
| - | db.run(" | + | |
| - | + | ||
| - | const res = db.exec(" | + | |
| - | console.log(" | + | |
| - | }).catch(err => { | + | |
| - | console.error(" | + | |
| - | }); | + | |
| - | </ | + | |
| - | </ | + | |
| - | </ | + | |
| - | </ | + | |
| - | + | ||
| - | There are two problems with this code. | + | |
| - | + | ||
| - | - ChatGPT has decided to drop functionality from the code we are writing. | + | |
| - | - It doesn' | + | |
| - | < | + | |
| - | I'm getting the error: wasm streaming compile failed: TypeError: Failed to execute ' | + | |
| - | </ | + | |
| - | + | ||
| - | And now we see how ChatGPT shines as a research assistant and guide, because it immediatly identified the problem and provides the fix: | + | |
| - | + | ||
| - | >>Ah, that's happening because the WebAssembly streaming compiler expects the MIME type to be application/ | + | |
| - | >> | + | |
| - | >> | + | |
| - | + | ||
| - | It then gives me a full page of code, but the only part that I'm interested in is this: | + | |
| - | < | + | |
| - | // Initialize sql.js using the in-memory WASM binary | + | |
| - | initSqlJs({ | + | |
| - | locateFile: () => { | + | |
| - | // Create a blob for the binary and generate a URL | + | |
| - | const blob = new Blob([bytes], | + | |
| - | return URL.createObjectURL(blob); | + | |
| - | } | + | |
| - | }).then(SQL => { ... }); | + | |
| - | </ | + | |
| - | + | ||
| - | This is then loaded into a string and converted into a binary blob so that it can be loaded without any reference to an external WASM resource. | + | |
| - | + | ||
| - | <code html> | + | |
| - | < | + | |
| - | <html lang=" | + | |
| - | < | + | |
| - | <meta charset=" | + | |
| - | <meta name=" | + | |
| - | < | + | |
| - | </ | + | |
| - | < | + | |
| - | < | + | |
| - | <button id=" | + | |
| - | <pre id=" | + | |
| - | + | ||
| - | <script src=" | + | |
| - | < | + | |
| - | const base64wasm = " | + | |
| - | const binaryString = atob(base64wasm); | + | |
| - | const bytes = new Uint8Array(binaryString.length); | + | |
| - | for (let i = 0; i < binaryString.length; | + | |
| - | bytes[i] = binaryString.charCodeAt(i); | + | |
| - | } | + | |
| - | + | ||
| - | (async () => { | + | |
| - | // Initialize sql.js using the in-memory WASM binary | + | |
| - | const sql = await initSqlJs({ | + | |
| - | locateFile: () => { | + | |
| - | // Create a blob for the binary and generate a URL | + | |
| - | const blob = new Blob([bytes], | + | |
| - | return URL.createObjectURL(blob); | + | |
| - | } | + | |
| - | }); | + | |
| - | + | ||
| - | const db = new sql.Database(); | + | |
| - | + | ||
| - | document.getElementById(' | + | |
| - | + | ||
| - | db.run(" | + | |
| - | db.run(" | + | |
| - | + | ||
| - | const result | + | |
| - | document.getElementById(' | + | |
| - | }); | + | |
| - | })(); | + | |
| - | </ | ||
| - | </ | ||
| - | </ | ||
| - | </ | ||
| - | Which completes my proof of concept. | + | - [[> |