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

@aplinkosministerija/dbsis-rest

v0.2.1

Published

REST-style client and HTTP gateway for the Lithuanian DBSIS (Dokumentų valdymo bendroji informacinė sistema) SOAP API. Wraps WS-Security UsernameToken auth, SOAP envelope construction, MTOM-friendly base64 attachments and JSON↔XML mapping so DBSIS web ser

Readme

dbsis-rest

REST-style Node.js client and HTTP gateway for the Lithuanian DBSIS (Dokumentų valdymo bendroji informacinė sistema) SOAP API.

DBSIS exposes ~85 SOAP operations across 11 web services (RDODocumentWS, OrgStructWS, ClassifierWS, JournalWS, OfficeCaseWS, TemplateWS, TDODocumentWS, …). Calling them directly requires:

  • hand-crafted SOAP 1.1 envelopes with WS-Security UsernameToken authentication,
  • xsi:type annotations on every Map entry value so the server picks the right Java class,
  • careful namespace bookkeeping (org:, cls:, jrl: …),
  • MTOM-style base64 attachments,
  • parsing the SOAP response into something usable.

This package handles all of the above and lets you call any operation as a JS function or as a JSON HTTP request:

const { createClient } = require('@aplinkosministerija/dbsis-rest');

const dbsis = createClient({
  baseUrl: process.env.DBSIS_BASE_URL,        // https://dbsis.lt/dbsis
  username: process.env.DBSIS_USERNAME,
  password: process.env.DBSIS_PASSWORD,
});

const { documentInfo } = await dbsis.documents.createDocumentFromTemplate({
  documentFromTemplateParam: {
    docAttributes: {
      entry: [
        { key: 'title', value: { $type: 'xs:string', $text: 'My title' } },
        { key: 'receivers', value: {
            $type: 'org:OrgNodeListParam',
            orgNode: { $type: 'org:OrgNodeCodeParam', code: '188774822' },
        }},
      ],
    },
    templateParam: { oid: 'inc1.188774822' },
    register: false,
    project: false,
  },
});

console.log(documentInfo.oid); // -> "c89099f0bec611e593e2d8d76fa79d4c"

Or run the bundled REST gateway and call each operation as JSON:

DBSIS_BASE_URL=https://dbsis.lt/dbsis \
DBSIS_USERNAME=integration_user \
DBSIS_PASSWORD=...                   \
npx dbsis-rest serve

curl -X POST http://localhost:3000/api/documents/getDocument \
  -H 'content-type: application/json' \
  -d '{"getDocumentParam":{"docOid":"c89099f0..."}}'

The gateway and the JS client share the same operation catalogue, so anything documented in the DBSIS spec can be invoked uniformly.


Installation

npm install @aplinkosministerija/dbsis-rest

Node.js ≥ 18 is required.

Configuration

Configuration is read from environment variables only — credentials are never hard-coded or sent over HTTP from the gateway. Copy .env.example to .env and fill in real values:

| Variable | Required | Notes | | --- | --- | --- | | DBSIS_BASE_URL | yes | e.g. https://dbsis.lt/dbsis. The package appends the per-service path (/ws-cxf/RDODocumentWS, /ws-cxf/OrgStructWS, …) automatically — see Service URL mapping below. | | DBSIS_USERNAME | yes | Dedicated integration user as recommended by the DBSIS team. | | DBSIS_PASSWORD | yes | The password is sent in WS-Security UsernameToken / PasswordText form, so HTTPS is mandatory. | | DBSIS_TIMEOUT_MS | no | HTTP timeout, default 60 000 ms (matches DBSIS server-side timeout). | | PORT | no | Gateway port, default 3000. | | GATEWAY_TOKEN | no | If set, the REST gateway requires Authorization: Bearer <token> on every request. |

Recommended: do not check .env into git. The package ships with a .gitignore that excludes it.

Service URL mapping

The live Apache CXF / Avilys DBSIS deployment exposes each SOAP service under <base>/ws-cxf/<ServiceName> (verified against the running endpoints, e.g. <base>/ws-cxf/RDODocumentWS?wsdl). The package uses these defaults — override them via the servicePaths constructor option if your installation differs.

