
Research
Namastex.ai npm Packages Hit with TeamPCP-Style CanisterWorm Malware
Malicious Namastex.ai npm packages appear to replicate TeamPCP-style Canister Worm tradecraft, including exfiltration and self-propagation.
afpnews-api
Advanced tools
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.
npm install afpnews-api
import { ApiCore } from 'afpnews-api'
// or CommonJS
const { ApiCore } = require('afpnews-api')
<script src="https://unpkg.com/afpnews-api/dist/bundles/apicore.min.js"></script>
import { ApiCore } from 'https://cdn.jsdelivr.net/npm/afpnews-api/dist/bundles/apicore.min.mjs'
You need an API key or client credentials (client ID + secret) to connect. For user-authenticated requests, you also need a username and password.
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' })
// 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
Get the most recent documents:
const { count, documents } = await afp.latest({ lang: 'fr', tz: 'Europe/Paris' })
const { count, documents } = await afp.search()
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' }]
})
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'] }
})
Pass an array of field names to limit the returned fields:
const { documents } = await afp.search({}, ['uno', 'title', 'published'])
Use searchAll() to iterate over large result sets automatically:
for await (const doc of afp.searchAll({ size: 5000, query: 'climate' })) {
console.log(doc.uno)
}
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) |
const document = await afp.get('uno')
Find documents similar to a given one:
const { count, documents } = await afp.mlt('uno', 'en', 10)
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)
Get the API field mapping:
const mapping = await afp.mapping('en')
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')
const { count, documents } = await afp.searchWithFilter('my-filter', {
startat: 0,
size: 50
})
Retrieve an RSS/ATOM feed based on a saved filter:
const xmlContent = await afp.feed('my-filter', { size: 20 })
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')
Retrieve the embeddable HTML for a social story document:
const html = afp.getStoryHtml(doc)
| 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.
# 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
MIT - see LICENSE.md
FAQs
Node helper functions to authenticate and fetch AFP Core API
The npm package afpnews-api receives a total of 79 weekly downloads. As such, afpnews-api popularity was classified as not popular.
We found that afpnews-api demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
Malicious Namastex.ai npm packages appear to replicate TeamPCP-style Canister Worm tradecraft, including exfiltration and self-propagation.

Product
Explore exportable charts for vulnerabilities, dependencies, and usage with Reports, Socket’s new extensible reporting framework.

Product
Socket for Jira lets teams turn alerts into Jira tickets with manual creation, automated ticketing rules, and two-way sync.