Skip to content

Repository files navigation

@domoinc/ryuu-proxy

npm versioninstall sizenpm downloadstypeslicenseKnown Vulnerabilities

Middleware for local Domo App development. It intercepts calls to Domo data/API endpoints and proxies authenticated requests to your Domo instance, so you can develop against real data from your local dev server.

Table of Contents

Features

  • Intercepts and proxies Domo API traffic: /data/v{d}, /sql/v{d}, /dql/v{d}, /domo/.../v{d}, /api/...
  • Drop-in Express / Connect middleware via proxy.express()
  • Framework-agnostic proxy.stream(req) for Koa, Node http, Fastify, etc.
  • Handles multipart/form-data uploads (file streams via busboy)
  • Injects OAuth access/refresh tokens for apps using DQL, writeback, or OAuth features
  • Reads auth from your existing Domo CLI login session — no extra config
  • Ships with TypeScript types
  • ESM package

Requirements

  • Node.js 18+
  • An active Domo CLI session (domo login) — see @ryuu
  • A project manifest.json that has been published at least once (domo publish)
  • Peer: express ^4.17.0 || ^5.0.0 (only required if you use proxy.express())

Installation

pnpm add -D @domoinc/ryuu-proxy
# or
npm install --save-dev @domoinc/ryuu-proxy
# or
yarn add -D @domoinc/ryuu-proxy

Usage

This library leverages the last login session from your Domo CLI. If that session is no longer active or doesn't exist, the proxy won't work. Log in before starting your dev server:

domo login

Configuration

import{Proxy}from'@domoinc/ryuu-proxy';importmanifestfrom'./path/to/app/manifest.json'with{type: 'json'};constproxy=newProxy({ manifest });

The Proxy constructor accepts a config object.

Required

  • manifest — parsed contents of your project's manifest.json. domo publish must have been run at least once so the manifest has an id.

Optional

  • manifest.proxyId — required for apps using DQL, writebacks, or OAuth. If you're unsure, you probably don't need it. See Getting a proxyId.
importexpressfrom'express';constapp=express();app.use(proxy.express());

With Other Frameworks

For other frameworks, stream() returns a readable stream you can pipe back to your response. It accepts a standard Node IncomingMessage, which most frameworks extend.

// koaapp.use(async(ctx,next)=>{awaitproxy.stream(ctx.req).then((data)=>(ctx.body=ctx.req.pipe(data))).catch(next);});
// expressapp.use((req,res,next)=>{proxy.stream(req).then((stream)=>stream.pipe(res)).catch(()=>next());});
// node httpimporthttpfrom'node:http';constserver=http.createServer((req,res)=>{if(req.url==='/'){loadHomePage(res);}else{proxy.stream(req).then((stream)=>stream.pipe(res));}});

Error Handling

Ignoring errors causes the proxy to fail silently and the request returns 404. To expose errors, catch DomoException and forward the status:

// koaapp.use(async(ctx,next)=>{awaitproxy.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();}});});
// express / connectapp.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();}});});
// node httpconstserver=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));}});}});

DomoException shape:

FieldDescription
nameAlways "DomoException"
status / statusCodeHTTP status code
statusMessageError description

HTTP Proxy Support

If you sit behind a corporate HTTP proxy, set any of the following environment variables. REACT_APP_-prefixed variants are also honored for Create React App projects.

VariablePurpose
PROXY_HOST / REACT_APP_PROXY_HOSTProxy hostname
PROXY_PORT / REACT_APP_PROXY_PORTProxy port
PROXY_USERNAME / REACT_APP_PROXY_USERNAMEBasic auth username (optional)
PROXY_PASSWORD / REACT_APP_PROXY_PASSWORDBasic auth password (optional)

Getting a proxyId (Advanced)

Apps using DQL, writeback, or OAuth features must supply a proxyId in the proxy configuration so the proxy can route requests correctly. A proxyId is of the form XXXXXXXX-XXXX-4XXX-XXXX-XXXXXXXXXXXX. To find it:

  1. Ensure the app has been published at least once with domo publish.
  2. Publish a new card from your app design, or open an existing card built from it.
  3. Right-click the card and choose Inspect element.
  4. Find the <iframe> containing your app. Its URL looks like //{HASH}.domoapps.prodX.domo.com?userId=....
  5. Copy the hash between // and .domoapps — that is your proxyId.

proxyIds tie apps to cards. If you delete the card you pulled the ID from, you'll need a new one from another card created from the same app design.

Related Packages

  • ryuu — the Domo CLI (domo login, domo publish, etc.)
  • ryuu-client — underlying Domo API client

Contributing

Workflow

  1. Create a branch (e.g. DOMO-XXXXXX)
  2. Make and commit changes
  3. Test — optionally publish an alpha/beta for integration testing
  4. Open a pull request
  5. After merge to master, bump the version and release to npm

Scripts

ScriptDescription
pnpm run buildCompile TypeScript to dist/
pnpm testRun the test suite (vitest)
pnpm run test:watchRun vitest in watch mode
pnpm run test:coverageRun tests with coverage
pnpm run formatFormat source with Prettier
pnpm run release:productionBuild and publish to npm
pnpm run release:betaBuild and publish under the beta tag
pnpm run release:alphaBuild and publish under the alpha tag

Versioning

This project uses standard-version with conventional commits to determine version bumps.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

10 stars

Watchers

20 watching

Forks

Releases

Packages

Used by

Contributors

Languages