From b8b05db590a2b7073c2e884d392b48099091105f Mon Sep 17 00:00:00 2001 From: Atiqa Naseer Date: Wed, 1 Apr 2026 23:45:30 +0200 Subject: [PATCH 1/2] task1 --- task-1/queries.sql | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/task-1/queries.sql b/task-1/queries.sql index fecf7ad..4d8bf98 100644 --- a/task-1/queries.sql +++ b/task-1/queries.sql @@ -1,21 +1,40 @@ ---- Queries -- **Question 1** — List the title and published year of every book in the `'Science Fiction'` genre, ordered by published year (oldest first). +SELECT title, published_year FROM books +WHERE genre='Science Fiction' +ORDER BY published_year ASC; -- **Question 2** — Show every book published before 1950. Display the title and year only. - +SELECT title, published_year FROM books +WHERE published_year < 50; -- **Question 3** — Show every book in the database along with its author's full name. Combine `first_name` and `last_name` into a single column called `author`. _(Hint: you will need a JOIN.)_ - +SELECT b.title, a.first_name || ' ' || a.last_name AS author +FROM books b +JOIN authors a ON a.id = b.author_id; -- **Question 4** — List all books written by Stephen King. Show the title and published year, ordered by year. _(Hint: JOIN the two tables and filter on the author's name.)_ +SELECT b.title, b.published_year +FROM books b +JOIN authors a ON a.id = b.author_id +WHERE a.first_name || ' ' || a.last_name = 'Stephen King' +ORDER BY b.published_year ASC; -- **Question 5** — Add yourself as a new author. Use your real name, or make one up. Pick any nationality and birth year. - +INSERT INTO authors (first_name, last_name, nationality, birth_year) +VALUES ('Atiqa', 'Naseer', 'Pakistani', 1999); -- **Question 6** — Add one book for the author you just inserted. It can be a real book or a made-up one. - +INSERT INTO books (title, published_year, genre, author_id) +VALUES ('Sunset Rose', '2026', 'Romance', 25); -- **Question 7** — The genre for "The Dark Tower: The Gunslinger" was entered incorrectly as `'Fantasy'`. It should be `'Horror'`. Write an UPDATE to fix it, then verify the change with a SELECT. +UPDATE books +SET genre = 'Horror' +WHERE title = 'The Dark Tower: The Gunslinger'; +SELECT title, genre FROM books +WHERE title = 'The Dark Tower: The Gunslinger'; -- **Question 8** — Delete the book you added in Question 6. Make sure your query targets only that specific row. - +DELETE FROM books +WHERE id = 101; --- -- ### Bonus questions _(optional)_ From 4fd0af5ffcf483050ecfd8b807a8702b9f813e21 Mon Sep 17 00:00:00 2001 From: Atiqa Naseer Date: Thu, 2 Apr 2026 01:09:50 +0200 Subject: [PATCH 2/2] task2 --- task-2/data/flashcards.db | Bin 0 -> 16384 bytes task-2/data/setup.sql | 16 ++ task-2/migrate.js | 50 ++++ task-2/package-lock.json | 467 ++++++++++++++++++++++++++++++++++++++ task-2/src/database.js | 65 ++++-- 5 files changed, 578 insertions(+), 20 deletions(-) create mode 100644 task-2/data/flashcards.db create mode 100644 task-2/data/setup.sql create mode 100644 task-2/migrate.js create mode 100644 task-2/package-lock.json diff --git a/task-2/data/flashcards.db b/task-2/data/flashcards.db new file mode 100644 index 0000000000000000000000000000000000000000..72e1366521b426bc6a61363d5a514d12172ed159 GIT binary patch literal 16384 zcmeI3&2Jk;6u{RXapK^3k$TAW6^Rh54sF!~s=zglv(5*O)7lOp;*gAYC-x}oS!ZVL zU~vkFLl68F{0H2S_zSpk;1B4PI}#EX-i+hKt*RJva!o z5v(o(9wLD4M%&x;n((x_y<2G>!WZ5lRQB6@+YRis>owX%+wyG4bu1zYZSSi#H1_b^ zuh%DaOzLy4URM)xrX;^sGVKQ&UahiUZ^MI$gn;{}M>EDu+f8a~drfb9vtdnJy=+>5 zrdRWtUZd)@z?A7#5fl~+Pm`JDd-oED7J)tsam{?BIa)7${>p3WB`mL0u1ePDMeJF) zNGB}Ti>{Svb=gburT(_)KVvmoUI#AV+E-$5MSQVf*5>p17moY8`;&X&9=Z?RZ2m?5 zm$z~%l2Jr}2oM1xKm>>Y5g-CYfCvx)BJlqsu#!zXA3oj`F{}Vyw}zcBxzgrWf*;9P zMIm&U7QSAYzhS$~4cpD#uwD9Q?I4wQ?mpaV@78f3)mCeLD8fLzHi3^e zvmk5M|GC_A$NkkExKHwb=YP)k^04&V(ho~_bARNX=SuJRu*rNPKm>>Y5g-CYfCvx) zB0vOghro`TaqgcjBo2DGcUWj(7<=vaMO?0cmTaJVQ4G-ujH96fzsDp7GeNTvW^Tt3 z#61p*4kzzgo9JEqwT&_s4Zbq9zq3u^- zyXu`}#`(1Sl3s+Q<74P^Cd(V#51F#w9x)}%hKq^Ed?wK^&@tZ((^_G Y9j1K{sM!J#%uEx5Q{$I*#bsj8zvAytZ~y=R literal 0 HcmV?d00001 diff --git a/task-2/data/setup.sql b/task-2/data/setup.sql new file mode 100644 index 0000000..50050ea --- /dev/null +++ b/task-2/data/setup.sql @@ -0,0 +1,16 @@ +-- CREATE NEW TABLES + +CREATE TABLE decks ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + description TEXT +); + +CREATE TABLE cards ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + question TEXT NOT NULL, + answer TEXT NOT NULL, + learned INTEGER NOT NULL DEFAULT 0, + deck_id INTEGER NOT NULL, + FOREIGN KEY (deck_id) REFERENCES decks(id) +); \ No newline at end of file diff --git a/task-2/migrate.js b/task-2/migrate.js new file mode 100644 index 0000000..091d4ab --- /dev/null +++ b/task-2/migrate.js @@ -0,0 +1,50 @@ +import { readFileSync } from 'fs'; +import Database from 'better-sqlite3'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const DATA_FILE = join(__dirname, 'data/data.json'); +const DB_FILE = join(__dirname, 'data/flashcards.db'); + +const raw = readFileSync(DATA_FILE, 'utf-8'); +const data = JSON.parse(raw); + +const db = new Database(DB_FILE); +db.pragma('foreign_keys = ON'); + +const insertDeck = db.prepare( + 'INSERT INTO decks (id, name, description) VALUES (?, ?, ?)' +); + +const insertCard = db.prepare( + 'INSERT INTO cards (id, question, answer, learned, deck_id) VALUES (?, ?, ?, ?, ?)' +); + +const migrate = db.transaction(() => { + // Clear existing rows so the migration can be re-run safely. + db.prepare('DELETE FROM cards').run(); + db.prepare('DELETE FROM decks').run(); + + for (const deck of data.decks) { + insertDeck.run(deck.id, deck.name, deck.description); + } + + for (const card of data.cards) { + insertCard.run( + card.id, + card.question, + card.answer, + card.learned ? 1 : 0, + card.deckId + ); + } +}); + +migrate(); + +console.log( + `Migration complete: inserted ${data.decks.length} decks and ${data.cards.length} cards.` +); + +db.close(); diff --git a/task-2/package-lock.json b/task-2/package-lock.json new file mode 100644 index 0000000..72fc35b --- /dev/null +++ b/task-2/package-lock.json @@ -0,0 +1,467 @@ +{ + "name": "flashcard-app", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "flashcard-app", + "version": "1.0.0", + "dependencies": { + "better-sqlite3": "^12.8.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/better-sqlite3": { + "version": "12.8.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.8.0.tgz", + "integrity": "sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + }, + "engines": { + "node": "20.x || 22.x || 23.x || 24.x || 25.x" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "3.89.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.89.0.tgz", + "integrity": "sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + } + } +} diff --git a/task-2/src/database.js b/task-2/src/database.js index a737fcb..550cbae 100644 --- a/task-2/src/database.js +++ b/task-2/src/database.js @@ -12,7 +12,6 @@ import { dirname, join } from 'path'; const __dirname = dirname(fileURLToPath(import.meta.url)); const DB_FILE = join(__dirname, '../data/flashcards.db'); - const db = new Database(DB_FILE); // ---------------------------------------------------------------- @@ -20,24 +19,28 @@ const db = new Database(DB_FILE); // ---------------------------------------------------------------- export function getAllDecks() { - // TODO: return all rows from the decks table - throw new Error('Not implemented'); + return db.prepare('SELECT * FROM decks').all(); } export function getDeckById(id) { - // TODO: return the deck row with the given id, or null if not found - throw new Error('Not implemented'); + return db.prepare('SELECT * FROM decks WHERE id = ?').get(id) ?? null; } export function addDeck(name, description) { - // TODO: insert a new deck and return the new row (including its id) - throw new Error('Not implemented'); + const info = db + .prepare('INSERT INTO decks (name, description) VALUES (?, ?)') + .run(name, description); + + return { + id: Number(info.lastInsertRowid), + name, + description, + }; } export function deleteDeck(deckId) { - // TODO: delete the deck with the given id - // return true if a row was deleted, false otherwise - throw new Error('Not implemented'); + const info = db.prepare('DELETE FROM decks WHERE id = ?').run(deckId); + return info.changes > 0; } // ---------------------------------------------------------------- @@ -45,23 +48,45 @@ export function deleteDeck(deckId) { // ---------------------------------------------------------------- export function getAllCardsForDeck(deckId) { - // TODO: return all card rows whose deckId matches - throw new Error('Not implemented'); + const rows = db + .prepare( + 'SELECT id, question, answer, learned, deck_id AS deckId FROM cards WHERE deck_id = ?' + ) + .all(deckId); + + return rows.map(card => ({ ...card, learned: Boolean(card.learned) })); } export function addCard(question, answer, deckId) { - // TODO: insert a new card and return the new row (including its id) - throw new Error('Not implemented'); + const info = db + .prepare( + 'INSERT INTO cards (question, answer, learned, deck_id) VALUES (?, ?, 0, ?)' + ) + .run(question, answer, deckId); + + return { + id: Number(info.lastInsertRowid), + question, + answer, + learned: false, + deckId, + }; } export function markCardLearned(cardId) { - // TODO: set learned = 1 for the card with the given id - // return the updated row, or null if not found - throw new Error('Not implemented'); + const info = db.prepare('UPDATE cards SET learned = 1 WHERE id = ?').run(cardId); + if (info.changes === 0) return null; + + const card = db + .prepare( + 'SELECT id, question, answer, learned, deck_id AS deckId FROM cards WHERE id = ?' + ) + .get(cardId); + + return card ? { ...card, learned: Boolean(card.learned) } : null; } export function deleteCard(cardId) { - // TODO: delete the card with the given id - // return true if a row was deleted, false otherwise - throw new Error('Not implemented'); + const info = db.prepare('DELETE FROM cards WHERE id = ?').run(cardId); + return info.changes > 0; }