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

@dbx-tools/appkit-shared

v0.1.13

Published

Shared utilities used by the other `@dbx-tools/appkit-*` plugins. The package has zero AppKit runtime dependency (it lists `@databricks/appkit` as a peer) so it's safe to consume from any plugin or app code.

Readme

@dbx-tools/appkit-shared

Shared utilities used by the other @dbx-tools/appkit-* plugins. The package has zero AppKit runtime dependency (it lists @databricks/appkit as a peer) so it's safe to consume from any plugin or app code.

Each utility module is exported as a namespace so call sites read naturally and never collide with similarly named helpers from other libraries:

import {
  apiUtils,
  commonUtils,
  httpUtils,
  logUtils,
  pluginUtils,
  projectUtils,
  stringUtils,
} from "@dbx-tools/appkit-shared";

apiUtils and projectUtils import Node-only modules (@databricks/appkit, node:fs) and are intentionally not re-exported from the browser entry. Vite / Webpack / esbuild builds that honor the browser condition will resolve @dbx-tools/appkit-shared to a barrel that omits both - import them only from server-side code.

pluginUtils - typed sibling-plugin lookup

AppKit's this.context.getPlugins() returns ReadonlyMap<string, BasePlugin>, so every cross-plugin call ends up writing the same as InstanceType<ReturnType<typeof someFactory>["plugin"]> cast. pluginUtils.instance / pluginUtils.require absorb that boilerplate:

import { lakebase } from "@databricks/appkit";
import { pluginUtils } from "@dbx-tools/appkit-shared";

const lake = pluginUtils.instance(this.context, lakebase);
//    ^^ inferred as LakebasePlugin | undefined
const pool = lake?.exports().pool;

// Throws "<caller>: required plugin not registered: lakebase" when missing.
const pool2 = pluginUtils
  .require(this.context, lakebase, "mastra")
  .exports().pool;

pluginUtils.data(factory) caches the static { plugin, name } descriptor per factory so repeated lookups don't allocate. Use it directly when you need the registered name for a manifest dependency.

httpUtils - framework-neutral request helpers

Public surface: joinUrlSegments, toURL, forEachHeaderValue, parseCookies. The header-shaped helpers work uniformly against any of:

  • Express req (Node-style req.headers)
  • Web Fetch Request (Headers instance)
  • Hono Context.req (c.req.raw.headers)
  • node:http IncomingMessage
  • Plain Record<string, string | string[] | undefined>
import { httpUtils } from "@dbx-tools/appkit-shared";

app.use((req, res, next) => {
  const session = httpUtils.parseCookies(req).session;

  // Walk every value of a (possibly repeated) header without committing
  // to a specific framework's accessor shape.
  let bearer: string | undefined;
  httpUtils.forEachHeaderValue(req, "authorization", (value) => {
    if (value.startsWith("Bearer ")) bearer = value.slice(7);
  });
});

// Tolerant URL coercion - bare hostnames, partial inputs, or
// objects with a `.url` field all round-trip through:
const url = httpUtils.toURL("example.com");  // https://example.com/

// Path-segment join: nullish/blank inputs are skipped, leading /
// trailing slashes are normalized, nested arrays recurse.
httpUtils.joinUrlSegments("/api/", ["v2", "items"], null); // "/api/v2/items"

apiUtils - authenticated Databricks REST calls (server only)

Wraps fetch against https://<workspace-host>/api/2.0/<path> with the auth header your AppKit execution context already carries, plus an optional CacheManager.getOrExecute hook so per-user TTL'd reads are a single positional arg:

import { apiUtils } from "@dbx-tools/appkit-shared";

// Bare GET against the workspace /api/2.0 namespace - leading /api/2.0
// is auto-stripped so you can pass either form.
const data = await apiUtils.fetchApi<{ endpoints?: unknown[] }>(
  "serving-endpoints",
);

// With a per-user cache (useful for "list everything" calls):
const cached = await apiUtils.fetchApi<{ endpoints?: unknown[] }>(
  "serving-endpoints",
  undefined,
  { userKey: req.userId, options: { ttl: 300 } },
);

// POST + custom client (e.g. service-account script outside a request).
await apiUtils.fetchApi<{ id: string }>(
  ["serving-endpoints", endpointName, "invocations"],
  {
    body: JSON.stringify({ inputs }),
    headers: { "Content-Type": "application/json" },
  },
  undefined,
  serviceClient,
);

Defaults to POST when init.body is set, GET otherwise. The wrapper needs an active getExecutionContext() to resolve the workspace client unless a WorkspaceClient is passed in explicitly, so it's server-only.

stringUtils - identifier + slug helpers

toIdentifier / toSlug are deterministic, length-bounded, and always lower-case at the type level (the lowerCase option literal is fixed to true so an explicit false is a compile error):

import { stringUtils } from "@dbx-tools/appkit-shared";

stringUtils.toIdentifier("My Cool Project!"); // "my_cool_project"
stringUtils.toSlug("My Cool Project!"); // "my-cool-project"

stringUtils.toIdentifierWithOptions({ maxLength: 12 }, "very long project name");
// "very_long_43c1"  <- hash suffix when truncated

projectUtils - project name + git-remote parsing

import { projectUtils } from "@dbx-tools/appkit-shared";

// Discovers a stable name for the current project. Order:
// 1. `package.json` name (root of an npm/bun workspace if applicable)
// 2. Closest `git remote origin` repo name
// 3. Process `cwd` basename
const name = await projectUtils.name();

// Strip "owner/" + ".git" from a remote URL.
projectUtils.parseGitRemote("[email protected]:org/my-repo.git"); // "my-repo"

commonUtils - memoize + hashing

import { commonUtils } from "@dbx-tools/appkit-shared";

// Memoize by all-args; sync results cache forever, async failures bust.
const fetchUser = commonUtils.memoize(async (id: string) => loadUser(id));

// Short, deterministic hash for cache keys / slug suffixes / etc.
// Pure-JS FNV-1a in Crockford-style base-32 (digits + lowercase
// alphabet minus i/l/o/u). Browser-safe.
commonUtils.fnvHash("databricks-claude-sonnet-4-6"); // e.g. "k3p9q7"
commonUtils.fnvHashWithOptions({ length: 4 }, "[email protected]");

@memoized is a TC39 stage-1 method decorator built on the same memoize (requires experimentalDecorators: true in tsconfig.json). fnvHash is intentionally not cryptographically secure - use it for keys and slugs, never for tokens or signatures.

logUtils - tagged console logger

logger(plugin) returns a leveled { debug, info, warn, error } interface that auto-tags every line with the plugin's name:

import { logUtils } from "@dbx-tools/appkit-shared";

class MyPlugin extends Plugin<MyConfig> {
  private log = logUtils.logger(this); // tags as "[my-plugin]"
  override async setup() {
    this.log.info("setup", { mode: this.config.mode });
  }
}

The logger is intentionally console-backed (no extra deps). For richer sinks pass your own { debug, info, warn, error } object - the plugins in this repo accept any matching shape.

LOG_LEVEL filtering

Each call checks process.env.LOG_LEVEL (case-insensitive, default info) and drops anything below the threshold before string formatting, so leaving log.debug({...heavy details}) calls in production code costs nothing as long as LOG_LEVEL isn't debug.

LOG_LEVEL=debug bun dev    # full verbosity
LOG_LEVEL=warn  bun start  # production: hide info chatter

The lookup is per-call (not module-load), so test runners can flip the threshold after the module has been imported. In browser bundles where process.env.LOG_LEVEL is undefined, the default info threshold applies.

License

Apache-2.0