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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@flink-app/contentone-plugin

v0.12.1-alpha.45

Published

Flink plugin that enables easy to use communication with content one

Downloads

416

Readme

@flink-app/contentone-plugin

A Flink plugin for integrating with Content One CMS (Aquro). This plugin provides a simple and type-safe way to consume content from Content One collections, execute management actions, and upload files to the Content One CDN.

Features

  • Retrieve documents from Content One collections
  • List and query collection documents with filtering and pagination
  • Execute Content One management actions
  • Upload files to Content One CDN with image processing options
  • Support for multiple collections and CDN configurations
  • Environment switching (Production/Staging)
  • Document relation resolution
  • Language-specific content retrieval
  • Full TypeScript support with generic types
  • Direct API calls without pre-configuration

Installation

npm install @flink-app/contentone-plugin

Usage

Basic Setup

import { FlinkApp } from "@flink-app/flink";
import {
  contentOnePlugin,
  ContentOneClient,
  ContentOneManagementAction,
  ContentOneCDN,
} from "@flink-app/contentone-plugin";

function start() {
  new FlinkApp<AppContext>({
    name: "My app",
    plugins: [
      contentOnePlugin({
        collections: {
          NewsItems: new ContentOneClient({
            collection: "collection_id_here",
            token: "your_token_here",
          }),
          Products: new ContentOneClient({
            collection: "another_collection_id",
            token: "your_token_here",
          }),
        },
        actions: {
          SendEmail: new ContentOneManagementAction({
            actionId: "send_email_action_id",
            apiKey: "your_api_key_here",
          }),
        },
        cdns: {
          photos: new ContentOneCDN({
            token: "file_archive_token",
          }),
        },
        baseUrl: "https://cdb.aquro.com", // optional
        managementBaseUrl: "https://api-cm.aquro.com", // optional
      }),
    ],
  }).start();
}

Add Plugin Context to Your Application

import { contentOnePluginContext } from "@flink-app/contentone-plugin";

export interface AppContext extends FlinkContext<contentOnePluginContext> {
  repos: {
    // your repos
  };
}

