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

@ojiepermana/angular-sdk

v22.0.59

Published

OpenAPI 3.x → Angular SDK generator (schematics + config surface) for @ojiepermana/angular.

Readme

@ojiepermana/angular-sdk

OpenAPI 3.x → Angular SDK generator for the @ojiepermana/angular design system. Source lives in library/sdk; the package publishes as @ojiepermana/angular-sdk and is also re-exported as the umbrella secondary entry point @ojiepermana/angular/sdk.

It generates a lightweight Angular SDK from any OpenAPI 3.x spec (including 3.2.0): typed HttpClient services, tree-shakeable fn modules, optional metadata (permissions / validators), and a navigation tree.

What the published package exposes

The npm artifact currently ships the typed config surface — the contract you author your sdk.config.json against — from public-api.ts:

import {
  resolveConfig,
  resolveTarget,
  type SdkConfig,
  type SdkTargetConfig,
  type SdkOutputMode,
  type SdkFeatureFlags,
} from '@ojiepermana/angular-sdk';

The generator implementation itself lives in the source tree:

| Path | Role | | -------------------- | ------------------------------------------------------------------------------------------------ | | src/config/ | Config schema + loader (JSONC, .js/.cjs) — resolveConfig / resolveTarget | | src/parser/ | OpenAPI → intermediate representation (bundle, ir, types) | | src/emit/ | One emitter per concern (models, operations, services, client, metadata, navigation, public-api) | | src/layout/ | Post-emit transforms (e.g. per-domain split-by-domain reorganisation) | | src/render/ | Template rendering | | src/writer/ | Output-mode wrappers (standalone / library / secondary-entrypoint) | | src/engine.ts | generate(target, workspaceRoot) — runs the full pipeline for one target | | schematics/init/ | Scaffolds config/sdk.config.json from sdk.config.example.json | | schematics/sdk/ | Runs the generator and writes files into the Angular CLI Tree | | schematics/ng-add/ | ng add support — installs peer deps | | bin/ | Compiled JS output of src/ + schematics/ (via tsconfig.schematics.json) |

Config shape

A single config file drives one or more generation targets:

{
  "targets": [
    {
      "input": "./openapi.yaml",
      "output": "./sdk",
      "mode": "library", // "standalone" | "library" | "secondary-entrypoint"
      "clientName": "Api",
      "packageName": "@my-scope/sdk", // used in "library" mode
      "packageVersion": "0.0.1", // used in "library" mode
      "rootUrl": "", // optional; empty string means same-origin requests
      "splitByDomain": true, // optional; defaults true for "library", false otherwise
      "splitDepth": "service", // "service" (default) | "tag"
      "features": {
        "models": true,
        "operations": true,
        "services": true,
        "client": true,
        "metadata": true,
        "navigation": true,
      },
    },
  ],
}

Multiple targets are supported — one config run can emit several SDKs. See sdk.config.example.json for the canonical template the init schematic scaffolds.

If rootUrl is omitted or left empty, the generated SDK uses same-origin requests by default. Consumer apps can override it at runtime with provideApiConfiguration(...).

Runtime base URL

The generated SDK does not read sdk.config.json at runtime. The value of targets[].rootUrl is only used during code generation to seed the default ApiConfiguration.rootUrl value.

  • rootUrl: "" or omitted: requests use the current origin, for example /api/users on the same host as the Angular app.
  • rootUrl: "https://api.example.com": the generated SDK defaults to that absolute backend URL.
  • Runtime override: consumer apps can replace the default by providing a new value during bootstrap.
import { bootstrapApplication } from '@angular/platform-browser';
import { provideHttpClient } from '@angular/common/http';

import { AppComponent } from './app/app.component';
import { provideApiConfiguration } from '@my-scope/sdk';

bootstrapApplication(AppComponent, {
  providers: [provideHttpClient(), provideApiConfiguration('https://api.example.com')],
});

For standalone generated output inside the same workspace, import provideApiConfiguration from the generated SDK barrel instead of an npm package path.

Output modes

| Mode | What it emits | Use when… | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------- | | standalone | A plain folder (no ng-package.json). | You consume the SDK via path alias / tsconfig.paths inside the same app. | | library | Split-by-domain output plus package metadata and nested ng-package.json manifests for secondary entrypoints. | You want a buildable/publishable Angular package with efficient deep imports. | | secondary-entrypoint | Standalone output plus a minimal ng-package.json pointing at public-api.ts, plus nested ng-package.json files for split-by-domain secondary entrypoints. | You drop the folder inside an existing library so ng-packagr picks it up as a subpath. |

