Skip to main content

Existing Components in Code-Native

Prismatic provides a number of existing components that you can use in your code-native integrations. By leveraging an existing component, you can save time and effort by reusing existing functionality. Both public and your private components can be used in your code-native integrations.

An example integration that uses the existing Slack OAuth 2.0 connection, Slack "Select Channel" data source, and Slack "Post Message" action is available in GitHub.

Importing types from existing components

To use an existing trigger, connection, data source or action you need to import TypeScript types from the existing component.

Importing types from public components

Manifests for Prismatic-provided public components are available through Prismatic's component manifests repository. When you initialized your code-native integration, an .npmrc file was created which read:

.npmrc
@component-manifests:registry=https://app.prismatic.io/packages/npm

That instructs your package manager to look for packages that begin with @component-manifests in the Prismatic repository.

Yarn 2+ configuration

NPM and Yarn "Classic" (1.x) both respect a .npmrc file. If you are using a more recent version of yarn, please replace the .npmrc file with a .yarnrc.yml file that reads:

.yarnrc.yml
npmScopes:
"component-manifests":
npmRegistryServer: "https://app.prismatic.io/packages/npm"

To add a component's manifest package to your code-native project, take note of the component's key and run:

Add the Slack component's manifest to a code-native project
npm install @component-manifests/slack

Importing types from private components

If you've developed your own custom component(s), you can do one of two things to share the component logic with the code-native integration:

  1. You can abstract the logic from the custom component into a distinct package, and reference that logic in both the custom component and code-native integration. In this case, your code-native integration won't depend on a custom component - it'll run utility and helper functions from your abstracted library.

  2. You can generate a component manifest, like those created for Prismatic-provided public components. To create your own component manifest, build and publish your component and then run:

    Generate a component manifest from a private component
    npx @prismatic-io/spectral@latest component-manifest

    This will generate a manifest project alongside your component project. You can save this project alongside your code-native project, or publish it to a package repository that you control.

Adding components to a code-native component manifest

Once the component manifest is installed, add it to componentRegistry.ts

componentRegistry.ts
import { componentManifests } from "@prismatic-io/spectral";
import slack from "@component-manifests/slack";

export const componentRegistry = componentManifests({
slack,
});

Behind the scenes, .spectral/index.ts will inspect your code-native project's exported componentRegistry object, and will provide type hinting to your TypeScript based on which components are included in your component registry.

Using existing connections in code-native

After adding an existing component's manifest to your code-native project, you can use a component's connection in your code-native integration's configPages definition. At the top of your config pages file, import the connectionConfigVar function from @prismatic-io/spectral. Within a config page, include a connectionConfigVar() that includes a connection property:

Using an existing connection in a code-native integration
import { configPage, connectionConfigVar } from "@prismatic-io/spectral";

export const configPages = {
Connections: configPage({
tagline: "Authenticate with Slack",
elements: {
"Slack OAuth Connection": connectionConfigVar({
stableKey: "my-slack-connection",
dataType: "connection",
connection: {
component: "slack",
key: "oauth2",
values: {
clientId: {
value: "REPLACE_ME_WITH_YOUR_CLIENT_ID",
permissionAndVisibilityType: "organization",
visibleToOrgDeployer: false,
},
clientSecret: {
value: "REPLACE_ME_WITH_YOUR_CLIENT_SECRET",
permissionAndVisibilityType: "organization",
visibleToOrgDeployer: false,
},
signingSecret: {
value: "REPLACE_ME_WITH_YOUR_SIGNING_SECRET",
permissionAndVisibilityType: "organization",
visibleToOrgDeployer: false,
},
scopes: {
value: "chat:write chat:write.public channels:read",
permissionAndVisibilityType: "organization",
visibleToOrgDeployer: false,
},
},
},
}),
},
}),
};

You can reference an connection template in a referenced connection if you provide a template name value to your connection definition.

Using existing data sources in code-native

After adding an existing component's manifest to your code-native project, you can use a component's data source in your code-native integration's configPages definition. At the top of your config pages file, import the dataSourceConfigVar function from @prismatic-io/spectral. Within a config page, include a dataSourceConfigVar() that includes a dataSource property:

import { configPage, dataSourceConfigVar } from "@prismatic-io/spectral";

export const configPages = {
// ...
"Slack Config": configPage({
tagline: "Select a Slack channel from a dropdown menu",
elements: {
"Select Slack Channel": dataSourceConfigVar({
stableKey: "my-slack-channel-picklist",
dataSource: {
component: "slack",
key: "selectChannels",
values: {
connection: { configVar: "Slack OAuth Connection" },
includePublicChannels: { value: "true" },
},
},
}),
},
}),
};

If the data source requires a connection, you can pass a connection to the data source using the appropriate input value by specifying a configVar by name (connection: { configVar: "Slack OAuth Connection" }, in the example above).

Using existing triggers in code-native

After adding an existing component's manifest to your code-native project, you can use a component's trigger in your code-native integration's flow definition.

Using an existing trigger in a code-native integration
export const existingComponentTriggerFlow = flow({
name: "Existing Component Trigger Flow",
stableKey: "6f58c32c-b29a-4f55-97e6-b86bf9e24551",
description: "This flow uses an existing component trigger",
onTrigger: {
component: "hash",
key: "hmacWebhookTrigger",
values: {
hmacHeaderName: { value: "X-Signature-256" },
secretKey: { configVar: "My Secret Key Config Var" },
hashFunction: { value: "sha256" },
},
},
onExecution: async (context, params) => {
const { logger } = context;

logger.info(`Action context: ${JSON.stringify(context)}`);
logger.info(`Action params: ${JSON.stringify(params)}`);

return Promise.resolve({ data: null });
},
});

If the trigger takes inputs, those inputs are passed to the trigger as values, and values can be either static string value, or can reference config variables with configVar: "Config Variable Name".

Using existing actions in code-native

After importing an existing component's manifest and adding it to your componentManifests export, you can call one of the component's actions from within your flow. Components are accessible through the context.components object.

For example,

Using an existing action in a code-native integration
export const existingComponentTriggerFlow = flow({
name: "Send a Slack Message",
stableKey: "send-a-slack-message",
description: "Send 'Hello World' to a Slack channel",
onExecution: async (context, params) => {
await context.components.slack.postMessage({
channelName: util.types.toString(configVars["Select Slack Channel"]),
connection: configVars["Slack OAuth Connection"],
message: `Incomplete item: ${item.task}`,
});

return { data: null };
},
});