TypeScript types for Pipedream components (sources and actions)
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Runtime context types available during component execution, including access to props, services, and authentication.
The main runtime context available in component methods with access to props, services, and special methods.
/**
* Runtime context object available in component methods (this)
*/
interface ComponentThis {
/** Dynamic access to all component props */
[propName: string]: any;
/** Method for emitting events */
$emit: EmitMethod;
/** Authentication context when using app integrations (optional) */
$auth?: AuthContext;
/** Database service when using $.service.db (optional) */
db?: DatabaseService;
/** HTTP interface when using $.interface.http (optional) */
http?: HttpEndpoint & { respond: HttpRespondMethod };
/** Timer interface when using $.interface.timer (optional) */
timer?: { type: "$.interface.timer" };
}Usage Examples:
import { PipedreamComponent, ComponentThis } from "@pipedream/types";
const contextAwareComponent: PipedreamComponent = {
name: "Context Aware Component",
version: "1.0.0",
props: {
apiKey: {
type: "string",
label: "API Key",
secret: true
},
maxResults: {
type: "integer",
label: "Max Results",
default: 10
},
db: "$.service.db"
},
async run(event) {
// Access props directly
console.log("API Key configured:", !!this.apiKey);
console.log("Max results:", this.maxResults);
// Use database service
const lastRun = this.db.get("lastRunTime") || 0;
this.db.set("lastRunTime", Date.now());
// Emit events
this.$emit({
message: "Component executed",
lastRun,
currentRun: Date.now()
});
}
};Authentication information available when using app integrations.
/**
* Authentication context for app integrations
*/
interface AuthContext {
/** OAuth 2.0 access token (optional) */
oauth_access_token?: string;
/** OAuth 2.0 refresh token (optional) */
oauth_refresh_token?: string;
/** API key for services that use API key authentication (optional) */
api_key?: string;
/** Discord bot token (optional) */
bot_token?: string;
/** Twilio Account SID (optional) */
Sid?: string;
/** Twilio Auth Token (optional) */
Secret?: string;
/** Twilio Account SID (optional) */
AccountSid?: string;
/** Salesforce instance identifier (optional) */
yourinstance?: string;
/** Salesforce instance URL (optional) */
instance_url?: string;
/** Additional service-specific authentication fields */
[key: string]: any;
}Usage Examples:
// OAuth-based component
const oauthComponent: PipedreamComponent = {
name: "OAuth Component",
version: "1.0.0",
props: {
github: {
type: "app",
app: "github"
}
},
async run(event) {
// Access OAuth token from app authentication
const token = this.github.$auth.oauth_access_token;
const response = await fetch("https://api.github.com/user/repos", {
headers: {
"Authorization": `Bearer ${token}`,
"Accept": "application/vnd.github.v3+json"
}
});
const repos = await response.json();
repos.forEach(repo => {
this.$emit(repo, {
id: repo.id,
summary: `Repository: ${repo.full_name}`
});
});
}
};
// API key-based component
const apiKeyComponent: PipedreamComponent = {
name: "API Key Component",
version: "1.0.0",
props: {
openai: {
type: "app",
app: "openai"
},
prompt: {
type: "string",
label: "Prompt",
description: "Text prompt for OpenAI"
}
},
async run(event) {
const apiKey = this.openai.$auth.api_key;
const response = await fetch("https://api.openai.com/v1/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "text-davinci-003",
prompt: this.prompt,
max_tokens: 100
})
});
const completion = await response.json();
this.$emit(completion, {
id: completion.id,
summary: "OpenAI completion generated"
});
}
};Database service interface available when using $.service.db.
/**
* Database service for persistent storage
*/
interface DatabaseService {
/** Service type identifier */
type: "$.service.db";
/**
* Retrieve a value by key
* @param key - The key to retrieve
* @returns The stored value or undefined if not found
*/
get: (key: string) => any;
/**
* Store a value by key
* @param key - The key to store under
* @param value - The value to store
*/
set: (key: string, value: any) => void;
}Usage Examples:
// State management with database
const statefulComponent: PipedreamComponent = {
name: "Stateful Component",
version: "1.0.0",
props: {
timer: {
type: "$.interface.timer",
default: { intervalSeconds: 300 }
},
db: "$.service.db"
},
async run(event) {
// Get previous state
const runCount = this.db.get("runCount") || 0;
const lastItems = this.db.get("lastItems") || [];
// Fetch new data
const newItems = await fetchNewItems();
// Update state
this.db.set("runCount", runCount + 1);
this.db.set("lastItems", newItems);
this.db.set("lastRunTime", Date.now());
// Use state in processing
console.log(`Run #${runCount + 1}, found ${newItems.length} items`);
// Emit only new items (not in lastItems)
const actuallyNew = newItems.filter(item =>
!lastItems.some(prev => prev.id === item.id)
);
actuallyNew.forEach(item => {
this.$emit(item, {
id: item.id,
summary: `New item: ${item.name}`,
ts: Date.now()
});
});
}
};
// Pagination state management
const paginatedComponent: PipedreamComponent = {
name: "Paginated Component",
version: "1.0.0",
props: {
timer: {
type: "$.interface.timer",
default: { intervalSeconds: 600 }
},
db: "$.service.db"
},
async run(event) {
let nextPageToken = this.db.get("nextPageToken");
let hasMorePages = true;
while (hasMorePages) {
const response = await fetchPage(nextPageToken);
// Process page items
response.items.forEach(item => {
this.$emit(item, {
id: item.id,
summary: `Item: ${item.name}`
});
});
// Update pagination state
nextPageToken = response.nextPageToken;
hasMorePages = !!nextPageToken;
// Prevent infinite loops
if (response.items.length === 0) {
hasMorePages = false;
}
}
// Store next page token for next run
this.db.set("nextPageToken", nextPageToken);
}
};HTTP-specific context available when using $.interface.http.
/**
* HTTP endpoint information
*/
interface HttpEndpoint {
/** Generated unique endpoint URL */
endpoint: string;
}
/**
* Combined HTTP context available in components
*/
interface HttpContext extends HttpEndpoint {
/** Method for sending HTTP responses */
respond: HttpRespondMethod;
}Usage Examples:
// HTTP endpoint with response
const httpEndpointComponent: PipedreamComponent = {
name: "HTTP Endpoint Component",
version: "1.0.0",
props: {
http: {
type: "$.interface.http",
customResponse: true
}
},
async run(event) {
console.log("Endpoint URL:", this.http.endpoint);
try {
// Process the request
const result = await processRequest(event.body);
// Send success response
this.http.respond({
status: 200,
headers: {
"Content-Type": "application/json"
},
body: {
success: true,
data: result,
timestamp: new Date().toISOString()
}
});
// Emit event for downstream processing
this.$emit(result);
} catch (error) {
// Send error response
this.http.respond({
status: 500,
headers: {
"Content-Type": "application/json"
},
body: {
success: false,
error: error.message,
timestamp: new Date().toISOString()
}
});
}
}
};Using component methods with proper context:
const methodComponent: PipedreamComponent = {
name: "Method Component",
version: "1.0.0",
props: {
apiEndpoint: {
type: "string",
label: "API Endpoint",
default: "https://api.example.com"
},
db: "$.service.db"
},
methods: {
async makeApiCall(path: string, params?: any) {
// Access component props and context
const response = await fetch(`${this.apiEndpoint}${path}`, {
method: params ? "POST" : "GET",
headers: {
"Content-Type": "application/json"
},
body: params ? JSON.stringify(params) : undefined
});
return response.json();
},
getCachedData(key: string) {
return this.db.get(`cache:${key}`);
},
setCachedData(key: string, data: any, ttl: number = 3600) {
this.db.set(`cache:${key}`, {
data,
expires: Date.now() + (ttl * 1000)
});
}
},
async run(event) {
// Use methods with proper context
const cachedData = this.getCachedData("users");
let users;
if (cachedData && cachedData.expires > Date.now()) {
users = cachedData.data;
} else {
users = await this.makeApiCall("/users");
this.setCachedData("users", users, 1800); // 30 minutes
}
users.forEach(user => {
this.$emit(user, {
id: user.id,
summary: `User: ${user.name}`
});
});
}
};Using multiple services in a single component:
const multiServiceComponent: PipedreamComponent = {
name: "Multi-Service Component",
version: "1.0.0",
props: {
slack: {
type: "app",
app: "slack"
},
github: {
type: "app",
app: "github"
},
http: {
type: "$.interface.http"
},
db: "$.service.db"
},
async run(event) {
// Access multiple app contexts
const slackToken = this.slack.$auth.bot_token;
const githubToken = this.github.$auth.oauth_access_token;
// Use database for coordination
const lastSyncTime = this.db.get("lastGithubSync") || 0;
// Process GitHub events
const events = await fetchGithubEvents(githubToken, lastSyncTime);
// Send notifications to Slack
for (const ghEvent of events) {
await sendSlackMessage(slackToken, {
text: `GitHub: ${ghEvent.type} in ${ghEvent.repo.name}`,
channel: "#dev-notifications"
});
// Emit for other systems
this.$emit(ghEvent, {
id: ghEvent.id,
summary: `${ghEvent.type}: ${ghEvent.repo.name}`
});
}
// Update sync time
this.db.set("lastGithubSync", Date.now());
}
};Install with Tessl CLI
npx tessl i tessl/npm-pipedream--types