@marianmeres/jay
v1.7.0
Published
The naive, the json, the CMS
Downloads
4
Readme
@marianmeres/jay
The Naive, the JSON, the CMS.
What is Jay?
Before we start, quick vocabulary context definition:
- model - data structure described by schema (in the DB context a table structure),
- entity - type of the model (in the DB context a table name). May be used interchangeably with the term "document type",
- document - concrete "instance" of the model, persisted as a physical json file (in the DB context a row),
- data - somewhat vague, but mostly means some or all documents,
- collection - list of document instances (in the DB context a set of rows),
- asset - a special case model, having both
data
(in whatever structure described by schema) and a physical raw representation as a file saved on disk, named by it's content hash.
All three words model
, entity
and document
may and probably will be used inaccurately, but are roughly describing the same thing.
The "no DB" CMS
Jay is a generic CMS server -- it provides a REST interface for managing and serving any documents and assets. It features a basic CRUD authentication system and allows the access rights and document schemas to be defined using YAML definition files (regular JSON schemas under the hood), ensuring proper validation. These same YAML files can also define some props for the frontend admin UI.
A single Jay server instance can support multiple isolated projects, each independently configurable with ease.
Notably, Jay operates without the need for a traditional database.
The JSON
Jay is a json files writer -- all documents are serialized to the filesystem as well-formatted json files. Every document json file can be safely edited by hand if needed. It should also be noted, that the raw json files are not statically served but are always processed (to be able to respect schema and more...).
Additionally, asset source files are efficiently stored in a separate configured directory. Images are treated with special care out of the box.
The Naive
Jay is an honest yet a bit naive servant -- it maintains all documents in memory, with serialization to disk occurring only during write operations. This design choice results in high performance but limits scalability.
For managing a vast number of documents, or the need to spawn multiple server instances across multiple nodes, alternative solutions should be considered.
What is the use case?
When you may not have access to a DB on the server but still need to reliably read/write some data... When you may want to bundle (and to version) your schemas and data in a git repo instead of worrying about DB backups and SQL migrations...
When you simply need a tiny and easy-to-configure, yet still reliable REST API with GUI for whatever data driven needs.
The admin GUI
Jay comes bundled with it's brother Joy -- a modern admin GUI, mounted on the /admin/
path by default. This GUI is an ongoing work-in-progress (currently in an alpha stage) and is not open source.
Installation (quick start)
git clone https://github.com/marianmeres/jay.git
cd jay
npm install
cp projects.config.example.json projects.config.json
vim projects.config.json
(can be skipped if you want to play with the demo only)cp .env.example .env
vim .env
(optional if you're OK with the defaults)npm run start
- open
http://localhost:6100/admin/
in your browser, add the default server and click on the "Demo project". Use[email protected]
andthis-user-should-be-deleted
as credentials.
Creating a new project (todo: improve docs)
This is a little bumpy for now... The detailed explanation on how to prepare the schema files will be added later.
- Create 2 directories anywhere on your system. Make sure they are writable. For example:
/home/foo/projects/bar/data/
, and/home/foo/projects/bar/public/uploads/
(it is currently required that the last segment is "uploads")
- Edit
projects.config.json
and add a new project:
[
// ...,
{
"id": "my-project",
"name": "My Project",
"dataDir": "/home/foo/projects/bar/data/",
"publicDir": "/home/foo/projects/bar/public/"
// note, that we're not adding the "uploads" segment above
}
]
Create any yaml definition files describing your models. Name of the yaml file will be the name of your entity. There are few entity names which are recognized by the system as a special cases (currently
_user
and_asset
). For now, look into the_cms-data-demo
folder for inspiration. At very minimum, copy the_user.yaml
and_user/[whatever-the-id-is].json
to your new project's data dir. Edit the user json file by hand to fit your needs, mainly the__password
key with some bcrypt value. You may usenpm run pswhash [your-password]
as a helper here.Now, restart the server and refresh your admin GUI browser window to reload project configuration and select "My Project" from the projects list and you should be good to go.
The REST endpoints (todo: improve docs)
Main collection and model endpoints. Whether they require HTTP authorized requests depends on the schema configuration.
/{PROJECT_ID}/api/_cms/{ENTITY}
(limit
andoffset
query params are supported)/{PROJECT_ID}/api/_cms/{ENTITY}/{DOCUMENT_ID}
Auth endpoint:
/{PROJECT_ID}/api/auth
Other miscellaneous. You must use the HTTP baerer auth header (token can be acquired from the auth endpoint above):
/{PROJECT_ID}/api/schema.json
/{PROJECT_ID}/api/upload
/{PROJECT_ID}/api/dump
/{PROJECT_ID}/api/readme
/{PROJECT_ID}/api/__refresh__
Naming convention magic
There are few document props naming conventions which expose some handy features.
_startsWithUnderscore
prop name is considered as a read-only and the REST endpoint will NEVER allow it to be overwritten by user-land data. Some of such props are also built-in into every document (_created_at
,_updated_at
,_owner
).__startsWithDoubleUnderscore
prop name is considered as a hidden and will NEVER leave the server and will NEVER be overwritten by user-land data. Those props are simply filtered out for both incoming requests and outgoing responses. Typical example is a__password
field of the_user
model (leaving aside, that the actual__password
value is a bcrypt hash, so even exposing it should not cause any harm).
Note that you can always edit the fields by hand in the actual json files (server restart is required for those changes to take effect).
What does the word "Jay" means?
I had to ask our LLM friend. This is the answer.
The word "jay" has several meanings depending on the context:
Bird: A "jay" is a type of bird known for its vibrant plumage and loud calls. Jays belong to the family Corvidae, which also includes crows and magpies.
Slang Term: In North American slang, particularly in the past, a "jay" referred to an unsophisticated or naive person, often someone from a rural area who is unfamiliar with urban ways.
Letter J: In some contexts, "jay" simply refers to the letter "J" in the English alphabet.
Traffic Violation: The term "jaywalking" is derived from this word, referring to the act of crossing the street illegally or recklessly, often not at a designated crosswalk.