| Alias | Prefix | Path | DBSIS service | | --- | --- | --- | --- | | documents | rdod | /ws-cxf/RDODocumentWS | RDODocumentWS — registered documents | | tasks | tdod | /ws-cxf/TDODocumentWS | TDODocumentWS — tasks | | contracts | cdod | /ws-cxf/CDODocumentWS | Contracts (sutartys) | | subst | subs | /ws-cxf/SubstDocumentWS | SubstDocumentWS — pavadavimai | | org | org | /ws-cxf/OrgStructWS | OrgStructWS | | classifiers | cls | /ws-cxf/ClassifierWS | ClassifierWS | | journals | jrl | /ws-cxf/JournalWS | JournalWS — registers | | officeCases | ofc | /ws-cxf/OfficeCaseWS | OfficeCaseWS — bylos | | templates | tpl | /ws-cxf/TemplateWS | TemplateWS | | documentSorts | dso | /ws-cxf/DocumentSortWS | DocumentSortWS | | linkTypes | lnk | /ws-cxf/LinkTypeWS | LinkTypeWS |

MTOM/XOP responses. The CXF endpoints return responses as multipart/related (MTOM). parseSoapResponse transparently extracts the SOAP envelope from the multipart wrapper, so callers get plain JSON as usual.

SOAPAction. The endpoints dispatch by the SOAP body element and register their operations with an empty SOAPAction; the client sends "" by default (override per call via soapAction).

Programmatic API

const { createClient } = require('@aplinkosministerija/dbsis-rest');
const dbsis = createClient({ baseUrl, username, password });

// Each service exposes one async method per documented SOAP operation:
await dbsis.documents.getDocument({ getDocumentParam: { docOid: '...' } });
await dbsis.org.getOrgUnit({ orgName: 'org.lt.root' });
await dbsis.classifiers.getClsEntryList({ getClsEntryListParam: { className: 'clsDocPrivacy' } });

// Operation discovery:
dbsis.documents.$operations;       // [ 'createDocumentFromTemplate', 'getDocument', ... ]
dbsis.documents.$invoke(name, p);  // dynamic dispatch by string name

// Low-level escape hatch — call any SOAP operation, even one not in the
// catalogue, on any service prefix:
await dbsis.invoke({
  servicePrefix: 'rdod',
  operation: 'getDocument',
  params: { getDocumentParam: { docOid: '...' } },
  extraNamespaces: ['doc'],
});

Building request payloads

The DBSIS SOAP body uses two non-trivial XML constructs — Map entries with typed values, and namespaced child elements. The package exposes them through three special object keys:

| Key | Effect | | --- | --- | | $type | Adds xsi:type="<value>" to the element. Use a prefix that matches a known namespace (xs:string, org:OrgNodeListParam, …). The relevant xmlns: declaration is added to the envelope automatically. | | $text | Inline text content. Useful when you also need attributes. | | $attrs | Plain XML attributes (e.g. wsu:Id). |

Arrays produce repeating sibling elements — exactly what the DBSIS entry/item/receivers lists need:

{
  docAttributes: {
    entry: [
      { key: 'title', value: { $type: 'xs:string', $text: 'Hello' } },
      { key: 'note',  value: { $type: 'xs:string', $text: 'World' } },
    ],
  },
}

Buffer values are automatically base64-encoded — useful when uploading ADOC/PDF attachments via bodyAttachment.content.

null becomes xsi:nil="true". Dates become ISO-8601 strings.

Recipe: create an outgoing document (RDO_OUT) project with a PDF

A complete, working createDocumentFromTemplate that uploads a plain PDF as the document body and wires the approval/signing chain. This is the shape that actually works against a live Avilys tenant — see Gotchas below for the non-obvious parts.

