completed content manager
This commit is contained in:
@@ -16,8 +16,19 @@ SERA Websiteのニュース等のコンテンツを管理する
|
|||||||
cd src-manager/ # このディレクトリーに移動
|
cd src-manager/ # このディレクトリーに移動
|
||||||
npm install # 依存パッケージのインストール、まだ一度も実行していない場合
|
npm install # 依存パッケージのインストール、まだ一度も実行していない場合
|
||||||
npm start # サーバーを起動、ブラウザで http://localhost:3001 に入る
|
npm start # サーバーを起動、ブラウザで http://localhost:3001 に入る
|
||||||
|
npm run dev # ファイル変更時に自動リロードが入る開発サーバーを起動する。同じく http://localhost:3001 でホストされる
|
||||||
```
|
```
|
||||||
|
|
||||||
## データベース
|
## データベース
|
||||||
|
|
||||||
|
テーブル: news
|
||||||
|
|
||||||
|
* id - PRIMARY KEY - 整数
|
||||||
|
* date - Unix時間 - 整数
|
||||||
|
* entryType - 記事(0) か ツイート風(1) - 整数
|
||||||
|
* cardcontent - ニュースリストで表示されるコンテンツ、Markdown可 - 文字列(Markdown)
|
||||||
|
* article - Markdownで書かれた記事 - 文字列(Markdown)
|
||||||
|
* linkPath - ニュースリストで表示されるリンク先 - 文字列
|
||||||
|
* coverImagePath - ニュースリストで表示される画像へのパス - 文字列
|
||||||
|
|
||||||
## API
|
## API
|
||||||
154
src-manager/app.js
Normal file
154
src-manager/app.js
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
import express from 'express';
|
||||||
|
import sqlite3 from 'sqlite3';
|
||||||
|
import path from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
import { asyncDatabaseRead, asyncDatabaseWrite } from './utils/asyncDatabase.js';
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const port = 3001;
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
|
app.use(express.urlencoded({ extended: true }));
|
||||||
|
app.use(express.static(path.join(__dirname, 'pages')));
|
||||||
|
app.use(express.static(path.join(__dirname, "../assets")));
|
||||||
|
app.use(express.static(path.join(__dirname, "../public")));
|
||||||
|
|
||||||
|
app.get('/api/news-list', async (request, response) => {
|
||||||
|
const database = new sqlite3.Database(path.join(__dirname, "../assets/databases/news.db"));
|
||||||
|
const sqlQuery = `SELECT * FROM news;`;
|
||||||
|
try {
|
||||||
|
const result = await asyncDatabaseRead(database, sqlQuery, (rows) => {
|
||||||
|
let ret = "";
|
||||||
|
for (const entry of rows) {
|
||||||
|
ret = ret + "<tr>\n";
|
||||||
|
for (const data in entry) {
|
||||||
|
if (data == "article" || data == "coverImagePath" || data == "linkPath") continue;
|
||||||
|
if (data == "entryType") {
|
||||||
|
ret = ret + `<td>${entry[data] == 0 ? "Article" : "Tweet"}</td>\n`;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (data == "date") {
|
||||||
|
ret = ret + `<td>${new Date(entry[data]).toLocaleString()}</td>\n`;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ret = ret + `<td>${entry[data]}</td>\n`;
|
||||||
|
}
|
||||||
|
ret = ret + `<td>\n
|
||||||
|
<button class='delete-button' hx-delete='/api/news?target=${entry["date"]}'>Delete</button>\n
|
||||||
|
<a href='/update-news.html?target=${entry["date"]}'><button class='edit-button' hx-confirm='unset'>Edit</button></a>\n
|
||||||
|
</td>\n</tr>\n`;
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
});
|
||||||
|
database.close();
|
||||||
|
response.send(result);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/api/news', async (request, response) => {
|
||||||
|
const database = new sqlite3.Database(path.join(__dirname, "../assets/databases/news.db"));
|
||||||
|
|
||||||
|
const target = Number(request.query.target);
|
||||||
|
|
||||||
|
if (isNaN(target)) {
|
||||||
|
response.status(500).send("Query is not number");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sqlQuery = `SELECT * FROM news WHERE date = ${target}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await asyncDatabaseRead(database, sqlQuery, (rows) => {return rows[0]});
|
||||||
|
database.close();
|
||||||
|
response.send(result);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.post('/api/news', async (request, response) => {
|
||||||
|
const database = new sqlite3.Database(path.join(__dirname, "../assets/databases/news.db"));
|
||||||
|
|
||||||
|
const currentDate = new Date();
|
||||||
|
const currentUnixTime = currentDate.valueOf();
|
||||||
|
const entryType = request.body.entryType;
|
||||||
|
const cardContent = request.body.cardContent;
|
||||||
|
const article = request.body.article;
|
||||||
|
const linkPath = entryType == 0 ? `/news/${request.body.linkPath}` : "";
|
||||||
|
const coverImagePath = request.body.coverImagePath;
|
||||||
|
|
||||||
|
const sqlQuery = `INSERT INTO news (date, entryType, cardContent, article, linkPath, coverImagePath) VALUES (${currentUnixTime}, ${entryType}, "${cardContent}", "${article}", "${linkPath}", "${coverImagePath}");`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await asyncDatabaseWrite(database, sqlQuery, () => {
|
||||||
|
console.log("News added successfully.");
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
response.status(500).send(err);
|
||||||
|
}
|
||||||
|
database.close();
|
||||||
|
response.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.put('/api/news', async (request, response) => {
|
||||||
|
const database = new sqlite3.Database(path.join(__dirname, "../assets/databases/news.db"));
|
||||||
|
|
||||||
|
const target = Number(request.body.target);
|
||||||
|
const entryType = Number(request.body.entryType);
|
||||||
|
const cardContent = request.body.cardContent;
|
||||||
|
const article = request.body.article;
|
||||||
|
const linkPath = entryType == 0 ? `/news/${request.body.linkPath}` : "";
|
||||||
|
const coverImagePath = request.body.coverImagePath;
|
||||||
|
|
||||||
|
if (isNaN(target)) {
|
||||||
|
response.status(500).send('Target is not number');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sqlQuery = `UPDATE news SET entryType = ${entryType}, cardContent = "${cardContent}", article = "${article}", linkPath = "${linkPath}", coverImagePath = "${coverImagePath}" WHERE date = ${target};`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await asyncDatabaseWrite(database, sqlQuery, () => {
|
||||||
|
console.log("News updated successfully.");
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
response.status(500).send(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
database.close();
|
||||||
|
response.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.delete('/api/news', async (request, response) => {
|
||||||
|
const database = new sqlite3.Database(path.join(__dirname, "../assets/databases/news.db"));
|
||||||
|
|
||||||
|
const target = Number(request.query.target);
|
||||||
|
|
||||||
|
if (isNaN(target)) {
|
||||||
|
response.status(404).send('No Entry Found!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sqlQuery = `DELETE FROM news WHERE date = ${target}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await asyncDatabaseWrite(database, sqlQuery, () => {
|
||||||
|
console.log("News deleted successfully.");
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
response.status(500).send(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
database.close();
|
||||||
|
|
||||||
|
response.status(200).send();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(port, () => {
|
||||||
|
console.log(`Manager is now listening on port ${port}`);
|
||||||
|
});
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const sqlite3 = require('sqlite3');
|
|
||||||
const path = require('path');
|
|
||||||
const app = express();
|
|
||||||
const port = 3001;
|
|
||||||
//const db = new sqlite3.Database("../assets/databases/news.db");
|
|
||||||
|
|
||||||
app.use(express.static('pages'));
|
|
||||||
app.use(express.static(path.join(__dirname, "../assets")));
|
|
||||||
app.use(express.static(path.join(__dirname, "../public")));
|
|
||||||
|
|
||||||
app.get('/api/hello', (req, res) => {
|
|
||||||
res.send('<li>Hello World!</li>');
|
|
||||||
});
|
|
||||||
|
|
||||||
app.listen(port, () => {
|
|
||||||
console.log(`Manager is now listening on port ${port}`);
|
|
||||||
});
|
|
||||||
831
src-manager/package-lock.json
generated
831
src-manager/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,14 +2,20 @@
|
|||||||
"name": "manager",
|
"name": "manager",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "content manager for sera hp",
|
"description": "content manager for sera hp",
|
||||||
"main": "index.js",
|
"main": "app.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node index.js"
|
"start": "node app.js",
|
||||||
|
"dev": "nodemon --watch . --ignore pages"
|
||||||
},
|
},
|
||||||
|
"type": "module",
|
||||||
"author": "kenryus",
|
"author": "kenryus",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"sqlite3": "^5.1.7"
|
"sqlite3": "^5.1.7"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"jsdoc": "^4.0.3",
|
||||||
|
"nodemon": "^3.1.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,50 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<script src="https://unpkg.com/htmx.org@2.0.1" integrity="sha384-QWGpdj554B4ETpJJC9z+ZHJcA/i59TyjxEPXiiUgN2WmTyV5OEZWCD6gQhgkdpB/" crossorigin="anonymous"></script>
|
<meta charset="UTF-8">
|
||||||
|
<title>Content Manager</title>
|
||||||
|
<script src="https://unpkg.com/htmx.org@2.0.2" integrity="sha384-Y7hw+L/jvKeWIRRkqWYfPcvVxHzVzn5REgzbawhxAuQGwX1XWe70vji+VSeHOThJ" crossorigin="anonymous"></script>
|
||||||
|
<style>
|
||||||
|
table, tr, td {
|
||||||
|
border: black solid 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead {
|
||||||
|
background-color: lightgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody {
|
||||||
|
background-color: beige;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Content Manager</h1>
|
<h1>Content Manager</h1>
|
||||||
|
|
||||||
<p>Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.</p>
|
<h3>Manager for SERA-HP's databases.</h3>
|
||||||
|
|
||||||
<button hx-get="/api/hello"
|
<ul>
|
||||||
hx-trigger="click"
|
<li>
|
||||||
hx-swap="afterend"
|
<a href="/new-news.html">New News</a>
|
||||||
hx-target="#list"
|
</li>
|
||||||
>
|
</ul>
|
||||||
Click Me!
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<ul id="list"></ul>
|
<button hx-get="/api/news-list" hx-trigger="click" hx-swap="innerHTML" hx-target="#entries">Refresh</button>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>ID</td>
|
||||||
|
<td>Date</td>
|
||||||
|
<td>Entry Type</td>
|
||||||
|
<td>Card Content</td>
|
||||||
|
<td>Actions</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="entries" hx-confirm='Are you sure you want to delete this news?' hx-target="closest tr" hx-swap="outerHTML"></tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
htmx.ajax('GET', '/api/news-list', {target: '#entries', swap: 'innerHTML'});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Content Manager - new news</title>
|
||||||
|
<script src="https://unpkg.com/htmx.org@2.0.2" integrity="sha384-Y7hw+L/jvKeWIRRkqWYfPcvVxHzVzn5REgzbawhxAuQGwX1XWe70vji+VSeHOThJ" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||||
|
<style>
|
||||||
|
form fieldset {
|
||||||
|
display: grid;
|
||||||
|
grid-auto-flow: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
#new-news {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#preview {
|
||||||
|
border: black solid 1px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="new-news">
|
||||||
|
<div>
|
||||||
|
<h3>New News</h3>
|
||||||
|
<form id="create-entry" hx-post="/api/news" hx-swap="none">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Create Entry</legend>
|
||||||
|
<label for="entryType">Entry Type:</label>
|
||||||
|
<div>
|
||||||
|
<input type="radio" id="entryType-article" name="entryType" value="0" checked>
|
||||||
|
<label for="entryType-article">Article</label>
|
||||||
|
<input type="radio" id="entryType-tweet" name="entryType" value="1">
|
||||||
|
<label for="entryType-tweet">Tweet</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label for="cardContent">Card Content:</label>
|
||||||
|
<input type="text" id="cardContent" name="cardContent" required>
|
||||||
|
|
||||||
|
<label for="article">Content:</label>
|
||||||
|
<textarea id="article" name="article" rows="24" cols="80"></textarea>
|
||||||
|
|
||||||
|
<label for="linkPath">Link Path (Optional):</label>
|
||||||
|
<div style="display: inline-flex;">
|
||||||
|
<p>/news/</p>
|
||||||
|
<input style="height: 1em; margin: auto 0;" text id="linkPath" name="linkPath">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label for="coverImagePath">Cover Image Path (Optional):</label>
|
||||||
|
<input type="text" id="coverImagePath" name="coverImagePath">
|
||||||
|
</fieldset>
|
||||||
|
<button id="submit-button" type="submit">Create Entry</button>
|
||||||
|
<a href="/index.html"><button role="none" type="button">Cancel</button></a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>Preview</h3>
|
||||||
|
<div id="preview"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const markdownPreivew = document.getElementById('preview');
|
||||||
|
const articleEditor = document.getElementById('article');
|
||||||
|
const submitButton = document.getElementById('submit-button');
|
||||||
|
|
||||||
|
articleEditor.addEventListener('input', () => {
|
||||||
|
markdownPreivew.innerHTML = marked.parse(articleEditor.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
submitButton.addEventListener('click', () => {
|
||||||
|
window.location.href = "/index.html";
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
106
src-manager/pages/update-news.html
Normal file
106
src-manager/pages/update-news.html
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Content Manager - update news</title>
|
||||||
|
<script src="https://unpkg.com/htmx.org@2.0.2" integrity="sha384-Y7hw+L/jvKeWIRRkqWYfPcvVxHzVzn5REgzbawhxAuQGwX1XWe70vji+VSeHOThJ" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||||
|
<style>
|
||||||
|
form fieldset {
|
||||||
|
display: grid;
|
||||||
|
grid-auto-flow: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
#new-news {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#preview {
|
||||||
|
border: black solid 1px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="new-news">
|
||||||
|
<div>
|
||||||
|
<h3>New News</h3>
|
||||||
|
<form id="create-entry" hx-put="/api/news" hx-swap="none">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Create Entry</legend>
|
||||||
|
<label for="entryType">Entry Type:</label>
|
||||||
|
<div>
|
||||||
|
<input type="radio" id="entry-type-article" name="entryType" value="0" checked>
|
||||||
|
<label for="entry-type-article">Article</label>
|
||||||
|
<input type="radio" id="entry-type-tweet" name="entryType" value="1">
|
||||||
|
<label for="entry-type-tweet">Tweet</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label for="cardContent">Card Content:</label>
|
||||||
|
<input type="text" id="cardContent" name="cardContent" required>
|
||||||
|
|
||||||
|
<label for="article">Content:</label>
|
||||||
|
<textarea id="article" name="article" rows="24" cols="80"></textarea>
|
||||||
|
|
||||||
|
<label for="linkPath">Link Path (Optional):</label>
|
||||||
|
<div style="display: inline-flex;">
|
||||||
|
<p>/news/</p>
|
||||||
|
<input style="height: 1em; margin: auto 0;" text id="linkPath" name="linkPath">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label for="coverImagePath">Cover Image Path (Optional):</label>
|
||||||
|
<input type="text" id="coverImagePath" name="coverImagePath">
|
||||||
|
|
||||||
|
<input type="hidden" name="target" id="targetValue" value="test" />
|
||||||
|
</fieldset>
|
||||||
|
<button id="submit-button" type="submit">Update Entry</button>
|
||||||
|
<a href="/index.html"><button role="none" type="button">Cancel</button></a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>Preview</h3>
|
||||||
|
<div id="preview"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const markdownPreivew = document.getElementById('preview');
|
||||||
|
const articleEditor = document.getElementById('article');
|
||||||
|
const submitButton = document.getElementById('submit-button');
|
||||||
|
const cardContentInput = document.getElementById('cardContent');
|
||||||
|
const coverImagePathInput = document.getElementById('coverImagePath');
|
||||||
|
const linkPathInput = document.getElementById('linkPath');
|
||||||
|
const entryTypeArticleInput = document.getElementById('entry-type-article');
|
||||||
|
const entryTypeTweetInput = document.getElementById('entry-type-tweet');
|
||||||
|
const targetValueInput = document.getElementById('targetValue');
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const targetEntry = urlParams.get('target');
|
||||||
|
|
||||||
|
axios.get('/api/news', {params: {target: targetEntry}})
|
||||||
|
.then((response) => {
|
||||||
|
targetValueInput.value = response.data.date;
|
||||||
|
cardContentInput.value = response.data.cardContent;
|
||||||
|
coverImagePathInput.value = response.data.coverImagePath;
|
||||||
|
linkPathInput.value = response.data.linkPath.split('/')[2];
|
||||||
|
articleEditor.value = response.data.article;
|
||||||
|
markdownPreivew.innerHTML = marked.parse(articleEditor.value);
|
||||||
|
if (response.data.entryType == 0) {
|
||||||
|
entryTypeArticleInput.checked = true;
|
||||||
|
} else if (response.data.entryType == 1) {
|
||||||
|
entryTypeTweetInput.checked = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {console.error(err)});
|
||||||
|
|
||||||
|
articleEditor.addEventListener('input', () => {
|
||||||
|
markdownPreivew.innerHTML = marked.parse(articleEditor.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
submitButton.addEventListener('click', () => {
|
||||||
|
window.location.href = "/index.html";
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
43
src-manager/utils/asyncDatabase.js
Normal file
43
src-manager/utils/asyncDatabase.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import sqlite3 from 'sqlite3';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param database
|
||||||
|
* @param sqlQuery
|
||||||
|
* @param callback - (rows) => {}
|
||||||
|
* @returns - Promise for database operation
|
||||||
|
*/
|
||||||
|
const asyncDatabaseRead = (database, sqlQuery, callback) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
database.serialize(() => {
|
||||||
|
database.all(sqlQuery, (err, rows) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve(callback(rows));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param database
|
||||||
|
* @param sqlQuery
|
||||||
|
* @param callback - () => {}
|
||||||
|
* @returns - Promise for database operation
|
||||||
|
*/
|
||||||
|
const asyncDatabaseWrite = (database, sqlQuery, callback) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
database.serialize(() => {
|
||||||
|
database.run(sqlQuery, (err, rows) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve(callback(rows));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export { asyncDatabaseRead, asyncDatabaseWrite };
|
||||||
Reference in New Issue
Block a user