Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improving type safety for fetch results #7

Merged
merged 3 commits into from
Aug 24, 2024
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
7 changes: 7 additions & 0 deletions .changeset/lucky-peas-run.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@zemd/http-client": major
"@zemd/flickr-rest-api": major
"@zemd/figma-rest-api": major
---

improving type safety for getting results instead Response, adding tests
34 changes: 34 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: CI

on:
pull_request:
branches:
- main

jobs:
test:
name: "Build & Test: ${{ matrix.os }}"
runs-on: ${{ matrix.os }}

strategy:
fail-fast: true
matrix:
os: [ubuntu-latest]

steps:
- name: Checkout Repo
uses: actions/checkout@v3

- name: Use Node.js ${{ matrix.node_version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node_version }}

- name: Setup bun
uses: oven-sh/setup-bun@v2

- name: Install Dependencies
run: bun install

- name: Run tests
run: bun run test
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
node-version: 20.x

- name: Setup bun
uses: oven-sh/setup-bun@v1
uses: oven-sh/setup-bun@v2

- name: Install Dependencies
run: bun install
Expand Down
96 changes: 66 additions & 30 deletions apis/figma/src/api/comments.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import { z } from "zod";
import { body, method, query, type TEndpointDecTuple } from "@zemd/http-client";
import { body, method, query } from "@zemd/http-client";

const GetCommentsQuerySchema = z.object({
as_md: z.coerce.boolean().optional(),
});

export interface GetCommentsQuery extends z.infer<typeof GetCommentsQuerySchema> {}
export interface GetCommentsQuery
extends z.infer<typeof GetCommentsQuerySchema> {}