// 1. Create the sending-document PROJECT from a template, with the PDF inline.
const { documentInfo } = await dbsis.documents.createDocumentFromTemplate({
  documentFromTemplateParam: {
    docAttributes: {
      entry: [
        { key: 'title',     value: { $type: 'xs:string',  $text: 'Leidimas Nr. 002-G-2026' } },
        // isElectro=false for a plain PDF body — `true` demands an ADOC/PDF-LT
        // electronic *package*, not a plain application/pdf attachment.
        { key: 'isElectro', value: { $type: 'xs:boolean', $text: 'false' } },
        { key: 'senders',    value: { $type: 'org:OrgNodeListParam', orgNode: { $type: 'org:OrgNodeParam', orgName: 'org.unit.…' } } },
        { key: 'receivers',  value: { $type: 'org:OrgNodeListParam', orgNode: { $type: 'org:OrgNodeParam', orgName: 'org.unit.…' } } },
        { key: 'preparedBy', value: { $type: 'org:OrgNodeListParam', orgNode: { $type: 'org:OrgNodeParam', orgName: 'org.import…' } } },
        { key: 'draftJournal',    value: { $type: 'jrl:JournalParam',    oid: '…' } },
        // draftOfficeCase is a SINGLE OfficeCaseParam{oid} — NOT an OfficeCaseListParam.
        { key: 'draftOfficeCase', value: { $type: 'ofc:OfficeCaseParam', oid: '…' } },
        { key: 'documentProcess', value: { $type: 'xs:string', $text: '…' } },
        { key: 'sort',   value: { $type: 'cls:ClsEntryParam', oid: '…' } },
        { key: 'nature', value: { $type: 'cls:ClsEntryParam', clsid: 'clsNature.PP' } },
      ],
    },
    // The PDF is the document BODY — an AttachmentActionParam via `bodyAttachment`
    // (inherited from ModifyDocumentParam). There is NO `eDocumentFile` field.
    bodyAttachment: {
      type: 'clsDHSAttaType.MAIN',
      action: 'add',
      title: 'leidimas.pdf',
      content: pdfBuffer,             // Buffer → inlined as base64 automatically
      contentType: 'application/pdf',
      customFields: {},
    },
    templateParam: { oid: '<templateOid>' },
    register: false,                 // false = create a PROJECT (draftas), not registered
    project: true,
  },
});
const docOid = documentInfo.oid;

// 2. Wire the dynamic review/sign chain, then start the workflow.
await dbsis.documents.$invoke('modifyApprovalSchema', {
  modifySchemaParam: { docOid, executors: [{ $type: 'org:OrgNodeParam', orgName: '…' }] },
});
await dbsis.documents.$invoke('modifySigningSchema', {
  modifySchemaParam: { docOid, executors: [{ $type: 'org:OrgNodeParam', orgName: '…' }] },
});
await dbsis.documents.$invoke('markVersionReady', { markVersionReadyParam: { docOid } });

Gotchas (hard-won against a live tenant)

  • DBSIS returns detail-less internal errors (GS-30000, GS-32001) on a malformed request — a generic "Nenumatyta vidinė sistemos klaida" with an empty <detail>/body, no field-level hint. Two ways to localise the offending field:
    1. Drop the attachment and send metadata only — a missing main body surfaces a meaningful error ("Elektroninio dokumento turinyje turi būti pagrindinis dokumentas") that tells you the create path is otherwise fine.
    2. getDocument after a "successful" create and inspect how each attribute was actually stored — e.g. a byla stored as xs:string instead of an office-case reference means it didn't resolve.
  • There is no eDocumentFile. The PDF/ADOC body is bodyAttachment (a single or array of AttachmentActionParam).
  • There is no OrgNodeNameParam. Reference org nodes with OrgNodeParam + orgName (or OrgNodeCodeParam + code).
  • draftOfficeCase is a single OfficeCaseParam { oid }, not an OfficeCaseListParam. Wrapping it makes the byla store as a raw string ("Lauko skaitymo klaida").
  • isElectro: true requires a real electronic package (ADOC/PDF-LT). For a plain application/pdf body use isElectro: false (Lentelė 59: project=true + isElectro=false ⇒ a plain outgoing-document project).
  • sort / documentProcess / nature are valid create docAttributes for tenants whose template needs them, even though the spec's Lentelė 51 lists only a minimal set (its note allows config-specific extras).
  • Attachment content works inline (the lib base64-encodes the Buffer); MTOM is only used on the response side.
  • Signing chain is set after create, via modifyApprovalSchema (derintojai) / modifySigningSchema (pasirašantys) + markVersionReady — not as create-time docAttributes.

