@x12i/static-memorix-explorer-api 1.1.0 → 1.1.1
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/README.md +48 -5
- package/dist/config.js +1 -1
- package/dist/server.js +35 -18
- package/guides/demo-app.md +6 -6
- package/guides/running-the-service.md +39 -4
- package/guides/using-the-api.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,20 +13,57 @@ See [guides/demo-app.md](./guides/demo-app.md) for the full walkthrough.
|
|
|
13
13
|
```bash
|
|
14
14
|
npm install
|
|
15
15
|
npm run build
|
|
16
|
-
npm start # listens on :
|
|
16
|
+
npm start # listens on :5030 (PORT / HOST / MOCKS_DIR env-overridable)
|
|
17
17
|
# dev (no build): npm run dev
|
|
18
18
|
|
|
19
19
|
# open the demo UI in your browser
|
|
20
|
-
open http://localhost:
|
|
20
|
+
open http://localhost:5030/demo
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
Health:
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
curl localhost:
|
|
27
|
-
curl "localhost:
|
|
26
|
+
curl localhost:5030/health
|
|
27
|
+
curl "localhost:5030/api/explorer/health?includeInventory=1"
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
+
## Run from CLI or code
|
|
31
|
+
|
|
32
|
+
Installed CLI, using the default port `5030`:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx @x12i/static-memorix-explorer-api
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Override the port from the shell:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
PORT=8080 npx @x12i/static-memorix-explorer-api
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Start it programmatically (explicit options take precedence over environment
|
|
45
|
+
defaults):
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
import { startServer } from "@x12i/static-memorix-explorer-api";
|
|
49
|
+
|
|
50
|
+
const app = await startServer({ port: 5030, host: "127.0.0.1" });
|
|
51
|
+
// await app.close();
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
For code-level tests without binding a port:
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
import { buildServer } from "@x12i/static-memorix-explorer-api";
|
|
58
|
+
|
|
59
|
+
const app = await buildServer();
|
|
60
|
+
const response = await app.inject({ method: "GET", url: "/health" });
|
|
61
|
+
await app.close();
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
See [guides/running-the-service.md](./guides/running-the-service.md) for all
|
|
65
|
+
CLI, environment, lifecycle, and programmatic examples.
|
|
66
|
+
|
|
30
67
|
## Architecture
|
|
31
68
|
|
|
32
69
|
```
|
|
@@ -139,7 +176,7 @@ Full implementation walkthrough: [guides/demo-app.md](./guides/demo-app.md).
|
|
|
139
176
|
|
|
140
177
|
| Var | Default | Notes |
|
|
141
178
|
|-----|---------|-------|
|
|
142
|
-
| `PORT` | `
|
|
179
|
+
| `PORT` | `5030` | Listen port |
|
|
143
180
|
| `HOST` | `0.0.0.0` | Listen host |
|
|
144
181
|
| `MOCKS_DIR` | `<project>/mocks` | Fixture root |
|
|
145
182
|
| `DISK_FLUSH_DEBOUNCE_MS` | `300` | Debounce before disk flush |
|
|
@@ -204,6 +241,12 @@ and `knowledgeId`.
|
|
|
204
241
|
|
|
205
242
|
## Release history
|
|
206
243
|
|
|
244
|
+
### v1.1.1
|
|
245
|
+
- Changed the default listen port from `4300` to `5030`.
|
|
246
|
+
- Added safe programmatic APIs: `buildServer()` and `startServer(options)`.
|
|
247
|
+
- Importing the package no longer starts a listener as a side effect.
|
|
248
|
+
- Added CLI, environment override, programmatic startup, and injected-test examples.
|
|
249
|
+
|
|
207
250
|
### v1.1.0
|
|
208
251
|
- **Added**: `delete` operation to the write engine
|
|
209
252
|
(`POST /records/write` body `operation:"delete"`).
|
package/dist/config.js
CHANGED
|
@@ -8,7 +8,7 @@ export const MOCKS_DIR = process.env.MOCKS_DIR
|
|
|
8
8
|
: path.resolve(ROOT_DIR, "..", "mocks");
|
|
9
9
|
export const METADATA_DIR = path.join(MOCKS_DIR, "metadata");
|
|
10
10
|
export const DATA_DIR = path.join(MOCKS_DIR, "data");
|
|
11
|
-
export const PORT = Number(process.env.PORT ||
|
|
11
|
+
export const PORT = Number(process.env.PORT || 5030);
|
|
12
12
|
export const HOST = process.env.HOST || "0.0.0.0";
|
|
13
13
|
export const DISK_FLUSH_DEBOUNCE_MS = Number(process.env.DISK_FLUSH_DEBOUNCE_MS || 300);
|
|
14
14
|
// ---------------------------------------------------------------------------
|
package/dist/server.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import Fastify from "fastify";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
3
5
|
import { store } from "./storage/InMemoryStore.js";
|
|
4
6
|
import { registerRoutes } from "./routes/index.js";
|
|
5
7
|
import { PORT, HOST, MOCKS_DIR } from "./config.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
/** Build a loaded Fastify instance without opening a network port. */
|
|
9
|
+
export async function buildServer(options = {}) {
|
|
10
|
+
const app = Fastify({ logger: options.logger ?? false });
|
|
8
11
|
// Global error handler matching predictable error shapes.
|
|
9
12
|
app.setErrorHandler((error, _request, reply) => {
|
|
10
13
|
const normalized = error instanceof Error
|
|
@@ -20,22 +23,36 @@ async function main() {
|
|
|
20
23
|
});
|
|
21
24
|
await store.load();
|
|
22
25
|
await registerRoutes(app);
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
return app;
|
|
27
|
+
}
|
|
28
|
+
/** Build and listen. Options override PORT/HOST environment configuration. */
|
|
29
|
+
export async function startServer(options = {}) {
|
|
30
|
+
const app = await buildServer(options);
|
|
31
|
+
const port = options.port ?? PORT;
|
|
32
|
+
const host = options.host ?? HOST;
|
|
33
|
+
await app.listen({ port, host });
|
|
25
34
|
// eslint-disable-next-line no-console
|
|
26
|
-
console.log(`[mock-memorix-explorer-api] listening on ${
|
|
35
|
+
console.log(`[mock-memorix-explorer-api] listening on ${host}:${port}`);
|
|
27
36
|
console.log(`[mock-memorix-explorer-api] mocks dir: ${MOCKS_DIR}`);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
if (options.installSignalHandlers ?? true) {
|
|
38
|
+
const shutdown = async () => {
|
|
39
|
+
console.log("\n[mock-memorix-explorer-api] flushing + shutting down");
|
|
40
|
+
await store.flushAll();
|
|
41
|
+
await app.close();
|
|
42
|
+
process.exit(0);
|
|
43
|
+
};
|
|
44
|
+
process.once("SIGINT", shutdown);
|
|
45
|
+
process.once("SIGTERM", shutdown);
|
|
46
|
+
}
|
|
47
|
+
return app;
|
|
48
|
+
}
|
|
49
|
+
const isCliEntry = process.argv[1]
|
|
50
|
+
? path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)
|
|
51
|
+
: false;
|
|
52
|
+
if (isCliEntry) {
|
|
53
|
+
startServer().catch((err) => {
|
|
54
|
+
// eslint-disable-next-line no-console
|
|
55
|
+
console.error(err);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
});
|
|
36
58
|
}
|
|
37
|
-
main().catch((err) => {
|
|
38
|
-
// eslint-disable-next-line no-console
|
|
39
|
-
console.error(err);
|
|
40
|
-
process.exit(1);
|
|
41
|
-
});
|
package/guides/demo-app.md
CHANGED
|
@@ -17,7 +17,7 @@ calls.
|
|
|
17
17
|
```bash
|
|
18
18
|
npm run build
|
|
19
19
|
npm start
|
|
20
|
-
# open http://localhost:
|
|
20
|
+
# open http://localhost:5030/demo
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
Every mutation you make in the UI is persisted back to `mocks/data/**/*.json`
|
|
@@ -454,23 +454,23 @@ A 30-second smoke test, runnable from the repo root:
|
|
|
454
454
|
npm run build && npm start &
|
|
455
455
|
|
|
456
456
|
# 2. Read
|
|
457
|
-
curl -s "localhost:
|
|
457
|
+
curl -s "localhost:5030/api/explorer/records/collection?entityName=users&limit=10"
|
|
458
458
|
|
|
459
459
|
# 3. Create
|
|
460
|
-
curl -s -X POST localhost:
|
|
460
|
+
curl -s -X POST localhost:5030/api/explorer/records/write \
|
|
461
461
|
-H "Content-Type: application/json" \
|
|
462
462
|
-d '{"writeDescriptorId":"product-task-write","operation":"add","input":{"recordId":"t-smoke-1","title":"Smoke","area":"product","status":"todo","priority":"normal"}}'
|
|
463
463
|
|
|
464
464
|
# 4. Update (partial)
|
|
465
|
-
curl -s -X POST localhost:
|
|
465
|
+
curl -s -X POST localhost:5030/api/explorer/records/write \
|
|
466
466
|
-H "Content-Type: application/json" \
|
|
467
467
|
-d '{"writeDescriptorId":"product-task-write","operation":"upsert","input":{"recordId":"t-smoke-1","status":"doing"}}'
|
|
468
468
|
|
|
469
469
|
# 5. Delete
|
|
470
|
-
curl -s -X DELETE "localhost:
|
|
470
|
+
curl -s -X DELETE "localhost:5030/api/explorer/records/item?entityName=product&recordId=t-smoke-1&writeDescriptorId=product-task-write"
|
|
471
471
|
|
|
472
472
|
# 6. Open the UI
|
|
473
|
-
open http://localhost:
|
|
473
|
+
open http://localhost:5030/demo
|
|
474
474
|
```
|
|
475
475
|
|
|
476
476
|
---
|
|
@@ -9,7 +9,7 @@ from in-memory state backed by JSON files on disk.
|
|
|
9
9
|
### From npm (global)
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npm install -g x12i/static-memorix-explorer-api
|
|
12
|
+
npm install -g @x12i/static-memorix-explorer-api
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
This makes the `mock-memorix-explorer-api` command available globally.
|
|
@@ -49,6 +49,41 @@ mock-memorix-explorer-api
|
|
|
49
49
|
After `npm install -g`, the CLI starts the server with default settings. The
|
|
50
50
|
mocks directory defaults to a `mocks/` folder relative to the installed package.
|
|
51
51
|
|
|
52
|
+
### With `npx` (no global install)
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx @x12i/static-memorix-explorer-api
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### From application code
|
|
59
|
+
|
|
60
|
+
Importing the package does not open a port. Call `startServer()` explicitly:
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
import { startServer } from "@x12i/static-memorix-explorer-api";
|
|
64
|
+
|
|
65
|
+
const app = await startServer({
|
|
66
|
+
port: 5030,
|
|
67
|
+
host: "127.0.0.1",
|
|
68
|
+
installSignalHandlers: false,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Later, for example during test teardown:
|
|
72
|
+
await app.close();
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
For tests that do not need a real TCP listener, build the Fastify app and use
|
|
76
|
+
its injection API:
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
import { buildServer } from "@x12i/static-memorix-explorer-api";
|
|
80
|
+
|
|
81
|
+
const app = await buildServer();
|
|
82
|
+
const response = await app.inject({ method: "GET", url: "/health" });
|
|
83
|
+
console.log(response.json()); // { ok: true }
|
|
84
|
+
await app.close();
|
|
85
|
+
```
|
|
86
|
+
|
|
52
87
|
## Configuration
|
|
53
88
|
|
|
54
89
|
All configuration is via environment variables. Defaults work out of the box.
|
|
@@ -57,7 +92,7 @@ All configuration is via environment variables. Defaults work out of the box.
|
|
|
57
92
|
|
|
58
93
|
| Variable | Default | Description |
|
|
59
94
|
| --------- | ----------- | ------------------------------ |
|
|
60
|
-
| `PORT` | `
|
|
95
|
+
| `PORT` | `5030` | HTTP listen port |
|
|
61
96
|
| `HOST` | `0.0.0.0` | HTTP listen host |
|
|
62
97
|
| `MOCKS_DIR` | `<project>/mocks` | Root directory for JSON fixtures |
|
|
63
98
|
|
|
@@ -117,10 +152,10 @@ mock-memorix-explorer-api
|
|
|
117
152
|
Once running, verify the server is up:
|
|
118
153
|
|
|
119
154
|
```bash
|
|
120
|
-
curl localhost:
|
|
155
|
+
curl localhost:5030/health
|
|
121
156
|
# {"ok":true}
|
|
122
157
|
|
|
123
|
-
curl "localhost:
|
|
158
|
+
curl "localhost:5030/api/explorer/health?includeInventory=1"
|
|
124
159
|
# {"ok":true,"mongoUriConfigured":true,"discoverySample":["assets","findings","memory"],...}
|
|
125
160
|
```
|
|
126
161
|
|
package/guides/using-the-api.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
The mock server exposes the full Memorix Explorer API under `/api/explorer/`.
|
|
4
4
|
All responses are JSON. Errors follow the shape `{ ok: false, error: "..." }`.
|
|
5
5
|
|
|
6
|
-
Base URL defaults to `http://localhost:
|
|
6
|
+
Base URL defaults to `http://localhost:5030`.
|
|
7
7
|
|
|
8
8
|
## Endpoints
|
|
9
9
|
|