### Install @domoinc/ryuu-proxy Source: https://github.com/domoapps/ryuu-proxy/blob/master/README.md Install the library as a development dependency using your preferred package manager. ```bash pnpm add -D @domoinc/ryuu-proxy # or npm install --save-dev @domoinc/ryuu-proxy # or yarn add -D @domoinc/ryuu-proxy ``` -------------------------------- ### Set HTTP Proxy Environment Variables Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Set these environment variables before starting your development server to enable corporate proxy support. Both standard and `REACT_APP_` prefixed variables are accepted. ```bash # Standard export PROXY_HOST=proxy.corp.example.com export PROXY_PORT=8080 export PROXY_USERNAME=jdoe # optional, for authenticated proxies export PROXY_PASSWORD=s3cr3t # optional # Create React App variant (also accepted) export REACT_APP_PROXY_HOST=proxy.corp.example.com export REACT_APP_PROXY_PORT=8080 # Then start your dev server as usual pnpm run start ``` -------------------------------- ### Run Vitest in Watch Mode Source: https://github.com/domoapps/ryuu-proxy/blob/master/CLAUDE.md Starts Vitest in watch mode, automatically re-running tests on file changes. ```bash pnpm run test:watch ``` -------------------------------- ### Handle DomoException in Node HTTP Proxy Stream Source: https://github.com/domoapps/ryuu-proxy/blob/master/README.md Catch DomoException to expose specific errors and set the appropriate HTTP status code. This example is for a basic Node.js HTTP server. ```javascript // node http const server = http.createServer((req, res) => { if (req.url === '/') { loadHomePage(); } else { proxy .stream(req) .then((stream) => stream.pipe(res)) .catch((err) => { if (err.name === 'DomoException') { res.writeHead(err.status || err.statusCode || 500); res.end(JSON.stringify(err)); } }); } }); ``` -------------------------------- ### Publish to npm (Beta) Source: https://github.com/domoapps/ryuu-proxy/blob/master/CLAUDE.md Builds the project and publishes a beta version to npm using the 'beta' dist-tag. ```bash pnpm run release:beta ``` -------------------------------- ### Initialize Proxy with Manifest Source: https://github.com/domoapps/ryuu-proxy/blob/master/README.md Initialize the Proxy class with your application's manifest configuration. Ensure the manifest has been published at least once. ```javascript import { Proxy } from '@domoinc/ryuu-proxy'; import manifest from './path/to/app/manifest.json' with { type: 'json' }; const proxy = new Proxy({ manifest }); ``` -------------------------------- ### Create Proxy Instance with createProxy Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Instantiate the proxy with required client, manifest, and domainUrl. The oauthTokens are optional and only needed for DQL, writeback, or OAuth apps. ```javascript import { createProxy } from '@domoinc/ryuu-proxy'; import { RyuuClient } from 'ryuu-client'; import manifest from './manifest.json' with { type: 'json' }; // Instantiate the underlying Domo client from your CLI session const client = new RyuuClient(manifest); const domainUrl = await client.getDomainUrl(); // e.g. 'https://abc123.domoapps.prod3.domo.com' const proxy = createProxy({ client, manifest, domainUrl, // oauthTokens: { access: '...', refresh: '...' }, // for DQL / writeback / OAuth apps }); // proxy.express() → Express/Connect middleware // proxy.stream(req) → Promise for any framework // proxy.isDomoRequest(url) → boolean ``` -------------------------------- ### Publish to npm (Latest) Source: https://github.com/domoapps/ryuu-proxy/blob/master/CLAUDE.md Builds the project and publishes the latest version to npm. ```bash pnpm run release:production ``` -------------------------------- ### Publish to npm (Alpha) Source: https://github.com/domoapps/ryuu-proxy/blob/master/CLAUDE.md Builds the project and publishes an alpha version to npm using the 'alpha' dist-tag. ```bash pnpm run release:alpha ``` -------------------------------- ### createProxy(config) Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Creates a proxy instance with the provided configuration. This instance offers methods for Express middleware, stream processing, and checking if a request is a Domo request. ```APIDOC ## createProxy(config) ### Description Creates a proxy instance by accepting a `ProxyConfig` object. This instance provides `express()`, `stream()`, and `isDomoRequest()` methods. The `client` and `domainUrl` fields are mandatory. The `oauthTokens` field is optional and is only required for applications utilizing DQL, writebacks, or OAuth features. ### Parameters #### Request Body - **client** (RyuuClient) - Required - An instance of the Domo client. - **manifest** (object) - Required - The application manifest. - **domainUrl** (string) - Required - The URL of the Domo instance. - **oauthTokens** (object) - Optional - An object containing `access` and `refresh` tokens, used for DQL, writeback, or OAuth apps. ### Request Example ```javascript import { createProxy } from '@domoinc/ryuu-proxy'; import { RyuuClient } from 'ryuu-client'; import manifest from './manifest.json' with { type: 'json' }; const client = new RyuuClient(manifest); const domainUrl = await client.getDomainUrl(); const proxy = createProxy({ client, manifest, domainUrl, // oauthTokens: { access: '...', refresh: '...' }, // for DQL / writeback / OAuth apps }); ``` ### Methods Provided by the Proxy Instance - `proxy.express()`: Returns an Express/Connect middleware function. - `proxy.stream(req)`: Returns a Promise that resolves to a readable stream for any framework. - `proxy.isDomoRequest(url)`: Returns a boolean indicating if the URL matches Domo request patterns. ``` -------------------------------- ### Bump Version with Standard Version Source: https://github.com/domoapps/ryuu-proxy/blob/master/CLAUDE.md Manually invokes standard-version for version bumping and changelog generation. ```bash pnpm exec standard-version ``` -------------------------------- ### Build and Compile TypeScript Source: https://github.com/domoapps/ryuu-proxy/blob/master/CLAUDE.md Use this command to clean the dist/ directory and compile TypeScript files. ```bash pnpm run build ``` -------------------------------- ### Format Code with Prettier Source: https://github.com/domoapps/ryuu-proxy/blob/master/CLAUDE.md Applies code formatting using Prettier. ```bash pnpm run format ``` -------------------------------- ### Run Vitest Suite Once Source: https://github.com/domoapps/ryuu-proxy/blob/master/CLAUDE.md Executes the Vitest test suite a single time. ```bash pnpm test ``` -------------------------------- ### Use Proxy with Express/Connect Source: https://github.com/domoapps/ryuu-proxy/blob/master/README.md Integrate the ryuu-proxy middleware into your Express or Connect application by using `proxy.express()`. ```javascript import express from 'express'; const app = express(); app.use(proxy.express()); ``` -------------------------------- ### Integrate with Express/Connect Middleware Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Mount the proxy.express() middleware before static file middleware. Non-Domo routes will fall through to the next handler. ```javascript import express from 'express'; import { createProxy } from '@domoinc/ryuu-proxy'; import { RyuuClient } from 'ryuu-client'; import manifest from './manifest.json' with { type: 'json' }; const app = express(); const client = new RyuuClient(manifest); const proxy = createProxy({ client, manifest, domainUrl: await client.getDomainUrl() }); // Mount the proxy before your static file middleware app.use(proxy.express()); // Non-Domo routes are unaffected app.use(express.static('public')); app.listen(3000, () => console.log('Dev server running on http://localhost:3000')); // In-browser fetch from the Domo app: // fetch('/data/v1/my-dataset?limit=100') → proxied to live Domo instance // fetch('/sql/v1/query', { method: 'POST', body: 'SELECT * FROM table' }) → proxied ``` -------------------------------- ### Clean Node Modules and Reinstall Source: https://github.com/domoapps/ryuu-proxy/blob/master/CLAUDE.md Removes node_modules and pnpm-lock.yaml, then reinstalls dependencies. ```bash pnpm run clean ``` -------------------------------- ### Run a Single Vitest File Source: https://github.com/domoapps/ryuu-proxy/blob/master/CLAUDE.md Executes a specific test file using Vitest. ```bash pnpm exec vitest run path/to/file.spec.ts ``` -------------------------------- ### proxy.express() - Error Handling (Express / Connect) Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Demonstrates how to implement error handling for proxy requests within an Express/Connect application by catching `DomoException` to forward appropriate error details. ```APIDOC ## proxy.express() - Error Handling ### Description Without error handling, failed proxy requests silently return `404`. Catch `DomoException` to forward the real HTTP status and error body to the client. ### Method Custom error handling middleware using `proxy.stream()` and `try...catch`. ### Usage Implement a middleware that calls `proxy.stream(req)` and handles potential `DomoException` errors. ### Request Example ```javascript import express from 'express'; import { createProxy } from '@domoinc/ryuu-proxy'; import { RyuuClient } from 'ryuu-client'; import manifest from './manifest.json' with { type: 'json' }; const app = express(); const client = new RyuuClient(manifest); const proxy = createProxy({ client, manifest, domainUrl: await client.getDomainUrl() }); app.use((req, res, next) => { proxy .stream(req) .then((stream) => { if (!stream) return next(); // non-Domo request stream.pipe(res); }) .catch((err) => { if (err.name === 'DomoException') { // err.status / err.statusCode → HTTP status (e.g. 401, 403, 404) // err.statusMessage → human-readable description res.status(err.status ?? err.statusCode ?? 500).json({ error: err.statusMessage, url: err.url, }); } else { next(err); } }); }); app.listen(3000); ``` ### Error Handling Details - `DomoException` objects contain `status`, `statusCode`, and `statusMessage` properties. - The error handling middleware forwards the HTTP status and error details to the client. ``` -------------------------------- ### Run Vitest with Coverage Source: https://github.com/domoapps/ryuu-proxy/blob/master/CLAUDE.md Executes the Vitest test suite and generates a code coverage report. ```bash pnpm run test:coverage ``` -------------------------------- ### getOauthTokens(instance, proxyId, scopes?) Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Retrieves scoped OAuth access and refresh tokens from the Domo CLI's local configstore for a specific `proxyId`. It returns an object with `access` and `refresh` tokens if they are present, or `undefined` if they have not been fetched yet. These tokens can be passed to `createProxy` for applications utilizing DQL, writebacks, or OAuth. ```APIDOC ## `getOauthTokens(instance, proxyId, scopes?)` — Retrieve OAuth Tokens Reads scoped OAuth access and refresh tokens from the Domo CLI's local configstore for a specific `proxyId`. Returns `{ access, refresh }` when tokens are present, or `undefined` if they have not been fetched yet. Pass the returned object as `oauthTokens` to `createProxy` for apps using DQL, writebacks, or OAuth. ``` -------------------------------- ### Retrieve OAuth Tokens for Domo Apps Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Fetches OAuth access and refresh tokens from the Domo CLI's local configstore for a specific proxy ID and instance. These tokens are required for apps using DQL, writebacks, or OAuth. ```js import { createProxy, getOauthTokens } from '@domoinc/ryuu-proxy'; import { RyuuClient } from 'ryuu-client'; import manifest from './manifest.json' with { type: 'json' }; const client = new RyuuClient(manifest); const domainUrl = await client.getDomainUrl(); // proxyId is extracted from the iframe URL of a published card: // //{proxyId}.domoapps.prod3.domo.com const proxyId = 'a1b2c3d4-e5f6-4789-abcd-ef1234567890'; const instance = 'mycompany.domo.com'; const oauthTokens = getOauthTokens(instance, proxyId); // oauthTokens → { access: 'eyJ...', refresh: 'eyJ...' } or undefined const proxy = createProxy({ client, manifest, domainUrl, oauthTokens, // injected as _daatv1 / _dartv1 cookies on every proxied request }); // With custom scopes (e.g., for writeback or DQL): const tokenWithScopes = getOauthTokens(instance, proxyId, ['data', 'audit']); ``` -------------------------------- ### Run a Single Vitest by Name Source: https://github.com/domoapps/ryuu-proxy/blob/master/CLAUDE.md Executes a specific test by its name using Vitest. ```bash pnpm exec vitest run -t "test name" ``` -------------------------------- ### proxy.express() - Express / Connect middleware Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Provides a standard Express/Connect middleware function that intercepts and proxies Domo-related requests, falling through to the next middleware for non-Domo requests. It automatically handles multipart/form-data uploads. ```APIDOC ## proxy.express() ### Description Returns a standard three-argument `(req, res, next)` middleware function. Requests matching Domo URL patterns are proxied and the response is piped back; all other requests fall through to `next()`. Multipart/form-data uploads are automatically handled. ### Method `app.use(proxy.express());` ### Usage Mount the proxy middleware before other middleware, such as static file serving. ### Request Example ```javascript import express from 'express'; import { createProxy } from '@domoinc/ryuu-proxy'; import { RyuuClient } from 'ryuu-client'; import manifest from './manifest.json' with { type: 'json' }; const app = express(); const client = new RyuuClient(manifest); const proxy = createProxy({ client, manifest, domainUrl: await client.getDomainUrl() }); // Mount the proxy before your static file middleware app.use(proxy.express()); // Non-Domo routes are unaffected app.use(express.static('public')); app.listen(3000, () => console.log('Dev server running on http://localhost:3000')); // In-browser fetch from the Domo app: // fetch('/data/v1/my-dataset?limit=100') → proxied to live Domo instance // fetch('/sql/v1/query', { method: 'POST', body: 'SELECT * FROM table' }) → proxied ``` ``` -------------------------------- ### Stream Requests with Plain Node http Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Demonstrates how to use ryuu-proxy's stream function with Node.js's built-in http module. It pipes the proxied response directly to the http response object. ```js import http from 'node:http'; import { createProxy } from '@domoinc/ryuu-proxy'; const proxy = createProxy({ client, manifest, domainUrl }); const server = http.createServer((req, res) => { const result = proxy.stream(req); if (!result) { // serve your app shell res.writeHead(200, { 'Content-Type': 'text/html' }); res.end('...'); return; } result .then((stream) => stream.pipe(res)) .catch((err) => { if (err.name === 'DomoException') { res.writeHead(err.status ?? err.statusCode ?? 500); res.end(JSON.stringify({ error: err.statusMessage })); } }); }); server.listen(3000); ``` -------------------------------- ### Check Code Formatting with Prettier Source: https://github.com/domoapps/ryuu-proxy/blob/master/CLAUDE.md Checks if the code adheres to Prettier formatting rules without modifying files. ```bash pnpm run format:check ``` -------------------------------- ### Proxy Stream for Koa Source: https://github.com/domoapps/ryuu-proxy/blob/master/README.md For Koa applications, use `proxy.stream(ctx.req)` to pipe the request stream to the response. ```javascript // koa app.use(async (ctx, next) => { await proxy .stream(ctx.req) .then((data) => (ctx.body = ctx.req.pipe(data))) .catch(next); }); ``` -------------------------------- ### Handle Proxy Errors with DomoException Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Demonstrates catching `DomoException` when a proxied request fails. This custom error object extends `Error` and provides context for meaningful error responses to the client. ```js import { createProxy } from '@domoinc/ryuu-proxy'; const proxy = createProxy({ client, manifest, domainUrl }); proxy.stream(req)?.catch((err) => { if (err.name === 'DomoException') { console.error({ name: err.name, // 'DomoException' statusCode: err.statusCode, // e.g. 401 error: err.error, // upstream error message url: err.url, // the URL that failed proxy: err.proxy, // guidance: run `domo login`, check manifest id }); /* { name: 'DomoException', statusCode: 401, error: 'Unauthorized', url: 'https://abc123.domoapps.prod3.domo.com/data/v1/my-alias', proxy: 'Ensure the app has been published at least once ...' } */ } }); ``` -------------------------------- ### proxy.stream(req) Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Handles streaming of responses from Domo URLs. It accepts a Node.js IncomingMessage and returns a Promise that resolves to a Response object for Domo URLs, or undefined for non-Domo URLs. The resolved response body can be piped directly to your framework's response object. ```APIDOC ## `proxy.stream(req)` — Framework-Agnostic Streaming Accepts a Node.js `IncomingMessage` (or any compatible superset) and returns `Promise` for Domo URLs, or `undefined` for non-Domo URLs. Pipe the resolved response body directly to your framework's response object. ``` -------------------------------- ### Stream Requests with Koa Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Handles streaming of incoming Node.js requests using the ryuu-proxy library within a Koa application. It pipes the response body directly to the Koa context's response. ```js import Koa from 'koa'; import { createProxy } from '@domoinc/ryuu-proxy'; const app = new Koa(); const proxy = createProxy({ client, manifest, domainUrl }); app.use(async (ctx, next) => { const result = proxy.stream(ctx.req); if (!result) return next(); await result .then((data) => { ctx.body = ctx.req.pipe(data); }) .catch((err) => { if (err.name === 'DomoException') { ctx.status = err.status ?? err.statusCode ?? 500; ctx.body = { error: err.statusMessage }; } else { return next(); } }); }); ``` -------------------------------- ### Handle Proxy Errors in Express/Connect Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Catch DomoException to forward the real HTTP status and error body to the client. Otherwise, failed proxy requests might silently return 404. ```javascript import express from 'express'; import { createProxy } from '@domoinc/ryuu-proxy'; import { RyuuClient } from 'ryuu-client'; import manifest from './manifest.json' with { type: 'json' }; const app = express(); const client = new RyuuClient(manifest); const proxy = createProxy({ client, manifest, domainUrl: await client.getDomainUrl() }); app.use((req, res, next) => { proxy .stream(req) .then((stream) => { if (!stream) return next(); // non-Domo request stream.pipe(res); }) .catch((err) => { if (err.name === 'DomoException') { // err.status / err.statusCode → HTTP status (e.g. 401, 403, 404) // err.statusMessage → human-readable description res.status(err.status ?? err.statusCode ?? 500).json({ error: err.statusMessage, url: err.url, }); } else { next(err); } }); }); app.listen(3000); ``` -------------------------------- ### Proxy Stream for Node HTTP Server Source: https://github.com/domoapps/ryuu-proxy/blob/master/README.md For a basic Node.js http server, proxy requests using `proxy.stream(req)` and pipe the resulting stream to the response. ```javascript // node http import http from 'node:http'; const server = http.createServer((req, res) => { if (req.url === '/') { loadHomePage(res); } else { proxy.stream(req).then((stream) => stream.pipe(res)); } }); ``` -------------------------------- ### proxy.isDomoRequest(url) Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Checks if a given URL string matches any of the Domo proxy patterns. This is useful for implementing conditional logic within custom middleware or routing layers. ```APIDOC ## `proxy.isDomoRequest(url)` — URL Pattern Check Returns `true` if the given URL string matches any of the Domo proxy patterns. Useful for conditional logic in custom middleware or routing layers. ``` -------------------------------- ### DomoException Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Represents an error that occurs during a proxied request. This exception extends the standard `Error` object and includes additional context such as `statusCode`, `error` message, `url`, and `proxy` guidance, which can be used to provide meaningful error feedback to the client. ```APIDOC ## `DomoException` — Proxy Error Shape `DomoException` is thrown (and should be caught) when a proxied request fails. It extends `Error` and carries enough context to surface a meaningful error response to the browser client. ``` -------------------------------- ### Handle DomoException in Express/Connect Proxy Stream Source: https://github.com/domoapps/ryuu-proxy/blob/master/README.md Catch DomoException to expose specific errors and set the appropriate HTTP status code. If the error is not a DomoException, pass control to the next middleware. ```javascript // express / connect app.use((req, res, next) => { proxy .stream(req) .then((stream) => stream.pipe(res)) .catch((err) => { if (err.name === 'DomoException') { res.status(err.status || err.statusCode || 500).json(err); } else { next(); } }); }); ``` -------------------------------- ### Check Domo Request URL Patterns Source: https://context7.com/domoapps/ryuu-proxy/llms.txt Utilizes the `isDomoRequest` function to determine if a given URL string matches Domo's proxy patterns. This is useful for conditional routing in custom middleware. ```js import { createProxy } from '@domoinc/ryuu-proxy'; const proxy = createProxy({ client, manifest, domainUrl }); // Matched patterns proxy.isDomoRequest('/data/v1/my-alias'); // true proxy.isDomoRequest('/data/v2/dataset?limit=50'); // true proxy.isDomoRequest('/sql/v1/query'); // true proxy.isDomoRequest('/dql/v1/alias'); // true proxy.isDomoRequest('/domo/users/v1'); // true proxy.isDomoRequest('/domo/avatars/v1'); // true proxy.isDomoRequest('/api/data/v2/datasources'); // true // Not matched proxy.isDomoRequest('/index.html'); // false proxy.isDomoRequest('/data/no-version'); // false proxy.isDomoRequest(undefined); // false ``` -------------------------------- ### Handle DomoException in Koa Proxy Stream Source: https://github.com/domoapps/ryuu-proxy/blob/master/README.md Catch DomoException to expose specific errors and set the appropriate HTTP status code. If the error is not a DomoException, pass control to the next middleware. ```javascript // koa app.use(async (ctx, next) => { await proxy .stream(ctx.req) .then((data) => (ctx.body = ctx.req.pipe(data))) .catch((err) => { if (err.name === 'DomoException') { ctx.status = err.status || err.statusCode || 500; ctx.body = err; } else { next(); } }); }); ``` -------------------------------- ### Proxy Stream for Express Source: https://github.com/domoapps/ryuu-proxy/blob/master/README.md In Express, pipe the stream returned by `proxy.stream(req)` directly to the response object. ```javascript // express app.use((req, res, next) => { proxy .stream(req) .then((stream) => stream.pipe(res)) .catch(() => next()); }); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.