Skip to content

Commit

Permalink
[Dub Link Shortener] Improvements to 'Search Links' and 'Shorten Link…
Browse files Browse the repository at this point in the history
…s' commands (#12992)

* perf(dub-link-shortener): adds workspace and domain selection to commands

closes #12991

* refactor(dub-link-shortener): lint fix

closes #12991

* doc(dub-link-shortener): improved docs

closes #12991

* perf(dub-link-shortener): better error handling and mutation

closes #12991

* refactor(dub-link-shortener): imports and accessories

closes #12991

* fix(dub-link-shortener): correct use for mutate

closes #12991

* fix(dub-link-shortener): more disambiguation for user-agent

closes #12991

* refactor(dub-link-shortener): optimize axios calls

closes #12991

* chore(dub-link-shortener): upgraded dependencies

closes #12991

* refactor(dub-link-shortener) adds todos

closes #12991

* Update CHANGELOG.md and optimise images

---------

Co-authored-by: raycastbot <bot@raycast.com>
  • Loading branch information
jfkisafk and raycastbot committed Jun 28, 2024
1 parent 55f01ca commit aa33412
Show file tree
Hide file tree
Showing 27 changed files with 1,165 additions and 673 deletions.
6 changes: 6 additions & 0 deletions extensions/dub-link-shortener/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Dub Link Shortener Changelog

## [Improvements] - 2024-06-28

- Search Links: Improved the UX, added metadata and a workspace selection accessory
- Shorten Links: Added form options for workspace, tags, domain and improved UX
- Replaced project slug with workspaceId as slug is deprecated now
- Used React hooks from @raycast/utils and upgraded dependencies

## [Enhancement: Remove long URL in the list view for clarity] - 2024-02-07
- Take in urlKey that sets a custom short URL
Expand Down
10 changes: 1 addition & 9 deletions extensions/dub-link-shortener/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,4 @@ Dub.co is the open-source link management infrastructure. This extension allows

# Instructions

You need 3 things from Dub:
1) API Key
2) Project Slug
3) Project Domain

