@wawjs/waw-sem
v26.0.1
Published
**waw-sem** is the server engine module for the waw platform. It wires together an Express HTTP server, optional MongoDB connection + session middleware, Socket.IO transport, and a convention-driven CRUD generator. Sem exposes its runtime API through the
Readme
waw-sem
waw-sem is the server engine module for the waw platform. It wires together an Express HTTP server, optional MongoDB connection + session middleware, Socket.IO transport, and a convention-driven CRUD generator. Sem exposes its runtime API through the shared waw context so other modules can contribute backend behavior by adding *.collection.js, *.api.js, and/or module.crud configuration.
🤖 AI agents: read
AI_INSTRUCTIONS.mdfirst — it is the agent-oriented working guide for this module (conventions to follow, how to extend it, and gotchas to avoid). This README is the human reference.
What Sem Does at Runtime
When index.js runs, it performs these steps in order:
- Initializes Express + HTTP server, base middleware, and auth helpers (
util.express) - Initializes MongoDB + the rotating session middleware (
util.mongo) —awaited- Builds
waw.mongoUrland connects Mongoose ifwaw.config.mongois configured - Always installs the store-backed
express-sessionmiddleware (store only when connected)
- Builds
- Initializes Socket.IO (
util.socket) - Initializes the CRUD engine (
util.crud) - Loads every module file ending with
collection.js(in module order),await require(file)(waw) - Loads every module file ending with
api.js(in module order),await require(file)(waw) - Calls
waw.crud.finalize()to register CRUD endpoints from module configs - Registers a global Express error-handling middleware that logs the error and responds
500withwaw.resp(false) - Registers a
process.on('unhandledRejection')safety-net handler - Starts listening on
waw.config.port(defaults to8080)
Exposed API on waw
Express / HTTP
util.express.js creates and exposes:
waw.app— Express appwaw.server— Node HTTP server created from the Express appwaw.express— Express exportwaw.cors— thecorspackage export (for use by other modules)waw.router(basePath)— mounts an Express Router atbasePathand returns it
Built-in routes / middleware (installed in this order):
- Optional favicon if
waw.config.iconpoints to an existing file - CORS preflight:
app.options(/.*/, cors()) app.set('trust proxy', 1)- An initial
express-session(secretwaw.config.sessionSecretor'Web Art Work Secret'; cookiehttpOnly,sameSite: 'none',secure: true). A second, store-backed session is installed later byutil.mongo(see below). cookie-parsermethod-override("X-HTTP-Method-Override")express.json({ limit: '10mb' })express.urlencoded({ extended: true, limit: '10mb' })GET /status— returns HTTP 200 withtrue
Auth helpers:
waw.ensure(req,res,next)— requiresreq.useror responds withwaw.resp(false)waw.role(roles, middleware?)— role gating based onreq.user.is[role], responds401withfalseon failurewaw.nextandwaw.blockconvenience helpers
Note:
util.expressdefineswaw.resp = (body) => bodyas a minimal default; CRUD useswaw.resp(...)when sending JSON responses.
MongoDB + Sessions
util.mongo.js sets:
waw.mongoose— Mongoose instancewaw.mongoUrl— resolved Mongo connection string when Mongo is configuredwaw.mongoConnected— boolean reflecting whether the connection succeededwaw.store— Connect-Mongo session store, set only when the connection succeeds (otherwiseundefined)
Mongo configuration behavior:
- If
waw.config.mongois a string, it is treated as the full Mongo URI. - If it has a
urifield, that is used directly. - Otherwise Sem builds a URI from keys such as
srv(choosesmongodb+srv://),host/hosts,port,user/pass(URL-encoded),db(defaulttest), and optional query options (via anoptionsobject or top-level fields likereplicaSet,authSource,readPreference,retryWrites,w,directConnection,tls/ssl). mongoose.set('bufferCommands', false)is applied. If a URL exists and Mongoose is not already connected, Sem connects withserverSelectionTimeoutMS: 5000and logsconnected/error/disconnectedevents. If the connection fails, the server keeps running without MongoDB — Mongo-dependent features will then error.
Sessions behavior (the store-backed session installed by util.mongo, in addition to the initial one from util.express):
- Installs
express-sessionwithrolling: trueand the Connect-Mongostore(when connected). - Cookie
maxAgedefaults to one year unlesswaw.config.sessionis a number (interpreted as milliseconds). - Cookie
domainuseswaw.config.domainwhen provided. - Session name is
express.sid.<prefix>where<prefix>iswaw.config.prefixor empty. - Secret rotation is maintained in the project’s
server.json(waw.configServerPath) undersecretKeysas an array of{ key, createdAt }; the full list is passed as the sessionsecretarray.- A new 32-byte hex secret is generated if there is no secret or the newest is older than one week.
- Up to 5 recent secrets are kept to allow rotation without invalidating existing sessions.
Socket.IO
util.socket.js creates a Socket.IO server on waw.server and exposes:
waw.socket.io— Socket.IO server instancewaw.socket.emit(event, payload, room?)— emits globally or to a roomwaw.socket.add(fn)— adds a connection handler(socket) => { ... }
Defaults:
- CORS allows any origin (
origin: "*") - Transports:
websocketandpolling - On connection, a default handler forwards
create,update,unique,deleteevents to all other clients viasocket.broadcast.emit(...).
CRUD Engine
util.crud.js provides:
waw.crud.config(part, config)— registers hooks and rules for CRUD actions into thewawobject under predictable nameswaw.crud.register(crud, part, unique = true)— mounts endpoints under/api/<crudName>and wires hookswaw.crud.finalize()— scanswaw.modules[*].crudand registers CRUD endpoints for each configured resource
Endpoint set
For each CRUD resource named <crudName>, Sem mounts routes under /api/<crudName>. Which routes are mounted depends on the resource config:
/create(POST) — always/get...(GET; supports named variants) —getdefaults to a single unnamed/getwhen not configured/fetch...(POST; supports named variants) —fetchdefaults to a single unnamed/fetch/update...(POST; supports named variants) — only whencrud.updateis an object/array; each entry lists thekeysit may modify/unique...(POST; supports named variants) — only whencrud.uniqueis an object/array/delete...(POST; supports named variants) — only whencrud.deleteis set
Default queries scope reads/writes by moderators: req.user._id (and author for delete). create, update, and delete broadcast a socket event via waw.emit('<crudName>_create' | '_update' | '_delete', doc).
Hook wiring
waw.crud.config(part, config) reads per-action config objects and stores behavior on waw using names like:
required_<action>_<part>[_<name>](array of required body fields)ensure_<action>_<part>[_<name>](custom ensure middleware)query_<action>_<part>[_<name>]sort_<action>_<part>[_<name>],skip_...,limit_...select_...,populate_...
At request time, Sem uses these to validate required fields, authorize access, and modify query behavior.
Models / schema resolution
When registering a resource, Sem resolves a Mongoose model as:
waw.<CrudCapitalName>if already present onwaw, otherwiserequire(<moduleRoot>/schema.js)(orschema_<crudName>.jswhenunique=false)
If the required schema export is a function without a name, it is invoked as Schema(waw). If the schema file cannot be found (MODULE_NOT_FOUND), the resource is logged and skipped rather than crashing the server.
A default schema is shipped at schema.js (name, description, author, moderators, url, plus a create(obj, user, waw) method) and uses the CNAME model-name token.
Convention-based Module Wiring
Sem loads files from all modules based on filename suffix:
*.collection.js— loaded first (intended for model/schema registration)*.api.js— loaded second (intended for mounting routes/endpoints)
Each such file is required and invoked as await require(file)(waw).
CLI
Sem exposes a module scaffolding command via server/sem/cli.js:
waw add <module>/waw a <module>— creates a module under the project modules directory using the Sem template (server/sem/module/default/scaffold.js)
Module Manifest
Sem is defined by server/sem/module.json:
after: "core"andbefore: "*"to ensure it runs after core but before other modules by default- Installs dependencies:
cors,express,express-session,mongoose,connect-mongo,formidable,method-override,serve-favicon,cookie-parser,socket.io, andmarked
License
MIT © Web Art Work
