retold-harness 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile_LUXURYCode +6 -23
- package/Dockerfile_Service +6 -46
- package/bin/retold-harness.js +2 -0
- package/docker_scripts/Entry-ServicesOnly.sh +6 -0
- package/docker_scripts/Entry.sh +29 -0
- package/docs/index.html +37 -27
- package/package.json +11 -6
- package/source/Retold-Harness.js +106 -40
- package/source/configuration-bookstore-serve-api.js +5 -11
- package/source/model/sqlite_create/BookStore-CreateSQLiteTables.sql +124 -0
- package/source/model/sqlite_create/BookStore-SeedData.sql +29490 -0
- package/source/web/index.html +407 -0
package/Dockerfile_LUXURYCode
CHANGED
|
@@ -1,33 +1,16 @@
|
|
|
1
|
-
# Use the codercom/code-server image
|
|
1
|
+
# Use the codercom/code-server image for the VS Code browser IDE
|
|
2
2
|
FROM codercom/code-server:latest
|
|
3
|
-
|
|
3
|
+
LABEL maintainer="steven velozo <steven@velozo.com>"
|
|
4
4
|
|
|
5
5
|
VOLUME /home/coder/.config
|
|
6
6
|
VOLUME /home/coder/.vscode
|
|
7
7
|
|
|
8
8
|
RUN echo "...installing debian dependencies..."
|
|
9
9
|
RUN sudo apt update
|
|
10
|
-
RUN sudo apt install vim curl tmux -y
|
|
10
|
+
RUN sudo apt install vim curl tmux python3 make g++ -y
|
|
11
11
|
|
|
12
12
|
RUN echo "Building development image..."
|
|
13
13
|
|
|
14
|
-
RUN echo "...configuring mariadb (mysql) server...."
|
|
15
|
-
RUN sudo apt install default-mysql-server default-mysql-client -y
|
|
16
|
-
RUN sudo sed -i "s|bind-address|#bind-address|g" /etc/mysql/mariadb.conf.d/50-server.cnf
|
|
17
|
-
ADD ./source/model/mysql_create/MySQL-Configure-Security.sql /home/coder/MySQL-Configure-Security.sql
|
|
18
|
-
ADD ./docker_scripts/MySQL-Laden-Entry.sh /usr/bin/MySQL-Laden-Entry.sh
|
|
19
|
-
RUN ( sudo mysqld_safe --skip-grant-tables --skip-networking & ) && sleep 5 && mysql -u root < /home/coder/MySQL-Configure-Security.sql
|
|
20
|
-
|
|
21
|
-
# Import the initial database
|
|
22
|
-
COPY ./source/model/mysql_create/MeadowModel-CreateMySQLDatabase.mysql.sql /home/coder/MeadowModel-CreateMySQLDatabase.mysql.sql
|
|
23
|
-
COPY ./source/model/mysql_create/MeadowModel-PopulateDatabase.sql /home/coder/MeadowModel-PopulateDatabase.sql
|
|
24
|
-
|
|
25
|
-
RUN sudo service mariadb restart && sleep 5 && mysql -u root -p"123456789" -e "CREATE DATABASE bookstore;"
|
|
26
|
-
RUN sudo service mariadb restart && sleep 5 && mysql -u root -p"123456789" bookstore < /home/coder/MeadowModel-CreateMySQLDatabase.mysql.sql
|
|
27
|
-
RUN sudo service mariadb restart && sleep 5 && mysql -u root -p"123456789" bookstore < /home/coder/MeadowModel-PopulateDatabase.sql
|
|
28
|
-
|
|
29
|
-
RUN echo "...mapping library specific volumes..."
|
|
30
|
-
|
|
31
14
|
# Volume mapping for code
|
|
32
15
|
VOLUME /home/coder/retold-harness
|
|
33
16
|
|
|
@@ -35,15 +18,15 @@ SHELL ["/bin/bash", "-c"]
|
|
|
35
18
|
USER coder
|
|
36
19
|
|
|
37
20
|
RUN echo "...installing node version manager..."
|
|
38
|
-
# Because there is a .bashrc chicken/egg problem, we will create one here to simulate logging in. This is not great.
|
|
39
21
|
RUN touch ~/.bashrc && chmod +x ~/.bashrc
|
|
40
22
|
RUN curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
|
|
41
23
|
RUN chmod +x ~/.nvm/nvm.sh
|
|
42
24
|
|
|
43
25
|
RUN echo "...installing node version 20 as the default..."
|
|
44
26
|
RUN . ~/.nvm/nvm.sh && source ~/.bashrc && nvm install 20
|
|
45
|
-
RUN . ~/.nvm/nvm.sh && source ~/.bashrc && nvm alias default 20
|
|
27
|
+
RUN . ~/.nvm/nvm.sh && source ~/.bashrc && nvm alias default 20
|
|
46
28
|
|
|
47
29
|
WORKDIR /home/coder/retold-harness
|
|
48
30
|
|
|
49
|
-
|
|
31
|
+
COPY --chmod=755 ./docker_scripts/Entry.sh /usr/bin/Entry.sh
|
|
32
|
+
ENTRYPOINT ["/usr/bin/Entry.sh"]
|
package/Dockerfile_Service
CHANGED
|
@@ -1,51 +1,11 @@
|
|
|
1
|
-
FROM
|
|
2
|
-
|
|
1
|
+
FROM node:20-alpine
|
|
2
|
+
LABEL maintainer="steven velozo <steven@velozo.com>"
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
RUN
|
|
6
|
-
RUN apt install vim curl tmux -y
|
|
7
|
-
|
|
8
|
-
RUN echo "Building service image..."
|
|
9
|
-
|
|
10
|
-
RUN echo "...configuring mariadb (mysql) server...."
|
|
11
|
-
RUN apt install default-mysql-server default-mysql-client -y
|
|
12
|
-
RUN sed -i "s|bind-address|#bind-address|g" /etc/mysql/mariadb.conf.d/50-server.cnf
|
|
13
|
-
ADD ./source/model/mysql_create/MySQL-Configure-Security.sql /home/coder/MySQL-Configure-Security.sql
|
|
14
|
-
ADD ./docker_scripts/MySQL-Laden-Entry.sh /usr/bin/MySQL-Laden-Entry.sh
|
|
15
|
-
RUN ( mysqld_safe --skip-grant-tables --skip-networking & ) && sleep 5 && mysql -u root < /home/coder/MySQL-Configure-Security.sql
|
|
16
|
-
|
|
17
|
-
# Import the initial database
|
|
18
|
-
COPY ./source/model/mysql_create/MeadowModel-CreateMySQLDatabase.mysql.sql /home/coder/MeadowModel-CreateMySQLDatabase.mysql.sql
|
|
19
|
-
COPY ./source/model/mysql_create/MeadowModel-PopulateDatabase.sql /home/coder/MeadowModel-PopulateDatabase.sql
|
|
20
|
-
|
|
21
|
-
RUN service mariadb restart && sleep 5 && mysql -u root -p"123456789" -e "CREATE DATABASE bookstore;"
|
|
22
|
-
RUN service mariadb restart && sleep 5 && mysql -u root -p"123456789" bookstore < /home/coder/MeadowModel-CreateMySQLDatabase.mysql.sql
|
|
23
|
-
RUN service mariadb restart && sleep 5 && mysql -u root -p"123456789" bookstore < /home/coder/MeadowModel-PopulateDatabase.sql
|
|
24
|
-
|
|
25
|
-
RUN echo "...mapping library specific volumes..."
|
|
4
|
+
# Build tools needed to compile better-sqlite3 native addon
|
|
5
|
+
RUN apk add --no-cache python3 make g++
|
|
26
6
|
|
|
27
7
|
VOLUME /retold-harness
|
|
28
|
-
|
|
29
|
-
SHELL ["/bin/bash", "-c"]
|
|
30
|
-
|
|
31
|
-
RUN echo "...installing node version manager..."
|
|
32
|
-
|
|
33
|
-
# Because there is a .bashrc chicken/egg problem, we will create one here to simulate logging in. This is not great.
|
|
34
|
-
RUN touch /root/.bashrc && chmod +x /root/.bashrc
|
|
35
|
-
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
|
|
36
|
-
|
|
37
|
-
ENV NODE_VERSION=20
|
|
38
|
-
ENV NVM_DIR=/root/.nvm
|
|
39
|
-
RUN . "$NVM_DIR/nvm.sh" && nvm install ${NODE_VERSION}
|
|
40
|
-
RUN . "$NVM_DIR/nvm.sh" && nvm use v${NODE_VERSION}
|
|
41
|
-
RUN . "$NVM_DIR/nvm.sh" && nvm alias default v${NODE_VERSION}
|
|
42
|
-
ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin/:${PATH}"
|
|
43
|
-
RUN . /root/.nvm/nvm.sh && source /root/.bashrc && node --version
|
|
44
|
-
RUN . /root/.nvm/nvm.sh && npm --version
|
|
45
|
-
|
|
46
8
|
WORKDIR /retold-harness
|
|
47
9
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
COPY ./docker_scripts/MySQL-Laden-Entry-ServicesOnly.sh /root/MySQL-Laden-Entry-ServicesOnly.sh
|
|
51
|
-
ENTRYPOINT ["/root/MySQL-Laden-Entry-ServicesOnly.sh"]
|
|
10
|
+
COPY --chmod=755 ./docker_scripts/Entry-ServicesOnly.sh /root/Entry-ServicesOnly.sh
|
|
11
|
+
ENTRYPOINT ["/root/Entry-ServicesOnly.sh"]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
trap 'kill -TERM $PID' TERM INT
|
|
4
|
+
|
|
5
|
+
# Start the Visual Studio Code Server
|
|
6
|
+
/usr/bin/entrypoint.sh --bind-addr "0.0.0.0:8080" . &
|
|
7
|
+
|
|
8
|
+
PID=$!
|
|
9
|
+
|
|
10
|
+
sleep 2
|
|
11
|
+
|
|
12
|
+
# Install the latest pm2 process manager
|
|
13
|
+
export HOME=/home/coder
|
|
14
|
+
bash -i <(echo "npm install pm2 -g")
|
|
15
|
+
# Install the dependencies for node
|
|
16
|
+
bash -i <(echo "npm install")
|
|
17
|
+
# Rebuild native addons for the container platform (the volume mount
|
|
18
|
+
# brings in the host's node_modules which may have Mac/Windows binaries).
|
|
19
|
+
# NOTE: This overwrites the host's better-sqlite3 binary with a Linux build.
|
|
20
|
+
# After stopping Docker, run `npm rebuild better-sqlite3` on the host to restore.
|
|
21
|
+
bash -i <(echo "npm rebuild better-sqlite3")
|
|
22
|
+
# Now run the harness API within the pm2 process manager
|
|
23
|
+
bash -i <(echo "pm2 start /home/coder/retold-harness/source/Retold-Harness.js")
|
|
24
|
+
|
|
25
|
+
wait $PID
|
|
26
|
+
trap - TERM INT
|
|
27
|
+
wait $PID
|
|
28
|
+
EXIT_STATUS=$?
|
|
29
|
+
echo "Service exited with status ${EXIT_STATUS}"
|
package/docs/index.html
CHANGED
|
@@ -1,29 +1,39 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
<
|
|
28
|
-
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
7
|
+
<meta name="description" content="Documentation powered by pict-docuserve">
|
|
8
|
+
|
|
9
|
+
<title>Documentation</title>
|
|
10
|
+
|
|
11
|
+
<!-- Application Stylesheet -->
|
|
12
|
+
<link href="https://cdn.jsdelivr.net/npm/pict-docuserve@0/dist/css/docuserve.css" rel="stylesheet">
|
|
13
|
+
<!-- KaTeX stylesheet for LaTeX equation rendering -->
|
|
14
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css">
|
|
15
|
+
<!-- PICT Dynamic View CSS Container -->
|
|
16
|
+
<style id="PICT-CSS"></style>
|
|
17
|
+
|
|
18
|
+
<!-- Load the PICT library from jsDelivr CDN -->
|
|
19
|
+
<script src="https://cdn.jsdelivr.net/npm/pict@1/dist/pict.min.js" type="text/javascript"></script>
|
|
20
|
+
<!-- Bootstrap the Application -->
|
|
21
|
+
<script type="text/javascript">
|
|
22
|
+
//<![CDATA[
|
|
23
|
+
Pict.safeOnDocumentReady(() => { Pict.safeLoadPictApplication(PictDocuserve, 2)});
|
|
24
|
+
//]]>
|
|
25
|
+
</script>
|
|
26
|
+
</head>
|
|
27
|
+
<body>
|
|
28
|
+
<!-- The root container for the Pict application -->
|
|
29
|
+
<div id="Docuserve-Application-Container"></div>
|
|
30
|
+
|
|
31
|
+
<!-- Mermaid diagram rendering -->
|
|
32
|
+
<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
|
|
33
|
+
<script>mermaid.initialize({ startOnLoad: false, theme: 'default' });</script>
|
|
34
|
+
<!-- KaTeX for LaTeX equation rendering -->
|
|
35
|
+
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.js"></script>
|
|
36
|
+
<!-- Load the Docuserve PICT Application Bundle from jsDelivr CDN -->
|
|
37
|
+
<script src="https://cdn.jsdelivr.net/npm/pict-docuserve@0/dist/pict-docuserve.min.js" type="text/javascript"></script>
|
|
38
|
+
</body>
|
|
29
39
|
</html>
|
package/package.json
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "retold-harness",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Restful API harness. Serves on 8086.",
|
|
5
5
|
"main": "source/Retold-Harness.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"retold-harness": "./bin/retold-harness.js"
|
|
8
|
+
},
|
|
6
9
|
"scripts": {
|
|
7
10
|
"start": "node source/Retold-Harness.js",
|
|
11
|
+
"harness": "node source/Retold-Harness.js",
|
|
8
12
|
"test": "npx mocha -u tdd -R spec",
|
|
9
13
|
"tests": "npx mocha -u tdd --exit -R spec --grep",
|
|
10
14
|
"coverage": "npx nyc --reporter=lcov --reporter=text-lcov npx mocha -- -u tdd -R spec",
|
|
11
15
|
"build": "npx quack build",
|
|
12
16
|
"build-model": "cd source && npx stricture -i model/ddl/BookStore.ddl",
|
|
13
17
|
"docker-dev-build": "docker build ./ -f Dockerfile_LUXURYCode -t retold-harness-image:local",
|
|
14
|
-
"docker-dev-run": "docker run -it -d --name retold-harness-dev -p 20001:8080 -p 8086:8086 -
|
|
18
|
+
"docker-dev-run": "docker run -it -d --name retold-harness-dev -p 20001:8080 -p 8086:8086 -v \"$PWD/.config:/home/coder/.config\" -v \"$PWD:/home/coder/retold-harness\" -u \"$(id -u):$(id -g)\" -e \"DOCKER_USER=$USER\" retold-harness-image:local",
|
|
15
19
|
"docker-dev-shell": "docker exec -it retold-harness-dev /bin/bash",
|
|
16
20
|
"docker-dev-service-build": "docker build ./ -f Dockerfile_Service -t retold-harness-service-image:local",
|
|
17
|
-
"docker-dev-service-run": "docker run -it --init -d --name retold-harness-dev-service -p 8086:8086 -
|
|
21
|
+
"docker-dev-service-run": "docker run -it --init -d --name retold-harness-dev-service -p 8086:8086 -v \"$(pwd):/retold-harness:z\" retold-harness-service-image:local",
|
|
18
22
|
"docker-dev-service-shell": "docker exec -it retold-harness-dev-service /bin/bash"
|
|
19
23
|
},
|
|
20
24
|
"repository": {
|
|
@@ -28,13 +32,14 @@
|
|
|
28
32
|
},
|
|
29
33
|
"homepage": "https://github.com/stevenvelozo/retold-harness#readme",
|
|
30
34
|
"dependencies": {
|
|
31
|
-
"
|
|
35
|
+
"meadow-connection-sqlite": "^1.0.11",
|
|
36
|
+
"retold-data-service": "^2.0.11"
|
|
32
37
|
},
|
|
33
38
|
"devDependencies": {
|
|
34
39
|
"chai": "^4.3.6",
|
|
35
40
|
"mocha": "^10.2.0",
|
|
36
|
-
"quackage": "^1.0.
|
|
37
|
-
"stricture": "^1.0.
|
|
41
|
+
"quackage": "^1.0.50",
|
|
42
|
+
"stricture": "^1.0.38",
|
|
38
43
|
"supertest": "^6.3.3"
|
|
39
44
|
},
|
|
40
45
|
"mocha": {
|
package/source/Retold-Harness.js
CHANGED
|
@@ -1,47 +1,113 @@
|
|
|
1
|
+
const libPath = require('path');
|
|
2
|
+
const libFS = require('fs');
|
|
3
|
+
|
|
1
4
|
const _Settings = require('./configuration-bookstore-serve-api.js');
|
|
2
5
|
|
|
3
6
|
const libFable = require('fable');
|
|
7
|
+
const libMeadowConnectionSQLite = require('meadow-connection-sqlite');
|
|
4
8
|
|
|
5
9
|
// Initialize fable
|
|
6
10
|
_Fable = new libFable(_Settings);
|
|
7
11
|
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
12
|
+
// Ensure the data directory exists
|
|
13
|
+
let tmpDataDir = libPath.dirname(_Settings.SQLite.SQLiteFilePath);
|
|
14
|
+
if (!libFS.existsSync(tmpDataDir))
|
|
15
|
+
{
|
|
16
|
+
libFS.mkdirSync(tmpDataDir, { recursive: true });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Register and connect the SQLite provider
|
|
20
|
+
_Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
|
|
21
|
+
_Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
|
|
22
|
+
|
|
23
|
+
_Fable.MeadowSQLiteProvider.connectAsync(
|
|
24
|
+
(pError) =>
|
|
25
|
+
{
|
|
26
|
+
if (pError)
|
|
27
|
+
{
|
|
28
|
+
_Fable.log.error(`SQLite connection error: ${pError}`);
|
|
29
|
+
return process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let tmpDB = _Fable.MeadowSQLiteProvider.db;
|
|
33
|
+
|
|
34
|
+
// Create the BookStore schema tables
|
|
35
|
+
let tmpCreateSQL = libFS.readFileSync(libPath.join(__dirname, 'model', 'sqlite_create', 'BookStore-CreateSQLiteTables.sql'), 'utf8');
|
|
36
|
+
tmpDB.exec(tmpCreateSQL);
|
|
37
|
+
|
|
38
|
+
// Check if the database has been seeded already
|
|
39
|
+
let tmpRowCount = tmpDB.prepare('SELECT COUNT(*) AS cnt FROM Book').get();
|
|
40
|
+
if (tmpRowCount.cnt < 1)
|
|
41
|
+
{
|
|
42
|
+
_Fable.log.info('Seeding initial BookStore data...');
|
|
43
|
+
let tmpSeedSQL = libFS.readFileSync(libPath.join(__dirname, 'model', 'sqlite_create', 'BookStore-SeedData.sql'), 'utf8');
|
|
44
|
+
tmpDB.exec(tmpSeedSQL);
|
|
45
|
+
_Fable.log.info('Seed data loaded.');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Add the data service type and initialize it
|
|
49
|
+
_Fable.serviceManager.addServiceType('RetoldDataService', require('retold-data-service'));
|
|
50
|
+
_Fable.serviceManager.instantiateServiceProvider('RetoldDataService', _Settings.RetoldDataServiceOptions);
|
|
51
|
+
|
|
52
|
+
_Fable.RetoldDataService.initializeService(
|
|
53
|
+
(pInitError) =>
|
|
54
|
+
{
|
|
55
|
+
if (pInitError)
|
|
56
|
+
{
|
|
57
|
+
_Fable.log.error(`Data service initialization error: ${pInitError}`);
|
|
58
|
+
return process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Create a post operation behavior for the book Read singular record endpoint only
|
|
62
|
+
_Fable.MeadowEndpoints.Book.controller.BehaviorInjection.setBehavior('Read-PostOperation',
|
|
63
|
+
(pRequest, pRequestState, fRequestComplete) =>
|
|
64
|
+
{
|
|
65
|
+
// Get the join records
|
|
66
|
+
_Fable.DAL.BookAuthorJoin.doReads(_Fable.DAL.BookAuthorJoin.query.addFilter('IDBook', pRequestState.Record.IDBook),
|
|
67
|
+
(pJoinReadError, pJoinReadQuery, pJoinRecords) =>
|
|
68
|
+
{
|
|
69
|
+
if (pJoinRecords.length < 1)
|
|
70
|
+
{
|
|
71
|
+
_Fable.log.trace(`Found no authors for IDBook ${pRequestState.Record.IDBook} (${pRequestState.Record.Title}). What even is a book without authors?`)
|
|
72
|
+
pRequestState.Record.Authors = [];
|
|
73
|
+
return fRequestComplete();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let tmpAuthors = [];
|
|
77
|
+
let tmpRemaining = pJoinRecords.length;
|
|
78
|
+
|
|
79
|
+
for (let j = 0; j < pJoinRecords.length; j++)
|
|
80
|
+
{
|
|
81
|
+
_Fable.DAL.Author.doRead(_Fable.DAL.Author.query.addFilter('IDAuthor', pJoinRecords[j].IDAuthor),
|
|
82
|
+
(pReadError, pReadQuery, pAuthor) =>
|
|
83
|
+
{
|
|
84
|
+
if (pAuthor && pAuthor.IDAuthor)
|
|
85
|
+
{
|
|
86
|
+
tmpAuthors.push(pAuthor);
|
|
87
|
+
}
|
|
88
|
+
tmpRemaining--;
|
|
89
|
+
if (tmpRemaining <= 0)
|
|
90
|
+
{
|
|
91
|
+
pRequestState.Record.Authors = tmpAuthors;
|
|
92
|
+
_Fable.log.info(`Found ${tmpAuthors.length} authors for IDBook ${pRequestState.Record.IDBook} (${pRequestState.Record.Title}).`)
|
|
93
|
+
return fRequestComplete();
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Serve the web UI at the root URL
|
|
101
|
+
let tmpWebUIHTML = libFS.readFileSync(libPath.join(__dirname, 'web', 'index.html'), 'utf8');
|
|
102
|
+
_Fable.OratorServiceServer.server.get('/',
|
|
103
|
+
(pRequest, pResponse, fNext) =>
|
|
104
|
+
{
|
|
105
|
+
pResponse.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
106
|
+
pResponse.end(tmpWebUIHTML);
|
|
107
|
+
return fNext();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
_Fable.log.info(`Retold Harness running on port ${_Settings.APIServerPort} with SQLite`);
|
|
111
|
+
_Fable.log.info(`Web UI available at http://localhost:${_Settings.APIServerPort}/`);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
@@ -21,21 +21,15 @@ module.exports = (
|
|
|
21
21
|
|
|
22
22
|
"RetoldDataServiceOptions":
|
|
23
23
|
{
|
|
24
|
-
"StorageProvider": "
|
|
25
|
-
"StorageProviderModule": "meadow-connection-
|
|
24
|
+
"StorageProvider": "SQLite",
|
|
25
|
+
"StorageProviderModule": "meadow-connection-sqlite",
|
|
26
26
|
|
|
27
27
|
"FullMeadowSchemaPath": `${__dirname}/model/`,
|
|
28
28
|
"FullMeadowSchemaFilename": `MeadowModel-Extended.json`,
|
|
29
29
|
},
|
|
30
30
|
|
|
31
|
-
"
|
|
31
|
+
"SQLite":
|
|
32
32
|
{
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
"User": "root",
|
|
36
|
-
"Password": "123456789",
|
|
37
|
-
"Database": "bookstore",
|
|
38
|
-
"ConnectionPoolLimit": 20
|
|
39
|
-
},
|
|
40
|
-
"MeadowConnectionMySQLAutoConnect": true
|
|
33
|
+
"SQLiteFilePath": `${__dirname}/../data/bookstore.sqlite`
|
|
34
|
+
}
|
|
41
35
|
});
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
-- BookStore Data Model -- SQLite Schema
|
|
2
|
+
-- Equivalent to MeadowModel-CreateMySQLDatabase.mysql.sql
|
|
3
|
+
|
|
4
|
+
CREATE TABLE IF NOT EXISTS User (
|
|
5
|
+
IDUser INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
6
|
+
GUIDUser INTEGER DEFAULT 0,
|
|
7
|
+
LoginID TEXT DEFAULT '',
|
|
8
|
+
Password TEXT DEFAULT '',
|
|
9
|
+
NameFirst TEXT DEFAULT '',
|
|
10
|
+
NameLast TEXT DEFAULT '',
|
|
11
|
+
FullName TEXT DEFAULT '',
|
|
12
|
+
Config TEXT DEFAULT ''
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE TABLE IF NOT EXISTS Book (
|
|
16
|
+
IDBook INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
17
|
+
GUIDBook TEXT DEFAULT '',
|
|
18
|
+
CreateDate TEXT DEFAULT '',
|
|
19
|
+
CreatingIDUser INTEGER DEFAULT 0,
|
|
20
|
+
UpdateDate TEXT DEFAULT '',
|
|
21
|
+
UpdatingIDUser INTEGER DEFAULT 0,
|
|
22
|
+
Deleted INTEGER DEFAULT 0,
|
|
23
|
+
DeleteDate TEXT DEFAULT '',
|
|
24
|
+
DeletingIDUser INTEGER DEFAULT 0,
|
|
25
|
+
Title TEXT DEFAULT '',
|
|
26
|
+
Type TEXT DEFAULT '',
|
|
27
|
+
Genre TEXT DEFAULT '',
|
|
28
|
+
ISBN TEXT DEFAULT '',
|
|
29
|
+
Language TEXT DEFAULT '',
|
|
30
|
+
ImageURL TEXT DEFAULT '',
|
|
31
|
+
PublicationYear INTEGER DEFAULT 0
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
CREATE TABLE IF NOT EXISTS BookAuthorJoin (
|
|
35
|
+
IDBookAuthorJoin INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
36
|
+
GUIDBookAuthorJoin TEXT DEFAULT '',
|
|
37
|
+
IDBook INTEGER DEFAULT 0,
|
|
38
|
+
IDAuthor INTEGER DEFAULT 0
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
CREATE TABLE IF NOT EXISTS Author (
|
|
42
|
+
IDAuthor INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
43
|
+
GUIDAuthor TEXT DEFAULT '',
|
|
44
|
+
CreateDate TEXT DEFAULT '',
|
|
45
|
+
CreatingIDUser INTEGER DEFAULT 0,
|
|
46
|
+
UpdateDate TEXT DEFAULT '',
|
|
47
|
+
UpdatingIDUser INTEGER DEFAULT 0,
|
|
48
|
+
Deleted INTEGER DEFAULT 0,
|
|
49
|
+
DeleteDate TEXT DEFAULT '',
|
|
50
|
+
DeletingIDUser INTEGER DEFAULT 0,
|
|
51
|
+
Name TEXT DEFAULT '',
|
|
52
|
+
IDUser INTEGER DEFAULT 0
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
CREATE TABLE IF NOT EXISTS BookPrice (
|
|
56
|
+
IDBookPrice INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
57
|
+
GUIDBookPrice TEXT DEFAULT '',
|
|
58
|
+
CreateDate TEXT DEFAULT '',
|
|
59
|
+
CreatingIDUser INTEGER DEFAULT 0,
|
|
60
|
+
UpdateDate TEXT DEFAULT '',
|
|
61
|
+
UpdatingIDUser INTEGER DEFAULT 0,
|
|
62
|
+
Deleted INTEGER DEFAULT 0,
|
|
63
|
+
DeleteDate TEXT DEFAULT '',
|
|
64
|
+
DeletingIDUser INTEGER DEFAULT 0,
|
|
65
|
+
Price REAL DEFAULT 0,
|
|
66
|
+
StartDate TEXT DEFAULT '',
|
|
67
|
+
EndDate TEXT DEFAULT '',
|
|
68
|
+
Discountable INTEGER DEFAULT 0,
|
|
69
|
+
CouponCode TEXT DEFAULT '',
|
|
70
|
+
IDBook INTEGER DEFAULT 0
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
CREATE TABLE IF NOT EXISTS BookStore (
|
|
74
|
+
IDBookStore INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
75
|
+
GUIDBookStore TEXT DEFAULT '',
|
|
76
|
+
CreateDate TEXT DEFAULT '',
|
|
77
|
+
CreatingIDUser INTEGER DEFAULT 0,
|
|
78
|
+
UpdateDate TEXT DEFAULT '',
|
|
79
|
+
UpdatingIDUser INTEGER DEFAULT 0,
|
|
80
|
+
Deleted INTEGER DEFAULT 0,
|
|
81
|
+
DeleteDate TEXT DEFAULT '',
|
|
82
|
+
DeletingIDUser INTEGER DEFAULT 0,
|
|
83
|
+
Name TEXT DEFAULT '',
|
|
84
|
+
Address TEXT DEFAULT '',
|
|
85
|
+
City TEXT DEFAULT '',
|
|
86
|
+
State TEXT DEFAULT '',
|
|
87
|
+
Postal TEXT DEFAULT '',
|
|
88
|
+
Country TEXT DEFAULT ''
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
CREATE TABLE IF NOT EXISTS BookStoreInventory (
|
|
92
|
+
IDBookStoreInventory INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
93
|
+
GUIDBookStoreInventory TEXT DEFAULT '',
|
|
94
|
+
CreateDate TEXT DEFAULT '',
|
|
95
|
+
CreatingIDUser INTEGER DEFAULT 0,
|
|
96
|
+
UpdateDate TEXT DEFAULT '',
|
|
97
|
+
UpdatingIDUser INTEGER DEFAULT 0,
|
|
98
|
+
Deleted INTEGER DEFAULT 0,
|
|
99
|
+
DeleteDate TEXT DEFAULT '',
|
|
100
|
+
DeletingIDUser INTEGER DEFAULT 0,
|
|
101
|
+
StockDate TEXT DEFAULT '',
|
|
102
|
+
BookCount INTEGER DEFAULT 0,
|
|
103
|
+
AggregateBookCount INTEGER DEFAULT 0,
|
|
104
|
+
IDBook INTEGER DEFAULT 0,
|
|
105
|
+
IDBookStore INTEGER DEFAULT 0,
|
|
106
|
+
IDBookPrice INTEGER DEFAULT 0,
|
|
107
|
+
StockingAssociate INTEGER DEFAULT 0
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
CREATE TABLE IF NOT EXISTS Review (
|
|
111
|
+
IDReview INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
112
|
+
GUIDReview TEXT DEFAULT '',
|
|
113
|
+
CreateDate TEXT DEFAULT '',
|
|
114
|
+
CreatingIDUser INTEGER DEFAULT 0,
|
|
115
|
+
UpdateDate TEXT DEFAULT '',
|
|
116
|
+
UpdatingIDUser INTEGER DEFAULT 0,
|
|
117
|
+
Deleted INTEGER DEFAULT 0,
|
|
118
|
+
DeleteDate TEXT DEFAULT '',
|
|
119
|
+
DeletingIDUser INTEGER DEFAULT 0,
|
|
120
|
+
Text TEXT DEFAULT '',
|
|
121
|
+
Rating INTEGER DEFAULT 0,
|
|
122
|
+
IDBook INTEGER DEFAULT 0,
|
|
123
|
+
IDUser INTEGER DEFAULT 0
|
|
124
|
+
);
|