npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sbroenne/dvq

v0.1.5

Published

CLI for querying Dataverse OData endpoints with Azure CLI credentials

Readme

dvq

dvq is a small CLI and Node.js library for querying Dataverse OData endpoints with Azure CLI credentials.

What exists today

  • CLI for running OData paths against /api/data/v9.2/
  • Azure authentication via az login
  • Pretty-printed JSON output
  • Library helpers for URL building, token acquisition, single requests, and paginated requests

Install

npm install @sbroenne/dvq

Run without installing:

npx @sbroenne/dvq --help

Requirements

  • Node.js 20 or later
  • Azure CLI (az)
  • Access to a Dataverse environment

Authenticate once before using the CLI or library:

az login

For development and release validation, npm test runs the unit suite and npm run test:integration runs the live Dataverse checks when .env.integration is configured.

Configuration

Set the base environment URL:

export DATAVERSE_URL="https://yourorg.crm.dynamics.com"

You can also pass --url on the CLI instead of setting DATAVERSE_URL.

By default, dvq requests Dataverse formatted-value annotations so OptionSet labels and other display values are present in responses. Use --no-formatted-values to disable that default, or --header to add custom request headers when debugging environment-specific behavior.

Use --verbose to emit request tracing to stderr. This is useful when you need to see the exact request URL, pagination flow, and sanitized headers without mixing trace output into the JSON response on stdout.

CLI quick start

The query is an OData path relative to /api/data/v9.2/.

dvq "accounts?$top=5"

With an explicit URL:

dvq --url "https://yourorg.crm.dynamics.com" "accounts?$select=name&$top=5"

From a file:

dvq --file query.odata

From stdin:

echo "accounts?$top=5" | dvq --url "https://yourorg.crm.dynamics.com"

Verify auth and connectivity:

dvq --whoami

Disable formatted-value annotations for a leaner payload or to isolate header-related issues:

dvq --url "https://yourorg.crm.dynamics.com" --no-formatted-values "accounts?$top=5"

Add custom request headers:

dvq --url "https://yourorg.crm.dynamics.com" -H "ConsistencyLevel: eventual" "accounts?$top=5"

Trace auth, request, and pagination flow to stderr:

dvq --verbose --url "https://yourorg.crm.dynamics.com" --all "accounts?$select=name&$top=5"

Follow @odata.nextLink pages automatically:

dvq --all "accounts?$select=name"

CLI usage

dvq [options] [query]

| Option | Argument | Description | | --- | --- | --- | | [query] | OData path | Inline query path after /api/data/v9.2/ | | -f, --file | <path> | Read the OData path from a file | | -a, --all | — | Follow @odata.nextLink pages up to the built-in safety cap | | -u, --url | <url> | Use this Dataverse base URL instead of DATAVERSE_URL | | -v, --verbose | — | Print auth/request/pagination tracing to stderr | | --no-formatted-values | — | Do not send the default Prefer header for formatted values | | -H, --header | <name:value> | Add a request header; may be repeated | | --whoami | — | Call WhoAmI and print the response | | --version | — | Print the package version | | --help | — | Show help text |

Notes:

  • If neither [query] nor --file is given, dvq reads stdin when input is piped.
  • Without --all, the CLI prints the first JSON response object exactly as returned by Dataverse.
  • With --all, the CLI prints a JSON array aggregated across pages.
  • By default, dvq sends Prefer: odata.include-annotations="OData.Community.Display.V1.FormattedValue".
  • --verbose writes tracing to stderr and never prints the bearer token.

Library API

The package currently exports low-level helpers from src/lib.ts, not a single high-level query() function.

Common request flow

import { buildUrl, fetchOData, getToken } from '@sbroenne/dvq';

const baseUrl = 'https://yourorg.crm.dynamics.com';
const token = await getToken({ baseUrl });
const url = buildUrl('accounts?$top=5', baseUrl);
const data = await fetchOData(url, token);

console.log(data);

Fetch all pages

import { getToken, queryAll } from '@sbroenne/dvq';

const baseUrl = 'https://yourorg.crm.dynamics.com';
const token = await getToken({ baseUrl });
const rows = await queryAll('accounts?$select=name', token, baseUrl);

console.log(rows);

Main exports

| Export | Purpose | | --- | --- | | resolveDataverseUrl, getDataverseUrl | Resolve the Dataverse base URL from an explicit value or DATAVERSE_URL | | getDataverseScope | Build the /.default scope for Azure auth | | buildUrl | Build a full Dataverse Web API URL from an OData path | | buildHeaders | Create request headers for Dataverse JSON calls, with optional annotation/header overrides | | getToken | Acquire an access token using AzureCliCredential | | fetchOData | Execute one HTTP request and parse the JSON response, with optional request overrides | | queryAll | Follow paginated @odata.nextLink responses and return one array, with optional request overrides | | readQueryFile, readStdin | CLI-oriented input helpers | | ODataError | Error type for non-2xx HTTP responses | | API_PATH, DEFAULT_API_PATH, MAX_PAGES | Public constants used by the helpers |

Errors and behavior

Missing configuration:

DATAVERSE_URL environment variable is required.

Authentication failure:

Failed to get token. Run:
  az login
Target: https://yourorg.crm.dynamics.com

queryAll() stops after MAX_PAGES pages and throws if the safety cap is exceeded.

Dataverse request failures now include the request URL and, when possible, a targeted troubleshooting hint. Example for the header-related 400 seen on some entity reads:

HTTP 400: Both header name and value should be specified.
URL: https://yourorg.crm.dynamics.com/api/data/v9.2/msp_accountteams?$top=5
Hint: Dataverse rejected a request header. Retry with formatted values disabled to isolate the default Prefer header, and review any custom headers.

Contributing

See CONTRIBUTING.md.

Security

Please do not report suspected vulnerabilities in public issues. See SECURITY.md for the current reporting path and maintainer security checklist.

License

MIT © 2026 sbroenne