${text}
` + + `You can close this window and go back to Loopable.
`, + ); +} + +function escape(text: string): string { + return text.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]!); +} + +/** + * Where the browser comes back after a connector's authorization. The attempt + * says which connector and workspace; the state is the only proof needed. + */ +async function oauthCallback(connectorId: string, url: URL, response: ServerResponse): Promise