Demo todo list app in Node.JS and React
|
1 год назад | |
---|---|---|
src | 1 год назад | |
web | 1 год назад | |
.dockerignore | 1 год назад | |
.eslintignore | 1 год назад | |
.eslintrc.cjs | 1 год назад | |
.gitignore | 1 год назад | |
Dockerfile | 1 год назад | |
LICENSE.md | 1 год назад | |
README.md | 1 год назад | |
docker-compose.herda.yml | 1 год назад | |
docker-compose.yml | 1 год назад | |
package-lock.json | 1 год назад | |
package.json | 1 год назад | |
tsconfig.json | 1 год назад |
Keep on top of it all with Herda :cow2:
If you prefer not to use Docker, you can set up MongoDB Community Server v7 manually. This documentation targets a Docker-based workflow and you will need to make any adjustments yourself.
:warning: This software is untested with other versions of MongoDB!
If you are planning to develop Herda, it is recommended to use nvm to help ensure you are running the correct version of Node.
Getting started developing Herda is simple, as both apps use development-friendly default configuration, with one exception: you are advised to set a static JWT secret. (If you don't, one will be generated randomly when the server starts up that can be used for a demo, but it won't persist through a restart.)
Run the following snippet to generate a static secret:
echo 'console.log(require("crypto").randomBytes(64).toString("hex"))' |\
node - |\
xargs -I{} echo "AUTH_JWT_SECRET={}" >> .env
You are now ready to start up services. First, start MongoDB:
docker compose up -d
After MongoDB has started and initialized, install and start the server:
# Install dependencies
npm install
# Start the server app
npm run dev
Open http://localhost:5001/api in your browser. If you receive a JSON response including "Herda Server" and a version number, then it's up and running.
To run the PWA, open a separate terminal in the web directory and run similar setup commands:
# Install dependencies
npm install
# Start the PWA
npm run dev
Open the URL shown in the terminal - most likely http://localhost:5173. If you see a login page, and the version number you saw in the API response earlier is displayed in the bottom left corner, then everything is connected up and you're all set.
:information_source: Both the server and PWA reload automatically when their source code is changed, so there's no need to manually stop and restart them unless you change a dependency.
When you are finished working on Herda and want to teardown the work environment, exit the npm processes (Ctrl-C or Cmd-C) and run docker compose stop
to exit MongoDB.
An alternative approach to running Herda is to build a Docker image which runs both the headless API and frontend statically. This is primarily intended for production use. The Dockerfile handles building the app into a distributable image, and you just need to configure its environment.
An additional Compose file is provided to help test the Docker image locally. You will need to set up a static JWT secret and the MongoDB connection string. Run the following to get going:
# Generate static JWT secret
echo 'console.log(require("crypto").randomBytes(64).toString("hex"))' |\
node - |\
xargs -I{} echo "AUTH_JWT_SECRET={}" >> .docker.env
# Set MongoDB connection string
echo 'MONGO_URI=mongodb://root:root@mongo:27017' >> .docker.env
Once .docker.env is in place, run the following command to automatically build and start services:
docker compose -f docker-compose.herda.yml -f docker-compose.yml up -d
After Docker finishes this process, open http://localhost:5001 in your browser. You should see a login page with the app version in the bottom left corner.
When you are finished testing Herda and want to teardown the test environment, run the opposite command to stop services:
docker compose -f docker-compose.herda.yml -f docker-compose.yml stop
:information_source: All Docker Compose actions, including rebuilding the Herda image, should continue to use both Compose files. They are automatically merged by Docker to create a complete environment.
Both the server app and PWA are configured using environment variables. These can be set in .env and web/.env respectively.
For complete configuration references, refer to:
process.env.*
in src/index.tsimport.meta.env.VITE_*
in web/src/build.ts:information_source: In development, both apps load configuration at startup (and in the case of the PWA, configuration is also hot reloaded).
When they are built, such as to a Docker image, this becomes slightly different. The server app still loads configuration at startup, but the PWA is configured at build time and cannot be reconfigured afterwards.
Accordingly, when building the PWA or Docker image, ensure the PWA is correctly configured as it cannot be changed afterwards.
:information_source: This section provides more detail for contributors interested in the internal workings of the Herda apps. If you do not need that much detail, you can safely stop reading here.
Herda, as a project, comes in three parts:
The PWA connects to the server, which in turn connects to the database.
The server app is built in Node.js with TypeScript and has minimal dependencies. Its root directory is the repository root, and most of its source code is located in src. Its 'global' code is located there, and subdirectories represent modules following a conventional structure. This section mostly focuses on how the server code is organised.
The PWA is built in React with TypeScript and uses Vite for development and build tooling. Its root directory is web and most of its source code is located in the corresponding src directory. Unlike the server app, this does not use a strong modular structure owing to its comparative simplicity. This may change in the future with expansion of scope.
The server app builds a 'context object' in its main function and then passes this down (usually by reference) to other code locations while constructing the app. This supports and encourages a functional, often stateless approach to adding new code. Where there is state, this is usually in the form of currying, where a new function is built using context objects or data.
The full context type is summarised in src/types.ts.
The server includes a simple logger which can be configured to provide more or less detail, depending on your needs. For development you may want to use debug
or even trace
level, whereas in production you most likely only need to see warn
and error
messages.
The logger context is put together in src/log.ts.
The server connects to MongoDB using the standard MongoClient. Data management proper typically goes through models that provide database initialization, common procedures, and where appropriate direct access to MongoDB collections.
Each module includes a model.ts file encapsulating relevant database functionality. For example, src/account/model.ts includes functions for creating and updating accounts with expanded support for password changes, amongst others.
The database context is created in src/db.ts.
Each module includes an api.ts file which exports functions reflecting REST procedures. For example, src/account/api.ts describes APIs for managing and accessing accounts.
The headless (RESTful) API is put together in src/http.ts.
On the client side, the best reference for the headless server API is in the API client library. This is maintained as part of the PWA in web/src/api.
Authentication uses JSON Web Tokens (JWT). This is expressed within the server as an authentication context in src/auth.ts, which is mainly used by API middleware and some account APIs.
Refer to the API client library for client-side usage. In terms of the PWA proper, authentication is managed via the useSession hook (using SessionContext) and verified by the Authenticated component.
See LICENSE.md