/**
* Gets a list of comments left on the file.
*/
export const getComments = (key: string, options?: GetCommentsQuery): TEndpointDecTuple => {
export const getComments = (key: string, options?: GetCommentsQuery) => {
const transformers = [method("GET")];
if (options) {
transformers.push(query(GetCommentsQuerySchema.passthrough().parse(options)));
transformers.push(
query(GetCommentsQuerySchema.passthrough().parse(options)),
);
}
return [`/v1/files/${key}/comments`, transformers];
return { url: `/v1/files/${key}/comments`, transformers };
};

const VectorSchema = z.object({
Expand All @@ -28,7 +31,9 @@ const FrameOffsetSchema = z.object({
node_offset: VectorSchema,
});

const CommentPinCornerSchema = z.enum(["bottom-right", "bottom-left", "top-right", "top-left"]).default("bottom-right");
const CommentPinCornerSchema = z
.enum(["bottom-right", "bottom-left", "top-right", "top-left"])
.default("bottom-right");

const RegionSchema = z.object({
x: z.number(),
Expand All @@ -49,33 +54,48 @@ const FrameOffsetRegionSchema = z.object({
export const PostCommentsQuerySchema = z.object({
message: z.string(),
comment_id: z.string().optional(),
client_meta: z.union([VectorSchema, FrameOffsetSchema, RegionSchema, FrameOffsetRegionSchema]),
client_meta: z.union([
VectorSchema,
FrameOffsetSchema,
RegionSchema,
FrameOffsetRegionSchema,
]),
});

export interface PostCommentsQuery extends z.infer<typeof PostCommentsQuerySchema> {}
export interface PostCommentsQuery
extends z.infer<typeof PostCommentsQuerySchema> {}

/**
* Posts a new comment on the file.
*/
export const postComments = (key: string, message: PostCommentsQuery): TEndpointDecTuple => {
return [
`/v1/files/${key}/comments`,
[method("POST"), body(JSON.stringify(PostCommentsQuerySchema.passthrough().parse(message)))],
];
export const postComments = (key: string, message: PostCommentsQuery) => {
return {
url: `/v1/files/${key}/comments`,
transformers: [
method("POST"),
body(
JSON.stringify(PostCommentsQuerySchema.passthrough().parse(message)),
),
],
};
};

/**
* Deletes a specific comment. Only the person who made the comment is allowed to delete it.
*/
export const deleteComments = (key: string, commendId: string): TEndpointDecTuple => {
return [`/v1/files/${key}/comments/${commendId}`, [method("DELETE")]];
export const deleteComments = (key: string, commendId: string) => {
return {
url: `/v1/files/${key}/comments/${commendId}`,
transformers: [method("DELETE")],
};
};

export const GetCommentsReactionsQuerySchema = z.object({
cursor: z.string().optional(),
});

export interface GetCommentsReactionsQuery extends z.infer<typeof GetCommentsReactionsQuerySchema> {}
export interface GetCommentsReactionsQuery
extends z.infer<typeof GetCommentsReactionsQuerySchema> {}

/**
* Gets a paginated list of reactions left on the comment.
Expand All @@ -84,19 +104,25 @@ export const getCommentsReactions = (
key: string,
commentId: string,
options?: GetCommentsReactionsQuery,
): TEndpointDecTuple => {
) => {
const transformers = [method("GET")];
if (options) {
transformers.push(query(GetCommentsReactionsQuerySchema.passthrough().parse(options)));
transformers.push(
query(GetCommentsReactionsQuerySchema.passthrough().parse(options)),
);
}
return [`/v1/files/${key}/comments/${commentId}/reactions`, transformers];
return {
url: `/v1/files/${key}/comments/${commentId}/reactions`,
transformers,
};
};

export const PostCommentsReactionsQuerySchema = z.object({
emoji: z.string(),
});

export interface PostCommentsReactionsQuery extends z.infer<typeof PostCommentsReactionsQuerySchema> {}
export interface PostCommentsReactionsQuery
extends z.infer<typeof PostCommentsReactionsQuerySchema> {}

/**
* Posts a new comment reaction on a file comment.
Expand All @@ -105,11 +131,18 @@ export const postCommentsReactions = (
key: string,
commentId: string,
options: PostCommentsReactionsQuery,
): TEndpointDecTuple => {
return [
`/v1/files/${key}/comments/${commentId}/reactions`,
[method("POST"), body(JSON.stringify(PostCommentsReactionsQuerySchema.passthrough().parse(options)))],
];
) => {
return {
url: `/v1/files/${key}/comments/${commentId}/reactions`,
transformers: [
method("POST"),
body(
JSON.stringify(
PostCommentsReactionsQuerySchema.passthrough().parse(options),
),
),
],
};
};

/**
Expand All @@ -120,9 +153,12 @@ export const deleteCommentsReactions = (
key: string,
commentId: string,
options: PostCommentsReactionsQuery,
): TEndpointDecTuple => {
return [
`/v1/files/${key}/comments/${commentId}/reactions`,
[method("DELETE"), query(PostCommentsReactionsQuerySchema.passthrough().parse(options))],
];
) => {
return {
url: `/v1/files/${key}/comments/${commentId}/reactions`,
transformers: [
method("DELETE"),
query(PostCommentsReactionsQuerySchema.passthrough().parse(options)),
],
};
};
92 changes: 67 additions & 25 deletions apis/figma/src/api/components.ts
Original file line number Diff line number Diff line change
@@ -1,79 +1,121 @@
import { z } from "zod";
import { method, query, type TEndpointDecTuple } from "@zemd/http-client";
import { method, query } from "@zemd/http-client";

export const PaginationQuerySchema = z.object({
page_size: z.number().optional(),
after: z.number().optional(),
before: z.number().optional(),
});

export interface GetTeamComponentsQuery extends z.infer<typeof PaginationQuerySchema> {}
export interface GetTeamComponentsQuery
extends z.infer<typeof PaginationQuerySchema> {}

/**
* Get a paginated list of published components within a team library
*/
export const getTeamComponents = (teamId: string, options: GetTeamComponentsQuery): TEndpointDecTuple => {
return [`/v1/teams/${teamId}/components`, [method("GET"), query(PaginationQuerySchema.passthrough().parse(options))]];
export const getTeamComponents = (
teamId: string,
options: GetTeamComponentsQuery,
) => {
return {
url: `/v1/teams/${teamId}/components`,
transformers: [
method("GET"),
query(PaginationQuerySchema.passthrough().parse(options)),
],
};
};

/**
* Get a list of published components within a file library
*/
export const getFileComponents = (key: string): TEndpointDecTuple => {
return [`/v1/files/${key}/components`, [method("GET")]];
export const getFileComponents = (key: string) => {
return {
url: `/v1/files/${key}/components`,
transformers: [method("GET")],
};
};

/**
* Get metadata on a component by key.
*/
export const getComponent = (key: string): TEndpointDecTuple => {
return [`/v1/components/${key}`, [method("GET")]];
export const getComponent = (key: string) => {
return {
url: `/v1/components/${key}`,
transformers: [method("GET")],
};
};

export interface GetTeamComponentSetsQuery extends z.infer<typeof PaginationQuerySchema> {}
export interface GetTeamComponentSetsQuery
extends z.infer<typeof PaginationQuerySchema> {}
/**
* Get a paginated list of published component sets within a team library
*/
export const getTeamComponentSets = (teamId: string, options: GetTeamComponentSetsQuery): TEndpointDecTuple => {
return [
`/v1/teams/${teamId}/component_sets`,
[method("GET"), query(PaginationQuerySchema.passthrough().parse(options))],
];
export const getTeamComponentSets = (
teamId: string,
options: GetTeamComponentSetsQuery,
) => {
return {
url: `/v1/teams/${teamId}/component_sets`,
transformers: [
method("GET"),
query(PaginationQuerySchema.passthrough().parse(options)),
],
};
};

/**
* Get a list of published component sets within a file library
*/
export const getFileComponentSets = (key: string): TEndpointDecTuple => {
return [`/v1/files/${key}/component_sets`, [method("GET")]];
export const getFileComponentSets = (key: string) => {
return {
url: `/v1/files/${key}/component_sets`,
transformers: [method("GET")],
};
};

/**
* Get metadata on a component set by key.
*/
export const getComponentSet = (key: string): TEndpointDecTuple => {
return [`/v1/component_sets/${key}`, [method("GET")]];
export const getComponentSet = (key: string) => {
return {
url: `/v1/component_sets/${key}`,
transformers: [method("GET")],
};
};

export interface GetTeamStylesQuery extends z.infer<typeof PaginationQuerySchema> {}
export interface GetTeamStylesQuery
extends z.infer<typeof PaginationQuerySchema> {}

/**
* Get a paginated list of published styles within a team library
*/
export const getTeamStyles = (teamId: string, options: GetTeamStylesQuery): TEndpointDecTuple => {
return [`/v1/teams/${teamId}/styles`, [method("GET"), query(PaginationQuerySchema.passthrough().parse(options))]];
export const getTeamStyles = (teamId: string, options: GetTeamStylesQuery) => {
return {
url: `/v1/teams/${teamId}/styles`,
transformers: [
method("GET"),
query(PaginationQuerySchema.passthrough().parse(options)),
],
};
};

/**
* Get a list of published styles within a file library
*/
export const getFileStyles = (key: string): TEndpointDecTuple => {
return [`/v1/files/${key}/styles`, [method("GET")]];
export const getFileStyles = (key: string) => {
return {
url: `/v1/files/${key}/styles`,
transformers: [method("GET")],
};
};

/**
* Get metadata on a style by key.
*/
export const getStyle = (key: string): TEndpointDecTuple => {
return [`/v1/styles/${key}`, [method("GET")]];
export const getStyle = (key: string) => {
return {
url: `/v1/styles/${key}`,
transformers: [method("GET")],
};
};
Loading
Loading