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

@spinajs/configuration-http

v3.0.26

Published

API for configuration module. Allows to set / get configuration values from db

Readme

@spinajs/configuration-http

HTTP API for reading and updating database-stored configuration values managed by @spinajs/configuration-db-source.

It exposes a read + update CRUD surface over the configuration table. Entries themselves are created by code that exposes config options (expose: true), so this API intentionally does not create or delete arbitrary entries — it only lets operators tune existing values.

Documentation

Full documentation: docs/configuration-http.

Endpoints

| Method | Path | Permission | Description | | ------ | ---------------------- | ---------------------- | ----------------------------------------------- | | GET | /configuration | configuration:read | List all entries (optional ?group= filter) | | GET | /configuration/:slug | configuration:read | Get a single entry by slug | | PATCH | /configuration/:slug | configuration:update | Update an entry's Value (+ Default/Watch) |

Every route is guarded by @Access (@spinajs/authz-http): 401 without a principal, 403 without the permission. The checks are type-level. Row limits come from the ORM: the package registers DbConfig as the configuration access resource (registerAccessResource), so a conditional grant limits the list and the entries GET and PATCH load. A principal that may update but not read gets 404 on PATCH, because the entry load needs configuration:read.

Incoming values are validated against the entry Type and Meta constraints (min/max, oneOf/manyOf, date bounds) and stored in their canonical string form.

Value schemas

An entry can carry its own JSON schema. Register a schema in @spinajs/validation whose $id equals the config path passed to @Config(path, { expose: true, ... }), e.g. a file in system.dirs.schemas:

{
  "$id": "legacy.v1.reports.financial_full",
  "type": "string",
  "pattern": "\\.xlsx$"
}

PATCH /configuration/:slug then validates Value and Default against the entry Type / Meta and that schema. The schema describes the JSON value as sent to the API (an ISO string for date, an array for manyOf, an object for json), not the typed runtime value. Entries without a registered schema are validated by Type / Meta only.

Schemas are compiled by ajv in strict mode: custom keywords (including x-* annotations) and formats must be registered with the validator, otherwise updates of that entry fail with a 500 and the error is logged.

The @spinajs/validation options apply to the incoming value: with useDefaults the schema's defaults are written into object / array values before they are stored (so they are fixed at write time), coerceTypes coerces values, and with removeAdditional unknown properties are stripped instead of rejected.

File uploads

Entries of type: 'file' with meta.file ( see @spinajs/configuration-db-source ) are uploaded through the ConfigFileUploads service. This package has no file route: the project composes the service in its own controller and owns everything after acceptance ( history, download, archive ).

const accepted = await uploads.accept(entry, file);   // 400 on a broken rule / validator / schema
try {
  await recordSomewhere(accepted);                    // the project's history row
} catch (err) {
  await uploads.discard(accepted);
  throw err;
}
await uploads.commit(entry, accepted.fileName);       // Value = stored name

The multipart temp file is removed inside accept; anything the caller does before entering accept (a permission check, a lookup) owns it until then and must remove it on its own failure path.

accept, in order: rejects with NotAFileEntry an entry that is not a file entry; with ConfigFileRejected an original name over 255 characters, an extension over 16 characters, a file over maxSize, an extension outside extensions, a content-detected mime type outside mimeTypes ( FileInfoService from @spinajs/fs ), a file the entry validator rejects with ValidationFailed ( its message is the response message ) and a generated name that fails the value schema of the slug; an unregistered validator name or fs provider throws an Error. The file is stored as <original base name>-<yyyyMMdd-HHmmss UTC>.<ext> ( characters outside [\w.-] replaced with _, the base cut to 100 characters, file when empty ); a name that already exists on the provider is refused.

commit is the only way a file entry's Value should change outside a PATCH; a project's "restore an earlier version" goes through it too. PATCH never moves or removes files.

Permissions

The package declares configuration:read and configuration:update (both with field sets) and the role admin.configuration, which holds both. It is not assignable; admin extends it. No other role gets access, because values can hold secrets.

All routes use fields: 'filter': a grant with fields.read hides the other fields (for example Value) in responses, and fields.write limits what PATCH accepts. The PATCH response is filtered by the fields.read of the update decision, not of the read grant.

ConfigFileUploads.commit does no authz check of its own. Guard the project's upload route with @Access('configuration:update').

Persistence of exposed options and the watch poll of @spinajs/configuration-db-source run as SYSTEM. This package opts in with requireSystemPrincipal(); they start after the root authz service boots.

Notes

Writes are persisted to the database only. The running application picks up the change through the db-source watch poll, and only for entries with Watch = true.