- Add debounced state updates for title and content (500ms delay) - Immediate UI updates with delayed history saving - Prevent one-letter-per-undo issue - Add cleanup for debounce timers on unmount
228 lines
6.7 KiB
JavaScript
228 lines
6.7 KiB
JavaScript
"use strict";
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
|
|
// src/request.ts
|
|
var request_exports = {};
|
|
__export(request_exports, {
|
|
GlobalRequest: () => GlobalRequest,
|
|
Request: () => Request,
|
|
RequestError: () => RequestError,
|
|
abortControllerKey: () => abortControllerKey,
|
|
getAbortController: () => getAbortController,
|
|
newRequest: () => newRequest,
|
|
toRequestError: () => toRequestError,
|
|
wrapBodyStream: () => wrapBodyStream
|
|
});
|
|
module.exports = __toCommonJS(request_exports);
|
|
var import_node_http2 = require("http2");
|
|
var import_node_stream = require("stream");
|
|
var RequestError = class extends Error {
|
|
constructor(message, options) {
|
|
super(message, options);
|
|
this.name = "RequestError";
|
|
}
|
|
};
|
|
var toRequestError = (e) => {
|
|
if (e instanceof RequestError) {
|
|
return e;
|
|
}
|
|
return new RequestError(e.message, { cause: e });
|
|
};
|
|
var GlobalRequest = global.Request;
|
|
var Request = class extends GlobalRequest {
|
|
constructor(input, options) {
|
|
if (typeof input === "object" && getRequestCache in input) {
|
|
input = input[getRequestCache]();
|
|
}
|
|
if (typeof options?.body?.getReader !== "undefined") {
|
|
;
|
|
options.duplex ??= "half";
|
|
}
|
|
super(input, options);
|
|
}
|
|
};
|
|
var newHeadersFromIncoming = (incoming) => {
|
|
const headerRecord = [];
|
|
const rawHeaders = incoming.rawHeaders;
|
|
for (let i = 0; i < rawHeaders.length; i += 2) {
|
|
const { [i]: key, [i + 1]: value } = rawHeaders;
|
|
if (key.charCodeAt(0) !== /*:*/
|
|
58) {
|
|
headerRecord.push([key, value]);
|
|
}
|
|
}
|
|
return new Headers(headerRecord);
|
|
};
|
|
var wrapBodyStream = Symbol("wrapBodyStream");
|
|
var newRequestFromIncoming = (method, url, headers, incoming, abortController) => {
|
|
const init = {
|
|
method,
|
|
headers,
|
|
signal: abortController.signal
|
|
};
|
|
if (method === "TRACE") {
|
|
init.method = "GET";
|
|
const req = new Request(url, init);
|
|
Object.defineProperty(req, "method", {
|
|
get() {
|
|
return "TRACE";
|
|
}
|
|
});
|
|
return req;
|
|
}
|
|
if (!(method === "GET" || method === "HEAD")) {
|
|
if ("rawBody" in incoming && incoming.rawBody instanceof Buffer) {
|
|
init.body = new ReadableStream({
|
|
start(controller) {
|
|
controller.enqueue(incoming.rawBody);
|
|
controller.close();
|
|
}
|
|
});
|
|
} else if (incoming[wrapBodyStream]) {
|
|
let reader;
|
|
init.body = new ReadableStream({
|
|
async pull(controller) {
|
|
try {
|
|
reader ||= import_node_stream.Readable.toWeb(incoming).getReader();
|
|
const { done, value } = await reader.read();
|
|
if (done) {
|
|
controller.close();
|
|
} else {
|
|
controller.enqueue(value);
|
|
}
|
|
} catch (error) {
|
|
controller.error(error);
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
init.body = import_node_stream.Readable.toWeb(incoming);
|
|
}
|
|
}
|
|
return new Request(url, init);
|
|
};
|
|
var getRequestCache = Symbol("getRequestCache");
|
|
var requestCache = Symbol("requestCache");
|
|
var incomingKey = Symbol("incomingKey");
|
|
var urlKey = Symbol("urlKey");
|
|
var headersKey = Symbol("headersKey");
|
|
var abortControllerKey = Symbol("abortControllerKey");
|
|
var getAbortController = Symbol("getAbortController");
|
|
var requestPrototype = {
|
|
get method() {
|
|
return this[incomingKey].method || "GET";
|
|
},
|
|
get url() {
|
|
return this[urlKey];
|
|
},
|
|
get headers() {
|
|
return this[headersKey] ||= newHeadersFromIncoming(this[incomingKey]);
|
|
},
|
|
[getAbortController]() {
|
|
this[getRequestCache]();
|
|
return this[abortControllerKey];
|
|
},
|
|
[getRequestCache]() {
|
|
this[abortControllerKey] ||= new AbortController();
|
|
return this[requestCache] ||= newRequestFromIncoming(
|
|
this.method,
|
|
this[urlKey],
|
|
this.headers,
|
|
this[incomingKey],
|
|
this[abortControllerKey]
|
|
);
|
|
}
|
|
};
|
|
[
|
|
"body",
|
|
"bodyUsed",
|
|
"cache",
|
|
"credentials",
|
|
"destination",
|
|
"integrity",
|
|
"mode",
|
|
"redirect",
|
|
"referrer",
|
|
"referrerPolicy",
|
|
"signal",
|
|
"keepalive"
|
|
].forEach((k) => {
|
|
Object.defineProperty(requestPrototype, k, {
|
|
get() {
|
|
return this[getRequestCache]()[k];
|
|
}
|
|
});
|
|
});
|
|
["arrayBuffer", "blob", "clone", "formData", "json", "text"].forEach((k) => {
|
|
Object.defineProperty(requestPrototype, k, {
|
|
value: function() {
|
|
return this[getRequestCache]()[k]();
|
|
}
|
|
});
|
|
});
|
|
Object.setPrototypeOf(requestPrototype, Request.prototype);
|
|
var newRequest = (incoming, defaultHostname) => {
|
|
const req = Object.create(requestPrototype);
|
|
req[incomingKey] = incoming;
|
|
const incomingUrl = incoming.url || "";
|
|
if (incomingUrl[0] !== "/" && // short-circuit for performance. most requests are relative URL.
|
|
(incomingUrl.startsWith("http://") || incomingUrl.startsWith("https://"))) {
|
|
if (incoming instanceof import_node_http2.Http2ServerRequest) {
|
|
throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
|
|
}
|
|
try {
|
|
const url2 = new URL(incomingUrl);
|
|
req[urlKey] = url2.href;
|
|
} catch (e) {
|
|
throw new RequestError("Invalid absolute URL", { cause: e });
|
|
}
|
|
return req;
|
|
}
|
|
const host = (incoming instanceof import_node_http2.Http2ServerRequest ? incoming.authority : incoming.headers.host) || defaultHostname;
|
|
if (!host) {
|
|
throw new RequestError("Missing host header");
|
|
}
|
|
let scheme;
|
|
if (incoming instanceof import_node_http2.Http2ServerRequest) {
|
|
scheme = incoming.scheme;
|
|
if (!(scheme === "http" || scheme === "https")) {
|
|
throw new RequestError("Unsupported scheme");
|
|
}
|
|
} else {
|
|
scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
|
|
}
|
|
const url = new URL(`${scheme}://${host}${incomingUrl}`);
|
|
if (url.hostname.length !== host.length && url.hostname !== host.replace(/:\d+$/, "")) {
|
|
throw new RequestError("Invalid host header");
|
|
}
|
|
req[urlKey] = url.href;
|
|
return req;
|
|
};
|
|
// Annotate the CommonJS export names for ESM import in node:
|
|
0 && (module.exports = {
|
|
GlobalRequest,
|
|
Request,
|
|
RequestError,
|
|
abortControllerKey,
|
|
getAbortController,
|
|
newRequest,
|
|
toRequestError,
|
|
wrapBodyStream
|
|
});
|