1) Create a new API key here: https://app.dub.co/settings/tokens
2) See below screenshot
3) See below screenshot
![instructions for project slug and domain](https://github.com/quuu/raycast-extensions/blob/main/extensions/dub-link-shortener/assets/project-instructions.png?raw=true)
You will need the API key from Dub.co. To generate API key, follow [these instructions](https://dub.co/docs/api-reference/introduction#authentication).
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
765 changes: 412 additions & 353 deletions extensions/dub-link-shortener/package-lock.json

Large diffs are not rendered by default.

34 changes: 9 additions & 25 deletions extensions/dub-link-shortener/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
"Applications",
"Web"
],
"contributors": [
"stelo"
],
"license": "MIT",
"commands": [
{
"name": "shorten-link",
"title": "Shorten Link",
"subtitle": "Shorten a link with dub.co",
"description": "Shorten links with dub.co",
"description": "Shorten links from arguments, clipboard or selection with dub.co using workspaces, custom domains, tags etc.",
"mode": "view",
"arguments": [
{
Expand All @@ -36,16 +38,14 @@
{
"name": "search-links",
"title": "Search Links",
"subtitle": "Search shortened dub.co links",
"description": "Search shortened links with dub.co",
"description": "Search shortened links with dub.co in different workspaces",
"mode": "view"
}
],
"dependencies": {
"@raycast/api": "^1.61.2",
"axios": "^1.6.2",
"react-dom": "^18.2.0",
"react-query": "^3.39.3"
"@raycast/utils": "^1.16.0",
"axios": "^1.6.2"
},
"preferences": [
{
Expand All @@ -54,28 +54,12 @@
"required": true,
"title": "API Key",
"description": "Dub.co API key."
},
{
"name": "projectSlug",
"type": "textfield",
"required": true,
"title": "Project Slug",
"description": "Dub.co project slug.",
"placeholder": "project-slug"
},
{
"name": "projectDomain",
"type": "textfield",
"required": true,
"title": "Project Domain",
"description": "Dub.co project domain.",
"placeholder": "dub.co"
}
],
"devDependencies": {
"@raycast/eslint-config": "^1.0.6",
"@types/node": "18.18.4",
"@types/react": "18.2.27",
"@types/node": "^20.14.2",
"@types/react": "^18.3.3",
"eslint": "^8.51.0",
"prettier": "^3.0.3",
"typescript": "^5.2.2"
Expand Down
64 changes: 64 additions & 0 deletions extensions/dub-link-shortener/src/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import axios, { AxiosRequestConfig } from "axios";
import { BASE_API_URL } from "@utils/constants";
import { apiKey, commandName, extensionName } from "@utils/env";
import { DeleteLinkResponseBody, LinkSchema, TagSchema, WorkspaceId, WorkspaceSchema } from "@/types";
import { captureException } from "@raycast/api";

const hasHttps = (url: string) => url.startsWith("https://");
const headers = {
Authorization: "Bearer " + apiKey,
"Content-Type": "application/json",
"user-agent": `raycast/${extensionName}/${commandName}`,
};

/**
* todo: Replace with SDK https://d.to/sdk once it is stable
* see: https://github.com/dubinc/dub-node/blob/765e170c45a361de3ae62e0d19571ceca4a3f0f4/README.md#maturity
*/
export const callApi = async <T>(config: AxiosRequestConfig) => {
return await axios({ ...config, headers })
.then(({ data }) => data as T)
.catch(({ response }) => {
const err = new Error(response?.data?.error?.message ?? "Unknown error");
captureException(err);
throw err;
});
};

export const getAllWorkspaces = async () => {
return await callApi<WorkspaceSchema[]>({ method: "GET", url: `${BASE_API_URL}/workspaces` });
};

export const createShortLink = async ({
originalUrl,
key,
workspaceId,
domain,
tagIds,
comments,
}: { originalUrl: string; key?: string; domain?: string; tagIds?: string[]; comments?: string } & WorkspaceId) => {
const url = hasHttps(originalUrl) ? originalUrl : `https://${originalUrl}`;
return await callApi<LinkSchema>({
method: "POST",
url: `${BASE_API_URL}/links?workspaceId=${workspaceId}`,
data: { domain, url, key, tagIds, comments },
});
};

export const getAllShortLinks = async ({ workspaceId }: WorkspaceId) => {
return await callApi<LinkSchema[]>({ method: "GET", url: `${BASE_API_URL}/links?workspaceId=${workspaceId}` });
};

export const deleteShortLink = async ({ linkId, workspaceId }: { linkId: string } & WorkspaceId) => {
return await callApi<DeleteLinkResponseBody>({
method: "DELETE",
url: `${BASE_API_URL}/links/${linkId}?workspaceId=${workspaceId}`,
});
};

/**
* todo: Add commands and api(s) to create/manage tags in the workspace.
*/
export const getAllTags = async ({ workspaceId }: WorkspaceId) => {
return await callApi<TagSchema[]>({ method: "GET", url: `${BASE_API_URL}/tags?workspaceId=${workspaceId}` });
};
10 changes: 0 additions & 10 deletions extensions/dub-link-shortener/src/components/action-go-dub-co.tsx

This file was deleted.

18 changes: 0 additions & 18 deletions extensions/dub-link-shortener/src/components/list-empty-view.tsx

This file was deleted.

18 changes: 18 additions & 0 deletions extensions/dub-link-shortener/src/hooks/use-short-links.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useCachedPromise } from "@raycast/utils";
import { getAllShortLinks } from "@/api";
import { WorkspaceId } from "@/types";

export const useShortLinks = ({ workspaceId, workspacesError }: WorkspaceId & { workspacesError?: Error }) => {
const {
data: shortLinks,
isLoading,
error,
mutate,
} = useCachedPromise(getAllShortLinks, [{ workspaceId }], {
initialData: [],
execute: workspaceId.length > 0 && !workspacesError,
failureToastOptions: { title: "❗ Failed to fetch short links" },
});

return { shortLinks, mutate, isLoading: (!shortLinks && !error) || isLoading, error };
};
28 changes: 28 additions & 0 deletions extensions/dub-link-shortener/src/hooks/use-workspaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useCachedPromise } from "@raycast/utils";
import { getAllTags, getAllWorkspaces } from "@/api";
import { WorkspaceSchema } from "@/types";

export const useWorkspaces = () => {
const {
data: workspaces,
isLoading,
error,
} = useCachedPromise(
async () => {
const workspaces = await getAllWorkspaces();
return await Promise.all(
workspaces.map(async (w) => {
const tags = await getAllTags({ workspaceId: w.id });
return { ...w, tags } as WorkspaceSchema;
}),
);
},
[],
{
initialData: [],
failureToastOptions: { title: "❗ Failed to fetch workspaces" },
},
);

return { workspaces, isLoading: (!workspaces && !error) || isLoading, error };
};
Loading

0 comments on commit aa33412

Please sign in to comment.