@upstash/workflow
Version:
Durable, Reliable and Performant Serverless Functions
380 lines (376 loc) • 11.2 kB
JavaScript
import {
SDK_TELEMETRY,
serveBase,
serveManyBase
} from "./chunk-BON2RKOR.mjs";
// node_modules/defu/dist/defu.mjs
function isPlainObject(value) {
if (value === null || typeof value !== "object") {
return false;
}
const prototype = Object.getPrototypeOf(value);
if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) {
return false;
}
if (Symbol.iterator in value) {
return false;
}
if (Symbol.toStringTag in value) {
return Object.prototype.toString.call(value) === "[object Module]";
}
return true;
}
function _defu(baseObject, defaults, namespace = ".", merger) {
if (!isPlainObject(defaults)) {
return _defu(baseObject, {}, namespace, merger);
}
const object = Object.assign({}, defaults);
for (const key in baseObject) {
if (key === "__proto__" || key === "constructor") {
continue;
}
const value = baseObject[key];
if (value === null || value === void 0) {
continue;
}
if (merger && merger(object, key, value, namespace)) {
continue;
}
if (Array.isArray(value) && Array.isArray(object[key])) {
object[key] = [...value, ...object[key]];
} else if (isPlainObject(value) && isPlainObject(object[key])) {
object[key] = _defu(
value,
object[key],
(namespace ? `${namespace}.` : "") + key.toString(),
merger
);
} else {
object[key] = value;
}
}
return object;
}
function createDefu(merger) {
return (...arguments_) => (
// eslint-disable-next-line unicorn/no-array-reduce
arguments_.reduce((p, c) => _defu(p, c, "", merger), {})
);
}
var defu = createDefu();
var defuFn = createDefu((object, key, currentValue) => {
if (object[key] !== void 0 && typeof currentValue === "function") {
object[key] = currentValue(object[key]);
return true;
}
});
var defuArrayFn = createDefu((object, key, currentValue) => {
if (Array.isArray(object[key]) && typeof currentValue === "function") {
object[key] = currentValue(object[key]);
return true;
}
});
// node_modules/h3/dist/index.mjs
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;
};
var H3Error = class 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);
function createError(input) {
if (typeof input === "string") {
return new H3Error(input);
}
if (isError(input)) {
return input;
}
const err = new H3Error(input.message ?? input.statusMessage ?? "", {
cause: input.cause || input
});
if (hasProp(input, "stack")) {
try {
Object.defineProperty(err, "stack", {
get() {
return input.stack;
}
});
} catch {
try {
err.stack = input.stack;
} catch {
}
}
}
if (input.data) {
err.data = input.data;
}
if (input.statusCode) {
err.statusCode = sanitizeStatusCode(input.statusCode, err.statusCode);
} else if (input.status) {
err.statusCode = sanitizeStatusCode(input.status, err.statusCode);
}
if (input.statusMessage) {
err.statusMessage = input.statusMessage;
} else if (input.statusText) {
err.statusMessage = input.statusText;
}
if (err.statusMessage) {
const originalMessage = err.statusMessage;
const sanitizedMessage = sanitizeStatusMessage(err.statusMessage);
if (sanitizedMessage !== originalMessage) {
console.warn(
"[h3] Please prefer using `message` for longer error messages instead of `statusMessage`. In the future, `statusMessage` will be sanitized by default."
);
}
}
if (input.fatal !== void 0) {
err.fatal = input.fatal;
}
if (input.unhandled !== void 0) {
err.unhandled = input.unhandled;
}
return err;
}
function isError(input) {
return input?.constructor?.__h3_error__ === true;
}
function isMethod(event, expected, allowHead) {
if (allowHead && event.method === "HEAD") {
return true;
}
if (typeof expected === "string") {
if (event.method === expected) {
return true;
}
} else if (expected.includes(event.method)) {
return true;
}
return false;
}
function assertMethod(event, expected, allowHead) {
if (!isMethod(event, expected, allowHead)) {
throw createError({
statusCode: 405,
statusMessage: "HTTP method is not allowed."
});
}
}
var RawBodySymbol = Symbol.for("h3RawBody");
var ParsedBodySymbol = Symbol.for("h3ParsedBody");
var PayloadMethods$1 = ["PATCH", "POST", "PUT", "DELETE"];
function readRawBody(event, encoding = "utf8") {
assertMethod(event, PayloadMethods$1);
const _rawBody = event._requestBody || event.web?.request?.body || event.node.req[RawBodySymbol] || event.node.req.rawBody || event.node.req.body;
if (_rawBody) {
const promise2 = Promise.resolve(_rawBody).then((_resolved) => {
if (Buffer.isBuffer(_resolved)) {
return _resolved;
}
if (typeof _resolved.pipeTo === "function") {
return new Promise((resolve, reject) => {
const chunks = [];
_resolved.pipeTo(
new WritableStream({
write(chunk) {
chunks.push(chunk);
},
close() {
resolve(Buffer.concat(chunks));
},
abort(reason) {
reject(reason);
}
})
).catch(reject);
});
} else if (typeof _resolved.pipe === "function") {
return new Promise((resolve, reject) => {
const chunks = [];
_resolved.on("data", (chunk) => {
chunks.push(chunk);
}).on("end", () => {
resolve(Buffer.concat(chunks));
}).on("error", reject);
});
}
if (_resolved.constructor === Object) {
return Buffer.from(JSON.stringify(_resolved));
}
if (_resolved instanceof URLSearchParams) {
return Buffer.from(_resolved.toString());
}
return Buffer.from(_resolved);
});
return encoding ? promise2.then((buff) => buff.toString(encoding)) : promise2;
}
if (!Number.parseInt(event.node.req.headers["content-length"] || "") && !String(event.node.req.headers["transfer-encoding"] ?? "").split(",").map((e) => e.trim()).filter(Boolean).includes("chunked")) {
return Promise.resolve(void 0);
}
const promise = event.node.req[RawBodySymbol] = new Promise(
(resolve, reject) => {
const bodyData = [];
event.node.req.on("error", (err) => {
reject(err);
}).on("data", (chunk) => {
bodyData.push(chunk);
}).on("end", () => {
resolve(Buffer.concat(bodyData));
});
}
);
const result = encoding ? promise.then((buff) => buff.toString(encoding)) : promise;
return result;
}
var 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;
}
var getSessionPromise = Symbol("getSession");
function defineEventHandler(handler) {
if (typeof handler === "function") {
handler.__is_handler__ = true;
return handler;
}
const _hooks = {
onRequest: _normalizeArray(handler.onRequest),
onBeforeResponse: _normalizeArray(handler.onBeforeResponse)
};
const _handler = (event) => {
return _callHandler(event, handler.handler, _hooks);
};
_handler.__is_handler__ = true;
_handler.__resolve__ = handler.handler.__resolve__;
_handler.__websocket__ = handler.websocket;
return _handler;
}
function _normalizeArray(input) {
return input ? Array.isArray(input) ? input : [input] : void 0;
}
async function _callHandler(event, handler, hooks) {
if (hooks.onRequest) {
for (const hook of hooks.onRequest) {
await hook(event);
if (event.handled) {
return;
}
}
}
const body = await handler(event);
const response = { body };
if (hooks.onBeforeResponse) {
for (const hook of hooks.onBeforeResponse) {
await hook(event, response);
}
}
return response.body;
}
var H3Headers = globalThis.Headers;
var H3Response = globalThis.Response;
// platforms/h3.ts
function transformHeaders(headers) {
const formattedHeaders = Object.entries(headers).map(([key, value]) => [
key,
Array.isArray(value) ? value.join(", ") : value ?? ""
]);
return formattedHeaders;
}
function getUrl(event) {
const request_ = event.node.req;
const protocol = request_.headers["x-forwarded-proto"];
const host = request_.headers.host;
const url = `${protocol}://${host}${event.path}`;
return url;
}
var telemetry = {
sdk: SDK_TELEMETRY,
framework: "h3",
runtime: process.versions.bun ? `bun@${process.versions.bun}/node@${process.version}` : `node@${process.version}`
};
var serve = (routeFunction, options) => {
const handler = defineEventHandler(async (event) => {
const method = event.node.req.method;
if (method?.toUpperCase() !== "POST") {
return new Response("Only POST requests are allowed in worklfows", {
status: 405
});
}
const url = getUrl(event);
const headers = transformHeaders(event.node.req.headers);
const request = new Request(url, {
headers,
body: await readRawBody(event),
method: "POST"
});
const { handler: serveHandler } = serveBase(routeFunction, telemetry, options);
return await serveHandler(request);
});
return { handler };
};
var createWorkflow = (...params) => {
const [routeFunction, options = {}] = params;
return {
routeFunction,
options,
workflowId: void 0
};
};
var serveMany = (workflows, options) => {
return serveManyBase({
workflows,
getUrl,
serveMethod: (...params) => serve(...params).handler,
options
});
};
export {
createWorkflow,
serve,
serveMany
};