Skip to content

Commit

Permalink
Add support for connection avatar icons
Browse files Browse the repository at this point in the history
  • Loading branch information
bkegley committed Oct 25, 2024
1 parent 3b5c0d7 commit 45cfa1e
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 39 deletions.
Binary file modified bun.lockb
Binary file not shown.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@prismatic-io/prism",
"version": "7.1.5",
"version": "7.2.0",
"description": "Build, deploy, and support integrations in Prismatic from the comfort of your command line",
"keywords": ["prismatic", "cli"],
"homepage": "https://prismatic.io",
Expand Down Expand Up @@ -44,7 +44,7 @@
"@oclif/plugin-help": "6.0.20",
"@oclif/plugin-plugins": "5.0.9",
"@oclif/plugin-warn-if-update-available": "3.1.18",
"@prismatic-io/spectral": "9.2.0",
"@prismatic-io/spectral": "10.0.0",
"archiver": "6.0.1",
"axios": "1.7.7",
"chardet": "1.5.1",
Expand Down
5 changes: 4 additions & 1 deletion src/commands/components/dev/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,10 @@ export default class TestCommand extends PrismaticBaseCommand {
const {
display: { iconPath },
} = definition;
await uploadFile(iconPath, iconUploadUrl);
if (iconPath) {
await uploadFile(iconPath, iconUploadUrl);
}

await uploadConnectionIcons(definition, connectionIconUploadUrls);
await uploadFile(packagePath, packageUploadUrl);

Expand Down
5 changes: 4 additions & 1 deletion src/commands/components/publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,10 @@ export default class PublishCommand extends PrismaticBaseCommand {
display: { iconPath },
} = definition;
await uploadFile(packagePath, packageUploadUrl);
await uploadFile(iconPath, iconUploadUrl);
if (iconPath) {
await uploadFile(iconPath, iconUploadUrl);
}

await uploadConnectionIcons(definition, connectionIconUploadUrls);

const {
Expand Down
22 changes: 16 additions & 6 deletions src/generate/formats/readers/openapi/connections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ export const buildConnections = (
const connection = stripUndefined<Connection>({
orderPriority: 50,
key: camelCase(key),
label: startCase(key),
comments: createDescription(scheme.description),
display: {
label: startCase(key),
description: createDescription(scheme.description),
},
inputs: {
apiKey: {
label: startCase(scheme.type === "apiKey" ? scheme.name : "Token"),
Expand All @@ -32,8 +34,10 @@ export const buildConnections = (
const connection = stripUndefined<Connection>({
orderPriority: 1000,
key: camelCase(key),
label: startCase(key),
comments: createDescription(scheme.description),
display: {
label: startCase(key),
description: createDescription(scheme.description),
},
inputs: {
username: {
label: "Username",
Expand All @@ -57,7 +61,10 @@ export const buildConnections = (
const connection = stripUndefined<Connection>({
orderPriority: 0,
key: camelCase(key),
label: "OAuth 2.0", // TODO: Apparently OpenAPI lacks a name/description for this scheme? Ok.
display: {
label: "OAuth 2.0", // TODO: Apparently OpenAPI lacks a name/description for this scheme? Ok.
description: "",
},
oauth2Type: OAuth2Type.AuthorizationCode,
inputs: {
authorizeUrl: stripUndefined<ConnectionInput>({
Expand Down Expand Up @@ -109,7 +116,10 @@ export const buildConnections = (
const connection = stripUndefined<Connection>({
orderPriority: 10,
key: camelCase(key),
label: "OAuth 2.0 Client Credentials",
display: {
label: "OAuth 2.0 Client Credentials",
description: "",
},
oauth2Type: OAuth2Type.ClientCredentials,
inputs: {
tokenUrl: stripUndefined<ConnectionInput>({
Expand Down
27 changes: 21 additions & 6 deletions src/generate/formats/writer/connections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,11 @@ const writeInput = (

const buildConnectionDeclaration = ({
key,
label,
display,
oauth2Type,
iconPath,
comments,
inputs,
}: Connection): VariableDeclarationStructure => {
const { label, description, icons } = display;
const connectionFn = oauth2Type === undefined ? "connection" : "oauth2Connection";

return {
Expand All @@ -57,9 +56,25 @@ const buildConnectionDeclaration = ({
writer
.writeLine(`${connectionFn}({`)
.writeLine(`key: "${key}",`)
.writeLine(`label: "${label}",`)
.conditionalWriteLine(comments !== undefined, `comments: "${escapeText(comments)}",`)
.conditionalWriteLine(iconPath !== undefined, `iconPath: "${iconPath}",`)
.write("display: ")
.block(() => {
writer
.writeLine(`label: "${label}",`)
.writeLine(`description: "${escapeText(description)}",`)
.write("icons: ")
.block(() => {
writer
.conditionalWriteLine(
icons?.avatarPath !== undefined,
`avatarPath: "${icons?.avatarPath}",`,
)
.conditionalWriteLine(
icons?.oauth2ConnectionIconPath !== undefined,
`oauth2ConnectionIconPath: "${icons?.oauth2ConnectionIconPath}",`,
);
});
})
.writeLine(",")
.conditionalWriteLine(oauth2Type !== undefined, () => {
if (oauth2Type === OAuth2Type.AuthorizationCode) {
return "oauth2Type: OAuth2Type.AuthorizationCode,";
Expand Down
11 changes: 7 additions & 4 deletions src/utils/component/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ComponentDefinition as ComponentDefinitionTemplate } from "@prismatic-io/spectral";
import { Component as ComponentDefinitionTemplate } from "@prismatic-io/spectral/dist/serverTypes";
import { ux } from "@oclif/core";
import { resolve } from "path";
import tempy from "tempy";
Expand All @@ -22,8 +22,8 @@ type LegacyDefinition = {
* Prism must be capable of publishing all past component definitions and
* gracefully publish future component definitions.
*/
export type ComponentDefinition = Omit<ComponentDefinitionTemplate<false, any>, "hooks"> &
Pick<ComponentDefinitionTemplate<true, any>, "documentationUrl"> &
export type ComponentDefinition = Omit<ComponentDefinitionTemplate, "hooks"> &
Pick<ComponentDefinitionTemplate, "documentationUrl"> &
LegacyDefinition;

interface ComponentEntrypoint {
Expand Down Expand Up @@ -86,7 +86,10 @@ export const validateDefinition = async (definition: ComponentDefinition): Promi
}

const connectionIconsValid = await Promise.all(
(connections ?? []).map(({ iconPath }) => validateIcon(iconPath)),
(connections ?? []).map(({ iconPath, avatarIconPath }) => [
validateIcon(iconPath),
validateIcon(avatarIconPath),
]),
);
if (connectionIconsValid.some((v) => !v)) {
ux.error("One or more connection icons do not exist or are not a png. Exiting.", {
Expand Down
81 changes: 62 additions & 19 deletions src/utils/component/publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { extname } from "path";
import crypto from "crypto";
import { ux } from "@oclif/core";
import mimetypes from "mime-types";
import axios from "axios";
import axios, { AxiosResponse } from "axios";

import { ComponentDefinition } from "./index.js";
import { fs } from "../../fs.js";
Expand All @@ -18,6 +18,7 @@ const componentDefinitionShape: Record<keyof ComponentDefinition, true> = {
key: true,
public: true,
triggers: true,
codeNativeIntegrationYAML: true,
};

export const checkPackageSignature = async (
Expand Down Expand Up @@ -88,7 +89,13 @@ export const publishDefinition = async (
): Promise<{
iconUploadUrl: string;
packageUploadUrl: string;
connectionIconUploadUrls: Record<string, string>;
connectionIconUploadUrls: Record<
string,
{
iconUploadUrl?: string;
avatarIconUploadUrl?: string;
}
>;
versionNumber: string;
}> => {
const componentDefinition: Record<string, unknown> = Object.entries(rest).reduce(
Expand Down Expand Up @@ -165,6 +172,10 @@ export const publishDefinition = async (
connectionKey
iconUploadUrl
}
connectionAvatarIconUploadUrls {
connectionKey
iconUploadUrl
}
}
errors {
field
Expand All @@ -189,21 +200,32 @@ export const publishDefinition = async (
iconUploadUrl,
packageUploadUrl,
connectionIconUploadUrls,
connectionAvatarIconUploadUrls,
component: { versionNumber },
} = result.publishComponent.publishResult;

const uploadUrls = (
connectionIconUploadUrls as {
const uploadUrls: Record<string, { iconUploadUrl?: string; avatarIconUploadUrl?: string }> = {};

(
connectionIconUploadUrls as Array<{
connectionKey: string;
iconUploadUrl: string;
}[]
).reduce<Record<string, string>>(
(result, { connectionKey, iconUploadUrl }) => ({
...result,
[connectionKey]: iconUploadUrl,
}),
{},
);
}>
).forEach(({ connectionKey, iconUploadUrl }) => {
uploadUrls[connectionKey] = { iconUploadUrl };
});

(
connectionAvatarIconUploadUrls as Array<{
connectionKey: string;
iconUploadUrl: string;
}>
).forEach(({ connectionKey, iconUploadUrl }) => {
uploadUrls[connectionKey] = {
...uploadUrls[connectionKey],
avatarIconUploadUrl: iconUploadUrl,
};
});

return {
iconUploadUrl,
Expand Down Expand Up @@ -231,7 +253,10 @@ export const uploadFile = async (filePath: string, destinationUrl: string) => {

export const uploadConnectionIcons = async (
{ connections }: ComponentDefinition,
connectionIconUploadUrls: Record<string, string>,
connectionIconUploadUrls: Record<
string,
{ iconUploadUrl?: string; avatarIconUploadUrl?: string }
>,
): Promise<void> => {
if (
!connections ||
Expand All @@ -242,18 +267,36 @@ export const uploadConnectionIcons = async (
return;
}

const iconPaths = connections.reduce<Record<string, string>>((result, { key, iconPath }) => {
if (!iconPath) {
const iconPaths = connections.reduce<
Record<string, { avatarIconPath?: string; iconPath?: string }>
>((result, { key, iconPath, avatarIconPath }) => {
if (!iconPath && !avatarIconPath) {
return result;
}
return {
...result,
[key]: iconPath,
[key]: {
iconPath,
avatarIconPath,
},
};
}, {});

const promises = Object.entries(connectionIconUploadUrls).map(
async ([connectionKey, uploadUrl]) => uploadFile(iconPaths[connectionKey], uploadUrl),
);
const promises = Object.entries(connectionIconUploadUrls).reduce<
Array<Promise<AxiosResponse<any, any>>>
>((acc, [connectionKey, { iconUploadUrl, avatarIconUploadUrl }]) => {
const connectionIconPaths = iconPaths[connectionKey];

if (connectionIconPaths.iconPath && iconUploadUrl) {
acc.push(uploadFile(connectionIconPaths.iconPath, iconUploadUrl));
}

if (connectionIconPaths.avatarIconPath && avatarIconUploadUrl) {
acc.push(uploadFile(connectionIconPaths.avatarIconPath, avatarIconUploadUrl));
}

return acc;
}, []);

await Promise.all(promises);
};

0 comments on commit 45cfa1e

Please sign in to comment.