trpc-browser
Version:
tRPC adapters and links for everywhere in the browser
110 lines • 5.52 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createChromeHandler = void 0;
const server_1 = require("@trpc/server");
const observable_1 = require("@trpc/server/observable");
const shared_1 = require("@trpc/server/shared");
const trpcMessage_1 = require("../shared/trpcMessage");
const errors_1 = require("./errors");
const createChromeHandler = (opts) => {
const { router, createContext, onError, chrome = global.chrome } = opts;
if (!chrome) {
console.warn("Skipping chrome handler creation: 'opts.chrome' not defined");
return;
}
chrome.runtime.onConnect.addListener((port) => {
// 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());
port.onDisconnect.addListener(cleanup);
listeners.push(() => port.onDisconnect.removeListener(cleanup));
const onMessage = async (message) => {
var _a;
if (!port || !(0, trpcMessage_1.isTRPCRequestWithId)(message))
return;
const { trpc } = message;
const sendResponse = (response) => {
port.postMessage({
trpc: Object.assign({ id: trpc.id, jsonrpc: trpc.jsonrpc }, response),
});
};
if (trpc.method === 'subscription.stop') {
(_a = subscriptions.get(trpc.id)) === null || _a === void 0 ? void 0 : _a.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: port, 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: port,
});
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);
}
};
port.onMessage.addListener(onMessage);
listeners.push(() => port.onMessage.removeListener(onMessage));
});
};
exports.createChromeHandler = createChromeHandler;
//# sourceMappingURL=chrome.js.map