Skip to content

Commit 5c2be59

Browse files
authored
Add Biome linter/formatter (#27)
1 parent 2a8128e commit 5c2be59

25 files changed

+323
-400
lines changed

.github/workflows/ci.yml

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,34 @@ on:
66
pull_request:
77

88
jobs:
9+
quality:
10+
name: Biome Check
11+
runs-on: ubuntu-latest
12+
permissions:
13+
contents: read
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v6
17+
with:
18+
persist-credentials: false
19+
- name: Setup Biome
20+
uses: biomejs/setup-biome@v2
21+
with:
22+
version: latest
23+
- name: Run Biome
24+
run: biome ci .
25+
926
build-mcp-server:
1027
name: Build MCP Server
28+
needs: quality
1129
runs-on: ubuntu-latest
1230

1331
steps:
1432
- name: Checkout
15-
uses: actions/checkout@v5
33+
uses: actions/checkout@v6
1634

1735
- name: Setup Node
18-
uses: actions/setup-node@v5
36+
uses: actions/setup-node@v6
1937
with:
2038
node-version: "22"
2139
cache: "yarn"

biome.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
3+
"vcs": {
4+
"enabled": true,
5+
"clientKind": "git",
6+
"useIgnoreFile": true
7+
},
8+
"files": {
9+
"includes": ["**", "!!**/dist"]
10+
},
11+
"formatter": {
12+
"enabled": true,
13+
"indentStyle": "space",
14+
"lineWidth": 120
15+
},
16+
"linter": {
17+
"enabled": true,
18+
"rules": {
19+
"recommended": true
20+
}
21+
},
22+
"javascript": {
23+
"formatter": {
24+
"quoteStyle": "double"
25+
}
26+
},
27+
"assist": {
28+
"enabled": true,
29+
"actions": {
30+
"source": {
31+
"organizeImports": "on"
32+
}
33+
}
34+
}
35+
}

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@
3939
"dev": "vite build --watch",
4040
"build": "tsc --noEmit && vite build",
4141
"typecheck": "tsc --noEmit",
42-
"start": "node dist/index.js"
42+
"start": "node dist/index.js",
43+
"biome:check": "biome check",
44+
"biome:fix": "biome check --write"
4345
},
4446
"packageManager": "yarn@4.9.2",
4547
"dependencies": {
@@ -48,6 +50,7 @@
4850
"zod": "^3.25.76"
4951
},
5052
"devDependencies": {
53+
"@biomejs/biome": "2.3.8",
5154
"@smithery/sdk": "^1.7.5",
5255
"@types/node": "^22.10.6",
5356
"typescript": "^5.7.3",

src/axiosConfig.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
import axios, { AxiosInstance } from "axios";
1+
import axios, { type AxiosInstance } from "axios";
22
import { PACKAGE_NAME, PACKAGE_VERSION } from "./contants";
33
import { PlainlyApiAuthenticationError, PlainlyApiError } from "./sdk/errors";
44

5-
export function createApiClient(config: {
6-
baseUrl: string;
7-
apiKey: string;
8-
}): AxiosInstance {
5+
export function createApiClient(config: { baseUrl: string; apiKey: string }): AxiosInstance {
96
const baseUrl = config.baseUrl;
107
const apiKey = config.apiKey;
118

@@ -40,7 +37,7 @@ export function createApiClient(config: {
4037
}
4138
// Network or other errors
4239
return Promise.reject(error);
43-
}
40+
},
4441
);
4542

4643
return instance;

src/cli.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#!/usr/bin/env node
22

3-
import { PlainlyMcpServer } from "./server";
4-
import env from "./env";
53
import { createApiClient } from "./axiosConfig";
4+
import env from "./env";
5+
import { PlainlyMcpServer } from "./server";
66

77
// Validate required environment variables
88
if (!env.PLAINLY_API_KEY) {

src/env.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ type Env = {
55
};
66

77
export default {
8-
PLAINLY_APP_URL:
9-
process.env.PLAINLY_APP_URL || "https://app.plainlyvideos.com",
10-
PLAINLY_API_URL:
11-
process.env.PLAINLY_API_URL || "https://api.plainlyvideos.com",
8+
PLAINLY_APP_URL: process.env.PLAINLY_APP_URL || "https://app.plainlyvideos.com",
9+
PLAINLY_API_URL: process.env.PLAINLY_API_URL || "https://api.plainlyvideos.com",
1210
PLAINLY_API_KEY: process.env.PLAINLY_API_KEY,
1311
} as Env;

src/sdk/api/getRenderItem.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
import { AxiosInstance, AxiosResponse } from "axios";
2-
import { Render } from "../types";
1+
import type { AxiosInstance, AxiosResponse } from "axios";
2+
import type { Render } from "../types";
33

4-
export const getRenderItem = async (
5-
client: AxiosInstance,
6-
renderingId: string
7-
): Promise<Render> => {
8-
const response = await client.get<Render, AxiosResponse<Render>, void>(
9-
`/api/v2/renders/${renderingId}`
10-
);
4+
export const getRenderItem = async (client: AxiosInstance, renderingId: string): Promise<Render> => {
5+
const response = await client.get<Render, AxiosResponse<Render>, void>(`/api/v2/renders/${renderingId}`);
116

127
return response.data;
138
};

src/sdk/api/getRenderableItemDetails.ts

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { AxiosInstance } from "axios";
2-
import {
1+
import type { AxiosInstance } from "axios";
2+
import type {
33
DesignDetails,
44
DesignVariant,
55
Layer,
@@ -11,7 +11,7 @@ import {
1111
export const getRenderableItemsDetails = async (
1212
client: AxiosInstance,
1313
renderableItemId: string,
14-
isDesign: boolean
14+
isDesign: boolean,
1515
): Promise<RenderableItemDetails[]> => {
1616
if (isDesign) {
1717
return await getDesignVariants(client, renderableItemId);
@@ -20,13 +20,8 @@ export const getRenderableItemsDetails = async (
2020
}
2121
};
2222

23-
const getDesignVariants = async (
24-
client: AxiosInstance,
25-
designId: string
26-
): Promise<RenderableItemDetails[]> => {
27-
const response = await client.get<DesignDetails>(
28-
`/api/v2/designs/${designId}`
29-
);
23+
const getDesignVariants = async (client: AxiosInstance, designId: string): Promise<RenderableItemDetails[]> => {
24+
const response = await client.get<DesignDetails>(`/api/v2/designs/${designId}`);
3025
const designDetails = response.data;
3126

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

49-
const getProjectTemplates = async (
50-
client: AxiosInstance,
51-
projectId: string
52-
): Promise<RenderableItemDetails[]> => {
53-
const response = await client.get<ProjectDetails>(
54-
`/api/v2/projects/${projectId}`
55-
);
44+
const getProjectTemplates = async (client: AxiosInstance, projectId: string): Promise<RenderableItemDetails[]> => {
45+
const response = await client.get<ProjectDetails>(`/api/v2/projects/${projectId}`);
5646
const projectDetails = response.data;
5747

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

7464
const isDynamicLayer = (
75-
layer: Layer
65+
layer: Layer,
7666
): layer is Layer & {
7767
parametrization: { value: string; mandatory: boolean };
7868
} => {
79-
return layer.parametrization != null && layer.parametrization.expression;
69+
return !!layer.parametrization?.expression;
8070
};
8171

8272
const getExampleVideoUrl = (variant: DesignVariant): string | undefined => {

src/sdk/api/listRenderableItems.ts

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,21 @@
1-
import { AxiosInstance } from "axios";
1+
import type { AxiosInstance } from "axios";
22
import { getAspectRatio } from "../../utils/aspectRatio";
3-
import {
4-
Design,
5-
Project,
6-
RenderableItem,
7-
RenderableItemsListOptions,
8-
} from "../types";
3+
import type { Design, Project, RenderableItem, RenderableItemsListOptions } from "../types";
94

105
export const listRenderableItems = async (
116
client: AxiosInstance,
127
options: RenderableItemsListOptions = {
138
excludeDesigns: false,
149
excludeProjects: false,
15-
}
10+
},
1611
): Promise<RenderableItem[]> => {
17-
const designs = options.excludeDesigns
18-
? []
19-
: await listRenderableDesigns(client);
20-
const projects = options.excludeProjects
21-
? []
22-
: await listRenderableProjects(client);
12+
const designs = options.excludeDesigns ? [] : await listRenderableDesigns(client);
13+
const projects = options.excludeProjects ? [] : await listRenderableProjects(client);
2314

2415
return [...projects, ...designs];
2516
};
2617

27-
const listRenderableDesigns = async (
28-
client: AxiosInstance
29-
): Promise<RenderableItem[]> => {
18+
const listRenderableDesigns = async (client: AxiosInstance): Promise<RenderableItem[]> => {
3019
const response = await client.get<Design[]>("/api/v2/designs");
3120

3221
return response.data
@@ -46,9 +35,7 @@ const listRenderableDesigns = async (
4635
}));
4736
};
4837

49-
const listRenderableProjects = async (
50-
client: AxiosInstance
51-
): Promise<RenderableItem[]> => {
38+
const listRenderableProjects = async (client: AxiosInstance): Promise<RenderableItem[]> => {
5239
const response = await client.get<Project[]>("/api/v2/projects");
5340

5441
return response.data
@@ -62,10 +49,7 @@ const listRenderableProjects = async (
6249
templates: project.templates.map((template) => ({
6350
id: template.id,
6451
name: template.name,
65-
aspectRatio: getAspectRatio(
66-
template.resolution.width,
67-
template.resolution.height
68-
),
52+
aspectRatio: getAspectRatio(template.resolution.width, template.resolution.height),
6953
durationSeconds: template.duration,
7054
})),
7155
}));

src/sdk/api/renderItem.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
1-
import { AxiosInstance, AxiosResponse } from "axios";
2-
import { ProjectRenderDto, Render, RenderItemParams } from "../types";
1+
import type { AxiosInstance, AxiosResponse } from "axios";
32
import { PACKAGE_NAME } from "../../contants";
3+
import type { ProjectRenderDto, Render, RenderItemParams } from "../types";
44

5-
export const renderItem = async (
6-
client: AxiosInstance,
7-
params: RenderItemParams
8-
): Promise<Render> => {
9-
const response = await client.post<
10-
Render,
11-
AxiosResponse<Render>,
12-
ProjectRenderDto
13-
>("/api/v2/renders", {
5+
export const renderItem = async (client: AxiosInstance, params: RenderItemParams): Promise<Render> => {
6+
const response = await client.post<Render, AxiosResponse<Render>, ProjectRenderDto>("/api/v2/renders", {
147
projectId: params.projectDesignId,
158
templateId: params.templateVariantId,
169
parameters: params.parameters,

0 commit comments

Comments
 (0)