@fly/edge
Version:
Fly's TypeScript Edge
147 lines • 18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CachedCollection = exports.cachedCollection = exports.restAPI = void 0;
const data_1 = require("@fly/v8env/lib/fly/data");
const cache_1 = require("@fly/v8env/lib/fly/cache");
const apiPathPattern = /^\/([a-zA-Z0-9-_]+)(\/(.+))?$/;
/**
* Creates a REST API for updating the Fly k/v data store.
*
* ```typescript
* import { data } from "@fly/edge"
* const api = restAPI({authToken: "aSeCUrToken", basePath: "/__data/"});
* fly.http.respondWith(req => {
* const url = new URL(req.url);
* if(url.pathname.startsWith("/__data/")){
* return api(req);
* }
* return new Response('not found', { status: 404});
* })
* ```
*
* @param tokenOrOptions
*/
function restAPI(tokenOrOptions) {
const options = typeof tokenOrOptions === "string" ? { authToken: tokenOrOptions } : tokenOrOptions;
const { authToken, basePath } = options;
return async function fetchRest(req, init) {
if (typeof req === "string") {
req = new Request(req, init);
init = undefined;
}
const auth = (req.headers.get("Authorization") || "").split("Bearer ", 2);
if (auth.length < 2 || auth[1] !== authToken) {
return new Response("Access denied", { status: 403 });
}
const url = new URL(req.url);
let path = url.pathname;
if (basePath && path.startsWith(basePath) && path.length > basePath.length) {
path = path.substr(basePath.length);
}
if (!path.startsWith("/")) {
path = `/${path}`;
}
const match = path.match(apiPathPattern);
if (!match) {
return jsonResponse({ error: "not found" }, { status: 404 });
}
const colName = match[1];
let key = match[3];
if (!key) {
return jsonResponse({ error: "not found" }, { status: 404 });
}
const collection = cachedCollection(colName, options.cache);
let data;
switch (req.method) {
case "GET":
data = await collection.get(key);
if (data === null) {
return jsonResponse({ error: "not found" }, { status: 404 });
}
return jsonResponse(data, { status: 200 });
case "PUT":
data = await req.json();
await collection.put(key, data);
return jsonResponse(data, { status: 201 });
case "DELETE":
await collection.del(key);
return jsonResponse({ ok: true }, { status: 204 });
}
return jsonResponse({ error: "not found" }, { status: 404 });
};
}
exports.restAPI = restAPI;
/**
* Get a collection with a write through cache. Data retrieved from the collection will
* be cached in the current region. Put/Delete will expire a key globally.
* @param name
* @param opts
*/
function cachedCollection(name, opts) {
return new CachedCollection(name);
}
exports.cachedCollection = cachedCollection;
class CachedCollection extends data_1.Collection {
constructor(name, options) {
super(name);
this.options = options;
this.options = options;
}
async get(key) {
const cacheKey = this.toCacheKey(key);
const value = await cache_1.default.getString(key);
if (value) {
try {
return JSON.parse(value);
}
catch (err) {
console.error("CacheCollection: JSON parse failed. ", err.message);
// fall through on parse fail.
}
}
const result = await super.get(key);
await cache_1.default.set(cacheKey, typeof result !== "string" ? JSON.stringify(result) : result);
return super.get(key);
}
async del(key) {
const result = await super.del(key);
await expire(this.name, key, this.options);
return result;
}
async put(key, obj) {
const result = await super.put(key, obj);
await expire(this.name, key, this.options);
return result;
}
toCacheKey(key) {
if (this.options && this.options.toCacheKey) {
return this.options.toCacheKey(this.name, key);
}
return toCacheKey(this.name, key);
}
}
exports.CachedCollection = CachedCollection;
function jsonResponse(data, init) {
if (!init)
init = {};
init.headers = new Headers(init.headers);
init.headers.set("content-type", "application/json");
if (typeof data !== "string") {
data = JSON.stringify(data);
}
return new Response(data, init);
}
function toCacheKey(colName, key) {
return `db.${colName}(${key})`;
}
async function expire(collection, key, opts) {
let cacheKey;
if (opts && opts.toCacheKey) {
cacheKey = opts.toCacheKey(collection, key);
}
else {
cacheKey = toCacheKey(collection, key);
}
return cache_1.default.global.del(cacheKey);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGtEQUF5RDtBQUN6RCxvREFBNkM7QUFjN0MsTUFBTSxjQUFjLEdBQUcsK0JBQStCLENBQUE7QUFDdEQ7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCxTQUFnQixPQUFPLENBQUMsY0FBb0M7SUFDMUQsTUFBTSxPQUFPLEdBQUcsT0FBTyxjQUFjLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFDLFNBQVMsRUFBRSxjQUFjLEVBQUMsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDO0lBQ2xHLE1BQU0sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLEdBQUcsT0FBTyxDQUFDO0lBQ3hDLE9BQU8sS0FBSyxVQUFVLFNBQVMsQ0FBQyxHQUFHLEVBQUUsSUFBSTtRQUN2QyxJQUFHLE9BQU8sR0FBRyxLQUFLLFFBQVEsRUFBQztZQUN6QixHQUFHLEdBQUcsSUFBSSxPQUFPLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzdCLElBQUksR0FBRyxTQUFTLENBQUM7U0FDbEI7UUFDRCxNQUFNLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDMUUsSUFBRyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssU0FBUyxFQUFDO1lBQzFDLE9BQU8sSUFBSSxRQUFRLENBQUMsZUFBZSxFQUFFLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBQyxDQUFDLENBQUM7U0FDdEQ7UUFFRCxNQUFNLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDN0IsSUFBSSxJQUFJLEdBQUcsR0FB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UUFDekIsUUFBUSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0tBQzdDO1NBQUk7UUFDSCxRQUFRLEdBQUcsVUFBVSxDQUFDLFVBQVUsRUFBRSxHQUFHLENBQUMsQ0FBQztLQUN4QztJQUVELE9BQU8sZUFBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDcEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBkYiwgeyBDb2xsZWN0aW9uIH0gZnJvbSBcIkBmbHkvdjhlbnYvbGliL2ZseS9kYXRhXCI7XG5pbXBvcnQgY2FjaGUgZnJvbSBcIkBmbHkvdjhlbnYvbGliL2ZseS9jYWNoZVwiO1xuaW1wb3J0IHsgRmV0Y2hGdW5jdGlvbiB9IGZyb20gXCIuL2ZldGNoXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzdE9wdGlvbnN7XG4gIGF1dGhUb2tlbjogc3RyaW5nLFxuICBiYXNlUGF0aD86IHN0cmluZyxcbiAgY2FjaGU/OiBDYWNoZU9wdGlvbnNcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDYWNoZU9wdGlvbnN7XG4gIHR0bD86IG51bWJlcixcbiAgdG9DYWNoZUtleT86IChjb2xsZWN0aW9uOiBzdHJpbmcsIGtleTogc3RyaW5nKSA9PiBzdHJpbmdcbn1cblxuY29uc3QgYXBpUGF0aFBhdHRlcm4gPSAvXlxcLyhbYS16QS1aMC05LV9dKykoXFwvKC4rKSk/JC9cbi8qKlxuICogQ3JlYXRlcyBhIFJFU1QgQVBJIGZvciB1cGRhdGluZyB0aGUgRmx5IGsvdiBkYXRhIHN0b3JlLlxuICogXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBkYXRhIH0gZnJvbSBcIkBmbHkvZWRnZVwiXG4gKiBjb25zdCBhcGkgPSByZXN0QVBJKHthdXRoVG9rZW46IFwiYVNlQ1VyVG9rZW5cIiwgYmFzZVBhdGg6IFwiL19fZGF0YS9cIn0pO1xuICogZmx5Lmh0dHAucmVzcG9uZFdpdGgocmVxID0+IHtcbiAqICAgY29uc3QgdXJsID0gbmV3IFVSTChyZXEudXJsKTtcbiAqICAgaWYodXJsLnBhdGhuYW1lLnN0YXJ0c1dpdGgoXCIvX19kYXRhL1wiKSl7XG4gKiAgICAgcmV0dXJuIGFwaShyZXEpO1xuICogICB9XG4gKiAgIHJldHVybiBuZXcgUmVzcG9uc2UoJ25vdCBmb3VuZCcsIHsgc3RhdHVzOiA0MDR9KTtcbiAqIH0pXG4gKiBgYGBcbiAqIFxuICogQHBhcmFtIHRva2VuT3JPcHRpb25zIFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzdEFQSSh0b2tlbk9yT3B0aW9uczogc3RyaW5nIHwgUmVzdE9wdGlvbnMpOiBGZXRjaEZ1bmN0aW9ue1xuICBjb25zdCBvcHRpb25zID0gdHlwZW9mIHRva2VuT3JPcHRpb25zID09PSBcInN0cmluZ1wiID8ge2F1dGhUb2tlbjogdG9rZW5Pck9wdGlvbnN9IDogdG9rZW5Pck9wdGlvbnM7XG4gIGNvbnN0IHsgYXV0aFRva2VuLCBiYXNlUGF0aCB9ID0gb3B0aW9ucztcbiAgcmV0dXJuIGFzeW5jIGZ1bmN0aW9uIGZldGNoUmVzdChyZXEsIGluaXQpe1xuICAgIGlmKHR5cGVvZiByZXEgPT09IFwic3RyaW5nXCIpe1xuICAgICAgcmVxID0gbmV3IFJlcXVlc3QocmVxLCBpbml0KTtcbiAgICAgIGluaXQgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGNvbnN0IGF1dGggPSAocmVxLmhlYWRlcnMuZ2V0KFwiQXV0aG9yaXphdGlvblwiKSB8fCBcIlwiKS5zcGxpdChcIkJlYXJlciBcIiwgMik7XG4gICAgaWYoYXV0aC5sZW5ndGggPCAyIHx8IGF1dGhbMV0gIT09IGF1dGhUb2tlbil7XG4gICAgICByZXR1cm4gbmV3IFJlc3BvbnNlKFwiQWNjZXNzIGRlbmllZFwiLCB7IHN0YXR1czogNDAzfSk7XG4gICAgfVxuXG4gICAgY29uc3QgdXJsID0gbmV3IFVSTChyZXEudXJsKTtcbiAgICBsZXQgcGF0aCA9IHVybC5wYXRobmFtZTtcbiAgICBpZihiYXNlUGF0aCAmJiBwYXRoLnN0YXJ0c1dpdGgoYmFzZVBhdGgpICYmIHBhdGgubGVuZ3RoID4gYmFzZVBhdGgubGVuZ3RoKXtcbiAgICAgIHBhdGggPSBwYXRoLnN1YnN0cihiYXNlUGF0aC5sZW5ndGgpO1xuICAgIH1cbiAgICBpZighcGF0aC5zdGFydHNXaXRoKFwiL1wiKSl7XG4gICAgICBwYXRoID0gYC8ke3BhdGh9YDtcbiAgICB9XG5cbiAgICBjb25zdCBtYXRjaCA9IHBhdGgubWF0Y2goYXBpUGF0aFBhdHRlcm4pO1xuXG4gICAgaWYoIW1hdGNoKXtcbiAgICAgIHJldHVybiBqc29uUmVzcG9uc2Uoe2Vycm9yOiBcIm5vdCBmb3VuZFwifSwgeyBzdGF0dXM6IDQwNH0pXG4gICAgfVxuXG4gICAgY29uc3QgY29sTmFtZTogc3RyaW5nID0gbWF0Y2hbMV07XG4gICAgbGV0IGtleTogc3RyaW5nIHwgdW5kZWZpbmVkID0gbWF0Y2hbM107XG4gICAgaWYoIWtleSl7XG4gICAgICByZXR1cm4ganNvblJlc3BvbnNlKHtlcnJvcjogXCJub3QgZm91bmRcIn0sIHsgc3RhdHVzOiA0MDQgfSlcbiAgICB9XG5cbiAgICBjb25zdCBjb2xsZWN0aW9uID0gY2FjaGVkQ29sbGVjdGlvbihjb2xOYW1lLCBvcHRpb25zLmNhY2hlKTtcblxuICAgIGxldCBkYXRhOiBhbnk7XG4gICAgc3dpdGNoKHJlcS5tZXRob2Qpe1xuICAgICAgY2FzZSBcIkdFVFwiOlxuICAgICAgICBkYXRhID0gYXdhaXQgY29sbGVjdGlvbi5nZXQoa2V5KTtcbiAgICAgICAgaWYoZGF0YSA9PT0gbnVsbCl7XG4gICAgICAgICAgcmV0dXJuIGpzb25SZXNwb25zZSh7ZXJyb3I6IFwibm90IGZvdW5kXCJ9LCB7IHN0YXR1czogNDA0IH0pXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGpzb25SZXNwb25zZShkYXRhLCB7IHN0YXR1czogMjAwfSlcbiAgICAgIGNhc2UgXCJQVVRcIjpcbiAgICAgICAgZGF0YSA9IGF3YWl0IHJlcS5qc29uKCk7XG4gICAgICAgIGF3YWl0IGNvbGxlY3Rpb24ucHV0KGtleSwgZGF0YSk7XG4gICAgICAgIHJldHVybiBqc29uUmVzcG9uc2UoZGF0YSwgeyBzdGF0dXM6IDIwMX0pXG4gICAgICBjYXNlIFwiREVMRVRFXCI6XG4gICAgICAgIGF3YWl0IGNvbGxlY3Rpb24uZGVsKGtleSk7XG4gICAgICAgIHJldHVybiBqc29uUmVzcG9uc2Uoe29rOiB0cnVlfSwgeyBzdGF0dXM6IDIwNH0pXG4gICAgfVxuXG4gICAgcmV0dXJuIGpzb25SZXNwb25zZSh7ZXJyb3I6IFwibm90IGZvdW5kXCJ9LCB7IHN0YXR1czogNDA0fSlcbiAgfVxufVxuXG4vKipcbiAqIEdldCBhIGNvbGxlY3Rpb24gd2l0aCBhIHdyaXRlIHRocm91Z2ggY2FjaGUuIERhdGEgcmV0cmlldmVkIGZyb20gdGhlIGNvbGxlY3Rpb24gd2lsbFxuICogYmUgY2FjaGVkIGluIHRoZSBjdXJyZW50IHJlZ2lvbi4gUHV0L0RlbGV0ZSB3aWxsIGV4cGlyZSBhIGtleSBnbG9iYWxseS5cbiAqIEBwYXJhbSBuYW1lIFxuICogQHBhcmFtIG9wdHMgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjYWNoZWRDb2xsZWN0aW9uKG5hbWU6IHN0cmluZywgb3B0cz86IENhY2hlT3B0aW9ucyk6IENvbGxlY3Rpb257XG4gIHJldHVybiBuZXcgQ2FjaGVkQ29sbGVjdGlvbihuYW1lKTtcbn1cblxuZXhwb3J0IGNsYXNzIENhY2hlZENvbGxlY3Rpb24gZXh0ZW5kcyBDb2xsZWN0aW9ue1xuICBjb25zdHJ1Y3RvcihuYW1lOiBzdHJpbmcsIHB1YmxpYyByZWFkb25seSBvcHRpb25zPzogQ2FjaGVPcHRpb25zKXtcbiAgICBzdXBlcihuYW1lKTtcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICB9XG4gIHB1YmxpYyBhc3luYyBnZXQoa2V5OiBzdHJpbmcpe1xuICAgIGNvbnN0IGNhY2hlS2V5ID0gdGhpcy50b0NhY2hlS2V5KGtleSk7XG4gICAgY29uc3QgdmFsdWUgPSBhd2FpdCBjYWNoZS5nZXRTdHJpbmcoa2V5KTtcblxuICAgIGlmKHZhbHVlKXtcbiAgICAgIHRyeXtcbiAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UodmFsdWUpO1xuICAgICAgfWNhdGNoKGVycil7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJDYWNoZUNvbGxlY3Rpb246IEpTT04gcGFyc2UgZmFpbGVkLiBcIiwgZXJyLm1lc3NhZ2UpXG4gICAgICAgIC8vIGZhbGwgdGhyb3VnaCBvbiBwYXJzZSBmYWlsLlxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN1cGVyLmdldChrZXkpO1xuICAgIGF3YWl0IGNhY2hlLnNldChjYWNoZUtleSwgdHlwZW9mIHJlc3VsdCAhPT0gXCJzdHJpbmdcIiA/IEpTT04uc3RyaW5naWZ5KHJlc3VsdCkgOiByZXN1bHQpO1xuICAgIHJldHVybiBzdXBlci5nZXQoa2V5KTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBkZWwoa2V5OiBzdHJpbmcpe1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN1cGVyLmRlbChrZXkpXG4gICAgYXdhaXQgZXhwaXJlKHRoaXMubmFtZSwga2V5LCB0aGlzLm9wdGlvbnMpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgcHV0KGtleTogc3RyaW5nLCBvYmo6IGFueSl7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3VwZXIucHV0KGtleSwgb2JqKTtcbiAgICBhd2FpdCBleHBpcmUodGhpcy5uYW1lLCBrZXksIHRoaXMub3B0aW9ucyk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHB1YmxpYyB0b0NhY2hlS2V5KGtleTogc3RyaW5nKXtcbiAgICBpZih0aGlzLm9wdGlvbnMgJiYgdGhpcy5vcHRpb25zLnRvQ2FjaGVLZXkpe1xuICAgICAgcmV0dXJuIHRoaXMub3B0aW9ucy50b0NhY2hlS2V5KHRoaXMubmFtZSwga2V5KTtcbiAgICB9XG4gICAgcmV0dXJuIHRvQ2FjaGVLZXkodGhpcy5uYW1lLCBrZXkpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGpzb25SZXNwb25zZShkYXRhOiBhbnksIGluaXQ/OiBSZXNwb25zZUluaXQpe1xuICBpZighaW5pdCkgaW5pdCA9IHt9O1xuICBpbml0LmhlYWRlcnMgPSBuZXcgSGVhZGVycyhpbml0LmhlYWRlcnMpO1xuICBpbml0LmhlYWRlcnMuc2V0KFwiY29udGVudC10eXBlXCIsIFwiYXBwbGljYXRpb24vanNvblwiKTtcbiAgaWYodHlwZW9mIGRhdGEgIT09IFwic3RyaW5nXCIpe1xuICAgIGRhdGEgPSBKU09OLnN0cmluZ2lmeShkYXRhKTtcbiAgfVxuICByZXR1cm4gbmV3IFJlc3BvbnNlKGRhdGEsIGluaXQpXG59XG5cbmZ1bmN0aW9uIHRvQ2FjaGVLZXkoY29sTmFtZTogc3RyaW5nLCBrZXk6IHN0cmluZyl7XG4gIHJldHVybiBgZGIuJHtjb2xOYW1lfSgke2tleX0pYDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZXhwaXJlKGNvbGxlY3Rpb246IHN0cmluZywga2V5OiBzdHJpbmcsIG9wdHM/OiBDYWNoZU9wdGlvbnMpe1xuICBsZXQgY2FjaGVLZXk6IHN0cmluZztcbiAgaWYob3B0cyAmJiBvcHRzLnRvQ2FjaGVLZXkpe1xuICAgIGNhY2hlS2V5ID0gb3B0cy50b0NhY2hlS2V5KGNvbGxlY3Rpb24sIGtleSk7XG4gIH1lbHNle1xuICAgIGNhY2hlS2V5ID0gdG9DYWNoZUtleShjb2xsZWN0aW9uLCBrZXkpO1xuICB9XG5cbiAgcmV0dXJuIGNhY2hlLmdsb2JhbC5kZWwoY2FjaGVLZXkpO1xufSJdfQ==