Skip to main content
The componentManifest() and componentManifests() functions define the shape of components that a code-native integration depends on. Component manifests are registered in the componentRegistry of an integration(), which makes the component’s actions available as typed functions via context.components inside flow execution functions.

Function signatures

// Define a single component manifest
export const componentManifest = <T extends ComponentManifest>(
  definition: T,
): T

// Define a record of multiple component manifests
export const componentManifests = <T extends Record<string, ComponentManifest>>(
  definition: T,
): T

Types

ComponentManifest

interface ComponentManifest {
  key: string;
  public: boolean;
  signature: string | null;
  actions: Record<string, ComponentManifestAction>;
  triggers: Record<string, ComponentManifestTrigger>;
  dataSources: Record<string, ComponentManifestDataSource>;
  connections: Record<string, ComponentManifestConnection>;
}
definition
ComponentManifest
required
An object describing the component and its available actions, triggers, data sources, and connections.

ComponentManifestAction

Describes a single action available in the component.
interface ComponentManifestAction {
  key?: string;
  perform: (values: any) => Promise<unknown>;
  inputs: Record<string, BaseInput>;
  examplePayload?: unknown;
}
key
string
Optional key override for this action. Defaults to the key used in the actions record.
perform
(values: any) => Promise<unknown>
The async function that implements the action. When called via context.components, Spectral routes execution through the Prismatic runtime.
inputs
Record<string, BaseInput>
Descriptions of the inputs this action accepts, including type, collection, required status, and default value.
examplePayload
unknown
An example of the value this action returns. Used for type inference — when provided, context.components.<component>.<action>() is typed with the shape of examplePayload.

BaseInput

interface BaseInput {
  inputType: InputFieldType;
  collection?: CollectionType | undefined;
  required?: boolean;
  default?: unknown;
}

Return type

componentManifest
T
The same manifest definition passed in, unchanged. Used for type inference.
Component manifests are typically auto-generated by the Prismatic CLI (prism) and imported from a generated file rather than written by hand. The functions exist primarily to provide type safety.

Using manifests in an integration

Register component manifests in the componentRegistry field of integration(). Once registered, actions are available as typed async functions in context.components.<componentKey>.<actionKey>(inputs) inside any flow’s onExecution function.
import {
  integration,
  flow,
  componentManifest,
} from "@prismatic-io/spectral";

const slackManifest = componentManifest({
  key: "slack",
  public: true,
  signature: null,
  actions: {
    postMessage: {
      perform: async (values) => {
        // Implemented by the Prismatic runtime
      },
      inputs: {
        connection: { inputType: "connection", required: true },
        message: { inputType: "string", required: true },
        channel: { inputType: "string", required: true },
      },
      examplePayload: {
        data: { ok: true, ts: "1234567890.123456" },
      },
    },
  },
  triggers: {},
  dataSources: {},
  connections: {},
});

export default integration({
  name: "Slack Notifier",
  flows: [
    flow({
      name: "Send Notification",
      stableKey: "send-notification",
      onExecution: async (context, params) => {
        // context.components.slack.postMessage is typed based on examplePayload
        const result = await context.components.slack.postMessage({
          connection: { configVar: "Slack Connection" },
          message: { value: "Hello from Prismatic!" },
          channel: { value: "#general" },
        });
        context.logger.info("Message sent", { ts: result.data.ts });
        return { data: null };
      },
    }),
  ],
  componentRegistry: { slack: slackManifest },
});

Using componentManifests() for multiple components

When registering several components, use componentManifests() to group them into a single typed record:
import {
  integration,
  flow,
  componentManifests,
} from "@prismatic-io/spectral";

const registry = componentManifests({
  slack: {
    key: "slack",
    public: true,
    signature: null,
    actions: {
      postMessage: {
        perform: async (values) => {},
        inputs: {
          connection: { inputType: "connection", required: true },
          message: { inputType: "string", required: true },
          channel: { inputType: "string", required: true },
        },
        examplePayload: { data: { ok: true } },
      },
    },
    triggers: {},
    dataSources: {},
    connections: {},
  },
  hubspot: {
    key: "hubspot",
    public: true,
    signature: null,
    actions: {
      createContact: {
        perform: async (values) => {},
        inputs: {
          connection: { inputType: "connection", required: true },
          email: { inputType: "string", required: true },
        },
        examplePayload: { data: { id: "12345" } },
      },
    },
    triggers: {},
    dataSources: {},
    connections: {},
  },
});

export default integration({
  name: "Multi-Component Integration",
  flows: [
    flow({
      name: "Notify and Create",
      stableKey: "notify-and-create",
      onExecution: async (context, params) => {
        await context.components.slack.postMessage({
          connection: { configVar: "Slack Connection" },
          message: { value: "New contact created!" },
          channel: { value: "#sales" },
        });
        const contact = await context.components.hubspot.createContact({
          connection: { configVar: "HubSpot Connection" },
          email: { value: "new@example.com" },
        });
        context.logger.info("Contact created", { id: contact.data.id });
        return { data: null };
      },
    }),
  ],
  componentRegistry: registry,
});

Module augmentation for full type safety

For full type inference on context.components, declare a module augmentation so that Spectral knows which components are registered:
import type { slackManifest } from "./manifests";

declare module "@prismatic-io/spectral" {
  interface IntegrationDefinitionComponentRegistry {
    slack: typeof slackManifest;
  }
}
This pattern (typically generated by the Prismatic CLI) ensures that context.components.slack.postMessage(...) is fully typed end-to-end.