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

obm-upload-form-ui

v0.3.6

Published

Reusable UI component library for rendering and submitting OpenBioMaps upload forms via obm-project-api

Downloads

1,107

Readme

obm-upload-form-ui

npm version pipeline status license

A reusable UI component library for rendering and submitting OpenBioMaps upload forms, built on the obm-project-api v3 form schema (GET /forms, GET /forms/{publishedFormId}, POST /forms/{formId}).

Status: v0, work in progress. Photo/attachment upload (file_id/photo_id fields, ADR 0007) is implemented. The spatial and custom_check validation rules are not evaluated client-side and report as "unsupported". ADR 0008 records why spatial stays that way (the boundary geometry is in the schema, but as hex EWKB, and it's enforced server-side anyway). ADR 0009 records why custom_check stays that way (it names arbitrary project-specific server PHP with no generic contract to mirror — and its one dispatch path turns out to have been broken, an uncaught server error, since 2019, unreachable in practice).

Installation

npm install obm-upload-form-ui

The /custom-elements entry point is also published to npm, so no-build hosts can load it straight from a CDN mirror instead of installing it, e.g.:

<script
  type="module"
  src="https://cdn.jsdelivr.net/npm/obm-upload-form-ui/dist/custom-elements/obm-upload-form.js"
></script>

Packages in one repo

| Entry point | What it is | Dependencies | | ------------------------------------ | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------- | | obm-upload-form-ui | Framework-free core: typed form schema, API client, validation engine, submit client, WKT↔GeoJSON utilities | none | | obm-upload-form-ui/vue | Vue 3 field widgets and the <UploadForm> orchestrator | vue (peer) | | obm-upload-form-ui/vue-leaflet | Leaflet-based geometry field widget | vue, leaflet, leaflet-draw (peers) | | obm-upload-form-ui/custom-elements | Self-contained <obm-upload-form> custom element (ES + IIFE bundles, Vue inlined) for no-build hosts | none |

Quick start (core)

import {
  createFormApi,
  cookieAuth,
  validateForm,
  canSubmit,
  submitObservation,
  buildMetadata,
} from 'obm-upload-form-ui';

const config = {
  baseUrl: 'https://example.org/projects/my_project/api/v3',
  language: 'en', // sent as Accept-Language (lowercased); localizes column short_name only
  appVersion: 'my-app 1.0.0',
  auth: cookieAuth(),
};

const api = createFormApi(config);
const forms = await api.listForms();
const schema = await api.getForm(forms[0].published_form_id);

const data = { species: 'Lanius collurio', number: 5 };
const result = validateForm(schema, data, 'final');
if (canSubmit(result)) {
  const live = await api.resolveLiveForm(schema.header.published_form_id);
  await submitObservation(config, {
    formId: live.formId,
    data,
    metadata: buildMetadata({ formVersion: live.formVersion, appVersion: config.appVersion }),
  });
}

Validation model

The API currently performs no field-level validation on write (it proxies to the legacy upload engine), so this library's validation engine is the enforcement layer. See docs/adr/0002-validation-policy-model.md:

  • Document states: draft (skips checks by default, matching existing OBM client behavior) and final (enforces).
  • soft rules warn but never block.
  • ValidationPolicy.enforcement can be set to 'warn' to make all validation non-blocking once server-side validation exists.

Linked submissions (repeated groups)

The form schema has no repeated/nested field groups. The established OBM convention is separate linked forms sharing a client-generated UUID as a foreign key. submitLinked() orchestrates this: one parent POST plus N child POSTs, all stamped with the shared id. There is no server-side transaction — partial failure is reported per item (failed + remaining), and resumeLinked(config, plan, result) finishes the submission under the same shared id, posting only the items not yet accepted. Don't retry by calling submitLinked() again: it re-posts the parent, which a unique shared-id column refuses (or, without one, duplicates). Note that remaining excludes the failed item itself; outstandingItems(result) lists both.

Development

npm install
npm test              # unit + component tests (integration tests skip without OBM_API_BASE)
npm run dev           # Storybook
npm run build         # library + custom-elements bundles into dist/
npm run typecheck
npm run lint

Testing against a live API

Contract fixtures under tests/fixtures/forms/ prefixed synthetic- are hand-derived from the API source, not captured responses. Replace them with real captures:

OBM_API_BASE=https://example.org/projects/my_project/api/v3 OBM_ACCESS_TOKEN=... npm run capture:fixtures
OBM_API_BASE=... npm run test:integration

Note: the API allows localhost/127.0.0.1 origins only when its ENV != PROD.

Demo app

demo/ is a Vite app deployable into an OBM project via the spa_integration module. See docs/spa-integration-deployment.md for build/packaging constraints and known host-side bugs.

npm run demo:dev      # local dev server
npm run demo:build    # dist + dist-archives/<appName>.zip ready for upload

Releases

Versioning, CHANGELOG.md, GitLab Releases, and npm publishing are all automated by semantic-release from commit messages on main — see .releaserc.json. Use Conventional Commits prefixes (feat:, fix:, docs:, refactor:, etc.) so the pipeline can compute the next version correctly; a feat: commit triggers a minor release, fix:/docs:/refactor:/... trigger a patch release, and a BREAKING CHANGE: footer (or ! after the type) triggers a major release. See docs/adr/0004-release-and-publish-strategy.md for the full pipeline design.

Publishing to npm uses Trusted Publishing (OIDC) — the CI pipeline exchanges a short-lived GitLab-issued token for a one-time npm publish token, so no long-lived NPM_TOKEN is stored in the project. See docs/adr/0005-npm-trusted-publishing.md for the setup and the one-time manual bootstrap it required.

Design documents

  • Architecture decisions: docs/adr/
  • Live-verification checklist (what automated tests cannot cover): docs/live-verification.md
  • Findings and production-readiness verdict from the THR SPA rebuild (0.3.0 → 0.3.5): docs/reviews/002-thr-spa-rebuild.md
  • Upstream feasibility study: web-app/docs/architecture/upload-form-component-library-feasibility-study.md

License

GPL-3.0-or-later, matching the OpenBioMaps ecosystem. Note: GPL on a library means consumers must be GPL-compatible; if embedding into non-GPL third-party apps ever becomes a goal, LGPL would be the deliberate alternative — relicensing later requires all contributors' consent (see ADR 0001).