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

afpnews-api

v2.4.0

Published

Node helper functions to authenticate and fetch AFP Core API

Readme

AfpNews API

npm version License: MIT

A TypeScript client library for the AFP Core API. Provides authentication, document search, notification management, saved filters, and social story retrieval for both Node.js and browser environments.

Installation

Node.js

npm install afpnews-api
import { ApiCore } from 'afpnews-api'
// or CommonJS
const { ApiCore } = require('afpnews-api')

Browser (UMD)

<script src="https://unpkg.com/afpnews-api/dist/bundles/apicore.min.js"></script>

Browser (ESM)

import { ApiCore } from 'https://cdn.jsdelivr.net/npm/afpnews-api/dist/bundles/apicore.min.mjs'

Prerequisites

You need an API key or client credentials (client ID + secret) to connect. For user-authenticated requests, you also need a username and password.

Quick Start

import { ApiCore } from 'afpnews-api'

// Initialize with client credentials
const afp = new ApiCore({ clientId: 'your-id', clientSecret: 'your-secret' })

// Or with an API key
const afp = new ApiCore({ apiKey: 'your-api-key' })

// Optionally override the base URL
const afp = new ApiCore({ clientId: 'your-id', clientSecret: 'your-secret', baseUrl: 'https://custom-api.afp.com' })

Authentication

// Anonymous authentication (uses API key or client credentials)
await afp.authenticate()

// Authenticate with user credentials
await afp.authenticate({ username: 'user', password: 'pass' })

// Listen for token changes
afp.on('tokenChanged', (token) => {
  console.log(token)
  // { accessToken, refreshToken, tokenExpires, authType }
})

// Token is automatically refreshed when expired

Latest Documents

Get the most recent documents:

const { count, documents } = await afp.latest({ lang: 'fr', tz: 'Europe/Paris' })

Searching Documents

Basic Search

const { count, documents } = await afp.search()

Search with Parameters

const { count, documents } = await afp.search({
  query: 'Macron',
  langs: ['fr', 'en'],
  dateFrom: '2024-01-01',
  dateTo: '2024-12-31',
  size: 20,
  sortField: 'published',
  sortOrder: 'desc',
  tz: 'Europe/Paris',
  dateGap: '+1HOUR',
  startAt: 0,
  wantedFacets: { slug: { size: 10, minDocCount: 1 }, country: { size: 5, minDocCount: 1 } },
  sort: [{ sortField: 'published', sortOrder: 'desc' }]
})

Additional Filtering Parameters

Any extra key-value pair is passed as an additional query filter:

const { documents } = await afp.search({
  query: 'climate',
  country: 'fra',
  urgency: 3,
  slug: ['politics', 'economy']
})

You can also use include/exclude syntax:

const { documents } = await afp.search({
  country: { in: ['fra', 'deu'] },
  product: { exclude: ['photo'] }
})

Specify Response Fields

Pass an array of field names to limit the returned fields:

const { documents } = await afp.search({}, ['uno', 'title', 'published'])

Paginated Search

Use searchAll() to iterate over large result sets automatically:

for await (const doc of afp.searchAll({ size: 5000, query: 'climate' })) {
  console.log(doc.uno)
}

Query Syntax

The query parameter supports a boolean query DSL:

| Syntax | Example | |---|---| | Simple term | Macron | | Field search | title:Macron | | AND | Macron AND Merkel | | OR | title:Macron OR title:Merkel | | NOT | Macron AND NOT country:fra | | Parentheses | (title:Macron OR title:Merkel) AND country:fra | | Quoted phrase | title:"climate change" | | Implicit AND | Macron France (space-separated terms) |

Retrieving a Single Document

const document = await afp.get('uno')

More Like This

Find documents similar to a given one:

const { count, documents } = await afp.mlt('uno', 'en', 10)

Listing Facet Values

Retrieve the most used values for a specific facet:

const { count, keywords } = await afp.list('slug')

// With custom search scope and minimum document count
const { keywords } = await afp.list('country', { dateFrom: 'now-7d', langs: ['en'] }, 5)

Field Mapping

Get the API field mapping:

const mapping = await afp.mapping('en')

Filter Center

Manage saved search filters.

const fc = afp.filterCenter

// Create a filter
await fc.add('breaking-politics', { query: 'urgency:1', country: 'fra' })

// Update a filter
await fc.update('breaking-politics', { query: 'urgency:1 OR urgency:2' })

// Get a specific filter
const filter = await fc.get('breaking-politics')

// List all filters
const allFilters = await fc.all()

// Delete a filter
await fc.delete('breaking-politics')

Search with Saved Filter

const { count, documents } = await afp.searchWithFilter('my-filter', {
  startat: 0,
  size: 50
})

RSS/ATOM Feed

Retrieve an RSS/ATOM feed based on a saved filter:

const xmlContent = await afp.feed('my-filter', { size: 20 })

Notification Center

Subscribe to real-time document notifications via mail, REST, SQS, or JMS services.

const nc = afp.notificationCenter

// Register a REST service
const serviceId = await nc.registerService({
  name: 'my-webhook',
  type: 'rest',
  datas: { href: 'https://example.com/webhook' }
})

// Add a subscription
const subId = await nc.addSubscription('breaking-news', 'my-webhook', {
  query: 'urgency:1',
  langs: ['en']
})

// List services and subscriptions
const services = await nc.listServices()
const subscriptions = await nc.listSubscriptions()
const subs = await nc.subscriptionsInService('my-webhook')

// Cleanup
await nc.deleteSubscription('my-webhook', 'breaking-news')
await nc.removeSubscriptionsFromService('my-webhook', ['sub1', 'sub2'])
await nc.deleteService('my-webhook')

Social Stories

Retrieve the embeddable HTML for a social story document:

const html = afp.getStoryHtml(doc)

Search Parameters Reference

| Parameter | Type | Default | Description | |---|---|---|---| | query | string | — | Boolean query string (see Query Syntax) | | langs | string[] | — | Filter by language codes | | dateFrom | string | '1980-01-01' | Start date (ISO date or relative like 'now-7d') | | dateTo | string | 'now' | End date | | size | number | 10 | Number of results (max 1000 per request) | | sortField | string | 'published' | Field to sort by | | sortOrder | 'asc' \| 'desc' | 'desc' | Sort direction | | startAt | number | — | Offset for pagination | | tz | string | — | Timezone (e.g. 'Europe/Paris') | | dateGap | string | — | Date gap for facet ranges (e.g. '+1HOUR', '+1DAY') | | wantedFacets | WantedFacets | — | Facets configuration { facetName: { size, minDocCount }, empty?: boolean } | | sort | SortEntry[] | — | Multi-field sort [{ sortField, sortOrder }] |

Any additional key-value pairs are treated as field filters.

Development

# Install dependencies
npm install

# Build (clean + parser + types + ESM/CJS/bundles)
npm run build

# Development with auto-rebuild
npm run build:watch

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Lint
npm run lint

Author

Jules Bonnard

License

MIT - see LICENSE.md