Configuration Options

  • collections (optional): Object mapping collection names to ContentOneClient instances
  • actions (optional): Object mapping action names to ContentOneManagementAction instances
  • cdns (optional): Object mapping CDN names to ContentOneCDN instances
  • baseUrl (optional): Content One API base URL (defaults to https://cdb.aquro.com)
  • managementBaseUrl (optional): Content One Management API base URL (defaults to https://api-cm.aquro.com)

Working with Collections

Get a Single Document

const document = (await ctx.plugins.contentOne.collections.NewsItems.get("document_id")).document;

With options:

const document = (
  await ctx.plugins.contentOne.collections.NewsItems.get("document_id", {
    language: "en",
    environment: "Production",
    resolve: "yes",
  })
).document;

List Documents

const documents = (await ctx.plugins.contentOne.collections.NewsItems.list()).documents;

With pagination and sorting:

const documents = (
  await ctx.plugins.contentOne.collections.NewsItems.list({
    skip: 0,
    limit: 50,
    sort: "createdDate",
    sort_direction: "desc",
    language: "en",
    environment: "Production",
    resolve: "yes",
  })
).documents;

Query Documents

Execute a named query with arguments:

const documents = (
  await ctx.plugins.contentOne.collections.NewsItems.query("GetNewsByCategory", {
    category: "Technology",
  })
).documents;

With options:

const documents = (
  await ctx.plugins.contentOne.collections.NewsItems.query(
    "GetNewsByCategory",
    {
      category: "Technology",
    },
    {
      limit: 20,
      sort: "publishDate",
      sort_direction: "desc",
    }
  )
).documents;

Request Options

Common Options

Available for get, list, and query:

  • language (string): Language code (ISO 639-1) to retrieve documents in (e.g., "en", "sv")
  • environment ("Production" | "Staging"): Which environment to fetch from
  • resolve ("yes" | "no"): Whether to resolve related documents

List and Query Options

Additional options for list and query:

  • skip (number): Number of documents to skip (default: 0)
  • limit (number): Maximum documents to return (default: 10,000)
  • sort (string): Field name to sort by
  • sort_direction ("asc" | "desc"): Sort direction

TypeScript Type Safety

Use generic types to get typed document responses:

interface NewsItem {
  _id: string;
  title: string;
  content: string;
  publishDate: string;
  category: string;
}

// Single document
const document = (
  await ctx.plugins.contentOne.collections.NewsItems.get<NewsItem>("document_id")
).document;
// document is typed as NewsItem

// Multiple documents
const documents = (
  await ctx.plugins.contentOne.collections.NewsItems.list<NewsItem>()
).documents;
// documents is typed as NewsItem[]

Management Actions

Execute Pre-configured Actions

const response = await ctx.plugins.contentOne.actions.SendEmail.execute({
  to: "[email protected]",
  subject: "Hello",
  body: "Welcome to our service",
});

if (response.status === "success") {
  console.log("Email sent:", response.data);
}

Execute Actions Directly

Without pre-configuration:

const response = await ctx.plugins.contentOne.management.action(
  "action_id",
  "api_key",
  {
    arg1: "value1",
    arg2: "value2",
  }
);

Typed Action Responses

interface EmailResponse {
  messageId: string;
  status: string;
}

const response = await ctx.plugins.contentOne.actions.SendEmail.execute<EmailResponse>({
  to: "[email protected]",
  subject: "Hello",
});

if (response.status === "success") {
  console.log("Message ID:", response.data.messageId);
}

File Upload (CDN)

Upload Files with Pre-configured CDN

const result = await ctx.plugins.contentOne.cdns.photos.upload("/tmp/photo.jpg", {
  image_rotate: "auto",
  image_resize_width: 1200,
  image_resize_max: "yes",
  image_thumb: "yes",
  image_thumb_width: 200,
  image_thumb_height: 200,
});

if (result.status === "success") {
  console.log("File URL:", result.file.Url);
  console.log("Thumbnail URL:", result.file.Thumbnail);
}

Upload Files Directly

Without pre-configuration:

const result = await ctx.plugins.contentOne.cdnClient.upload("/tmp/photo.jpg", "file_archive_token", {
  image_rotate: "auto",
  image_resize_width: 1200,
});

Upload Options

  • folderId (string): Folder to save the file to
  • image_rotate ("90" | "180" | "270" | "auto"): Rotate image (auto uses EXIF data)
  • image_resize_width (number): Resize to specific width
  • image_resize_height (number): Resize to specific height
  • image_resize_max ("yes" | "no"): Keep aspect ratio, fit within dimensions
  • image_resize_crop ("center" | "attention"): Crop strategy for exact dimensions
  • image_thumb ("yes" | "no"): Generate thumbnail
  • image_thumb_width (number): Thumbnail width
  • image_thumb_height (number): Thumbnail height

Upload Response

{
  status: "success" | "fail",
  file: {
    _id: string;
    ProjectID: string;
    Local_FileName: string;
    CDN_FileName: string;
    Url: string;
    Type: string;
    Size: number;
    CreatedDate: string;
    FolderID: string;
    Thumbnail?: string;
    ThumbnailCDN_Filename?: string;
  }
}

Direct API Calls

The plugin supports direct API calls without pre-configuration:

Direct Collection Access

const document = (
  await ctx.plugins.contentOne.getClient({
    token: "token",
    collection: "collection_id",
  }).get("document_id")
).document;

Direct Action Execution

const response = await ctx.plugins.contentOne.management.action(
  "action_id",
  "api_key",
  {
    argument: "value",
  }
);

Direct CDN Upload

const result = await ctx.plugins.contentOne.cdnClient.upload(
  "./file.txt",
  "token",
  {}
);

Complete Example

import { FlinkApp } from "@flink-app/flink";
import {
  contentOnePlugin,
  ContentOneClient,
  ContentOneManagementAction,
  ContentOneCDN,
} from "@flink-app/contentone-plugin";

interface Article {
  _id: string;
  title: string;
  content: string;
  author: string;
  publishedAt: string;
}

const plugin = contentOnePlugin({
  collections: {
    Articles: new ContentOneClient({
      collection: "articles_collection_id",
      token: process.env.CONTENTONE_TOKEN!,
      debug: true, // Enable logging
    }),
  },
  actions: {
    PublishArticle: new ContentOneManagementAction({
      actionId: "publish_article",
      apiKey: process.env.CONTENTONE_API_KEY!,
    }),
  },
  cdns: {
    images: new ContentOneCDN({
      token: process.env.CONTENTONE_CDN_TOKEN!,
    }),
  },
});

// Later in your handler or job:
async function publishArticle(ctx: AppContext, articleId: string) {
  // Get the article
  const article = (
    await ctx.plugins.contentOne.collections.Articles.get<Article>(articleId, {
      language: "en",
      environment: "Production",
    })
  ).document;

  // Execute publish action
  const result = await ctx.plugins.contentOne.actions.PublishArticle.execute({
    articleId: article._id,
    publishDate: new Date().toISOString(),
  });

  return result;
}

async function uploadArticleImage(ctx: AppContext, imagePath: string) {
  const upload = await ctx.plugins.contentOne.cdns.images.upload(imagePath, {
    image_rotate: "auto",
    image_resize_width: 1200,
    image_resize_max: "yes",
    image_thumb: "yes",
    image_thumb_width: 300,
    image_thumb_height: 200,
  });

  if (upload.status === "success") {
    return {
      imageUrl: upload.file.Url,
      thumbnailUrl: upload.file.Thumbnail,
    };
  }

  throw new Error("Upload failed");
}

Error Handling

Always wrap API calls in try-catch blocks:

try {
  const document = (
    await ctx.plugins.contentOne.collections.NewsItems.get("document_id")
  ).document;
} catch (error) {
  console.error("Failed to fetch document:", error);
  // Handle error appropriately
}

Debug Mode

Enable debug mode for a collection to log all API requests and responses:

new ContentOneClient({
  collection: "collection_id",
  token: "token",
  debug: true, // Logs all requests and responses
});

API Response Types

Document Response

{
  status: "success" | "error",
  document: T,
  message?: string
}

Document List Response

{
  status: "success" | "error",
  documents: T[],
  message?: string
}

Action Response

{
  status: "success" | "error",
  data: T
}

License

MIT