@piadina/fetch-jsonl
Version:
Stream and parse (**JSON Lines**)[https://jsonlines.org/] directly with fetch. Yields parsed JSON objects one line at a time.
115 lines (114 loc) • 3.1 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
var LINE_SPLIT_REGEX = /\r\n|[\r\n]/g;
var LinesTransformer = class {
lastString = "";
decoder = new TextDecoder();
transform(chunk, controller) {
const lines = `${this.lastString}${this.decoder.decode(chunk, { stream: true })}`.split(LINE_SPLIT_REGEX);
this.lastString = lines.pop() || "";
lines.forEach((line) => {
controller.enqueue(line);
});
}
flush(controller) {
if (this.lastString) controller.enqueue(this.lastString);
}
};
var FetchJSONL = class {
static instance;
#fetchImpl;
#reviver;
hooks = { beforeRequest: [] };
constructor(options = {}) {
this.#fetchImpl = options.fetchImpl ?? fetch;
this.#reviver = options.reviver;
this.hooks = {
...this.hooks,
...options?.hooks ?? {}
};
}
parseJSON(input) {
return JSON.parse(input, this.#reviver);
}
async applyBeforeRequestHooks(request) {
let req = request;
for (const hook of this.hooks.beforeRequest ?? []) {
const result = await hook(req);
if (result instanceof Request) req = result;
}
return req;
}
async *stream(input, init) {
let request = input instanceof Request ? input : new Request(input, init);
request = await this.applyBeforeRequestHooks(request);
const response = await this.#fetchImpl(request);
if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
if (!response.body) throw new Error("Response body is null");
const ts = new TransformStream(new LinesTransformer());
const reader = response.body.pipeThrough(ts).getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
try {
yield this.parseJSON(value);
} catch (e) {
throw e;
}
}
} finally {
reader.releaseLock();
}
}
#validateRequestMethod(input, expected) {
if (input instanceof Request && input.method.toUpperCase() !== expected) throw new Error(`Request method mismatch: expected ${expected}, got ${input.method}`);
}
get(url, init) {
this.#validateRequestMethod(url, "GET");
return this.stream(url, {
...init,
method: "GET"
});
}
post(url, init) {
this.#validateRequestMethod(url, "POST");
return this.stream(url, {
...init,
method: "POST"
});
}
put(url, init) {
this.#validateRequestMethod(url, "PUT");
return this.stream(url, {
...init,
method: "PUT"
});
}
patch(url, init) {
this.#validateRequestMethod(url, "PATCH");
return this.stream(url, {
...init,
method: "PATCH"
});
}
delete(url, init) {
this.#validateRequestMethod(url, "DELETE");
return this.stream(url, {
...init,
method: "DELETE"
});
}
};
const createInstance = (defaults = {}) => {
return new FetchJSONL(defaults);
};
var fetchJSONL = createInstance();
var fetch_json_lines_default = fetchJSONL;
var src_default = fetch_json_lines_default;
const version = "0.0.1";
exports.FetchJSONL = FetchJSONL;
exports.LinesTransformer = LinesTransformer;
exports.createInstance = createInstance;
exports.default = src_default;
exports.version = version;
//# sourceMappingURL=index.umd.debug.cjs.map