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

liferay-headless-sdk

v1.0.8

Published

A production-ready JavaScript SDK dynamically generated from Liferay Headless API Swagger/OpenAPI specifications.

Readme

Liferay Headless SDK

A JavaScript SDK that dynamically generates API client methods from Liferay's OpenAPI specifications at runtime.

Zero manual mapping required — point it at a Liferay instance and call APIs immediately.


Table of Contents

  • Installation
  • Quick Start
  • Configuration
  • Authentication
  • Dynamic Method Usage
  • Pagination
  • Interceptors
  • Error Handling
  • CLI Tool
  • TypeScript
  • Advanced Usage
  • File Structure

Installation

npm install liferay-headless-sdk

Node.js 18+ required (uses native fetch and ESM).


Quick Start

import { LiferayHeadlessClient } from 'liferay-headless-sdk';

const client = new LiferayHeadlessClient({
  baseUrl: 'https://your-liferay.com',
  swaggerUrls: ['/o/headless-delivery/v1.0/openapi.json', '/o/headless-admin-user/v1.0/openapi.json'],
  username: '[email protected]',
  password: 'test',
});

await client.init();

const { data } = await client.headlessAdminUser.site.getMyUserAccountSitesPage();

console.log(data.items);

Configuration

const client = new LiferayHeadlessClient({
  baseUrl: 'https://your-liferay.com',

  swaggerUrls: ['/o/headless-delivery/v1.0/openapi.json', '/o/headless-admin-user/v1.0/openapi.json'],

  operationIds: [], // optional filter
  tags: [], // optional filter

  username: '[email protected]',
  password: 'test',

  timeout: 30000,
  retries: 2,

  autoGenerate: true, // Proxy-based lazy init
});

Authentication

Basic Auth

const client = new LiferayHeadlessClient({
  baseUrl: '...',
  username: '[email protected]',
  password: 'test',
});

OAuth2 Bearer Token

const client = new LiferayHeadlessClient({
  baseUrl: '...',
  clientId: 'id-cbc930e2-3766-4ea2-24bd-6887b5fc112',
  clientSecret: 'secret-95f02f64-1033-5ad2-7066-2c393bdd',
});

Switch Authentication at Runtime

client.setBasicAuth('username', 'password');

client.setClientCredentials('clientId', 'clientSecret');

client.clearAuth();

Dynamic Method Usage

After initialization:

await client.init();

Access APIs:

// GET /v1.0/sites/{siteId}
const { data } = await client.headlessAdminUser.site.getSite({ siteId: 12345 });

// GET /v1.0/structured-contents/{structuredContentId}
const { data: content } = await client.headlessDelivery.structuredContent.getStructuredContent({
  structuredContentId: 123,
});

// POST /v1.0/sites/{siteId}/structured-contents
await client.headlessDelivery.structuredContent.postSiteStructuredContent({
  siteId: 1,
  body: {
    title: 'My Article',
  },
});

Parameter Mapping

| Type | Example | | ----------- | -------------------- | | Path param | { siteId: 123 } | | Query param | { page: 1 } | | Body | { body: {...} } | | Headers | { headers: {...} } |


Pagination

Iterate lazily

import { iteratePages } from 'liferay-headless-sdk';

for await (const item of iteratePages(client.headlessAdminUser.site.getMyUserAccountSitesPage, { pageSize: 50 })) {
  console.log(item);
}

Collect all

import { collectAllPages } from 'liferay-headless-sdk';

const all = await collectAllPages(client.headlessAdminUser.site.getMyUserAccountSitesPage, { pageSize: 100 });

Interceptors

Request Interceptor

client.addRequestInterceptor((config) => {
  console.log('→', config.method, config.path);
  return config;
});

Response Interceptor

client.addResponseInterceptor((response) => {
  console.log('←', response.status);
  return response;
});

Add headers dynamically

client.addRequestInterceptor((config) => ({
  ...config,
  headers: {
    ...config.headers,
    'X-Request-ID': crypto.randomUUID(),
  },
}));

Error Handling

import { LiferayAPIError, LiferayNetworkError, LiferayTimeoutError } from 'liferay-headless-sdk';

try {
  await client.headlessAdminUser.site.getMyUserAccountSitesPage();
} catch (err) {
  if (err instanceof LiferayAPIError) {
    console.log(err.statusCode);
    console.log(err.responseBody);
  }

  if (err instanceof LiferayTimeoutError) {
    console.log(err.timeoutMs);
  }

  if (err instanceof LiferayNetworkError) {
    console.log(err.cause);
  }
}

Behavior

  • 4xx errors → not retried
  • 5xx + network errors → retried with exponential backoff
  • timeouts → wrapped in LiferayTimeoutError

CLI Tool

npx liferay-sdk-cli generate \
  --baseUrl https://your-liferay.com \
  --output ./generated-sdk \
  --username [email protected] \
  --password test

Options

| Flag | Description | | ------------ | ------------------------ | | --baseUrl | Liferay instance URL | | --output | Output directory | | --swagger | Custom OpenAPI endpoints | | --username | Basic auth username | | --password | Basic auth password | | --token | OAuth token |


TypeScript

import { LiferayHeadlessClient } from 'liferay-headless-sdk';

const client = new LiferayHeadlessClient({
  baseUrl: 'https://your-liferay.com',
  username: '[email protected]',
  password: 'test',
});

Dynamic access:

const ns = client['headlessDelivery'];

const result = await ns['structuredContent']['getStructuredContents']();

Advanced Usage

Load schema on demand

await client.loadSchema('/o/headless-delivery/v1.0/openapi.json');

Raw HTTP access

const { data } = await client.request({
  method: 'GET',
  path: '/o/headless-delivery/v1.0/sites',
});

Cache reset

client.clearSchemaCache();
await client.init();

File Structure

src/
├── client.js
├── http.js
├── auth.js
├── swagger-loader.js
├── api-generator.js
├── pagination.js
├── errors.js
├── utils.js
├── cli.js

License

MIT