Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions .github/workflows/ci.yml
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is changed

Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,34 @@ on:
pull_request:

jobs:
quality:
name: Biome Check
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Setup Biome
uses: biomejs/setup-biome@v2
with:
version: latest
- name: Run Biome
run: biome ci .

build-mcp-server:
name: Build MCP Server
needs: quality
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: Setup Node
uses: actions/setup-node@v5
uses: actions/setup-node@v6
with:
node-version: "22"
cache: "yarn"
Expand Down
35 changes: 35 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"includes": ["**", "!!**/dist"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"lineWidth": 120
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
"dev": "vite build --watch",
"build": "tsc --noEmit && vite build",
"typecheck": "tsc --noEmit",
"start": "node dist/index.js"
"start": "node dist/index.js",
"biome:check": "biome check",
"biome:fix": "biome check --write"
},
"packageManager": "yarn@4.9.2",
"dependencies": {
Expand All @@ -48,6 +50,7 @@
"zod": "^3.25.76"
},
"devDependencies": {
"@biomejs/biome": "2.3.8",
"@smithery/sdk": "^1.7.5",
"@types/node": "^22.10.6",
"typescript": "^5.7.3",
Expand Down
9 changes: 3 additions & 6 deletions src/axiosConfig.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import axios, { AxiosInstance } from "axios";
import axios, { type AxiosInstance } from "axios";
import { PACKAGE_NAME, PACKAGE_VERSION } from "./contants";
import { PlainlyApiAuthenticationError, PlainlyApiError } from "./sdk/errors";

export function createApiClient(config: {
baseUrl: string;
apiKey: string;
}): AxiosInstance {
export function createApiClient(config: { baseUrl: string; apiKey: string }): AxiosInstance {
const baseUrl = config.baseUrl;
const apiKey = config.apiKey;

Expand Down Expand Up @@ -40,7 +37,7 @@ export function createApiClient(config: {
}
// Network or other errors
return Promise.reject(error);
}
},
);

return instance;
Expand Down
4 changes: 2 additions & 2 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env node

import { PlainlyMcpServer } from "./server";
import env from "./env";
import { createApiClient } from "./axiosConfig";
import env from "./env";
import { PlainlyMcpServer } from "./server";

// Validate required environment variables
if (!env.PLAINLY_API_KEY) {
Expand Down
6 changes: 2 additions & 4 deletions src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ type Env = {
};

export default {
PLAINLY_APP_URL:
process.env.PLAINLY_APP_URL || "https://app.plainlyvideos.com",
PLAINLY_API_URL:
process.env.PLAINLY_API_URL || "https://api.plainlyvideos.com",
PLAINLY_APP_URL: process.env.PLAINLY_APP_URL || "https://app.plainlyvideos.com",
PLAINLY_API_URL: process.env.PLAINLY_API_URL || "https://api.plainlyvideos.com",
PLAINLY_API_KEY: process.env.PLAINLY_API_KEY,
} as Env;
13 changes: 4 additions & 9 deletions src/sdk/api/getRenderItem.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import { AxiosInstance, AxiosResponse } from "axios";
import { Render } from "../types";
import type { AxiosInstance, AxiosResponse } from "axios";
import type { Render } from "../types";

export const getRenderItem = async (
client: AxiosInstance,
renderingId: string
): Promise<Render> => {
const response = await client.get<Render, AxiosResponse<Render>, void>(
`/api/v2/renders/${renderingId}`
);
export const getRenderItem = async (client: AxiosInstance, renderingId: string): Promise<Render> => {
const response = await client.get<Render, AxiosResponse<Render>, void>(`/api/v2/renders/${renderingId}`);

return response.data;
};
28 changes: 9 additions & 19 deletions src/sdk/api/getRenderableItemDetails.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AxiosInstance } from "axios";
import {
import type { AxiosInstance } from "axios";
import type {
DesignDetails,
DesignVariant,
Layer,
Expand All @@ -11,7 +11,7 @@ import {
export const getRenderableItemsDetails = async (
client: AxiosInstance,
renderableItemId: string,
isDesign: boolean
isDesign: boolean,
): Promise<RenderableItemDetails[]> => {
if (isDesign) {
return await getDesignVariants(client, renderableItemId);
Expand All @@ -20,13 +20,8 @@ export const getRenderableItemsDetails = async (
}
};

const getDesignVariants = async (
client: AxiosInstance,
designId: string
): Promise<RenderableItemDetails[]> => {
const response = await client.get<DesignDetails>(
`/api/v2/designs/${designId}`
);
const getDesignVariants = async (client: AxiosInstance, designId: string): Promise<RenderableItemDetails[]> => {
const response = await client.get<DesignDetails>(`/api/v2/designs/${designId}`);
const designDetails = response.data;

// flatten variants into renderable items with parameter details
Expand All @@ -46,13 +41,8 @@ const getDesignVariants = async (
}));
};

const getProjectTemplates = async (
client: AxiosInstance,
projectId: string
): Promise<RenderableItemDetails[]> => {
const response = await client.get<ProjectDetails>(
`/api/v2/projects/${projectId}`
);
const getProjectTemplates = async (client: AxiosInstance, projectId: string): Promise<RenderableItemDetails[]> => {
const response = await client.get<ProjectDetails>(`/api/v2/projects/${projectId}`);
const projectDetails = response.data;

// flatten templates into renderable items with parameter details
Expand All @@ -72,11 +62,11 @@ const getProjectTemplates = async (
};

const isDynamicLayer = (
layer: Layer
layer: Layer,
): layer is Layer & {
parametrization: { value: string; mandatory: boolean };
} => {
return layer.parametrization != null && layer.parametrization.expression;
return !!layer.parametrization?.expression;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is changed

};

const getExampleVideoUrl = (variant: DesignVariant): string | undefined => {
Expand Down
32 changes: 8 additions & 24 deletions src/sdk/api/listRenderableItems.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,21 @@
import { AxiosInstance } from "axios";
import type { AxiosInstance } from "axios";
import { getAspectRatio } from "../../utils/aspectRatio";
import {
Design,
Project,
RenderableItem,
RenderableItemsListOptions,
} from "../types";
import type { Design, Project, RenderableItem, RenderableItemsListOptions } from "../types";

export const listRenderableItems = async (
client: AxiosInstance,
options: RenderableItemsListOptions = {
excludeDesigns: false,
excludeProjects: false,
}
},
): Promise<RenderableItem[]> => {
const designs = options.excludeDesigns
? []
: await listRenderableDesigns(client);
const projects = options.excludeProjects
? []
: await listRenderableProjects(client);
const designs = options.excludeDesigns ? [] : await listRenderableDesigns(client);
const projects = options.excludeProjects ? [] : await listRenderableProjects(client);

return [...projects, ...designs];
};

const listRenderableDesigns = async (
client: AxiosInstance
): Promise<RenderableItem[]> => {
const listRenderableDesigns = async (client: AxiosInstance): Promise<RenderableItem[]> => {
const response = await client.get<Design[]>("/api/v2/designs");

return response.data
Expand All @@ -46,9 +35,7 @@ const listRenderableDesigns = async (
}));
};

const listRenderableProjects = async (
client: AxiosInstance
): Promise<RenderableItem[]> => {
const listRenderableProjects = async (client: AxiosInstance): Promise<RenderableItem[]> => {
const response = await client.get<Project[]>("/api/v2/projects");

return response.data
Expand All @@ -62,10 +49,7 @@ const listRenderableProjects = async (
templates: project.templates.map((template) => ({
id: template.id,
name: template.name,
aspectRatio: getAspectRatio(
template.resolution.width,
template.resolution.height
),
aspectRatio: getAspectRatio(template.resolution.width, template.resolution.height),
durationSeconds: template.duration,
})),
}));
Expand Down
15 changes: 4 additions & 11 deletions src/sdk/api/renderItem.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
import { AxiosInstance, AxiosResponse } from "axios";
import { ProjectRenderDto, Render, RenderItemParams } from "../types";
import type { AxiosInstance, AxiosResponse } from "axios";
import { PACKAGE_NAME } from "../../contants";
import type { ProjectRenderDto, Render, RenderItemParams } from "../types";

export const renderItem = async (
client: AxiosInstance,
params: RenderItemParams
): Promise<Render> => {
const response = await client.post<
Render,
AxiosResponse<Render>,
ProjectRenderDto
>("/api/v2/renders", {
export const renderItem = async (client: AxiosInstance, params: RenderItemParams): Promise<Render> => {
const response = await client.post<Render, AxiosResponse<Render>, ProjectRenderDto>("/api/v2/renders", {
projectId: params.projectDesignId,
templateId: params.templateVariantId,
parameters: params.parameters,
Expand Down
33 changes: 9 additions & 24 deletions src/sdk/index.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,23 @@
import { AxiosInstance } from "axios";

import {
import type { AxiosInstance } from "axios";
import { getRenderableItemsDetails, getRenderItem, listRenderableItems, renderItem } from "./api";
import type {
Render,
RenderableItem,
RenderableItemDetails,
RenderableItemsListOptions,
RenderItemParams,
} from "./types";
import {
getRenderableItemsDetails,
renderItem,
getRenderItem,
listRenderableItems,
} from "./api";

export * from "./types";

export interface PlainlySdk {
listRenderableItems: (
options: RenderableItemsListOptions
) => Promise<RenderableItem[]>;
getRenderableItemsDetails: (
id: string,
isDesign: boolean
) => Promise<RenderableItemDetails[]>;
listRenderableItems: (options: RenderableItemsListOptions) => Promise<RenderableItem[]>;
getRenderableItemsDetails: (id: string, isDesign: boolean) => Promise<RenderableItemDetails[]>;
renderItem: (params: RenderItemParams) => Promise<Render>;
getRenderItem: (renderingId: string) => Promise<Render>;
}

export default function createPlainlyClient(
apiClient: AxiosInstance
): PlainlySdk {
export default function createPlainlyClient(apiClient: AxiosInstance): PlainlySdk {
return {
listRenderableItems: withClient(listRenderableItems, apiClient),
getRenderableItemsDetails: withClient(getRenderableItemsDetails, apiClient),
Expand All @@ -38,9 +26,6 @@ export default function createPlainlyClient(
};
}

function withClient<T extends (...args: any[]) => any>(
fn: (client: AxiosInstance, ...args: Parameters<T>) => ReturnType<T>,
client: AxiosInstance
) {
return (...args: Parameters<T>) => fn(client, ...args);
function withClient<A extends unknown[], R>(fn: (client: AxiosInstance, ...args: A) => R, client: AxiosInstance) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is changed

return (...args: A): R => fn(client, ...args);
}
Loading