In library mode, output also includes tsconfig.lib.json and tsconfig.lib.prod.json. ng-package.dest defaults to dist/<output-folder-name>.

Per-domain layout

By default, standalone and secondary-entrypoint targets emit a flat layout (models/, fn/, services/, … all at the output root). mode: "library" defaults to splitByDomain: true so the generated package is split into secondary entrypoints immediately. You can still set splitByDomain: false if you need the older flat library shape. Cross-domain models and client primitives land in shared/.

splitDepth controls granularity. It is only read when splitByDomain is true.

| splitDepth | Folder strategy | Example (spec with tags Access/Role, Access/Permission, Storage/GCS, Storage/S3, Auth) | | ------------ | ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | service | One folder per root tag (each tag's parent chain collapses to its root). One folder per backend service. | access/ (holds Role + Permission + Role-Permission + …), storage/ (holds GCS + S3), auth/, shared/, root public-api.ts | | tag | One folder per leaf tag, nested under the parent chain. Keeps fine-grained separation while staying grouped. | access/role/, access/permission/, access/role-permission/, storage/gcs/, storage/s3/, auth/, shared/, root public-api.ts |

Every domain folder contains services/, fn/, models/, permissions/, and its own public-api.ts. The root still owns the aggregate metadata barrel: metadata.ts, openapi-helpers.ts, and permissions/index.ts stay at the SDK root so shared/ never depends on sibling domains. In standalone and secondary-entrypoint modes, the root public-api.ts aggregates shared, root metadata helpers, and every domain for convenience. In library mode, domain exports stay in their secondary entrypoints so consumers deep import the domain they need.

Model ownership rule (per-domain mode):

  • A model used by exactly one domain → emitted inside that domain's models/.
  • A model shared across two or more domains → emitted inside shared/models/.
  • Client primitives (ApiConfiguration, BaseService, RequestBuilder, StrictHttpResponse, Api), shared metadata types, validators, and navigation always live under shared/.
  • Aggregate metadata helpers (metadata.ts, openapi-helpers.ts) and the top-level permissions/index.ts stay at the SDK root.

Example consumption when using mode: 'library':

import { RoleService } from '@my-scope/sdk/access';
import { ApprovalInstanceService, SubmitRequest } from '@my-scope/sdk/approval';
import { GCSService } from '@my-scope/sdk/storage'; // splitDepth: 'service'
import { GCSService } from '@my-scope/sdk/storage/gcs'; // splitDepth: 'tag'

Feature flags

All default to true. Turn off anything you don't need to shrink the output.

| Flag | Emits | | ------------ | ------------------------------------------------------------------------------------------ | | models | models/*.ts — flat interfaces, enum aliases, array aliases. | | operations | fn/<tag>/<operation-id>.ts — tree-shakeable request functions with .PATH. | | services | services/<tag>.service.ts@Injectable({providedIn:'root'}) wrappers. | | client | api-configuration.ts, base-service.ts, request-builder.ts, api.ts. | | metadata | permissions/*, validators/*, metadata.ts, openapi-helpers.ts. | | navigation | api.navigation.tsNavigationItem[] ready for NavigationService.registerItems(...). |

Pipeline

sdk.config.json → loader → spec (YAML/JSON) → IR → emitters → layout → writer → Angular CLI Tree

Output ownership and safe cleanup

Each generated output directory contains .ojiepermana-sdk-manifest.json with the relative files owned by the generator. A later run deletes stale files only when they were recorded in that manifest; unrelated source and documentation in the same directory are preserved.

The schematic rejects output at the workspace root, outside the workspace, or inside .git/node_modules, and rejects absolute, traversing, duplicate, and reserved virtual paths. It also refuses to overwrite an unmanaged file whose content differs. On the first managed run, identical existing files are adopted; move conflicting manual files (or regenerate into a clean directory) before running again. Angular CLI --dry-run previews the complete Tree transaction.

Generated runtime conventions

  • Tree-shakeable: import { listUsers } from './sdk/fn/user/list-users' pulls only one HTTP call.
  • Services: every operation gets op() (body Observable<T>) and op$Response() (full StrictHttpResponse<T>).
  • RequestBuilder is intentionally minimal — no style/explode logic — to keep the output lightweight.
  • All files carry a DO NOT EDIT banner and /* eslint-disable */.