retold-harness 1.0.4 → 1.0.6
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/.vscode/launch.json +18 -0
- package/.vscode/settings.json +19 -0
- package/Dockerfile_LUXURYCode +10 -51
- package/Dockerfile_Service +51 -0
- package/README.md +131 -39
- package/docker_scripts/MySQL-Laden-Entry-ServicesOnly.sh +11 -0
- package/docker_scripts/Service-Only_docker-entrypoint-combined.sh +35 -0
- package/docs/.nojekyll +0 -0
- package/docs/README.md +48 -0
- package/docs/_coverpage.md +11 -0
- package/docs/_sidebar.md +20 -0
- package/docs/behavior-injection.md +100 -0
- package/docs/configuration.md +107 -0
- package/docs/docker.md +78 -0
- package/docs/endpoints.md +111 -0
- package/docs/entities.md +125 -0
- package/docs/filtering.md +103 -0
- package/docs/index.html +29 -0
- package/docs/luxury-code.md +52 -0
- package/docs/quickstart.md +60 -0
- package/docs/schema.md +66 -0
- package/docs/testing.md +70 -0
- package/images/API-Author-Susans.png +0 -0
- package/package.json +13 -8
- package/source/Retold-Harness.js +4 -20
- package/source/configuration-bookstore-serve-api.js +10 -1
- package/source/model/MeadowModel-Extended.json +4310 -0
- package/source/model/MeadowModel.json +523 -0
- package/source/model/ddl/BookStore.ddl +52 -5
- package/source/model/{generated_documentation → doc}/Dictionary.md +6 -3
- package/source/model/{generated_documentation → doc}/Model-Author.md +6 -5
- package/source/model/{generated_documentation → doc}/Model-Book.md +6 -6
- package/source/model/{generated_documentation → doc}/Model-BookAuthorJoin.md +4 -4
- package/source/model/{generated_documentation → doc}/Model-BookPrice.md +6 -6
- package/source/model/doc/Model-BookStore.md +25 -0
- package/source/model/doc/Model-BookStoreInventory.md +26 -0
- package/source/model/{generated_documentation → doc}/Model-Review.md +9 -8
- package/source/model/doc/Model-User.md +18 -0
- package/source/model/{generated_documentation → doc}/ModelChangeTracking.md +4 -1
- package/source/model/doc/diagrams/Relationships.dot +22 -0
- package/source/model/doc/diagrams/Relationships.png +0 -0
- package/source/model/doc/diagrams/RelationshipsFull.dot +22 -0
- package/source/model/doc/diagrams/RelationshipsFull.png +0 -0
- package/source/model/meadow/MeadowSchemaAuthor.json +447 -0
- package/source/model/meadow/MeadowSchemaBook.json +527 -0
- package/source/model/meadow/MeadowSchemaBookAuthorJoin.json +335 -0
- package/source/model/meadow/MeadowSchemaBookPrice.json +511 -0
- package/source/model/meadow/MeadowSchemaBookStore.json +511 -0
- package/source/model/meadow/MeadowSchemaBookStoreInventory.json +527 -0
- package/source/model/meadow/MeadowSchemaReview.json +479 -0
- package/source/model/meadow/MeadowSchemaUser.json +399 -0
- package/source/model/{sql_create/BookStore-CreateDatabase.mysql.sql → mysql_create/MeadowModel-CreateMySQLDatabase.mysql.sql} +84 -10
- package/source/model/{manual_scripts/DropTables.sql → mysql_create/MeadowModel-DropMySQLTables.sql} +2 -1
- package/source/model/mysql_create/MeadowModel-PopulateDatabase.sql +28 -0
- package/source/model/{manual_scripts/MySQL-Security.sql → mysql_create/MySQL-Configure-Security.sql} +1 -1
- package/test/RetoldHarness_tests.js +2229 -0
- package/.config/configstore/update-notifier-npm.json +0 -4
- package/source/model/Model-Extended.json +0 -915
- package/source/model/Model.json +0 -280
- package/source/model/bookstore-api-endpoint-exercises.paw +0 -0
- package/source/model/generated_diagram/README.md +0 -1
- package/source/model/generated_diagram/Stricture_Output.dot +0 -13
- package/source/model/generated_diagram/Stricture_Output.png +0 -0
- package/source/model/generated_documentation/README.md +0 -1
- package/source/model/manual_scripts/MySQL-Laden-Entry.sh +0 -17
- package/source/model/manual_scripts/README.md +0 -2
- package/source/model/manual_scripts/my.cnf +0 -4
- package/source/model/meadow/Model-MeadowSchema-Author.json +0 -220
- package/source/model/meadow/Model-MeadowSchema-Book.json +0 -268
- package/source/model/meadow/Model-MeadowSchema-BookAuthorJoin.json +0 -172
- package/source/model/meadow/Model-MeadowSchema-BookPrice.json +0 -260
- package/source/model/meadow/Model-MeadowSchema-Review.json +0 -236
- package/source/model/meadow/README.md +0 -1
- package/source/model/sql_create/BookStore-DeleteAndRepopulateTables.sql +0 -194
- package/source/model/sql_create/MySQL-Security.sql +0 -5
- package/source/model/sql_create/README.md +0 -1
- /package/source/model/{Model-PICT.json → MeadowModel-PICT.json} +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Use IntelliSense to learn about possible attributes.
|
|
3
|
+
// Hover to view descriptions of existing attributes.
|
|
4
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"configurations": [
|
|
7
|
+
|
|
8
|
+
{
|
|
9
|
+
"type": "node",
|
|
10
|
+
"request": "launch",
|
|
11
|
+
"name": "Launch Program",
|
|
12
|
+
"skipFiles": [
|
|
13
|
+
"<node_internals>/**"
|
|
14
|
+
],
|
|
15
|
+
"program": "${workspaceFolder}/source/Retold-Harness.js"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"sqltools.connections": [
|
|
3
|
+
{
|
|
4
|
+
"mysqlOptions": {
|
|
5
|
+
"authProtocol": "default",
|
|
6
|
+
"enableSsl": "Disabled"
|
|
7
|
+
},
|
|
8
|
+
"ssh": "Disabled",
|
|
9
|
+
"previewLimit": 50,
|
|
10
|
+
"server": "localhost",
|
|
11
|
+
"port": 3306,
|
|
12
|
+
"driver": "MariaDB",
|
|
13
|
+
"name": "Local MariaDB server",
|
|
14
|
+
"database": "bookstore",
|
|
15
|
+
"username": "root",
|
|
16
|
+
"password": "123456789"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
package/Dockerfile_LUXURYCode
CHANGED
|
@@ -11,61 +11,20 @@ RUN sudo apt install vim curl tmux -y
|
|
|
11
11
|
|
|
12
12
|
RUN echo "Building development image..."
|
|
13
13
|
|
|
14
|
-
RUN echo "...installing vscode extensions..."
|
|
15
|
-
|
|
16
|
-
# Mocha unit testing in the sidebar
|
|
17
|
-
RUN code-server --install-extension hbenl.vscode-mocha-test-adapter
|
|
18
|
-
RUN code-server --install-extension hbenl.test-adapter-converter
|
|
19
|
-
RUN code-server --install-extension hbenl.vscode-test-explorer
|
|
20
|
-
|
|
21
|
-
# Magic indentation rainbow
|
|
22
|
-
RUN code-server --install-extension oderwat.indent-rainbow
|
|
23
|
-
RUN code-server --install-extension dbaeumer.vscode-eslint
|
|
24
|
-
|
|
25
|
-
# Contextual git
|
|
26
|
-
RUN code-server --install-extension eamodio.gitlens
|
|
27
|
-
|
|
28
|
-
# Other extensions (uncomment them to have them automagic, or run this from a terminal to install in the container):
|
|
29
|
-
|
|
30
|
-
# SQL Tools
|
|
31
|
-
RUN code-server --install-extension mtxr.sqltools
|
|
32
|
-
RUN code-server --install-extension mtxr.sqltools-driver-mysql
|
|
33
|
-
|
|
34
|
-
# Microsoft's AI code completion
|
|
35
|
-
# RUN code-server --install-extension VisualStudioExptTeam.vscodeintellicode
|
|
36
|
-
|
|
37
|
-
# Live server -- make sure to open up the port on the docker image
|
|
38
|
-
# RUN code-server --install-extension ritwickdey.LiveServer
|
|
39
|
-
|
|
40
|
-
# Quick link to required modules' documentation
|
|
41
|
-
# RUN code-server --install-extension bengreenier.vscode-node-readme
|
|
42
|
-
|
|
43
|
-
# Switch up fonts
|
|
44
|
-
# RUN code-server --install-extension evan-buss.font-switcher
|
|
45
|
-
|
|
46
|
-
# Icons
|
|
47
|
-
# RUN code-server --install-extension vscode-icons-team.vscode-icons
|
|
48
|
-
# RUN code-server --install-extension PKief.material-icon-theme
|
|
49
|
-
|
|
50
|
-
# Hover over CSS colors to see them previewed
|
|
51
|
-
# RUN code-server --install-extension bierner.color-info
|
|
52
|
-
|
|
53
|
-
# An easy on the eyes color theme
|
|
54
|
-
# RUN code-server --install-extension daylerees.rainglow
|
|
55
|
-
|
|
56
14
|
RUN echo "...configuring mariadb (mysql) server...."
|
|
57
15
|
RUN sudo apt install default-mysql-server default-mysql-client -y
|
|
58
16
|
RUN sudo sed -i "s|bind-address|#bind-address|g" /etc/mysql/mariadb.conf.d/50-server.cnf
|
|
59
|
-
ADD ./source/model/
|
|
17
|
+
ADD ./source/model/mysql_create/MySQL-Configure-Security.sql /home/coder/MySQL-Configure-Security.sql
|
|
60
18
|
ADD ./docker_scripts/MySQL-Laden-Entry.sh /usr/bin/MySQL-Laden-Entry.sh
|
|
61
19
|
RUN ( sudo mysqld_safe --skip-grant-tables --skip-networking & ) && sleep 5 && mysql -u root < /home/coder/MySQL-Configure-Security.sql
|
|
62
20
|
|
|
63
21
|
# Import the initial database
|
|
64
|
-
COPY ./source/model/
|
|
65
|
-
COPY ./source/model/
|
|
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
|
+
|
|
66
25
|
RUN sudo service mariadb restart && sleep 5 && mysql -u root -p"123456789" -e "CREATE DATABASE bookstore;"
|
|
67
|
-
RUN sudo service mariadb restart && sleep 5 && mysql -u root -p"123456789" bookstore < /home/coder/
|
|
68
|
-
RUN sudo service mariadb restart && sleep 5 && mysql -u root -p"123456789" bookstore < /home/coder/
|
|
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
|
|
69
28
|
|
|
70
29
|
RUN echo "...mapping library specific volumes..."
|
|
71
30
|
|
|
@@ -81,10 +40,10 @@ RUN touch ~/.bashrc && chmod +x ~/.bashrc
|
|
|
81
40
|
RUN curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
|
|
82
41
|
RUN chmod +x ~/.nvm/nvm.sh
|
|
83
42
|
|
|
84
|
-
RUN echo "...installing node version
|
|
85
|
-
RUN . ~/.nvm/nvm.sh && source ~/.bashrc && nvm install
|
|
86
|
-
RUN . ~/.nvm/nvm.sh && source ~/.bashrc && nvm alias default
|
|
43
|
+
RUN echo "...installing node version 20 as the default..."
|
|
44
|
+
RUN . ~/.nvm/nvm.sh && source ~/.bashrc && nvm install 20
|
|
45
|
+
RUN . ~/.nvm/nvm.sh && source ~/.bashrc && nvm alias default 20
|
|
87
46
|
|
|
88
47
|
WORKDIR /home/coder/retold-harness
|
|
89
48
|
|
|
90
|
-
ENTRYPOINT ["/usr/bin/MySQL-Laden-Entry.sh"]
|
|
49
|
+
ENTRYPOINT ["/usr/bin/MySQL-Laden-Entry.sh"]
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
FROM debian:latest
|
|
2
|
+
MAINTAINER steven velozo
|
|
3
|
+
|
|
4
|
+
RUN echo "...installing debian dependencies..."
|
|
5
|
+
RUN apt update
|
|
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..."
|
|
26
|
+
|
|
27
|
+
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
|
+
WORKDIR /retold-harness
|
|
47
|
+
|
|
48
|
+
RUN echo "...configuring entrypoint..."
|
|
49
|
+
|
|
50
|
+
COPY ./docker_scripts/MySQL-Laden-Entry-ServicesOnly.sh /root/MySQL-Laden-Entry-ServicesOnly.sh
|
|
51
|
+
ENTRYPOINT ["/root/MySQL-Laden-Entry-ServicesOnly.sh"]
|
package/README.md
CHANGED
|
@@ -1,77 +1,127 @@
|
|
|
1
1
|
# Retold Harness
|
|
2
2
|
|
|
3
|
-
A
|
|
4
|
-
images for the cover of each book. Useful for more complex harnesses.
|
|
3
|
+
> A self-contained REST API harness for the Retold framework
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
Retold Harness brings together the full Retold stack into a running bookstore application. Point a browser at `http://localhost:8086/1.0/Books/0/100` and you have a working REST API backed by 10,000+ book records, author joins, pricing, store inventory, and reviews -- all auto-generated from a Stricture DDL.
|
|
7
6
|
|
|
8
|
-
##
|
|
7
|
+
## Features
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
- **8-Entity Bookstore Model** - Users, Books, Authors, Joins, Prices, Stores, Inventory, and Reviews
|
|
10
|
+
- **Auto-Generated CRUD** - Every entity gets Create, Read, Reads, Update, Delete, Count, Schema, and New endpoints
|
|
11
|
+
- **Author Enrichment** - Single Book reads include an Authors array via behavior injection
|
|
12
|
+
- **Pre-Loaded Data** - 10,000+ book records with associated authors for realistic testing
|
|
13
|
+
- **Docker Containerized** - MariaDB database and API server in a single container
|
|
14
|
+
- **Luxury Code IDE** - Browser-based VS Code for in-container development
|
|
15
|
+
- **SQLite Testing** - In-memory test suite requires no external database
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
## Quick Start (Docker)
|
|
14
18
|
|
|
15
|
-
```
|
|
19
|
+
```bash
|
|
16
20
|
git clone https://github.com/stevenvelozo/retold-harness
|
|
21
|
+
cd retold-harness
|
|
22
|
+
npm run docker-dev-build
|
|
23
|
+
npm run docker-dev-run
|
|
17
24
|
```
|
|
18
25
|
|
|
26
|
+
The REST API is now at `http://localhost:8086`.
|
|
19
27
|
|
|
20
|
-
|
|
28
|
+

|
|
21
29
|
|
|
22
|
-
|
|
30
|
+
## Quick Start (Manual)
|
|
23
31
|
|
|
24
|
-
```
|
|
25
|
-
|
|
32
|
+
```bash
|
|
33
|
+
# Start a MariaDB container
|
|
34
|
+
docker run -d --name mariadb -p 3306:3306 \
|
|
35
|
+
-e MARIADB_ROOT_PASSWORD=123456789 \
|
|
36
|
+
-e MARIADB_DATABASE=bookstore \
|
|
37
|
+
mariadb:latest
|
|
38
|
+
|
|
39
|
+
# Create the tables
|
|
40
|
+
cat ./source/model/mysql_create/MeadowModel-CreateMySQLDatabase.mysql.sql \
|
|
41
|
+
| docker exec -i mariadb mariadb -u root -p123456789 bookstore
|
|
42
|
+
|
|
43
|
+
# Install and start
|
|
44
|
+
npm install
|
|
45
|
+
npm start
|
|
26
46
|
```
|
|
27
47
|
|
|
28
|
-
|
|
48
|
+
Alternatively, if using a true MySQL image:
|
|
29
49
|
|
|
30
|
-
|
|
50
|
+
```bash
|
|
51
|
+
cat ./source/model/mysql_create/MeadowModel-CreateMySQLDatabase.mysql.sql \
|
|
52
|
+
| docker exec -i mariadb mysql -u root -p123456789 bookstore
|
|
53
|
+
```
|
|
31
54
|
|
|
32
|
-
|
|
55
|
+
## Architecture
|
|
33
56
|
|
|
34
57
|
```
|
|
35
|
-
|
|
58
|
+
Retold Harness
|
|
59
|
+
├── Retold Data Service
|
|
60
|
+
│ ├── Orator + Restify (HTTP Server, port 8086)
|
|
61
|
+
│ ├── Meadow (DAL for each entity)
|
|
62
|
+
│ │ └── Provider (MySQL / SQLite)
|
|
63
|
+
│ └── Meadow Endpoints (REST Routes)
|
|
64
|
+
│ └── Behavior Injection (Author enrichment)
|
|
65
|
+
├── Data Model (8 entities from Stricture DDL)
|
|
66
|
+
└── Docker Environment
|
|
67
|
+
├── MariaDB (pre-loaded bookstore database)
|
|
68
|
+
└── Luxury Code (browser VS Code, port 20001)
|
|
36
69
|
```
|
|
37
70
|
|
|
38
|
-
|
|
71
|
+
## REST API Examples
|
|
39
72
|
|
|
40
|
-
|
|
73
|
+
### List the first 100 books: `http://localhost:8086/1.0/Books/0/100`
|
|
41
74
|
|
|
75
|
+

|
|
42
76
|
|
|
43
|
-
|
|
77
|
+
### Get a single book with authors: `http://localhost:8086/1.0/Book/1`
|
|
44
78
|
|
|
45
|
-
|
|
46
|
-
* a browser-based visual studio code environment ready to run node applications
|
|
47
|
-
* a mariadb instance, preloaded with 10,000 Book records joined to their Author records
|
|
48
|
-
* a partridge
|
|
49
|
-
* a pear tree
|
|
79
|
+
When fetching a single book, the response includes an `Authors` array populated via the behavior injection hook in `source/Retold-Harness.js`. In the multi-record list, the array is not included because the hook is only on the singular Read endpoint.
|
|
50
80
|
|
|
51
|
-
|
|
81
|
+

|
|
52
82
|
|
|
53
|
-
|
|
83
|
+
### Filter authors by name: `http://localhost:8086/1.0/Authors/FilteredTo/FBV~Name~LK~Susan%25/0/10`
|
|
54
84
|
|
|
55
|
-
|
|
85
|
+

|
|
56
86
|
|
|
57
|
-
|
|
87
|
+
### Count books by genre
|
|
58
88
|
|
|
59
|
-
|
|
89
|
+
```
|
|
90
|
+
GET http://localhost:8086/1.0/Books/Count/FilteredTo/FBV~Genre~EQ~Science Fiction
|
|
91
|
+
```
|
|
60
92
|
|
|
61
|
-
|
|
62
|
-
### Get the book with `IDBook` 1: (http://localhost:8086/1.0/Book/1)
|
|
93
|
+
## Data Model
|
|
63
94
|
|
|
64
|
-
|
|
95
|
+
| Entity | Columns | Description |
|
|
96
|
+
|--------|---------|-------------|
|
|
97
|
+
| User | 8 | System user accounts |
|
|
98
|
+
| Book | 16 | Books with title, genre, ISBN, language, cover image |
|
|
99
|
+
| Author | 11 | Authors with name and optional user link |
|
|
100
|
+
| BookAuthorJoin | 4 | Many-to-many join between Books and Authors |
|
|
101
|
+
| BookPrice | 15 | Pricing periods with discount and coupon support |
|
|
102
|
+
| BookStore | 15 | Physical store locations with address |
|
|
103
|
+
| BookStoreInventory | 16 | Stock levels per book per store |
|
|
104
|
+
| Review | 13 | User reviews with text and rating |
|
|
65
105
|
|
|
66
|
-
|
|
106
|
+
## Docker Services
|
|
67
107
|
|
|
68
|
-
|
|
108
|
+
| Port | Service |
|
|
109
|
+
|------|---------|
|
|
110
|
+
| 8086 | REST API |
|
|
111
|
+
| 31306 | MariaDB (mapped from 3306) |
|
|
112
|
+
| 20001 | Luxury Code (VS Code in browser) |
|
|
69
113
|
|
|
70
|
-
|
|
114
|
+
### Database Credentials
|
|
115
|
+
|
|
116
|
+
| Setting | Value |
|
|
117
|
+
|---------|-------|
|
|
118
|
+
| User | `root` |
|
|
119
|
+
| Password | `123456789` |
|
|
120
|
+
| Database | `bookstore` |
|
|
71
121
|
|
|
72
122
|
## Luxury Code
|
|
73
123
|
|
|
74
|
-
Luxury
|
|
124
|
+
Luxury Code provides a browser-based VS Code environment inside the Docker container. Open `http://localhost:20001` after launching the container. Password: `luxury`
|
|
75
125
|
|
|
76
126
|

|
|
77
127
|
|
|
@@ -79,12 +129,54 @@ Luxury code is a set of tools to provide easy debugging and test running regardl
|
|
|
79
129
|
|
|
80
130
|
## MySQL
|
|
81
131
|
|
|
82
|
-
The
|
|
132
|
+
The Docker image exposes a MariaDB server. Connect with your tool of choice using the credentials above.
|
|
83
133
|
|
|
84
134
|

|
|
85
135
|
|
|
86
136
|

|
|
87
137
|
|
|
88
|
-
##
|
|
138
|
+
## Source Code
|
|
139
|
+
|
|
140
|
+
The harness is intentionally minimal:
|
|
141
|
+
|
|
142
|
+
- `source/Retold-Harness.js` (47 lines) -- Initializes Fable, creates the data service, installs the Author enrichment hook
|
|
143
|
+
- `source/configuration-bookstore-serve-api.js` (41 lines) -- Configuration with MySQL connection details and server port
|
|
144
|
+
- `source/model/` -- Compiled Stricture model, DDL source, SQL scripts, and sample data
|
|
145
|
+
|
|
146
|
+
## Building the Model
|
|
147
|
+
|
|
148
|
+
To recompile the DDL after schema changes:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
npm run build-model
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Testing
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npm test
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The test suite contains 90 tests covering all 8 entities, behavior injection, DAL access, filtering, pagination, and soft deletes. Tests use in-memory SQLite and require no external database.
|
|
161
|
+
|
|
162
|
+
## Documentation
|
|
163
|
+
|
|
164
|
+
Detailed documentation is available in the `docs/` folder and can be served locally:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
npx docsify-cli serve docs
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Customizing
|
|
171
|
+
|
|
172
|
+
All ports, passwords, and configuration are in `source/configuration-bookstore-serve-api.js` and `package.json`. Docker port mappings are in the npm scripts.
|
|
173
|
+
|
|
174
|
+
## Related Packages
|
|
89
175
|
|
|
90
|
-
|
|
176
|
+
- [retold-data-service](https://github.com/stevenvelozo/retold-data-service) - All-in-one data service
|
|
177
|
+
- [meadow](https://github.com/stevenvelozo/meadow) - Data access layer and ORM
|
|
178
|
+
- [meadow-endpoints](https://github.com/stevenvelozo/meadow-endpoints) - Automatic REST endpoint generation
|
|
179
|
+
- [foxhound](https://github.com/stevenvelozo/foxhound) - Query DSL for SQL generation
|
|
180
|
+
- [stricture](https://github.com/stevenvelozo/stricture) - Schema definition language
|
|
181
|
+
- [orator](https://github.com/stevenvelozo/orator) - API server abstraction
|
|
182
|
+
- [fable](https://github.com/stevenvelozo/fable) - Service provider framework
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
# This script will:
|
|
5
|
+
# 1. Start MariaDB (via the official entrypoint) in the background
|
|
6
|
+
# 2. Wait until MariaDB is ready
|
|
7
|
+
# 3. Start the Node app using pm2-runtime
|
|
8
|
+
|
|
9
|
+
# If first argument looks like an option, assume it's for mysqld (same behavior as official entrypoint)
|
|
10
|
+
if [ "${1:0:1}" = '-' ]; then
|
|
11
|
+
set -- mysqld "$@"
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
# Start MariaDB using the original entrypoint in the background
|
|
15
|
+
# The official MariaDB image's entrypoint is still at this path
|
|
16
|
+
/usr/local/bin/docker-entrypoint.sh mysqld "$@" &
|
|
17
|
+
|
|
18
|
+
# Wait for MariaDB to be ready
|
|
19
|
+
echo "Waiting for MariaDB to be ready..."
|
|
20
|
+
until mariadb-admin ping -h "127.0.0.1" --silent; do
|
|
21
|
+
sleep 1
|
|
22
|
+
done
|
|
23
|
+
echo "MariaDB is up."
|
|
24
|
+
|
|
25
|
+
# Load nvm and use Node 22
|
|
26
|
+
export NVM_DIR=/usr/local/nvm
|
|
27
|
+
# shellcheck disable=SC1091
|
|
28
|
+
. "$NVM_DIR/nvm.sh"
|
|
29
|
+
|
|
30
|
+
# Move to app directory
|
|
31
|
+
cd /usr/src/app
|
|
32
|
+
|
|
33
|
+
echo "Starting Node app with pm2-runtime..."
|
|
34
|
+
# pm2-runtime keeps the process in the foreground (PID 1) for Docker
|
|
35
|
+
exec pm2-runtime ecosystem.config.js
|
package/docs/.nojekyll
ADDED
|
File without changes
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Retold Harness
|
|
2
|
+
|
|
3
|
+
A self-contained REST API harness for the [Retold](https://github.com/stevenvelozo/retold) framework. It serves a complete bookstore data model with auto-generated CRUD endpoints, pre-loaded sample data, and a containerized development environment.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
Retold Harness brings together several Retold modules into a running application:
|
|
8
|
+
|
|
9
|
+
- **[Retold Data Service](https://github.com/stevenvelozo/retold-data-service)** orchestrates the stack
|
|
10
|
+
- **[Meadow](https://github.com/stevenvelozo/meadow)** provides the data access layer
|
|
11
|
+
- **[Meadow Endpoints](https://github.com/stevenvelozo/meadow-endpoints)** generates REST routes
|
|
12
|
+
- **[Orator](https://github.com/stevenvelozo/orator)** serves the HTTP API
|
|
13
|
+
- **[Stricture](https://github.com/stevenvelozo/stricture)** defines the schema
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- **8-Entity Bookstore Model** -- Users, Books, Authors, Joins, Prices, Stores, Inventory, and Reviews
|
|
18
|
+
- **Auto-Generated CRUD** -- Every entity gets Create, Read, Reads, Update, Delete, Count, Schema, and New endpoints
|
|
19
|
+
- **Author Enrichment** -- Single Book reads are enriched with related Author data via behavior injection
|
|
20
|
+
- **Pre-Loaded Data** -- 10,000+ book records with associated authors for realistic testing
|
|
21
|
+
- **Docker Containerized** -- MariaDB database and API server in a single container
|
|
22
|
+
- **Luxury Code IDE** -- Browser-based VS Code for in-container development
|
|
23
|
+
|
|
24
|
+
## Architecture
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
Retold Harness
|
|
28
|
+
├── Retold Data Service
|
|
29
|
+
│ ├── Orator + Restify (HTTP Server, port 8086)
|
|
30
|
+
│ ├── Meadow (DAL for each entity)
|
|
31
|
+
│ │ └── Provider (MySQL / SQLite)
|
|
32
|
+
│ └── Meadow Endpoints (REST Routes)
|
|
33
|
+
│ └── Behavior Injection (Author enrichment)
|
|
34
|
+
├── Data Model (8 entities from Stricture DDL)
|
|
35
|
+
└── Docker Environment
|
|
36
|
+
├── MariaDB (pre-loaded bookstore database)
|
|
37
|
+
└── Luxury Code (browser VS Code, port 20001)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Related Packages
|
|
41
|
+
|
|
42
|
+
- [retold-data-service](https://github.com/stevenvelozo/retold-data-service) -- All-in-one data service
|
|
43
|
+
- [meadow](https://github.com/stevenvelozo/meadow) -- Data access layer
|
|
44
|
+
- [meadow-endpoints](https://github.com/stevenvelozo/meadow-endpoints) -- REST endpoint generation
|
|
45
|
+
- [foxhound](https://github.com/stevenvelozo/foxhound) -- Query DSL
|
|
46
|
+
- [stricture](https://github.com/stevenvelozo/stricture) -- Schema definition language
|
|
47
|
+
- [orator](https://github.com/stevenvelozo/orator) -- API server abstraction
|
|
48
|
+
- [fable](https://github.com/stevenvelozo/fable) -- Service provider framework
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Retold Harness <small>1.0</small>
|
|
2
|
+
|
|
3
|
+
> A self-contained REST API harness for the Retold framework
|
|
4
|
+
|
|
5
|
+
- Fully containerized bookstore REST API
|
|
6
|
+
- 8 entities with 10,000+ pre-loaded records
|
|
7
|
+
- Author enrichment via behavior injection
|
|
8
|
+
- Browser-based VS Code development environment
|
|
9
|
+
|
|
10
|
+
[Getting Started](#retold-harness)
|
|
11
|
+
[GitHub](https://github.com/stevenvelozo/retold-harness)
|
package/docs/_sidebar.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
- Getting Started
|
|
2
|
+
- [Overview](/)
|
|
3
|
+
- [Quick Start](quickstart.md)
|
|
4
|
+
- [Docker Setup](docker.md)
|
|
5
|
+
|
|
6
|
+
- Data Model
|
|
7
|
+
- [Schema Overview](schema.md)
|
|
8
|
+
- [Entity Reference](entities.md)
|
|
9
|
+
|
|
10
|
+
- API
|
|
11
|
+
- [REST Endpoints](endpoints.md)
|
|
12
|
+
- [Filtering & Pagination](filtering.md)
|
|
13
|
+
|
|
14
|
+
- Customization
|
|
15
|
+
- [Behavior Injection](behavior-injection.md)
|
|
16
|
+
- [Configuration](configuration.md)
|
|
17
|
+
|
|
18
|
+
- Development
|
|
19
|
+
- [Testing](testing.md)
|
|
20
|
+
- [Luxury Code IDE](luxury-code.md)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Behavior Injection
|
|
2
|
+
|
|
3
|
+
The harness demonstrates behavior injection by enriching single Book reads with Author data. This is the core customization pattern for Meadow Endpoints.
|
|
4
|
+
|
|
5
|
+
## How It Works
|
|
6
|
+
|
|
7
|
+
In `source/Retold-Harness.js`, a `Read-PostOperation` hook is installed on the Book endpoint after initialization:
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
_Fable.MeadowEndpoints.Book.controller.BehaviorInjection.setBehavior('Read-PostOperation',
|
|
11
|
+
(pRequest, pRequestState, fRequestComplete) =>
|
|
12
|
+
{
|
|
13
|
+
// 1. Find join records for this book
|
|
14
|
+
_Fable.DAL.BookAuthorJoin.doReads(
|
|
15
|
+
_Fable.DAL.BookAuthorJoin.query.addFilter('IDBook', pRequestState.Record.IDBook),
|
|
16
|
+
(pJoinError, pJoinQuery, pJoinRecords) =>
|
|
17
|
+
{
|
|
18
|
+
// 2. Collect author IDs from the join records
|
|
19
|
+
let tmpAuthorList = pJoinRecords.map(j => j.IDAuthor);
|
|
20
|
+
|
|
21
|
+
if (tmpAuthorList.length < 1)
|
|
22
|
+
{
|
|
23
|
+
pRequestState.Record.Authors = [];
|
|
24
|
+
return fRequestComplete();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 3. Load the actual Author records
|
|
28
|
+
_Fable.DAL.Author.doReads(
|
|
29
|
+
_Fable.DAL.Author.query.addFilter('IDAuthor', tmpAuthorList, 'IN'),
|
|
30
|
+
(pError, pQuery, pAuthors) =>
|
|
31
|
+
{
|
|
32
|
+
// 4. Attach to the response record
|
|
33
|
+
pRequestState.Record.Authors = pAuthors;
|
|
34
|
+
return fRequestComplete();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Result
|
|
41
|
+
|
|
42
|
+
When you fetch a single book:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
GET /1.0/Book/1
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The response includes an `Authors` array:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"IDBook": 1,
|
|
53
|
+
"Title": "Dune",
|
|
54
|
+
"Genre": "Science Fiction",
|
|
55
|
+
"Authors": [
|
|
56
|
+
{
|
|
57
|
+
"IDAuthor": 42,
|
|
58
|
+
"Name": "Frank Herbert"
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
When you fetch multiple books (`/1.0/Books/0/10`), the Authors array is **not** included because the hook is only on the singular Read, not the plural Reads.
|
|
65
|
+
|
|
66
|
+
## Available Hook Points
|
|
67
|
+
|
|
68
|
+
Each entity supports pre- and post-operation hooks:
|
|
69
|
+
|
|
70
|
+
| Hook | When |
|
|
71
|
+
|------|------|
|
|
72
|
+
| `Create-PreOperation` | Before a record is created |
|
|
73
|
+
| `Create-PostOperation` | After a record is created |
|
|
74
|
+
| `Read-PreOperation` | Before a single record read |
|
|
75
|
+
| `Read-PostOperation` | After a single record read |
|
|
76
|
+
| `Reads-PreOperation` | Before a multi-record read |
|
|
77
|
+
| `Reads-PostOperation` | After a multi-record read |
|
|
78
|
+
| `Update-PreOperation` | Before a record is updated |
|
|
79
|
+
| `Update-PostOperation` | After a record is updated |
|
|
80
|
+
| `Delete-PreOperation` | Before a record is deleted |
|
|
81
|
+
| `Delete-PostOperation` | After a record is deleted |
|
|
82
|
+
| `Count-PreOperation` | Before a count query |
|
|
83
|
+
| `Count-PostOperation` | After a count query |
|
|
84
|
+
|
|
85
|
+
## Accessing Request State
|
|
86
|
+
|
|
87
|
+
The callback receives three arguments:
|
|
88
|
+
|
|
89
|
+
| Argument | Description |
|
|
90
|
+
|----------|-------------|
|
|
91
|
+
| `pRequest` | The HTTP request object |
|
|
92
|
+
| `pRequestState` | Contains `Record`, `RecordToCreate`, `Query`, `SessionData` |
|
|
93
|
+
| `fRequestComplete` | Callback: pass `false` to continue, `true` to signal an error |
|
|
94
|
+
|
|
95
|
+
## Removing a Behavior
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
delete _Fable.MeadowEndpoints.Book.controller
|
|
99
|
+
.BehaviorInjection._BehaviorFunctions['Read-PostOperation'];
|
|
100
|
+
```
|