UNPKG

trpc-browser

Version:

tRPC adapters and links for everywhere in the browser

114 lines 5.71 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createWindowHandler = void 0; const server_1 = require("@trpc/server"); const observable_1 = require("@trpc/server/observable"); const shared_1 = require("@trpc/server/shared"); const constants_1 = require("../shared/constants"); const trpcMessage_1 = require("../shared/trpcMessage"); const errors_1 = require("./errors"); const createWindowHandler = (opts) => { var _a, _b; const { router, createContext, onError, window, postOrigin } = opts; if (!window) { console.warn("Skipping window handler creation: 'opts.window' not defined"); return; } const loadListener = (_b = (_a = opts.postWindow) !== null && _a !== void 0 ? _a : window.opener) !== null && _b !== void 0 ? _b : window; loadListener.postMessage(constants_1.TRPC_BROWSER_LOADED_EVENT, { targetOrigin: postOrigin }); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const { transformer } = router._def._config; const subscriptions = new Map(); const listeners = []; const cleanup = () => listeners.forEach((unsub) => unsub()); window.addEventListener('beforeunload', cleanup); listeners.push(() => window.removeEventListener('beforeunload', cleanup)); const onMessage = async (event) => { var _a, _b, _c; const { data: message, source } = event; const postWindow = (_b = (_a = opts.postWindow) !== null && _a !== void 0 ? _a : source) !== null && _b !== void 0 ? _b : window; if (!postWindow || !(0, trpcMessage_1.isTRPCRequestWithId)(message)) return; const { trpc } = message; const sendResponse = (response) => { postWindow.postMessage({ trpc: Object.assign({ id: trpc.id, jsonrpc: trpc.jsonrpc }, response), }, { targetOrigin: postOrigin }); }; if (trpc.method === 'subscription.stop') { (_c = subscriptions.get(trpc.id)) === null || _c === void 0 ? void 0 : _c.unsubscribe(); subscriptions.delete(trpc.id); return sendResponse({ result: { type: 'stopped' } }); } const { method, params, id } = trpc; const ctx = await (createContext === null || createContext === void 0 ? void 0 : createContext({ req: { origin: event.origin }, res: undefined })); const handleError = (cause) => { const error = (0, errors_1.getErrorFromUnknown)(cause); onError === null || onError === void 0 ? void 0 : onError({ error, type: method, path: params.path, input: params.input, ctx, req: { origin: event.origin }, }); sendResponse({ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment error: (0, shared_1.getErrorShape)({ config: router._def._config, error, type: method, path: params.path, input: params.input, ctx, }), }); }; try { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call const input = transformer.input.deserialize(trpc.params.input); const caller = router.createCaller(ctx); const procedureFn = trpc.params.path .split('.') // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-explicit-any .reduce((acc, segment) => acc[segment], caller); // eslint-disable-next-line @typescript-eslint/no-unsafe-argument const result = await procedureFn(input); if (trpc.method !== 'subscription') { return sendResponse({ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call result: { type: 'data', data: transformer.output.serialize(result) }, }); } if (!(0, observable_1.isObservable)(result)) { throw new server_1.TRPCError({ message: `Subscription ${params.path} did not return an observable`, code: 'INTERNAL_SERVER_ERROR', }); } const subscription = result.subscribe({ next: (data) => { const serializedData = transformer.output.serialize(data); sendResponse({ result: { type: 'data', data: serializedData } }); }, error: handleError, complete: () => sendResponse({ result: { type: 'stopped' } }), }); if (subscriptions.has(id)) { subscription.unsubscribe(); sendResponse({ result: { type: 'stopped' } }); throw new server_1.TRPCError({ message: `Duplicate id ${id}`, code: 'BAD_REQUEST' }); } listeners.push(() => subscription.unsubscribe()); subscriptions.set(id, subscription); sendResponse({ result: { type: 'started' } }); } catch (cause) { handleError(cause); } }; window.addEventListener('message', onMessage); listeners.push(() => window.removeEventListener('message', onMessage)); }; exports.createWindowHandler = createWindowHandler; //# sourceMappingURL=window.js.map