Errors

Any SOAP Fault is thrown as SoapError (extends Error):

const { SoapError } = require('@aplinkosministerija/dbsis-rest');
try { ... }
catch (err) {
  if (err instanceof SoapError) {
    console.error(err.message);   // faultstring
    console.error(err.faultCode); // optional
    console.error(err.detail);    // optional <detail> contents
  }
}

HTTP-level failures (timeout, 5xx without a SOAP body, etc.) also surface as SoapError with a status and responseBody.

REST gateway

npx dbsis-rest serve
# or
node scripts/cli.js serve

| Method | Path | Body | Description | | --- | --- | --- | --- | | GET | /health | — | { ok: true } | | GET | /api/operations | — | Machine-readable catalogue of every registered operation. | | POST | /api/<service>/<operation> | JSON | Same params object as the JS API. Returns { ok: true, result: ... } or { ok: false, error, soap }. |

The <service> segment accepts both the alias (documents) and the short prefix (rdod).

If GATEWAY_TOKEN is set, every request must include Authorization: Bearer <token>.

Catalogue

Run node scripts/cli.js list to print every supported operation grouped by service — same set the gateway exposes.

Receiving DBSIS callbacks (receiveDhsEvent, receiveDhsTaskEvent)

DBSIS calls your system back when a document/task changes state. The taikymo aprašymas (§3.2) and the spec (§2.18) describe the expected ReceiveDhsEventParam / ReceiveDhsTaskEventParam payload and the ReceiveDhsEventResult shape you must return.

This package does not run a SOAP server for you — that is intentional, because the URL, port, certificates and side-effects belong to your application. A complete reference example using only the standard library is in examples/receive-dhs-event-server.js (forthcoming): parse the envelope with parseSoapResponse, do your work, and reply with a SOAP envelope containing ReceiveDhsEventResult (statusCode, errorMessage, persistentError).

Development

npm install
npm test          # node:test, no external test runner
npm run start     # runs `dbsis-rest serve` against env vars

CI/CD

GitHub Actions workflows mirror the conventions used by other Ministry repos (see biip-tools):

| Workflow | Trigger | Purpose | | --- | --- | --- | | ci.yml | push / PR to main | npm test on Node 18/20/22, npm audit, actionlint | | codeql.yml | push / PR to main | Code scanning — skipped automatically on private repos (requires GHAS) | | publish.yml | tag X.Y.Z push, GitHub Release, or workflow_dispatch | Test then npm publish --access public --provenance | | dependabot.yml | daily | Security updates only (open-pull-requests-limit: 0) |

Releasing a new version:

# bump in package.json, e.g. 0.1.0 -> 0.1.1
git tag 0.1.1
git push origin 0.1.1
# publish workflow runs automatically

The publish job needs a repo or org secret named NPM_REGISTRY_TOKEN — same name biip-tools uses, so an org-level secret will work without per-repo setup.

Mapping back to the spec

Every operation in src/services/operations.js has a docSection field that points to the chapter in DBSIS_SOAP_API_20250114_v3.0.docx. If a method is missing or its body shape is unclear, that is the place to look first.

Security notes

  • Credentials never leave process.env. The REST gateway never accepts SOAP credentials in the request body. If you expose the gateway externally, set GATEWAY_TOKEN and front it with TLS.
  • WS-Security UsernameToken sends the password as PasswordText. DBSIS itself recommends running over HTTPS — do not call the SOAP endpoint over plain HTTP.
  • Templates, sender/receiver codes, OIDs etc. are not secrets in themselves but identify documents in your tenant. Treat the JSON request bodies you log accordingly.

License

MIT.