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

@happyvertical/smrt-fields

v0.51.10

Published

Layered field policy store and resolver (defaults, visibility tiers, help text) for SMRT objects

Readme

@happyvertical/smrt-fields

@happyvertical/smrt-fields lets an application adjust an object's form defaults, labels, help, order, visibility, and locks without changing the object's source. Policies layer organization and personal choices over the code-authored field definition.

For the complete application and operator guide, see the field policy guide.

Install

pnpm add @happyvertical/smrt-fields

The package includes @happyvertical/smrt-users because policy writes and operator actions use its permission and tenant context services.

Define a safe code seed

The decorated model remains the definition of a field. Use its description and ui hints to supply a useful first form before any policy row exists.

import { field, SmrtObject, smrt } from '@happyvertical/smrt-core';

@smrt({ packageName: '@acme/billing' })
export class Invoice extends SmrtObject {
  @field({
    required: true,
    description: 'Shown on the customer invoice.',
    ui: { basic: true, group: 'billing', order: 1 },
  })
  title = '';

  @field({ ui: { basic: false, group: 'billing', order: 2 } })
  internalNotes = '';
}

If no field has ui.basic: true, fields start in the basic view. Once at least one field is marked basic, unmarked fields start advanced. group and order are code-owned hints; locked: true seeds a lock that can prevent a personal override.

Resolve on the server

Use the resolver in trusted server code when rendering SSR or applying a server-owned workflow. It merges code → app → tenant ancestry → user.

import { resolveFieldPolicy } from '@happyvertical/smrt-fields';

const policy = await resolveFieldPolicy(
  '@acme/billing:Invoice',
  { tenantId: requestTenant.id, userId: session.user.id, db },
);

const title = policy.fields.title;

The client-facing generated resolveBatch action derives the tenant and user from the authenticated request context. Do not accept those identifiers from a browser request. It returns only fields that are safe to expose; sensitive, transient, and read-permission-gated fields are omitted.

Use policy-aware Svelte forms

For a custom form, provide a resolved policy with FieldPolicyProvider and wrap each input in PolicyField. The wrapper applies visibility, labels, help, and new-record defaults while preserving your markup and input component.

<script lang="ts">
  import {
    FieldPolicyProvider,
    PolicyField,
  } from '@happyvertical/smrt-fields/svelte';

  let { policy, invoice = $bindable({}) } = $props();
</script>

<FieldPolicyProvider {policy}>
  <PolicyField name="title">
    <input id="title" bind:value={invoice.title} />
  </PolicyField>
</FieldPolicyProvider>

For generated forms, register the application's generated collection definitions once in an ObjectFormSourceRegistry, place it in an ObjectFormSourceProvider, then render an ObjectForm by canonical objectRef. The registry validates both the generated field definition and the resolveBatch response before rendering. See the guide for the complete setup, including field-specific input renderers and policy-aware tables.

Administration and personal settings

Use FieldPolicyGearProvider with an adapter to the generated getEditorState, create, update, and delete actions. It derives identity on the server; adapter methods intentionally do not accept tenant or user ids. Use FieldPolicyGearButton or showPolicyGear on ObjectForm to expose the editor.

For a settings destination, the server builds data with buildFieldPolicySettingsCatalog() and the browser renders it through FieldPolicyControlPanel. Hosts supply route, transport, confirmation, and AdminShell adapters. fieldPolicyControlPanelNavItem() and registerFieldPolicyFocusTool() are structural seams, so Fields does not take a dependency on a particular application shell.

fields.policy.manage permits app and tenant administration. fields.policy.personalize permits only the current user's personal choices. The host must still establish a trusted authenticated principal context and enforce the route permission before rendering an operator destination.

Important behavior

  • A policy row is sparse: null means inherit the lower layer. Delete a row to reset that scope completely.
  • defaultValue is the JSON-encoded wire channel. Server code with a plain value should use defaultValueRaw or setDefaultValue().
  • Required fields cannot be hidden or moved to advanced without a usable resolved default. Resolution forces a required, default-less field back to basic as a safety net.
  • App and tenant rows may lock a field. While the resolved organization policy is locked, personal writes are rejected and old personal rows do not apply.
  • Defaults are rejected for sensitive, transient, and read-permission-gated fields. Reference defaults must use a valid UUID unless that reference declares a text id type.

Usage learning

Optional usage capture records bounded, aggregated submissions from authenticated tenant members and turns qualified patterns into administrator-reviewed tenant-policy suggestions. It never auto-applies a suggestion. ObjectForm reports only after its host confirms persistence; browser values transit only for low-cardinality boolean and reference fields, and telemetry failures never affect the saved submit.

Operators enable the dormant maintenance and suggestion schedules explicitly with ensureFieldUsageLearningSchedules({ db }). The learning loop retains aggregates and uses conservative thresholds; its accepted/dismissed suggestion queue is restricted to fields.policy.manage. See the field policy guide for the capture, privacy, retention, and schedule contract.

Example application

The s-m-r-t SaaS starter field-policy walkthrough uses s-m-r-t 0.40.61 and shows the owner/admin controls and the member-facing personal form flow in a working application.