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

@ftisindia/sdk

v0.3.0

Published

Per-project client SDK generator for FTIS backends — emits a self-contained Dart/Flutter package from a backend's OpenAPI contract.

Readme

@ftisindia/sdk

ftis-sdk — per-project client SDK generator for FTIS backends. Reads a backend's OpenAPI contract (including custom modules and the x-ftis vendor extensions) and emits a self-contained Dart/Flutter package: the ftis_core runtime (vendored) plus typed models, per-tag API classes, an org-scoped facade, permission-key constants, and — on by default — the full clean-architecture stack (domain entities, pure request inputs, repository contracts + implementations, one use case per operation, and a sealed Result/Failure core), so a BLoC app only hand-writes its presentation layer.

# inside a scaffolded FTIS backend
npm run sdk:generate                       # → sdk/dart/<name>_sdk/

# against any backend
ftis-sdk generate --backend ./my-backend   # exports the contract fresh
ftis-sdk generate --backend https://api.example.com --out ./my_sdk   # fetches /docs-json (URL mode requires --out)

Flutter apps consume the output via a path or git dependency — no pub.dev needed. See the generated package's README and the backend template's docs/SDK.md for usage; run ftis-sdk --help for all flags (--use-existing, --strict, --force, --name, --out, --no-domain).

Clean-architecture layers

The generated tree mirrors the standard Flutter clean-architecture layout:

lib/src/generated/
├─ core/            Result, Failure, PagedResult, guardApiCall
├─ data/
│  ├─ models/       wire models (JSON) — *_model.dart
│  ├─ datasources/  typed API classes (remote data sources)
│  ├─ mappers/      model ↔ domain conversions
│  └─ repositories/ repository implementations
└─ domain/          entities/ inputs/ repositories/ usecases/<feature>/

Backend schema names ending in Dto are emitted as *Model Dart classes (SettingResponseDtoSettingResponseModel in setting_response_model.dart); a rare name collision with an existing *Model schema keeps the original name with a warning.

Everything is derived deterministically from the contract: response-reachable models become pure *Entity classes (plus toEntity() mappers), request-only models become pure *Input classes (plus toModel() mappers), each API class becomes a repository contract + implementation, and every operation becomes a <Feature><Action>UseCase returning Future<Result<T>> (ApiException and transport errors normalize into a Failure value in one generated guard). Domain files import nothing outside the domain layer and the pure core trio (result/failure/paged_result) — enforced by tests. Session-managed auth operations (login, signup, oauth/exchange, refresh, logout) delegate to the vendored AuthEngine instead of the raw API so token storage and silent refresh keep working; the engine surface the templates rely on is pinned by test/engine-surface.test.mjs. Skipped operations get no domain surface. Pass --no-domain to emit only data/models/ + data/datasources/ (same nested layout, no core/domain/ mapper/repository layers).

How generation is driven

The backend declares SDK-relevant facts in its OpenAPI document (x-ftis block, x-ftis-public, x-ftis-skip — see the template's src/common/swagger/ftis-sdk.decorators.ts). The generator consumes those first; documents without any x-ftis metadata fall back to heuristics (path allowlists + a hard-coded skip ledger) with a warning. --strict turns warnings into failures.

Operations a typed client cannot call (file streams, multipart uploads, browser redirects, dual-format exports) are listed in the generated README and stay reachable through the SDK's raw request escape hatch.

Two behaviours worth knowing:

  • The heuristic fallback can rot. The ledger in src/ir.mjs (FALLBACK_SKIP_LEDGER, FALLBACK_PUBLIC_PATHS) hard-codes template routes as they existed before the x-ftis decorators; it is only consulted for contracts with no x-ftis block (typically URL mode against an old deployment). If those routes have since changed, fallback output can be wrong — prefer regenerating the backend so the contract carries metadata, and treat the fallback warning (fatal under --strict) as a prompt to do so.
  • Pagination detection is shape-exact. A response schema maps to the runtime's Page<T> only when it has exactly two properties, items (array) + nextCursor. Adding any field to a page envelope silently demotes it to a plain generated class — intentional, so enriched envelopes keep their fields, but worth knowing when you extend list responses.

Development (monorepo)

The Dart runtime lives at mobile-starter/packages/ftis_core and is baked into assets/ by scripts/sync-sdk-runtime.mjs at prepack/pretest (the same lifecycle packages/cli uses for its template). Tests: npm test (goldens under test/golden/; refresh deliberately with node test/update-golden.mjs after contract or emitter changes).