@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-pluginUsage
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 toContentOneClientinstancesactions(optional): Object mapping action names toContentOneManagementActioninstancescdns(optional): Object mapping CDN names toContentOneCDNinstancesbaseUrl(optional): Content One API base URL (defaults tohttps://cdb.aquro.com)managementBaseUrl(optional): Content One Management API base URL (defaults tohttps://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 fromresolve("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 bysort_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 toimage_rotate("90" | "180" | "270" | "auto"): Rotate image (auto uses EXIF data)image_resize_width(number): Resize to specific widthimage_resize_height(number): Resize to specific heightimage_resize_max("yes" | "no"): Keep aspect ratio, fit within dimensionsimage_resize_crop("center" | "attention"): Crop strategy for exact dimensionsimage_thumb("yes" | "no"): Generate thumbnailimage_thumb_width(number): Thumbnail widthimage_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
