@zpg6-test-pkgs/better-auth
Version:
The most comprehensive authentication library for TypeScript.
784 lines (773 loc) • 21.4 kB
JavaScript
import { AsyncLocalStorage } from 'node:async_hooks';
import 'defu';
function parse(str, options) {
if (typeof str !== "string") {
throw new TypeError("argument str must be a string");
}
const obj = {};
const opt = {};
const dec = opt.decode || decode;
let index = 0;
while (index < str.length) {
const eqIdx = str.indexOf("=", index);
if (eqIdx === -1) {
break;
}
let endIdx = str.indexOf(";", index);
if (endIdx === -1) {
endIdx = str.length;
} else if (endIdx < eqIdx) {
index = str.lastIndexOf(";", eqIdx - 1) + 1;
continue;
}
const key = str.slice(index, eqIdx).trim();
if (opt?.filter && !opt?.filter(key)) {
index = endIdx + 1;
continue;
}
if (void 0 === obj[key]) {
let val = str.slice(eqIdx + 1, endIdx).trim();
if (val.codePointAt(0) === 34) {
val = val.slice(1, -1);
}
obj[key] = tryDecode(val, dec);
}
index = endIdx + 1;
}
return obj;
}
function decode(str) {
return str.includes("%") ? decodeURIComponent(str) : str;
}
function tryDecode(str, decode2) {
try {
return decode2(str);
} catch {
return str;
}
}
const fieldContentRegExp = /^[\u0009\u0020-\u007E\u0080-\u00FF]+$/;
function serialize(name, value, options) {
const opt = options || {};
const enc = opt.encode || encodeURIComponent;
if (typeof enc !== "function") {
throw new TypeError("option encode is invalid");
}
if (!fieldContentRegExp.test(name)) {
throw new TypeError("argument name is invalid");
}
const encodedValue = enc(value);
if (encodedValue && !fieldContentRegExp.test(encodedValue)) {
throw new TypeError("argument val is invalid");
}
let str = name + "=" + encodedValue;
if (void 0 !== opt.maxAge && opt.maxAge !== null) {
const maxAge = opt.maxAge - 0;
if (Number.isNaN(maxAge) || !Number.isFinite(maxAge)) {
throw new TypeError("option maxAge is invalid");
}
str += "; Max-Age=" + Math.floor(maxAge);
}
if (opt.domain) {
if (!fieldContentRegExp.test(opt.domain)) {
throw new TypeError("option domain is invalid");
}
str += "; Domain=" + opt.domain;
}
if (opt.path) {
if (!fieldContentRegExp.test(opt.path)) {
throw new TypeError("option path is invalid");
}
str += "; Path=" + opt.path;
}
if (opt.expires) {
if (!isDate(opt.expires) || Number.isNaN(opt.expires.valueOf())) {
throw new TypeError("option expires is invalid");
}
str += "; Expires=" + opt.expires.toUTCString();
}
if (opt.httpOnly) {
str += "; HttpOnly";
}
if (opt.secure) {
str += "; Secure";
}
if (opt.priority) {
const priority = typeof opt.priority === "string" ? opt.priority.toLowerCase() : opt.priority;
switch (priority) {
case "low": {
str += "; Priority=Low";
break;
}
case "medium": {
str += "; Priority=Medium";
break;
}
case "high": {
str += "; Priority=High";
break;
}
default: {
throw new TypeError("option priority is invalid");
}
}
}
if (opt.sameSite) {
const sameSite = typeof opt.sameSite === "string" ? opt.sameSite.toLowerCase() : opt.sameSite;
switch (sameSite) {
case true: {
str += "; SameSite=Strict";
break;
}
case "lax": {
str += "; SameSite=Lax";
break;
}
case "strict": {
str += "; SameSite=Strict";
break;
}
case "none": {
str += "; SameSite=None";
break;
}
default: {
throw new TypeError("option sameSite is invalid");
}
}
}
if (opt.partitioned) {
str += "; Partitioned";
}
return str;
}
function isDate(val) {
return Object.prototype.toString.call(val) === "[object Date]" || val instanceof Date;
}
const defaults = Object.freeze({
ignoreUnknown: false,
respectType: false,
respectFunctionNames: false,
respectFunctionProperties: false,
unorderedObjects: true,
unorderedArrays: false,
unorderedSets: false,
excludeKeys: void 0,
excludeValues: void 0,
replacer: void 0
});
function objectHash(object, options) {
if (options) {
options = { ...defaults, ...options };
} else {
options = defaults;
}
const hasher = createHasher(options);
hasher.dispatch(object);
return hasher.toString();
}
const defaultPrototypesKeys = Object.freeze([
"prototype",
"__proto__",
"constructor"
]);
function createHasher(options) {
let buff = "";
let context = /* @__PURE__ */ new Map();
const write = (str) => {
buff += str;
};
return {
toString() {
return buff;
},
getContext() {
return context;
},
dispatch(value) {
if (options.replacer) {
value = options.replacer(value);
}
const type = value === null ? "null" : typeof value;
return this[type](value);
},
object(object) {
if (object && typeof object.toJSON === "function") {
return this.object(object.toJSON());
}
const objString = Object.prototype.toString.call(object);
let objType = "";
const objectLength = objString.length;
if (objectLength < 10) {
objType = "unknown:[" + objString + "]";
} else {
objType = objString.slice(8, objectLength - 1);
}
objType = objType.toLowerCase();
let objectNumber = null;
if ((objectNumber = context.get(object)) === void 0) {
context.set(object, context.size);
} else {
return this.dispatch("[CIRCULAR:" + objectNumber + "]");
}
if (typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(object)) {
write("buffer:");
return write(object.toString("utf8"));
}
if (objType !== "object" && objType !== "function" && objType !== "asyncfunction") {
if (this[objType]) {
this[objType](object);
} else if (!options.ignoreUnknown) {
this.unkown(object, objType);
}
} else {
let keys = Object.keys(object);
if (options.unorderedObjects) {
keys = keys.sort();
}
let extraKeys = [];
if (options.respectType !== false && !isNativeFunction(object)) {
extraKeys = defaultPrototypesKeys;
}
if (options.excludeKeys) {
keys = keys.filter((key) => {
return !options.excludeKeys(key);
});
extraKeys = extraKeys.filter((key) => {
return !options.excludeKeys(key);
});
}
write("object:" + (keys.length + extraKeys.length) + ":");
const dispatchForKey = (key) => {
this.dispatch(key);
write(":");
if (!options.excludeValues) {
this.dispatch(object[key]);
}
write(",");
};
for (const key of keys) {
dispatchForKey(key);
}
for (const key of extraKeys) {
dispatchForKey(key);
}
}
},
array(arr, unordered) {
unordered = unordered === void 0 ? options.unorderedArrays !== false : unordered;
write("array:" + arr.length + ":");
if (!unordered || arr.length <= 1) {
for (const entry of arr) {
this.dispatch(entry);
}
return;
}
const contextAdditions = /* @__PURE__ */ new Map();
const entries = arr.map((entry) => {
const hasher = createHasher(options);
hasher.dispatch(entry);
for (const [key, value] of hasher.getContext()) {
contextAdditions.set(key, value);
}
return hasher.toString();
});
context = contextAdditions;
entries.sort();
return this.array(entries, false);
},
date(date) {
return write("date:" + date.toJSON());
},
symbol(sym) {
return write("symbol:" + sym.toString());
},
unkown(value, type) {
write(type);
if (!value) {
return;
}
write(":");
if (value && typeof value.entries === "function") {
return this.array(
Array.from(value.entries()),
true
/* ordered */
);
}
},
error(err) {
return write("error:" + err.toString());
},
boolean(bool) {
return write("bool:" + bool);
},
string(string) {
write("string:" + string.length + ":");
write(string);
},
function(fn) {
write("fn:");
if (isNativeFunction(fn)) {
this.dispatch("[native]");
} else {
this.dispatch(fn.toString());
}
if (options.respectFunctionNames !== false) {
this.dispatch("function-name:" + String(fn.name));
}
if (options.respectFunctionProperties) {
this.object(fn);
}
},
number(number) {
return write("number:" + number);
},
xml(xml) {
return write("xml:" + xml.toString());
},
null() {
return write("Null");
},
undefined() {
return write("Undefined");
},
regexp(regex) {
return write("regex:" + regex.toString());
},
uint8array(arr) {
write("uint8array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
uint8clampedarray(arr) {
write("uint8clampedarray:");
return this.dispatch(Array.prototype.slice.call(arr));
},
int8array(arr) {
write("int8array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
uint16array(arr) {
write("uint16array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
int16array(arr) {
write("int16array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
uint32array(arr) {
write("uint32array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
int32array(arr) {
write("int32array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
float32array(arr) {
write("float32array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
float64array(arr) {
write("float64array:");
return this.dispatch(Array.prototype.slice.call(arr));
},
arraybuffer(arr) {
write("arraybuffer:");
return this.dispatch(new Uint8Array(arr));
},
url(url) {
return write("url:" + url.toString());
},
map(map) {
write("map:");
const arr = [...map];
return this.array(arr, options.unorderedSets !== false);
},
set(set) {
write("set:");
const arr = [...set];
return this.array(arr, options.unorderedSets !== false);
},
file(file) {
write("file:");
return this.dispatch([file.name, file.size, file.type, file.lastModfied]);
},
blob() {
if (options.ignoreUnknown) {
return write("[blob]");
}
throw new Error(
'Hashing Blob objects is currently not supported\nUse "options.replacer" or "options.ignoreUnknown"\n'
);
},
domwindow() {
return write("domwindow");
},
bigint(number) {
return write("bigint:" + number.toString());
},
/* Node.js standard native objects */
process() {
return write("process");
},
timer() {
return write("timer");
},
pipe() {
return write("pipe");
},
tcp() {
return write("tcp");
},
udp() {
return write("udp");
},
tty() {
return write("tty");
},
statwatcher() {
return write("statwatcher");
},
securecontext() {
return write("securecontext");
},
connection() {
return write("connection");
},
zlib() {
return write("zlib");
},
context() {
return write("context");
},
nodescript() {
return write("nodescript");
},
httpparser() {
return write("httpparser");
},
dataview() {
return write("dataview");
},
signal() {
return write("signal");
},
fsevent() {
return write("fsevent");
},
tlswrap() {
return write("tlswrap");
}
};
}
const nativeFunc = "[native code] }";
const nativeFuncLength = nativeFunc.length;
function isNativeFunction(f) {
if (typeof f !== "function") {
return false;
}
return Function.prototype.toString.call(f).slice(-nativeFuncLength) === nativeFunc;
}
function hasProp(obj, prop) {
try {
return prop in obj;
} catch {
return false;
}
}
var __defProp$2 = Object.defineProperty;
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField$2 = (obj, key, value) => {
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
class H3Error extends Error {
constructor(message, opts = {}) {
super(message, opts);
__publicField$2(this, "statusCode", 500);
__publicField$2(this, "fatal", false);
__publicField$2(this, "unhandled", false);
__publicField$2(this, "statusMessage");
__publicField$2(this, "data");
__publicField$2(this, "cause");
if (opts.cause && !this.cause) {
this.cause = opts.cause;
}
}
toJSON() {
const obj = {
message: this.message,
statusCode: sanitizeStatusCode(this.statusCode, 500)
};
if (this.statusMessage) {
obj.statusMessage = sanitizeStatusMessage(this.statusMessage);
}
if (this.data !== void 0) {
obj.data = this.data;
}
return obj;
}
}
__publicField$2(H3Error, "__h3_error__", true);
const DISALLOWED_STATUS_CHARS = /[^\u0009\u0020-\u007E]/g;
function sanitizeStatusMessage(statusMessage = "") {
return statusMessage.replace(DISALLOWED_STATUS_CHARS, "");
}
function sanitizeStatusCode(statusCode, defaultStatusCode = 200) {
if (!statusCode) {
return defaultStatusCode;
}
if (typeof statusCode === "string") {
statusCode = Number.parseInt(statusCode, 10);
}
if (statusCode < 100 || statusCode > 999) {
return defaultStatusCode;
}
return statusCode;
}
function setCookie$1(event, name, value, serializeOptions) {
serializeOptions = { path: "/", ...serializeOptions };
const cookieStr = serialize(name, value, serializeOptions);
let setCookies = event.node.res.getHeader("set-cookie");
if (!Array.isArray(setCookies)) {
setCookies = [setCookies];
}
const _optionsHash = objectHash(serializeOptions);
setCookies = setCookies.filter((cookieValue) => {
return cookieValue && _optionsHash !== objectHash(parse(cookieValue));
});
event.node.res.setHeader("set-cookie", [...setCookies, cookieStr]);
}
function splitCookiesString(cookiesString) {
if (Array.isArray(cookiesString)) {
return cookiesString.flatMap((c) => splitCookiesString(c));
}
if (typeof cookiesString !== "string") {
return [];
}
const cookiesStrings = [];
let pos = 0;
let start;
let ch;
let lastComma;
let nextStart;
let cookiesSeparatorFound;
const skipWhitespace = () => {
while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) {
pos += 1;
}
return pos < cookiesString.length;
};
const notSpecialChar = () => {
ch = cookiesString.charAt(pos);
return ch !== "=" && ch !== ";" && ch !== ",";
};
while (pos < cookiesString.length) {
start = pos;
cookiesSeparatorFound = false;
while (skipWhitespace()) {
ch = cookiesString.charAt(pos);
if (ch === ",") {
lastComma = pos;
pos += 1;
skipWhitespace();
nextStart = pos;
while (pos < cookiesString.length && notSpecialChar()) {
pos += 1;
}
if (pos < cookiesString.length && cookiesString.charAt(pos) === "=") {
cookiesSeparatorFound = true;
pos = nextStart;
cookiesStrings.push(cookiesString.slice(start, lastComma));
start = pos;
} else {
pos = lastComma + 1;
}
} else {
pos += 1;
}
}
if (!cookiesSeparatorFound || pos >= cookiesString.length) {
cookiesStrings.push(cookiesString.slice(start));
}
}
return cookiesStrings;
}
typeof setImmediate === "undefined" ? (fn) => fn() : setImmediate;
function sendStream(event, stream) {
if (!stream || typeof stream !== "object") {
throw new Error("[h3] Invalid stream provided.");
}
event.node.res._data = stream;
if (!event.node.res.socket) {
event._handled = true;
return Promise.resolve();
}
if (hasProp(stream, "pipeTo") && typeof stream.pipeTo === "function") {
return stream.pipeTo(
new WritableStream({
write(chunk) {
event.node.res.write(chunk);
}
})
).then(() => {
event.node.res.end();
});
}
if (hasProp(stream, "pipe") && typeof stream.pipe === "function") {
return new Promise((resolve, reject) => {
stream.pipe(event.node.res);
if (stream.on) {
stream.on("end", () => {
event.node.res.end();
resolve();
});
stream.on("error", (error) => {
reject(error);
});
}
event.node.res.on("close", () => {
if (stream.abort) {
stream.abort();
}
});
});
}
throw new Error("[h3] Invalid or incompatible stream provided.");
}
function sendWebResponse(event, response) {
for (const [key, value] of response.headers) {
if (key === "set-cookie") {
event.node.res.appendHeader(key, splitCookiesString(value));
} else {
event.node.res.setHeader(key, value);
}
}
if (response.status) {
event.node.res.statusCode = sanitizeStatusCode(
response.status,
event.node.res.statusCode
);
}
if (response.statusText) {
event.node.res.statusMessage = sanitizeStatusMessage(response.statusText);
}
if (response.redirected) {
event.node.res.setHeader("location", response.url);
}
if (!response.body) {
event.node.res.end();
return;
}
return sendStream(event, response.body);
}
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
class H3Event {
constructor(req, res) {
__publicField(this, "__is_event__", true);
// Context
__publicField(this, "node");
// Node
__publicField(this, "web");
// Web
__publicField(this, "context", {});
// Shared
// Request
__publicField(this, "_method");
__publicField(this, "_path");
__publicField(this, "_headers");
__publicField(this, "_requestBody");
// Response
__publicField(this, "_handled", false);
// Hooks
__publicField(this, "_onBeforeResponseCalled");
__publicField(this, "_onAfterResponseCalled");
this.node = { req, res };
}
// --- Request ---
get method() {
if (!this._method) {
this._method = (this.node.req.method || "GET").toUpperCase();
}
return this._method;
}
get path() {
return this._path || this.node.req.url || "/";
}
get headers() {
if (!this._headers) {
this._headers = _normalizeNodeHeaders(this.node.req.headers);
}
return this._headers;
}
// --- Respoonse ---
get handled() {
return this._handled || this.node.res.writableEnded || this.node.res.headersSent;
}
respondWith(response) {
return Promise.resolve(response).then(
(_response) => sendWebResponse(this, _response)
);
}
// --- Utils ---
toString() {
return `[${this.method}] ${this.path}`;
}
toJSON() {
return this.toString();
}
// --- Deprecated ---
/** @deprecated Please use `event.node.req` instead. */
get req() {
return this.node.req;
}
/** @deprecated Please use `event.node.res` instead. */
get res() {
return this.node.res;
}
}
function _normalizeNodeHeaders(nodeHeaders) {
const headers = new Headers();
for (const [name, value] of Object.entries(nodeHeaders)) {
if (Array.isArray(value)) {
for (const item of value) {
headers.append(name, item);
}
} else if (value) {
headers.set(name, value);
}
}
return headers;
}
const eventStorage = new AsyncLocalStorage();
function getEvent() {
const event = eventStorage.getStore();
if (!event) {
throw new Error(
`No HTTPEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`
);
}
return event;
}
const HTTPEventSymbol = Symbol("$HTTPEvent");
function isEvent(obj) {
return typeof obj === "object" && (obj instanceof H3Event || (obj == null ? void 0 : obj[HTTPEventSymbol]) instanceof H3Event || (obj == null ? void 0 : obj.__is_event__) === true);
}
function createWrapperFunction(h3Function) {
return function(...args) {
const event = args[0];
if (!isEvent(event)) {
args.unshift(getEvent());
} else {
args[0] = event instanceof H3Event || event.__is_event__ ? event : event[HTTPEventSymbol];
}
return h3Function(...args);
};
}
const setCookie = createWrapperFunction(setCookie$1);
export { H3Error, H3Event, HTTPEventSymbol, getEvent, isEvent, sanitizeStatusCode, sanitizeStatusMessage, setCookie, splitCookiesString };