Fix regression in CSV and JSON streaming
This commit is contained in:
1 parent
ab80a62c5c
commit
60e6d8b175
1 file changed
+26
-24
+26
-24
@@ -1,4 +1,4 @@
|
|||||||
import { PassThrough } from "node:stream";
|
import { Readable } from "node:stream";
|
||||||
import Router from "koa-router";
|
import Router from "koa-router";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
import * as db from "./db.ts";
|
import * as db from "./db.ts";
|
||||||
@@ -88,10 +88,9 @@ router.get(`/devices/:id.csv`, async (ctx) => {
|
|||||||
.replace(/[:.]/g, "")}.csv`,
|
.replace(/[:.]/g, "")}.csv`,
|
||||||
);
|
);
|
||||||
|
|
||||||
ctx.body = new PassThrough();
|
const lines: string[] = [
|
||||||
ctx.body.write(
|
"Parameter,Object,Object timestamp,Writable,Writable timestamp,Value,Value type,Value timestamp,Notification,Notification timestamp,Access list,Access list timestamp",
|
||||||
"Parameter,Object,Object timestamp,Writable,Writable timestamp,Value,Value type,Value timestamp,Notification,Notification timestamp,Access list,Access list timestamp\n",
|
];
|
||||||
);
|
|
||||||
|
|
||||||
for (const k of Object.keys(device).sort()) {
|
for (const k of Object.keys(device).sort()) {
|
||||||
const p = device[k];
|
const p = device[k];
|
||||||
@@ -118,9 +117,9 @@ router.get(`/devices/:id.csv`, async (ctx) => {
|
|||||||
p.accessList ? p.accessList.join(", ") : "",
|
p.accessList ? p.accessList.join(", ") : "",
|
||||||
new Date(p.accessListTimestamp).toJSON(),
|
new Date(p.accessListTimestamp).toJSON(),
|
||||||
];
|
];
|
||||||
ctx.body.write(row.map((r) => (r != null ? r : "")).join(",") + "\n");
|
lines.push(row.map((r) => (r != null ? r : "")).join(","));
|
||||||
}
|
}
|
||||||
ctx.body.end();
|
ctx.body = lines.join("\n");
|
||||||
logger.accessInfo(log);
|
logger.accessInfo(log);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -201,16 +200,17 @@ for (const [resource, flags] of Object.entries(resources)) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.body = new PassThrough();
|
|
||||||
ctx.type = "application/json";
|
|
||||||
|
|
||||||
let c = 0;
|
|
||||||
ctx.body.write("[\n");
|
|
||||||
for await (const obj of db.query(resource, filter, options))
|
|
||||||
ctx.body.write((c++ ? "," : "") + JSON.stringify(obj) + "\n");
|
|
||||||
|
|
||||||
ctx.body.end("]");
|
|
||||||
logger.accessInfo(log);
|
logger.accessInfo(log);
|
||||||
|
ctx.type = "application/json";
|
||||||
|
ctx.body = Readable.from(
|
||||||
|
(async function* () {
|
||||||
|
let c = 0;
|
||||||
|
yield "[\n";
|
||||||
|
for await (const obj of db.query(resource, filter, options))
|
||||||
|
yield (c++ ? "," : "") + JSON.stringify(obj) + "\n";
|
||||||
|
yield "]";
|
||||||
|
})(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// CSV download
|
// CSV download
|
||||||
@@ -260,15 +260,16 @@ for (const [resource, flags] of Object.entries(resources)) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.body = new PassThrough();
|
logger.accessInfo(log);
|
||||||
ctx.type = "text/csv";
|
ctx.type = "text/csv";
|
||||||
ctx.attachment(
|
ctx.attachment(
|
||||||
`${resource}-${new Date(now).toISOString().replace(/[:.]/g, "")}.csv`,
|
`${resource}-${new Date(now).toISOString().replace(/[:.]/g, "")}.csv`,
|
||||||
);
|
);
|
||||||
|
|
||||||
ctx.body.write(
|
ctx.body = Readable.from(
|
||||||
Object.keys(columns).map((k) => `"${k.replace(/"/, '""')}"`) + "\n",
|
(async function* () {
|
||||||
);
|
yield Object.keys(columns).map((k) => `"${k.replace(/"/, '""')}"`) +
|
||||||
|
"\n";
|
||||||
for await (const obj of db.query(resource, filter, options)) {
|
for await (const obj of db.query(resource, filter, options)) {
|
||||||
const arr = Object.values(columns).map((exp) => {
|
const arr = Object.values(columns).map((exp) => {
|
||||||
const v = evaluate(exp, obj, null, (e) => {
|
const v = evaluate(exp, obj, null, (e) => {
|
||||||
@@ -278,7 +279,8 @@ for (const [resource, flags] of Object.entries(resources)) {
|
|||||||
if (e[1] === "Tags") {
|
if (e[1] === "Tags") {
|
||||||
const tags = [];
|
const tags = [];
|
||||||
for (const p in obj)
|
for (const p in obj)
|
||||||
if (p.startsWith("Tags.")) tags.push(decodeTag(p.slice(5)));
|
if (p.startsWith("Tags."))
|
||||||
|
tags.push(decodeTag(p.slice(5)));
|
||||||
|
|
||||||
return tags.join(", ");
|
return tags.join(", ");
|
||||||
}
|
}
|
||||||
@@ -310,10 +312,10 @@ for (const [resource, flags] of Object.entries(resources)) {
|
|||||||
if (typeof v === "string") return `"${v.replace(/"/g, '""')}"`;
|
if (typeof v === "string") return `"${v.replace(/"/g, '""')}"`;
|
||||||
return v;
|
return v;
|
||||||
});
|
});
|
||||||
ctx.body.write(arr.join(",") + "\n");
|
yield arr.join(",") + "\n";
|
||||||
}
|
}
|
||||||
ctx.body.end();
|
})(),
|
||||||
logger.accessInfo(log);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
router.head(`/${resource}/:id`, async (ctx) => {
|
router.head(`/${resource}/:id`, async (ctx) => {
|
||||||
|
|||||||
Reference in new issue
Block a user