@yrest/cli 0.11.1 → 0.12.0
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 +170 -24
- package/dist/cli/index.js +230 -16
- package/dist/cli/index.mjs +230 -16
- package/dist/index.d.mts +110 -3
- package/dist/index.d.ts +110 -3
- package/dist/index.js +243 -11
- package/dist/index.mjs +243 -11
- package/package.json +6 -2
package/dist/index.js
CHANGED
|
@@ -153,6 +153,49 @@ var init_parseRelations = __esm({
|
|
|
153
153
|
}
|
|
154
154
|
});
|
|
155
155
|
|
|
156
|
+
// src/storage/parseSseRoutes.ts
|
|
157
|
+
function parseSseRoutes(raw) {
|
|
158
|
+
if (!Array.isArray(raw)) return [];
|
|
159
|
+
return raw.map(normaliseSseRoute).filter((r) => r !== null);
|
|
160
|
+
}
|
|
161
|
+
function normaliseSseRoute(raw) {
|
|
162
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
163
|
+
const v = raw;
|
|
164
|
+
const method = typeof v["_method"] === "string" ? v["_method"].toUpperCase() : null;
|
|
165
|
+
const path = v["_path"];
|
|
166
|
+
const sse = v["_sse"];
|
|
167
|
+
if (method !== "SSE") return null;
|
|
168
|
+
if (typeof path !== "string" || !sse || typeof sse !== "object" || Array.isArray(sse)) {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
const s = sse;
|
|
172
|
+
const rawEvents = s["_events"];
|
|
173
|
+
if (!Array.isArray(rawEvents)) return null;
|
|
174
|
+
const events = rawEvents.map(normaliseEvent).filter((e) => e !== null);
|
|
175
|
+
if (!events.length) return null;
|
|
176
|
+
return {
|
|
177
|
+
path,
|
|
178
|
+
interval: typeof s["_interval"] === "number" ? s["_interval"] : 1e3,
|
|
179
|
+
loop: s["_loop"] !== false,
|
|
180
|
+
repeat: typeof s["_repeat"] === "number" ? s["_repeat"] : void 0,
|
|
181
|
+
events
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function normaliseEvent(raw) {
|
|
185
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
186
|
+
const v = raw;
|
|
187
|
+
if (!("_data" in v)) return null;
|
|
188
|
+
const event = { data: v["_data"] };
|
|
189
|
+
if (typeof v["_event"] === "string") event.event = v["_event"];
|
|
190
|
+
return event;
|
|
191
|
+
}
|
|
192
|
+
var init_parseSseRoutes = __esm({
|
|
193
|
+
"src/storage/parseSseRoutes.ts"() {
|
|
194
|
+
"use strict";
|
|
195
|
+
init_cjs_shims();
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
156
199
|
// src/storage/parseSchema.ts
|
|
157
200
|
function parseSchema(raw) {
|
|
158
201
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
|
|
@@ -174,18 +217,48 @@ function normaliseFieldDef(value) {
|
|
|
174
217
|
const v = value;
|
|
175
218
|
const def = {};
|
|
176
219
|
if (v["_required"] === true || v["_required"] === false) def.required = v["_required"];
|
|
177
|
-
if (typeof v["_type"] === "string" &&
|
|
220
|
+
if (typeof v["_type"] === "string" && VALID_TYPES.has(v["_type"]))
|
|
178
221
|
def.type = v["_type"];
|
|
179
222
|
if (typeof v["_format"] === "string") def.format = v["_format"];
|
|
180
223
|
if (Array.isArray(v["_enum"])) def.enum = v["_enum"];
|
|
181
224
|
if (typeof v["_description"] === "string") def.description = v["_description"];
|
|
182
225
|
if (v["_default"] !== void 0) def.default = v["_default"];
|
|
226
|
+
if (v["_example"] !== void 0) def.example = v["_example"];
|
|
227
|
+
if (v["_nullable"] === true || v["_nullable"] === false) def.nullable = v["_nullable"];
|
|
228
|
+
if (typeof v["_minLength"] === "number") def.minLength = v["_minLength"];
|
|
229
|
+
if (typeof v["_maxLength"] === "number") def.maxLength = v["_maxLength"];
|
|
230
|
+
if (typeof v["_pattern"] === "string") def.pattern = v["_pattern"];
|
|
231
|
+
if (typeof v["_minimum"] === "number") def.minimum = v["_minimum"];
|
|
232
|
+
if (typeof v["_maximum"] === "number") def.maximum = v["_maximum"];
|
|
233
|
+
if (typeof v["_exclusiveMinimum"] === "number") def.exclusiveMinimum = v["_exclusiveMinimum"];
|
|
234
|
+
if (typeof v["_exclusiveMaximum"] === "number") def.exclusiveMaximum = v["_exclusiveMaximum"];
|
|
235
|
+
if (typeof v["_multipleOf"] === "number") def.multipleOf = v["_multipleOf"];
|
|
236
|
+
if (typeof v["_minItems"] === "number") def.minItems = v["_minItems"];
|
|
237
|
+
if (typeof v["_maxItems"] === "number") def.maxItems = v["_maxItems"];
|
|
238
|
+
if (v["_uniqueItems"] === true || v["_uniqueItems"] === false)
|
|
239
|
+
def.uniqueItems = v["_uniqueItems"];
|
|
240
|
+
if (v["_items"] && typeof v["_items"] === "object" && !Array.isArray(v["_items"])) {
|
|
241
|
+
const items = v["_items"];
|
|
242
|
+
const itemsDef = {};
|
|
243
|
+
if (typeof items["_type"] === "string" && VALID_TYPES.has(items["_type"]))
|
|
244
|
+
itemsDef.type = items["_type"];
|
|
245
|
+
if (typeof items["_format"] === "string") itemsDef.format = items["_format"];
|
|
246
|
+
if (Array.isArray(items["_enum"])) itemsDef.enum = items["_enum"];
|
|
247
|
+
def.items = itemsDef;
|
|
248
|
+
}
|
|
249
|
+
if (v["_deprecated"] === true || v["_deprecated"] === false)
|
|
250
|
+
def.deprecated = v["_deprecated"];
|
|
251
|
+
if (v["_readOnly"] === true || v["_readOnly"] === false) def.readOnly = v["_readOnly"];
|
|
252
|
+
if (v["_writeOnly"] === true || v["_writeOnly"] === false)
|
|
253
|
+
def.writeOnly = v["_writeOnly"];
|
|
183
254
|
return def;
|
|
184
255
|
}
|
|
256
|
+
var VALID_TYPES;
|
|
185
257
|
var init_parseSchema = __esm({
|
|
186
258
|
"src/storage/parseSchema.ts"() {
|
|
187
259
|
"use strict";
|
|
188
260
|
init_cjs_shims();
|
|
261
|
+
VALID_TYPES = /* @__PURE__ */ new Set(["string", "integer", "number", "boolean", "object", "array"]);
|
|
189
262
|
}
|
|
190
263
|
});
|
|
191
264
|
|
|
@@ -211,6 +284,8 @@ function normaliseRoute(raw) {
|
|
|
211
284
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
212
285
|
const v = raw;
|
|
213
286
|
const method = v["_method"];
|
|
287
|
+
if (typeof method === "string" && method.toUpperCase() === "SSE") return null;
|
|
288
|
+
if ("_sse" in v) return null;
|
|
214
289
|
const path = v["_path"];
|
|
215
290
|
if (typeof method !== "string" || typeof path !== "string") return null;
|
|
216
291
|
const route = { method, path };
|
|
@@ -256,6 +331,30 @@ var init_parseRoutes = __esm({
|
|
|
256
331
|
}
|
|
257
332
|
});
|
|
258
333
|
|
|
334
|
+
// src/storage/parseData.ts
|
|
335
|
+
function parseData(raw) {
|
|
336
|
+
const block = raw["_data"];
|
|
337
|
+
const fromBlock = block && typeof block === "object" && !Array.isArray(block) ? Object.fromEntries(
|
|
338
|
+
Object.entries(block).filter(([, v]) => Array.isArray(v))
|
|
339
|
+
) : {};
|
|
340
|
+
const fromRoot = Object.fromEntries(
|
|
341
|
+
Object.entries(raw).filter(([key, val]) => !RESERVED.has(key) && Array.isArray(val))
|
|
342
|
+
);
|
|
343
|
+
return { ...fromBlock, ...fromRoot };
|
|
344
|
+
}
|
|
345
|
+
function hasDataBlock(raw) {
|
|
346
|
+
const d = raw["_data"];
|
|
347
|
+
return d !== null && d !== void 0 && typeof d === "object" && !Array.isArray(d);
|
|
348
|
+
}
|
|
349
|
+
var RESERVED;
|
|
350
|
+
var init_parseData = __esm({
|
|
351
|
+
"src/storage/parseData.ts"() {
|
|
352
|
+
"use strict";
|
|
353
|
+
init_cjs_shims();
|
|
354
|
+
RESERVED = /* @__PURE__ */ new Set(["_rel", "_routes", "_schema", "_data"]);
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
|
|
259
358
|
// src/storage/yrestStorage.ts
|
|
260
359
|
var yrestStorage_exports = {};
|
|
261
360
|
__export(yrestStorage_exports, {
|
|
@@ -318,13 +417,12 @@ function serializeScenario(s) {
|
|
|
318
417
|
function createYrestStorage(filePath) {
|
|
319
418
|
const absPath = (0, import_node_path2.resolve)(filePath);
|
|
320
419
|
const raw = (0, import_yaml3.parse)((0, import_node_fs3.readFileSync)(absPath, "utf8")) ?? {};
|
|
321
|
-
const RESERVED = /* @__PURE__ */ new Set(["_rel", "_routes", "_schema"]);
|
|
322
420
|
const relations = parseRelations(raw["_rel"]);
|
|
323
421
|
const routes = parseRoutes(raw["_routes"]);
|
|
422
|
+
const sseRoutes = parseSseRoutes(raw["_routes"]);
|
|
324
423
|
const schema = parseSchema(raw["_schema"]);
|
|
325
|
-
const
|
|
326
|
-
|
|
327
|
-
);
|
|
424
|
+
const dataBlock = hasDataBlock(raw);
|
|
425
|
+
const data = parseData(raw);
|
|
328
426
|
let snapshot = {
|
|
329
427
|
data: deepCopyData(data),
|
|
330
428
|
relations: { ...relations },
|
|
@@ -343,6 +441,9 @@ function createYrestStorage(filePath) {
|
|
|
343
441
|
getRoutes() {
|
|
344
442
|
return routes;
|
|
345
443
|
},
|
|
444
|
+
getSseRoutes() {
|
|
445
|
+
return sseRoutes;
|
|
446
|
+
},
|
|
346
447
|
getCollection(name) {
|
|
347
448
|
return data[name];
|
|
348
449
|
},
|
|
@@ -353,7 +454,11 @@ function createYrestStorage(filePath) {
|
|
|
353
454
|
const payload = {};
|
|
354
455
|
if (Object.keys(relations).length > 0) payload._rel = serializeRelations(relations);
|
|
355
456
|
if (routes.length > 0) payload._routes = serializeRoutes(routes);
|
|
356
|
-
|
|
457
|
+
if (dataBlock) {
|
|
458
|
+
payload._data = data;
|
|
459
|
+
} else {
|
|
460
|
+
Object.assign(payload, data);
|
|
461
|
+
}
|
|
357
462
|
const tmp = (0, import_node_path2.resolve)((0, import_node_path2.dirname)(absPath), `.yrest-${(0, import_node_crypto2.randomUUID)()}.tmp`);
|
|
358
463
|
(0, import_node_fs3.writeFileSync)(tmp, (0, import_yaml3.stringify)(payload), "utf8");
|
|
359
464
|
(0, import_node_fs3.renameSync)(tmp, absPath);
|
|
@@ -361,9 +466,7 @@ function createYrestStorage(filePath) {
|
|
|
361
466
|
reload() {
|
|
362
467
|
const fresh = (0, import_yaml3.parse)((0, import_node_fs3.readFileSync)(absPath, "utf8")) ?? {};
|
|
363
468
|
const freshRelations = parseRelations(fresh["_rel"]);
|
|
364
|
-
const freshData =
|
|
365
|
-
Object.entries(fresh).filter(([key]) => !RESERVED.has(key))
|
|
366
|
-
);
|
|
469
|
+
const freshData = parseData(fresh);
|
|
367
470
|
for (const key of Object.keys(data)) delete data[key];
|
|
368
471
|
Object.assign(data, freshData);
|
|
369
472
|
for (const key of Object.keys(relations)) delete relations[key];
|
|
@@ -400,7 +503,9 @@ var init_yrestStorage = __esm({
|
|
|
400
503
|
import_yaml3 = require("yaml");
|
|
401
504
|
init_parseRelations();
|
|
402
505
|
init_parseRoutes();
|
|
506
|
+
init_parseSseRoutes();
|
|
403
507
|
init_parseSchema();
|
|
508
|
+
init_parseData();
|
|
404
509
|
init_deepCopy();
|
|
405
510
|
}
|
|
406
511
|
});
|
|
@@ -464,6 +569,7 @@ function dedent(str) {
|
|
|
464
569
|
init_cjs_shims();
|
|
465
570
|
var import_node_path3 = require("path");
|
|
466
571
|
init_parseRelations();
|
|
572
|
+
init_parseSseRoutes();
|
|
467
573
|
init_parseSchema();
|
|
468
574
|
|
|
469
575
|
// src/utils/handlers.ts
|
|
@@ -575,6 +681,8 @@ var METHOD_COLOR = {
|
|
|
575
681
|
PUT: "#d29922",
|
|
576
682
|
PATCH: "#a371f7",
|
|
577
683
|
DELETE: "#f85149",
|
|
684
|
+
SSE: "#0ea5e9",
|
|
685
|
+
WS: "#8b5cf6",
|
|
578
686
|
fn: "#f0883e"
|
|
579
687
|
};
|
|
580
688
|
function escapeHtml(str) {
|
|
@@ -766,6 +874,30 @@ function handlersAccordion(handlers, routes, base) {
|
|
|
766
874
|
</tbody></table>
|
|
767
875
|
</details>`;
|
|
768
876
|
}
|
|
877
|
+
function sseRoutesAccordion(routes, base) {
|
|
878
|
+
if (!routes.length) return "";
|
|
879
|
+
const rows = routes.map((r) => {
|
|
880
|
+
const tags = [
|
|
881
|
+
`<span style="color:#0ea5e9;font-size:11px">interval\xB7${r.interval}ms</span>`,
|
|
882
|
+
`<span style="color:var(--text-muted);font-size:11px">${r.events.length} event${r.events.length !== 1 ? "s" : ""}</span>`
|
|
883
|
+
];
|
|
884
|
+
if (!r.loop) tags.push(`<span style="color:var(--text-muted);font-size:11px">no\xB7loop</span>`);
|
|
885
|
+
if (r.repeat !== void 0)
|
|
886
|
+
tags.push(`<span style="color:var(--text-muted);font-size:11px">repeat\xB7${r.repeat}\xD7</span>`);
|
|
887
|
+
const desc = `SSE stream ${tags.join(" ")}`;
|
|
888
|
+
return endpointRow("SSE", `${base}${r.path}`, desc);
|
|
889
|
+
});
|
|
890
|
+
return `
|
|
891
|
+
<details class="resource-card nested-card">
|
|
892
|
+
<summary>
|
|
893
|
+
<span class="resource-name">SSE streams</span>
|
|
894
|
+
<span class="route-count">${routes.length} stream${routes.length !== 1 ? "s" : ""}</span>
|
|
895
|
+
</summary>
|
|
896
|
+
<table><tbody>
|
|
897
|
+
${rows.join("")}
|
|
898
|
+
</tbody></table>
|
|
899
|
+
</details>`;
|
|
900
|
+
}
|
|
769
901
|
function examplesBlock(collections, relations, base, host, options, firstCustomRoute) {
|
|
770
902
|
const examples = [];
|
|
771
903
|
const firstCol = collections[0];
|
|
@@ -1438,6 +1570,7 @@ function generateAboutHtml(storage, options, handlers = /* @__PURE__ */ new Map(
|
|
|
1438
1570
|
const collections = Object.keys(storage.getData());
|
|
1439
1571
|
const relations = storage.getRelations();
|
|
1440
1572
|
const customRoutes = storage.getRoutes();
|
|
1573
|
+
const sseRoutes = storage.getSseRoutes();
|
|
1441
1574
|
const base = options.base;
|
|
1442
1575
|
const host = `http://${options.host}:${options.port}`;
|
|
1443
1576
|
const swaggerUrl = `https://petstore.swagger.io/?url=${encodeURIComponent(`${host}/_openapi.json`)}`;
|
|
@@ -1621,6 +1754,7 @@ function generateAboutHtml(storage, options, handlers = /* @__PURE__ */ new Map(
|
|
|
1621
1754
|
${accordions}
|
|
1622
1755
|
${nestedRoutesAccordion(relations, base)}
|
|
1623
1756
|
${options.snapshot ? snapshotAccordion() : ""}
|
|
1757
|
+
${sseRoutesAccordion(sseRoutes, base)}
|
|
1624
1758
|
${customRoutesAccordion(customRoutes, base, handlers)}
|
|
1625
1759
|
${handlersAccordion(handlers, customRoutes, base)}
|
|
1626
1760
|
</div>
|
|
@@ -2059,15 +2193,19 @@ function resolveRequestPath(dotPath, req) {
|
|
|
2059
2193
|
const [root, ...rest] = dotPath.split(".");
|
|
2060
2194
|
let value;
|
|
2061
2195
|
switch (root) {
|
|
2196
|
+
case "_body":
|
|
2062
2197
|
case "body":
|
|
2063
2198
|
value = req.body;
|
|
2064
2199
|
break;
|
|
2200
|
+
case "_params":
|
|
2065
2201
|
case "params":
|
|
2066
2202
|
value = req.params;
|
|
2067
2203
|
break;
|
|
2204
|
+
case "_query":
|
|
2068
2205
|
case "query":
|
|
2069
2206
|
value = req.query;
|
|
2070
2207
|
break;
|
|
2208
|
+
case "_headers":
|
|
2071
2209
|
case "headers":
|
|
2072
2210
|
value = req.headers;
|
|
2073
2211
|
break;
|
|
@@ -2368,6 +2506,23 @@ function buildCollectionSchema(items, fieldDefs = {}) {
|
|
|
2368
2506
|
if (def?.description) prop.description = def.description;
|
|
2369
2507
|
if (def?.enum) prop.enum = def.enum;
|
|
2370
2508
|
if (def?.default !== void 0) prop.default = def.default;
|
|
2509
|
+
if (def?.example !== void 0) prop.example = def.example;
|
|
2510
|
+
if (def?.nullable) prop.nullable = def.nullable;
|
|
2511
|
+
if (def?.minLength !== void 0) prop.minLength = def.minLength;
|
|
2512
|
+
if (def?.maxLength !== void 0) prop.maxLength = def.maxLength;
|
|
2513
|
+
if (def?.pattern) prop.pattern = def.pattern;
|
|
2514
|
+
if (def?.minimum !== void 0) prop.minimum = def.minimum;
|
|
2515
|
+
if (def?.maximum !== void 0) prop.maximum = def.maximum;
|
|
2516
|
+
if (def?.exclusiveMinimum !== void 0) prop.exclusiveMinimum = def.exclusiveMinimum;
|
|
2517
|
+
if (def?.exclusiveMaximum !== void 0) prop.exclusiveMaximum = def.exclusiveMaximum;
|
|
2518
|
+
if (def?.multipleOf !== void 0) prop.multipleOf = def.multipleOf;
|
|
2519
|
+
if (def?.items) prop.items = def.items;
|
|
2520
|
+
if (def?.minItems !== void 0) prop.minItems = def.minItems;
|
|
2521
|
+
if (def?.maxItems !== void 0) prop.maxItems = def.maxItems;
|
|
2522
|
+
if (def?.uniqueItems !== void 0) prop.uniqueItems = def.uniqueItems;
|
|
2523
|
+
if (def?.deprecated) prop.deprecated = def.deprecated;
|
|
2524
|
+
if (def?.readOnly) prop.readOnly = def.readOnly;
|
|
2525
|
+
if (def?.writeOnly) prop.writeOnly = def.writeOnly;
|
|
2371
2526
|
properties[field] = prop;
|
|
2372
2527
|
if (def?.required === true) required.push(field);
|
|
2373
2528
|
}
|
|
@@ -2752,6 +2907,80 @@ var SnapshotRouteCommand = class {
|
|
|
2752
2907
|
}
|
|
2753
2908
|
};
|
|
2754
2909
|
|
|
2910
|
+
// src/router/routes/sse.routes.ts
|
|
2911
|
+
init_cjs_shims();
|
|
2912
|
+
var SSERouteCommand = class {
|
|
2913
|
+
constructor(storage, base) {
|
|
2914
|
+
this.storage = storage;
|
|
2915
|
+
this.base = base;
|
|
2916
|
+
}
|
|
2917
|
+
storage;
|
|
2918
|
+
base;
|
|
2919
|
+
register(server) {
|
|
2920
|
+
for (const route of this.storage.getSseRoutes()) {
|
|
2921
|
+
const url = `${this.base}${route.path}`;
|
|
2922
|
+
server.route({
|
|
2923
|
+
method: "GET",
|
|
2924
|
+
url,
|
|
2925
|
+
handler: async (req, reply) => {
|
|
2926
|
+
reply.hijack();
|
|
2927
|
+
const raw = reply.raw;
|
|
2928
|
+
raw.setHeader("Content-Type", "text/event-stream");
|
|
2929
|
+
raw.setHeader("Cache-Control", "no-cache");
|
|
2930
|
+
raw.setHeader("Connection", "keep-alive");
|
|
2931
|
+
raw.setHeader("Access-Control-Allow-Origin", "*");
|
|
2932
|
+
raw.flushHeaders();
|
|
2933
|
+
let alive = true;
|
|
2934
|
+
req.raw.on("close", () => {
|
|
2935
|
+
alive = false;
|
|
2936
|
+
});
|
|
2937
|
+
const keepAlive = setInterval(() => {
|
|
2938
|
+
if (alive) raw.write(": ping\n\n");
|
|
2939
|
+
}, 15e3);
|
|
2940
|
+
let frameIndex = 0;
|
|
2941
|
+
let cycleCount = 0;
|
|
2942
|
+
function sendNext() {
|
|
2943
|
+
if (!alive) {
|
|
2944
|
+
clearInterval(keepAlive);
|
|
2945
|
+
return;
|
|
2946
|
+
}
|
|
2947
|
+
const ev = route.events[frameIndex];
|
|
2948
|
+
const ctx = {
|
|
2949
|
+
params: req.params,
|
|
2950
|
+
query: req.query,
|
|
2951
|
+
body: null,
|
|
2952
|
+
headers: req.headers
|
|
2953
|
+
};
|
|
2954
|
+
const data = hasTemplates(ev.data) ? interpolate(ev.data, ctx) : ev.data;
|
|
2955
|
+
let chunk = "";
|
|
2956
|
+
if (ev.event) chunk += `event: ${ev.event}
|
|
2957
|
+
`;
|
|
2958
|
+
chunk += `data: ${JSON.stringify(data)}
|
|
2959
|
+
|
|
2960
|
+
`;
|
|
2961
|
+
raw.write(chunk);
|
|
2962
|
+
frameIndex++;
|
|
2963
|
+
if (frameIndex >= route.events.length) {
|
|
2964
|
+
frameIndex = 0;
|
|
2965
|
+
cycleCount++;
|
|
2966
|
+
const done = !route.loop || route.repeat !== void 0 && cycleCount >= route.repeat;
|
|
2967
|
+
if (done) {
|
|
2968
|
+
clearInterval(keepAlive);
|
|
2969
|
+
raw.end();
|
|
2970
|
+
return;
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
if (alive) {
|
|
2974
|
+
setTimeout(sendNext, route.interval);
|
|
2975
|
+
}
|
|
2976
|
+
}
|
|
2977
|
+
sendNext();
|
|
2978
|
+
}
|
|
2979
|
+
});
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
};
|
|
2983
|
+
|
|
2755
2984
|
// src/router/resource.router.ts
|
|
2756
2985
|
function buildResourceRouteCommands(storage, options) {
|
|
2757
2986
|
const commands = [];
|
|
@@ -2793,6 +3022,7 @@ async function createServer(storage, options, handlers = /* @__PURE__ */ new Map
|
|
|
2793
3022
|
new AboutRouteCommand(storage, options, handlers),
|
|
2794
3023
|
new OpenApiRouteCommand(storage, options),
|
|
2795
3024
|
...options.snapshot ? [new SnapshotRouteCommand(storage)] : [],
|
|
3025
|
+
new SSERouteCommand(storage, options.base),
|
|
2796
3026
|
new CustomRouteCommand(storage, options.base, handlers),
|
|
2797
3027
|
...buildResourceRouteCommands(storage, options)
|
|
2798
3028
|
];
|
|
@@ -2871,12 +3101,13 @@ function buildOptions(opts) {
|
|
|
2871
3101
|
}
|
|
2872
3102
|
function createInMemoryStorage(data) {
|
|
2873
3103
|
const raw = data;
|
|
2874
|
-
const
|
|
3104
|
+
const RESERVED2 = /* @__PURE__ */ new Set(["_rel", "_routes", "_schema"]);
|
|
2875
3105
|
const relations = parseRelations(raw["_rel"]);
|
|
2876
3106
|
const routes = Array.isArray(raw["_routes"]) ? raw["_routes"] : [];
|
|
3107
|
+
const sseRoutes = parseSseRoutes(raw["_routes"]);
|
|
2877
3108
|
const schema = parseSchema(raw["_schema"]);
|
|
2878
3109
|
const collections = Object.fromEntries(
|
|
2879
|
-
Object.entries(raw).filter(([k]) => !
|
|
3110
|
+
Object.entries(raw).filter(([k]) => !RESERVED2.has(k))
|
|
2880
3111
|
);
|
|
2881
3112
|
let snapshot = {
|
|
2882
3113
|
data: deepCopyData(collections),
|
|
@@ -2888,6 +3119,7 @@ function createInMemoryStorage(data) {
|
|
|
2888
3119
|
getRelations: () => relations,
|
|
2889
3120
|
getSchema: () => schema,
|
|
2890
3121
|
getRoutes: () => routes,
|
|
3122
|
+
getSseRoutes: () => sseRoutes,
|
|
2891
3123
|
getCollection: (name) => collections[name],
|
|
2892
3124
|
setCollection: (name, items) => {
|
|
2893
3125
|
collections[name] = items;
|