UNPKG

masto

Version:

Mastodon API client for JavaScript, TypeScript, Node.js, browsers

82 lines (81 loc) 2.07 kB
import { snakeCase } from "change-case"; import { noop } from "../../utils/noop.js"; export const createActionProxy = (actionDispatcher, options = {}) => { const { context = [], applicable = false } = options; let target = {}; const handler = { get: get(actionDispatcher, context), }; if (applicable) { target = noop; handler.apply = apply(actionDispatcher, context); } return new Proxy(target, handler); }; const SPECIAL_PROPERTIES = new Set([ "then", "catch", "finally", "inspect", "toString", "valueOf", "toJSON", "constructor", "prototype", "length", "name", "caller", "callee", "arguments", "bind", "apply", "call", ]); const get = (actionDispatcher, context) => (_, property) => { if (typeof property === "string" && SPECIAL_PROPERTIES.has(property)) { return; } if (property === Symbol.dispose) { return actionDispatcher[Symbol.dispose]; } if (typeof property === "symbol") { return; } if (property.startsWith("$")) { return createActionProxy(actionDispatcher, { context: [...context, property], applicable: true, }); } return createActionProxy(actionDispatcher, { context: [...context, snakeCase(property)], applicable: true, }); }; const apply = (actionDispatcher, context) => (_1, _2, args) => { let action = context.pop(); let raw = false; if (action === "$select") { return createActionProxy(actionDispatcher, { context: [...context, ...args], applicable: true, }); } if (action === "$raw") { action = context.pop(); raw = true; } /* c8 ignore next 3 */ if (!action) { throw new Error("No action specified"); } const path = "/" + context.join("/"); const [data, meta] = args; return actionDispatcher.dispatch({ type: action, path, data, meta: meta, raw, }); };