Add Activepieces integration for workflow automation
- Add Activepieces fork with SmoothSchedule custom piece - Create integrations app with Activepieces service layer - Add embed token endpoint for iframe integration - Create Automations page with embedded workflow builder - Add sidebar visibility fix for embed mode - Add list inactive customers endpoint to Public API - Include SmoothSchedule triggers: event created/updated/cancelled - Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
export * from './lib';
|
||||
@@ -0,0 +1,81 @@
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { ActionContext } from '../context';
|
||||
import { ActionBase } from '../piece-metadata';
|
||||
import { InputPropertyMap } from '../property';
|
||||
import { ExtractPieceAuthPropertyTypeForMethods, PieceAuthProperty } from '../property/authentication';
|
||||
|
||||
export type ActionRunner<PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = PieceAuthProperty, ActionProps extends InputPropertyMap = InputPropertyMap> =
|
||||
(ctx: ActionContext<PieceAuth, ActionProps>) => Promise<unknown | void>
|
||||
|
||||
export const ErrorHandlingOptionsParam = Type.Object({
|
||||
retryOnFailure: Type.Object({
|
||||
defaultValue: Type.Optional(Type.Boolean()),
|
||||
hide: Type.Optional(Type.Boolean()),
|
||||
}),
|
||||
continueOnFailure: Type.Object({
|
||||
defaultValue: Type.Optional(Type.Boolean()),
|
||||
hide: Type.Optional(Type.Boolean()),
|
||||
}),
|
||||
})
|
||||
export type ErrorHandlingOptionsParam = Static<typeof ErrorHandlingOptionsParam>
|
||||
|
||||
type CreateActionParams<PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined, ActionProps extends InputPropertyMap> = {
|
||||
/**
|
||||
* A dummy parameter used to infer {@code PieceAuth} type
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* this parameter is used to infer the type of the piece auth value in run and test methods
|
||||
*/
|
||||
auth?: PieceAuth
|
||||
displayName: string
|
||||
description: string
|
||||
props: ActionProps
|
||||
run: ActionRunner<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, ActionProps>
|
||||
test?: ActionRunner<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, ActionProps>
|
||||
requireAuth?: boolean
|
||||
errorHandlingOptions?: ErrorHandlingOptionsParam
|
||||
}
|
||||
|
||||
export class IAction<PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = any, ActionProps extends InputPropertyMap = InputPropertyMap> implements ActionBase {
|
||||
constructor(
|
||||
public readonly name: string,
|
||||
public readonly displayName: string,
|
||||
public readonly description: string,
|
||||
public readonly props: ActionProps,
|
||||
public readonly run: ActionRunner<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, ActionProps>,
|
||||
public readonly test: ActionRunner<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, ActionProps>,
|
||||
public readonly requireAuth: boolean,
|
||||
public readonly errorHandlingOptions: ErrorHandlingOptionsParam,
|
||||
) { }
|
||||
}
|
||||
|
||||
export type Action<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = any,
|
||||
ActionProps extends InputPropertyMap = any,
|
||||
> = IAction<PieceAuth, ActionProps>
|
||||
|
||||
export const createAction = <
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = PieceAuthProperty,
|
||||
ActionProps extends InputPropertyMap = any
|
||||
>(
|
||||
params: CreateActionParams<PieceAuth, ActionProps>,
|
||||
) => {
|
||||
return new IAction(
|
||||
params.name,
|
||||
params.displayName,
|
||||
params.description,
|
||||
params.props,
|
||||
params.run,
|
||||
params.test ?? params.run,
|
||||
params.requireAuth ?? true,
|
||||
params.errorHandlingOptions ?? {
|
||||
continueOnFailure: {
|
||||
defaultValue: false,
|
||||
},
|
||||
retryOnFailure: {
|
||||
defaultValue: false,
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
import {
|
||||
AgentTool,
|
||||
AppConnectionType,
|
||||
AppConnectionValue,
|
||||
ExecutionType,
|
||||
FlowRunId,
|
||||
PopulatedFlow,
|
||||
ProjectId,
|
||||
RespondResponse,
|
||||
ResumePayload,
|
||||
SeekPage,
|
||||
TriggerPayload,
|
||||
TriggerStrategy,
|
||||
} from '@activepieces/shared';
|
||||
|
||||
import {
|
||||
BasicAuthProperty,
|
||||
CustomAuthProperty,
|
||||
InputPropertyMap,
|
||||
OAuth2Property,
|
||||
SecretTextProperty,
|
||||
StaticPropsValue,
|
||||
} from '../property';
|
||||
import { PieceAuthProperty } from '../property/authentication';
|
||||
import { DelayPauseMetadata, PauseMetadata, WebhookPauseMetadata } from '@activepieces/shared';
|
||||
|
||||
export type BaseContext<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined,
|
||||
Props extends InputPropertyMap
|
||||
> = {
|
||||
flows: FlowsContext;
|
||||
step: StepContext;
|
||||
auth: AppConnectionValueForAuthProperty<PieceAuth>;
|
||||
propsValue: StaticPropsValue<Props>;
|
||||
store: Store;
|
||||
project: {
|
||||
id: ProjectId;
|
||||
externalId: () => Promise<string | undefined>;
|
||||
};
|
||||
connections: ConnectionsManager;
|
||||
};
|
||||
|
||||
|
||||
type ExtractCustomAuthProps<T> = T extends CustomAuthProperty<infer Props> ? Props : never;
|
||||
|
||||
type ExtractOAuth2Props<T> = T extends OAuth2Property<infer Props> ? Props : never;
|
||||
|
||||
|
||||
export type AppConnectionValueForAuthProperty<T extends PieceAuthProperty | PieceAuthProperty[] | undefined> =
|
||||
T extends PieceAuthProperty[] ? AppConnectionValueForSingleAuthProperty<T[number]> :
|
||||
T extends PieceAuthProperty ? AppConnectionValueForSingleAuthProperty<T> :
|
||||
T extends undefined ? undefined : never;
|
||||
|
||||
type AppConnectionValueForSingleAuthProperty<T extends PieceAuthProperty | undefined> =
|
||||
T extends SecretTextProperty<boolean> ? AppConnectionValue<AppConnectionType.SECRET_TEXT> :
|
||||
T extends BasicAuthProperty ? AppConnectionValue<AppConnectionType.BASIC_AUTH> :
|
||||
T extends CustomAuthProperty<any> ? AppConnectionValue<AppConnectionType.CUSTOM_AUTH, StaticPropsValue<ExtractCustomAuthProps<T>>> :
|
||||
T extends OAuth2Property<any> ? AppConnectionValue<AppConnectionType.OAUTH2, StaticPropsValue<ExtractOAuth2Props<T>>> :
|
||||
T extends undefined ? undefined : never;
|
||||
type AppWebhookTriggerHookContext<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined,
|
||||
TriggerProps extends InputPropertyMap
|
||||
> = BaseContext<PieceAuth, TriggerProps> & {
|
||||
webhookUrl: string;
|
||||
payload: TriggerPayload;
|
||||
app: {
|
||||
createListeners({
|
||||
events,
|
||||
identifierValue,
|
||||
}: {
|
||||
events: string[];
|
||||
identifierValue: string;
|
||||
}): void;
|
||||
};
|
||||
};
|
||||
|
||||
type PollingTriggerHookContext<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined,
|
||||
TriggerProps extends InputPropertyMap
|
||||
> = BaseContext<PieceAuth, TriggerProps> & {
|
||||
setSchedule(schedule: { cronExpression: string; timezone?: string }): void;
|
||||
};
|
||||
|
||||
type WebhookTriggerHookContext<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined,
|
||||
TriggerProps extends InputPropertyMap,
|
||||
> = BaseContext<PieceAuth, TriggerProps> & {
|
||||
webhookUrl: string;
|
||||
payload: TriggerPayload;
|
||||
server: ServerContext;
|
||||
};
|
||||
export type TriggerHookContext<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined,
|
||||
TriggerProps extends InputPropertyMap,
|
||||
S extends TriggerStrategy,
|
||||
> = S extends TriggerStrategy.APP_WEBHOOK
|
||||
? AppWebhookTriggerHookContext<PieceAuth, TriggerProps>
|
||||
: S extends TriggerStrategy.POLLING
|
||||
? PollingTriggerHookContext<PieceAuth, TriggerProps>
|
||||
: S extends TriggerStrategy.WEBHOOK
|
||||
? WebhookTriggerHookContext<PieceAuth, TriggerProps> & {
|
||||
server: ServerContext;
|
||||
}
|
||||
: never;
|
||||
|
||||
export type TestOrRunHookContext<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined,
|
||||
TriggerProps extends InputPropertyMap,
|
||||
S extends TriggerStrategy
|
||||
> = TriggerHookContext<PieceAuth, TriggerProps, S> & {
|
||||
files: FilesService;
|
||||
};
|
||||
|
||||
export type StopHookParams = {
|
||||
response: RespondResponse;
|
||||
};
|
||||
|
||||
export type RespondHookParams = {
|
||||
response: RespondResponse;
|
||||
};
|
||||
|
||||
export type StopHook = (params?: StopHookParams) => void;
|
||||
|
||||
export type RespondHook = (params?: RespondHookParams) => void;
|
||||
|
||||
export type PauseHookParams = {
|
||||
pauseMetadata: PauseMetadata;
|
||||
};
|
||||
|
||||
export type PauseHook = (params: {
|
||||
pauseMetadata: Omit<DelayPauseMetadata, 'requestIdToReply'> | Omit<WebhookPauseMetadata, 'requestId' | 'requestIdToReply'>
|
||||
}) => void;
|
||||
|
||||
export type FlowsContext = {
|
||||
list(params?: ListFlowsContextParams): Promise<SeekPage<PopulatedFlow>>
|
||||
current: {
|
||||
id: string;
|
||||
version: {
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export type StepContext = {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export type ListFlowsContextParams = {
|
||||
externalIds?: string[]
|
||||
}
|
||||
|
||||
|
||||
export type PropertyContext = {
|
||||
server: ServerContext;
|
||||
project: {
|
||||
id: ProjectId;
|
||||
externalId: () => Promise<string | undefined>;
|
||||
};
|
||||
searchValue?: string;
|
||||
flows: FlowsContext;
|
||||
connections: ConnectionsManager;
|
||||
};
|
||||
|
||||
export type ServerContext = {
|
||||
apiUrl: string;
|
||||
publicUrl: string;
|
||||
token: string;
|
||||
};
|
||||
|
||||
export type RunContext = {
|
||||
id: FlowRunId;
|
||||
stop: StopHook;
|
||||
pause: PauseHook;
|
||||
respond: RespondHook;
|
||||
}
|
||||
|
||||
export type OnStartContext<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined,
|
||||
TriggerProps extends InputPropertyMap
|
||||
> = Omit<BaseContext<PieceAuth, TriggerProps>, 'flows'> & {
|
||||
run: Pick<RunContext, 'id'>;
|
||||
payload: unknown;
|
||||
}
|
||||
|
||||
|
||||
export type OutputContext = {
|
||||
update: (params: {
|
||||
data: {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
}) => Promise<void>;
|
||||
}
|
||||
|
||||
type BaseActionContext<
|
||||
ET extends ExecutionType,
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined,
|
||||
ActionProps extends InputPropertyMap
|
||||
> = BaseContext<PieceAuth, ActionProps> & {
|
||||
executionType: ET;
|
||||
tags: TagsManager;
|
||||
server: ServerContext;
|
||||
files: FilesService;
|
||||
output: OutputContext;
|
||||
agent: AgentContext;
|
||||
run: RunContext;
|
||||
generateResumeUrl: (params: {
|
||||
queryParams: Record<string, string>,
|
||||
sync?: boolean
|
||||
}) => string;
|
||||
};
|
||||
|
||||
type BeginExecutionActionContext<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = undefined,
|
||||
ActionProps extends InputPropertyMap = InputPropertyMap
|
||||
> = BaseActionContext<ExecutionType.BEGIN, PieceAuth, ActionProps>;
|
||||
|
||||
type ResumeExecutionActionContext<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = undefined,
|
||||
ActionProps extends InputPropertyMap = InputPropertyMap
|
||||
> = BaseActionContext<ExecutionType.RESUME, PieceAuth, ActionProps> & {
|
||||
resumePayload: ResumePayload;
|
||||
};
|
||||
|
||||
export type ActionContext<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = undefined,
|
||||
ActionProps extends InputPropertyMap = InputPropertyMap
|
||||
> =
|
||||
| BeginExecutionActionContext<PieceAuth, ActionProps>
|
||||
| ResumeExecutionActionContext<PieceAuth, ActionProps>;
|
||||
|
||||
|
||||
|
||||
|
||||
export type ConstructToolParams = {
|
||||
tools: AgentTool[]
|
||||
model: unknown,
|
||||
}
|
||||
|
||||
export interface AgentContext {
|
||||
tools: (params: ConstructToolParams) => Promise<Record<string, unknown>>;
|
||||
}
|
||||
|
||||
export interface FilesService {
|
||||
write({
|
||||
fileName,
|
||||
data,
|
||||
}: {
|
||||
fileName: string;
|
||||
data: Buffer;
|
||||
}): Promise<string>;
|
||||
}
|
||||
|
||||
export interface ConnectionsManager {
|
||||
get(
|
||||
key: string
|
||||
): Promise<AppConnectionValue | Record<string, unknown> | string | null>;
|
||||
}
|
||||
|
||||
export interface TagsManager {
|
||||
add(params: { name: string }): Promise<void>;
|
||||
}
|
||||
|
||||
export interface Store {
|
||||
put<T>(key: string, value: T, scope?: StoreScope): Promise<T>;
|
||||
get<T>(key: string, scope?: StoreScope): Promise<T | null>;
|
||||
delete(key: string, scope?: StoreScope): Promise<void>;
|
||||
}
|
||||
|
||||
export enum StoreScope {
|
||||
// Collection were deprecated in favor of project
|
||||
PROJECT = 'COLLECTION',
|
||||
FLOW = 'FLOW',
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { ActionContext } from ".";
|
||||
import { InputPropertyMap, PieceAuthProperty } from "../property";
|
||||
|
||||
export enum ContextVersion {
|
||||
V1 = '1'
|
||||
}
|
||||
//bump these two constants after creating a new context version
|
||||
export const LATEST_CONTEXT_VERSION = ContextVersion.V1;
|
||||
export const MINIMUM_SUPPORTED_RELEASE_AFTER_LATEST_CONTEXT_VERSION = '0.73.0';
|
||||
|
||||
export const backwardCompatabilityContextUtils = {
|
||||
makeActionContextBackwardCompatible({ context, contextVersion }: MakeActionContextBackwardCompatibleParams): ActionContext<PieceAuthProperty,InputPropertyMap> {
|
||||
switch (contextVersion) {
|
||||
case undefined:
|
||||
return migrateActionContextV1ToV0(context);
|
||||
case ContextVersion.V1:
|
||||
return context;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function migrateActionContextV1ToV0(context: ActionContext<PieceAuthProperty,InputPropertyMap>): ActionContext<PieceAuthProperty,InputPropertyMap> {
|
||||
return {
|
||||
...context,
|
||||
serverUrl: context.server.publicUrl,
|
||||
} as unknown as ActionContext<PieceAuthProperty,InputPropertyMap>
|
||||
}
|
||||
|
||||
type MakeActionContextBackwardCompatibleParams = {
|
||||
context: ActionContext<PieceAuthProperty,InputPropertyMap>;
|
||||
contextVersion: ContextVersion | undefined;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
import { I18nForPiece, PieceMetadataModel, PieceMetadataModelSummary } from "./piece-metadata"
|
||||
import { LocalesEnum, MAX_KEY_LENGTH_FOR_CORWDIN } from "@activepieces/shared"
|
||||
import path from 'path';
|
||||
import fs from 'fs/promises';
|
||||
|
||||
export const pieceTranslation = {
|
||||
translatePiece: <T extends PieceMetadataModelSummary | PieceMetadataModel>(piece: T, locale?: LocalesEnum): T => {
|
||||
if (!locale) {
|
||||
return piece
|
||||
}
|
||||
try {
|
||||
const target = piece.i18n?.[locale]
|
||||
if (!target) {
|
||||
return piece
|
||||
}
|
||||
const translatedPiece: T = JSON.parse(JSON.stringify(piece))
|
||||
pieceTranslation.pathsToValuesToTranslate.forEach(key => {
|
||||
translateProperty(translatedPiece, key, target)
|
||||
})
|
||||
return translatedPiece
|
||||
}
|
||||
catch (err) {
|
||||
console.error(`error translating piece ${piece.name}:`, err)
|
||||
return piece
|
||||
}
|
||||
},
|
||||
|
||||
/**Gets the piece metadata regardles of piece location (node_modules or dist), wasn't included inside piece.metadata() for backwards compatibility issues (if an old ap version installs a new piece it would fail)*/
|
||||
initializeI18n: async (pieceOutputPath: string): Promise<I18nForPiece | undefined> => {
|
||||
try {
|
||||
const locales = Object.values(LocalesEnum);
|
||||
const i18n: I18nForPiece = {};
|
||||
|
||||
for (const locale of locales) {
|
||||
const translations = await readLocaleFile(locale, pieceOutputPath);
|
||||
if (translations) {
|
||||
i18n[locale] = translations;
|
||||
}
|
||||
}
|
||||
|
||||
return Object.keys(i18n).length > 0 ? i18n : undefined;
|
||||
}
|
||||
catch (err) {
|
||||
console.log(`Error initializing i18n for ${pieceOutputPath}:`, err)
|
||||
return undefined
|
||||
}
|
||||
},
|
||||
|
||||
pathsToValuesToTranslate: [
|
||||
"description",
|
||||
"auth.username.displayName",
|
||||
"auth.username.description",
|
||||
"auth.password.displayName",
|
||||
"auth.password.description",
|
||||
"auth.props.*.displayName",
|
||||
"auth.props.*.description",
|
||||
"auth.props.*.options.options.*.label",
|
||||
"auth.description",
|
||||
"actions.*.displayName",
|
||||
"actions.*.description",
|
||||
"actions.*.props.*.displayName",
|
||||
"actions.*.props.*.description",
|
||||
"actions.*.props.*.options.options.*.label",
|
||||
"triggers.*.displayName",
|
||||
"triggers.*.description",
|
||||
"triggers.*.props.*.displayName",
|
||||
"triggers.*.props.*.description",
|
||||
"triggers.*.props.*.options.options.*.label"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
/**This function translates a property inside a piece, i.e description, displayName, etc...
|
||||
*
|
||||
* @param pieceModelOrProperty - The piece model or property to translate
|
||||
* @param path - The path to the property to translate, i.e auth.username.displayName
|
||||
* @param i18n - The i18n object
|
||||
*/
|
||||
function translateProperty(pieceModelOrProperty: Record<string, unknown>, path: string, i18n: Record<string, string>) {
|
||||
const parsedKeys = path.split('.');
|
||||
if (parsedKeys[0] === '*') {
|
||||
return Object.values(pieceModelOrProperty).forEach(item => translateProperty(item as Record<string, unknown>, parsedKeys.slice(1).join('.'), i18n))
|
||||
}
|
||||
const nextObject = pieceModelOrProperty[parsedKeys[0]] as Record<string, unknown>;
|
||||
if (!nextObject) {
|
||||
return;
|
||||
}
|
||||
if (parsedKeys.length > 1) {
|
||||
return translateProperty(nextObject, parsedKeys.slice(1).join('.'), i18n);
|
||||
}
|
||||
const propertyValue = pieceModelOrProperty[parsedKeys[0]] as string
|
||||
const valueInI18n = i18n[propertyValue.slice(0, MAX_KEY_LENGTH_FOR_CORWDIN)]
|
||||
if (valueInI18n) {
|
||||
pieceModelOrProperty[parsedKeys[0]] = valueInI18n
|
||||
}
|
||||
}
|
||||
|
||||
async function fileExists(filePath: string) {
|
||||
try {
|
||||
await fs.access(filePath);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const readLocaleFile = async (locale: LocalesEnum, pieceOutputPath: string) => {
|
||||
const filePath = path.join(pieceOutputPath, 'src', 'i18n', `${locale}.json`);
|
||||
if (!(await fileExists(filePath))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const fileContent = await fs.readFile(filePath, 'utf8');
|
||||
const translations = JSON.parse(fileContent);
|
||||
if (typeof translations === 'object' && translations !== null) {
|
||||
return translations;
|
||||
}
|
||||
throw new Error(`Invalid i18n file format for ${locale} in piece ${pieceOutputPath}`);
|
||||
} catch (error) {
|
||||
console.error(`Error reading i18n file for ${locale} in piece ${pieceOutputPath}:`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export * from './action/action';
|
||||
export * from './property';
|
||||
export * from './trigger/trigger';
|
||||
export * from './context';
|
||||
export * from './piece';
|
||||
export * from './piece-metadata';
|
||||
export * from './i18n'
|
||||
export * from './context/versioning'
|
||||
@@ -0,0 +1,144 @@
|
||||
import { PiecePropertyMap } from "./property";
|
||||
import { WebhookRenewConfiguration } from "./trigger/trigger";
|
||||
import { ErrorHandlingOptionsParam } from "./action/action";
|
||||
import { PieceAuthProperty } from "./property/authentication";
|
||||
import { Static, Type } from "@sinclair/typebox";
|
||||
import { LocalesEnum, PackageType, PieceCategory, PieceType, ProjectId, TriggerStrategy, TriggerTestStrategy, WebhookHandshakeConfiguration } from "@activepieces/shared";
|
||||
import { ContextVersion } from "./context/versioning";
|
||||
|
||||
const I18nForPiece = Type.Optional(Type.Partial(Type.Record(Type.Enum(LocalesEnum), Type.Record(Type.String(), Type.String()))));
|
||||
export type I18nForPiece = Static<typeof I18nForPiece>
|
||||
export const PieceBase = Type.Object({
|
||||
id: Type.Optional(Type.String()),
|
||||
name: Type.String(),
|
||||
displayName: Type.String(),
|
||||
logoUrl: Type.String(),
|
||||
description: Type.String(),
|
||||
projectId: Type.Optional(Type.String()),
|
||||
authors: Type.Array(Type.String()),
|
||||
platformId: Type.Optional(Type.String()),
|
||||
directoryPath: Type.Optional(Type.String()),
|
||||
auth: Type.Optional(Type.Union([PieceAuthProperty, Type.Array(PieceAuthProperty)])),
|
||||
version: Type.String(),
|
||||
categories: Type.Optional(Type.Array(Type.Enum(PieceCategory))),
|
||||
minimumSupportedRelease: Type.Optional(Type.String()),
|
||||
maximumSupportedRelease: Type.Optional(Type.String()),
|
||||
i18n:I18nForPiece,
|
||||
})
|
||||
|
||||
export type PieceBase = {
|
||||
id?: string;
|
||||
name: string;
|
||||
displayName: string;
|
||||
logoUrl: string;
|
||||
description: string;
|
||||
projectId?: ProjectId;
|
||||
platformId?: string;
|
||||
authors: string[],
|
||||
directoryPath?: string;
|
||||
auth?: PieceAuthProperty | PieceAuthProperty[];
|
||||
version: string;
|
||||
categories?: PieceCategory[];
|
||||
minimumSupportedRelease?: string;
|
||||
maximumSupportedRelease?: string;
|
||||
i18n?: Partial<Record<LocalesEnum, Record<string, string>>>
|
||||
// this method didn't exist in older version
|
||||
getContextInfo: (() => { version: ContextVersion }) | undefined;
|
||||
}
|
||||
|
||||
|
||||
export const ActionBase = Type.Object({
|
||||
name: Type.String(),
|
||||
displayName: Type.String(),
|
||||
description: Type.String(),
|
||||
props: PiecePropertyMap,
|
||||
requireAuth: Type.Boolean(),
|
||||
errorHandlingOptions: Type.Optional(ErrorHandlingOptionsParam),
|
||||
})
|
||||
|
||||
export type ActionBase = {
|
||||
name: string,
|
||||
displayName: string,
|
||||
description: string,
|
||||
props: PiecePropertyMap,
|
||||
requireAuth: boolean;
|
||||
errorHandlingOptions?: ErrorHandlingOptionsParam;
|
||||
}
|
||||
|
||||
export const TriggerBase = Type.Composite([
|
||||
Type.Omit(ActionBase, ["requireAuth"]),
|
||||
Type.Object({
|
||||
type: Type.Enum(TriggerStrategy),
|
||||
sampleData: Type.Unknown(),
|
||||
handshakeConfiguration: Type.Optional(WebhookHandshakeConfiguration),
|
||||
renewConfiguration: Type.Optional(WebhookRenewConfiguration),
|
||||
testStrategy: Type.Enum(TriggerTestStrategy),
|
||||
})
|
||||
])
|
||||
export type TriggerBase = ActionBase & {
|
||||
type: TriggerStrategy;
|
||||
sampleData: unknown,
|
||||
handshakeConfiguration?: WebhookHandshakeConfiguration;
|
||||
renewConfiguration?: WebhookRenewConfiguration;
|
||||
testStrategy: TriggerTestStrategy;
|
||||
};
|
||||
|
||||
export const PieceMetadata = Type.Composite([
|
||||
PieceBase,
|
||||
Type.Object({
|
||||
actions: Type.Record(Type.String(), ActionBase),
|
||||
triggers: Type.Record(Type.String(), TriggerBase),
|
||||
})
|
||||
])
|
||||
|
||||
export type PieceMetadata = Omit<PieceBase, 'getContextInfo'> & {
|
||||
actions: Record<string, ActionBase>;
|
||||
triggers: Record<string, TriggerBase>;
|
||||
// this property didn't exist in older version
|
||||
contextInfo: { version: ContextVersion } | undefined;
|
||||
};
|
||||
|
||||
export const PieceMetadataSummary = Type.Composite([
|
||||
Type.Omit(PieceMetadata, ["actions", "triggers"]),
|
||||
Type.Object({
|
||||
actions: Type.Number(),
|
||||
triggers: Type.Number(),
|
||||
suggestedActions: Type.Optional(Type.Array(TriggerBase)),
|
||||
suggestedTriggers: Type.Optional(Type.Array(ActionBase)),
|
||||
})
|
||||
])
|
||||
export type PieceMetadataSummary = Omit<PieceMetadata, "actions" | "triggers"> & {
|
||||
actions: number;
|
||||
triggers: number;
|
||||
suggestedActions?: ActionBase[];
|
||||
suggestedTriggers?: TriggerBase[];
|
||||
}
|
||||
|
||||
|
||||
const PiecePackageMetadata = Type.Object({
|
||||
projectUsage: Type.Number(),
|
||||
tags: Type.Optional(Type.Array(Type.String())),
|
||||
pieceType: Type.Enum(PieceType),
|
||||
packageType: Type.Enum(PackageType),
|
||||
platformId: Type.Optional(Type.String()),
|
||||
archiveId: Type.Optional(Type.String()),
|
||||
})
|
||||
type PiecePackageMetadata = Static<typeof PiecePackageMetadata>
|
||||
|
||||
export const PieceMetadataModel = Type.Composite([
|
||||
PieceMetadata,
|
||||
PiecePackageMetadata
|
||||
])
|
||||
export type PieceMetadataModel = PieceMetadata & PiecePackageMetadata
|
||||
|
||||
export const PieceMetadataModelSummary = Type.Composite([
|
||||
PieceMetadataSummary,
|
||||
PiecePackageMetadata
|
||||
])
|
||||
export type PieceMetadataModelSummary = PieceMetadataSummary & PiecePackageMetadata;
|
||||
|
||||
export const PiecePackageInformation = Type.Object({
|
||||
name: Type.String(),
|
||||
version: Type.String(),
|
||||
})
|
||||
export type PiecePackageInformation = Static<typeof PiecePackageInformation>
|
||||
@@ -0,0 +1,132 @@
|
||||
import { Trigger } from './trigger/trigger';
|
||||
import { Action } from './action/action';
|
||||
import {
|
||||
EventPayload,
|
||||
ParseEventResponse,
|
||||
PieceCategory,
|
||||
} from '@activepieces/shared';
|
||||
import { PieceBase, PieceMetadata} from './piece-metadata';
|
||||
import { PieceAuthProperty } from './property/authentication';
|
||||
import { ServerContext } from './context';
|
||||
import { ContextVersion, LATEST_CONTEXT_VERSION, MINIMUM_SUPPORTED_RELEASE_AFTER_LATEST_CONTEXT_VERSION } from './context/versioning';
|
||||
import * as semver from 'semver';
|
||||
|
||||
|
||||
|
||||
export class Piece<PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = PieceAuthProperty>
|
||||
implements Omit<PieceBase, 'version' | 'name'>
|
||||
{
|
||||
private readonly _actions: Record<string, Action> = {};
|
||||
private readonly _triggers: Record<string, Trigger> = {};
|
||||
// this method didn't exist in older version
|
||||
public getContextInfo: (() => { version: ContextVersion } )| undefined = () => ({ version: LATEST_CONTEXT_VERSION });
|
||||
constructor(
|
||||
public readonly displayName: string,
|
||||
public readonly logoUrl: string,
|
||||
public readonly authors: string[],
|
||||
public readonly events: PieceEventProcessors | undefined,
|
||||
actions: Action[],
|
||||
triggers: Trigger[],
|
||||
public readonly categories: PieceCategory[],
|
||||
public readonly auth?: PieceAuth,
|
||||
public readonly minimumSupportedRelease: string = MINIMUM_SUPPORTED_RELEASE_AFTER_LATEST_CONTEXT_VERSION,
|
||||
public readonly maximumSupportedRelease?: string,
|
||||
public readonly description = '',
|
||||
) {
|
||||
if(!semver.valid(minimumSupportedRelease) || semver.lt(minimumSupportedRelease, MINIMUM_SUPPORTED_RELEASE_AFTER_LATEST_CONTEXT_VERSION)) {
|
||||
this.minimumSupportedRelease = MINIMUM_SUPPORTED_RELEASE_AFTER_LATEST_CONTEXT_VERSION;
|
||||
}
|
||||
actions.forEach((action) => (this._actions[action.name] = action));
|
||||
triggers.forEach((trigger) => (this._triggers[trigger.name] = trigger));
|
||||
}
|
||||
|
||||
|
||||
metadata(): BackwardCompatiblePieceMetadata {
|
||||
return {
|
||||
displayName: this.displayName,
|
||||
logoUrl: this.logoUrl,
|
||||
actions: this._actions,
|
||||
triggers: this._triggers,
|
||||
categories: this.categories,
|
||||
description: this.description,
|
||||
authors: this.authors,
|
||||
auth: this.auth,
|
||||
minimumSupportedRelease: this.minimumSupportedRelease,
|
||||
maximumSupportedRelease: this.maximumSupportedRelease,
|
||||
contextInfo: this.getContextInfo?.()
|
||||
};
|
||||
}
|
||||
|
||||
getAction(actionName: string): Action | undefined {
|
||||
return this._actions[actionName];
|
||||
}
|
||||
|
||||
getTrigger(triggerName: string): Trigger | undefined {
|
||||
return this._triggers[triggerName];
|
||||
}
|
||||
|
||||
actions() {
|
||||
return this._actions;
|
||||
}
|
||||
|
||||
triggers() {
|
||||
return this._triggers;
|
||||
}
|
||||
}
|
||||
|
||||
export const createPiece = <PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined>(
|
||||
params: CreatePieceParams<PieceAuth>
|
||||
) => {
|
||||
if(params.auth && Array.isArray(params.auth)) {
|
||||
const isUnique = params.auth.every((auth, index, self) =>
|
||||
index === self.findIndex((t) => t.type === auth.type)
|
||||
);
|
||||
if(!isUnique) {
|
||||
throw new Error('Auth properties must be unique by type');
|
||||
}
|
||||
}
|
||||
return new Piece<PieceAuth>(
|
||||
params.displayName,
|
||||
params.logoUrl,
|
||||
params.authors ?? [],
|
||||
params.events,
|
||||
params.actions,
|
||||
params.triggers,
|
||||
params.categories ?? [],
|
||||
params.auth,
|
||||
params.minimumSupportedRelease,
|
||||
params.maximumSupportedRelease,
|
||||
params.description,
|
||||
);
|
||||
};
|
||||
|
||||
type CreatePieceParams<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = undefined
|
||||
> = {
|
||||
displayName: string;
|
||||
logoUrl: string;
|
||||
authors: string[];
|
||||
description?: string;
|
||||
auth: PieceAuth | undefined;
|
||||
events?: PieceEventProcessors;
|
||||
minimumSupportedRelease?: string;
|
||||
maximumSupportedRelease?: string;
|
||||
actions: Action[];
|
||||
triggers: Trigger[];
|
||||
categories?: PieceCategory[];
|
||||
};
|
||||
|
||||
type PieceEventProcessors = {
|
||||
parseAndReply: (ctx: { payload: EventPayload, server: Omit<ServerContext, 'token' | 'apiUrl'> }) => ParseEventResponse;
|
||||
verify: (ctx: {
|
||||
webhookSecret: string | Record<string, string>;
|
||||
payload: EventPayload;
|
||||
appWebhookUrl: string;
|
||||
}) => boolean;
|
||||
};
|
||||
|
||||
type BackwardCompatiblePieceMetadata = Omit<PieceMetadata, 'name' | 'version' | 'authors' | 'i18n' | 'getContextInfo'> & {
|
||||
authors?: PieceMetadata['authors']
|
||||
i18n?: PieceMetadata['i18n']
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { TPropertyValue } from '../input/common';
|
||||
import { PropertyType } from '../input/property-type';
|
||||
import { BasePieceAuthSchema } from './common';
|
||||
|
||||
export const BasicAuthPropertyValue = Type.Object({
|
||||
username: Type.String(),
|
||||
password: Type.String(),
|
||||
})
|
||||
|
||||
export type BasicAuthPropertyValue = Static<typeof BasicAuthPropertyValue>
|
||||
|
||||
export const BasicAuthProperty = Type.Composite([
|
||||
BasePieceAuthSchema,
|
||||
Type.Object({
|
||||
username: Type.Object({
|
||||
displayName: Type.String(),
|
||||
description: Type.Optional(Type.String())
|
||||
}),
|
||||
password: Type.Object({
|
||||
displayName: Type.String(),
|
||||
description: Type.Optional(Type.String())
|
||||
})
|
||||
}),
|
||||
TPropertyValue(BasicAuthPropertyValue, PropertyType.BASIC_AUTH)
|
||||
])
|
||||
|
||||
export type BasicAuthProperty =
|
||||
BasePieceAuthSchema<BasicAuthPropertyValue> & {
|
||||
username: {
|
||||
displayName: string;
|
||||
description?: string;
|
||||
};
|
||||
password: {
|
||||
displayName: string;
|
||||
description?: string;
|
||||
};
|
||||
} &
|
||||
TPropertyValue<
|
||||
BasicAuthPropertyValue,
|
||||
PropertyType.BASIC_AUTH,
|
||||
true
|
||||
>;
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { ServerContext } from '../../context';
|
||||
|
||||
export const BasePieceAuthSchema = Type.Object({
|
||||
displayName: Type.String(),
|
||||
description: Type.Optional(Type.String())
|
||||
});
|
||||
|
||||
export type BasePieceAuthSchema<AuthValueSchema> = {
|
||||
displayName: string;
|
||||
description?: string;
|
||||
validate?: (params: { auth: AuthValueSchema; server: Omit<ServerContext, 'token'> }) => Promise<
|
||||
| { valid: true }
|
||||
| {
|
||||
valid: false;
|
||||
error: string;
|
||||
}
|
||||
>;
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { TPropertyValue } from '../input/common';
|
||||
import { PropertyType } from '../input/property-type';
|
||||
import { LongTextProperty, ShortTextProperty } from '../input/text-property';
|
||||
import { NumberProperty } from '../input/number-property';
|
||||
import { CheckboxProperty } from '../input/checkbox-property';
|
||||
import { StaticDropdownProperty, StaticMultiSelectDropdownProperty } from '../input/dropdown/static-dropdown';
|
||||
import { StaticPropsValue } from '..';
|
||||
import { SecretTextProperty } from './secret-text-property';
|
||||
import { BasePieceAuthSchema } from './common';
|
||||
import { MarkDownProperty } from '../input/markdown-property';
|
||||
|
||||
const CustomAuthProps = Type.Record(Type.String(), Type.Union([
|
||||
ShortTextProperty,
|
||||
LongTextProperty,
|
||||
NumberProperty,
|
||||
CheckboxProperty,
|
||||
StaticDropdownProperty,
|
||||
]));
|
||||
|
||||
export type CustomAuthProps = Record<
|
||||
string,
|
||||
| ShortTextProperty<boolean>
|
||||
| LongTextProperty<boolean>
|
||||
| SecretTextProperty<boolean>
|
||||
| NumberProperty<boolean>
|
||||
| StaticDropdownProperty<unknown, boolean>
|
||||
| CheckboxProperty<boolean>
|
||||
| MarkDownProperty
|
||||
| StaticMultiSelectDropdownProperty<unknown, boolean>
|
||||
>;
|
||||
|
||||
export const CustomAuthProperty = Type.Composite([
|
||||
BasePieceAuthSchema,
|
||||
Type.Object({
|
||||
props: CustomAuthProps,
|
||||
}),
|
||||
TPropertyValue(Type.Unknown(), PropertyType.CUSTOM_AUTH)
|
||||
])
|
||||
|
||||
export type CustomAuthProperty<
|
||||
T extends CustomAuthProps
|
||||
> = BasePieceAuthSchema<StaticPropsValue<T>> & {
|
||||
props: T;
|
||||
} &
|
||||
TPropertyValue<
|
||||
StaticPropsValue<T>,
|
||||
PropertyType.CUSTOM_AUTH,
|
||||
true
|
||||
>;
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { BasicAuthProperty } from "./basic-auth-prop";
|
||||
import { CustomAuthProperty, CustomAuthProps } from "./custom-auth-prop";
|
||||
import { SecretTextProperty } from "./secret-text-property";
|
||||
import { PropertyType } from "../input/property-type";
|
||||
import { OAuth2Property, OAuth2Props } from "./oauth2-prop";
|
||||
import { AppConnectionType, isNil } from "@activepieces/shared";
|
||||
|
||||
export const PieceAuthProperty = Type.Union([
|
||||
BasicAuthProperty,
|
||||
CustomAuthProperty,
|
||||
OAuth2Property,
|
||||
SecretTextProperty,
|
||||
])
|
||||
|
||||
export type PieceAuthProperty = BasicAuthProperty | CustomAuthProperty<any> | OAuth2Property<any> | SecretTextProperty<boolean>;
|
||||
|
||||
type AuthProperties<T> = Omit<Properties<T>, 'displayName'> & {
|
||||
displayName?: string;
|
||||
};
|
||||
|
||||
type Properties<T> = Omit<
|
||||
T,
|
||||
'valueSchema' | 'type' | 'defaultValidators' | 'defaultProcessors'
|
||||
>;
|
||||
|
||||
export const DEFAULT_CONNECTION_DISPLAY_NAME = 'Connection';
|
||||
export const PieceAuth = {
|
||||
SecretText<R extends boolean>(
|
||||
request: Properties<SecretTextProperty<R>>
|
||||
): R extends true ? SecretTextProperty<true> : SecretTextProperty<false> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.SECRET_TEXT,
|
||||
} as unknown as R extends true ? SecretTextProperty<true> : SecretTextProperty<false>;
|
||||
},
|
||||
OAuth2<T extends OAuth2Props>(
|
||||
request: AuthProperties<OAuth2Property<T>>
|
||||
): OAuth2Property<T> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.OAUTH2,
|
||||
displayName: request.displayName || DEFAULT_CONNECTION_DISPLAY_NAME,
|
||||
} as unknown as OAuth2Property<T>
|
||||
},
|
||||
BasicAuth(
|
||||
request: AuthProperties<BasicAuthProperty>
|
||||
): BasicAuthProperty {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.BASIC_AUTH,
|
||||
displayName: request.displayName || DEFAULT_CONNECTION_DISPLAY_NAME,
|
||||
required: true,
|
||||
} as unknown as BasicAuthProperty;
|
||||
},
|
||||
CustomAuth<T extends CustomAuthProps>(
|
||||
request: AuthProperties<CustomAuthProperty<T>>
|
||||
): CustomAuthProperty<T> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.CUSTOM_AUTH,
|
||||
displayName: request.displayName || DEFAULT_CONNECTION_DISPLAY_NAME,
|
||||
} as unknown as CustomAuthProperty<T>
|
||||
},
|
||||
None() {
|
||||
return undefined;
|
||||
},
|
||||
};
|
||||
|
||||
export type ExtractPieceAuthPropertyTypeForMethods<T extends PieceAuthProperty | PieceAuthProperty[] | undefined> = T extends PieceAuthProperty[] ? T[number] : T extends undefined ? undefined : T;
|
||||
|
||||
export function getAuthPropertyForValue({ authValueType, pieceAuth }: GetAuthPropertyForValue) {
|
||||
if (!Array.isArray(pieceAuth) || isNil(pieceAuth)) {
|
||||
return pieceAuth;
|
||||
}
|
||||
return pieceAuth.find(auth => authConnectionTypeToPropertyType[authValueType] === auth.type);
|
||||
}
|
||||
|
||||
type GetAuthPropertyForValue = {
|
||||
authValueType: AppConnectionType
|
||||
pieceAuth: PieceAuthProperty | PieceAuthProperty[] | undefined
|
||||
}
|
||||
|
||||
const authConnectionTypeToPropertyType: Record<AppConnectionType, PropertyType | undefined> = {
|
||||
[AppConnectionType.OAUTH2]: PropertyType.OAUTH2,
|
||||
[AppConnectionType.CLOUD_OAUTH2]: PropertyType.OAUTH2,
|
||||
[AppConnectionType.PLATFORM_OAUTH2]: PropertyType.OAUTH2,
|
||||
[AppConnectionType.BASIC_AUTH]: PropertyType.BASIC_AUTH,
|
||||
[AppConnectionType.CUSTOM_AUTH]: PropertyType.CUSTOM_AUTH,
|
||||
[AppConnectionType.SECRET_TEXT]: PropertyType.SECRET_TEXT,
|
||||
[AppConnectionType.NO_AUTH]: undefined,
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import { BOTH_CLIENT_CREDENTIALS_AND_AUTHORIZATION_CODE, OAuth2GrantType } from '@activepieces/shared';
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { ShortTextProperty } from '../input/text-property';
|
||||
import { SecretTextProperty } from './secret-text-property';
|
||||
import { BasePieceAuthSchema } from './common';
|
||||
import { TPropertyValue } from '../input/common';
|
||||
import { PropertyType } from '../input/property-type';
|
||||
import { StaticDropdownProperty } from '../input/dropdown/static-dropdown';
|
||||
import { StaticPropsValue } from '..';
|
||||
|
||||
export enum OAuth2AuthorizationMethod {
|
||||
HEADER = 'HEADER',
|
||||
BODY = 'BODY',
|
||||
}
|
||||
|
||||
const OAuthProp = Type.Union([
|
||||
ShortTextProperty,
|
||||
SecretTextProperty,
|
||||
StaticDropdownProperty,
|
||||
])
|
||||
|
||||
type OAuthProp =
|
||||
| ShortTextProperty<boolean>
|
||||
| SecretTextProperty<boolean>
|
||||
| StaticDropdownProperty<any, boolean>;
|
||||
|
||||
|
||||
export const OAuth2Props = Type.Record(Type.String(), OAuthProp);
|
||||
|
||||
export type OAuth2Props = {
|
||||
[key: string]: OAuthProp;
|
||||
}
|
||||
|
||||
type OAuthPropsValue<T extends OAuth2Props> = StaticPropsValue<T>;
|
||||
|
||||
|
||||
const OAuth2ExtraProps = Type.Object({
|
||||
props: Type.Optional(Type.Record(Type.String(), OAuthProp)),
|
||||
authUrl: Type.String(),
|
||||
tokenUrl: Type.String(),
|
||||
scope: Type.Array(Type.String()),
|
||||
prompt: Type.Optional(Type.Union([Type.Literal('none'), Type.Literal('consent'), Type.Literal('login'), Type.Literal('omit')])),
|
||||
pkce: Type.Optional(Type.Boolean()),
|
||||
pkceMethod: Type.Optional(Type.Union([Type.Literal('plain'), Type.Literal('S256')])),
|
||||
authorizationMethod: Type.Optional(Type.Enum(OAuth2AuthorizationMethod)),
|
||||
grantType: Type.Optional(Type.Union([Type.Enum(OAuth2GrantType), Type.Literal(BOTH_CLIENT_CREDENTIALS_AND_AUTHORIZATION_CODE)])),
|
||||
extra: Type.Optional(Type.Record(Type.String(), Type.String())),
|
||||
})
|
||||
|
||||
type OAuth2ExtraProps = {
|
||||
props?: OAuth2Props
|
||||
authUrl: string
|
||||
tokenUrl: string
|
||||
scope: string[]
|
||||
prompt?: 'none' | 'consent' | 'login' | 'omit'
|
||||
pkce?: boolean
|
||||
pkceMethod?: 'plain' | 'S256'
|
||||
authorizationMethod?: OAuth2AuthorizationMethod
|
||||
grantType?: OAuth2GrantType | typeof BOTH_CLIENT_CREDENTIALS_AND_AUTHORIZATION_CODE
|
||||
extra?: Record<string, string>,
|
||||
}
|
||||
|
||||
export const OAuth2PropertyValue = Type.Object({
|
||||
access_token: Type.String(),
|
||||
props: Type.Optional(OAuth2Props),
|
||||
data: Type.Record(Type.String(), Type.Any())
|
||||
})
|
||||
|
||||
export type OAuth2PropertyValue<T extends OAuth2Props = any> = {
|
||||
access_token: string;
|
||||
props?: OAuthPropsValue<T>;
|
||||
data: Record<string, any>;
|
||||
};
|
||||
|
||||
export const OAuth2Property = Type.Composite([
|
||||
BasePieceAuthSchema,
|
||||
OAuth2ExtraProps,
|
||||
TPropertyValue(OAuth2PropertyValue, PropertyType.OAUTH2)
|
||||
])
|
||||
|
||||
export type OAuth2Property<
|
||||
T extends OAuth2Props
|
||||
> = BasePieceAuthSchema<OAuth2PropertyValue<T>> &
|
||||
OAuth2ExtraProps &
|
||||
TPropertyValue<
|
||||
OAuth2PropertyValue<T>,
|
||||
PropertyType.OAUTH2,
|
||||
true
|
||||
>;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { BasePieceAuthSchema } from "./common";
|
||||
import { TPropertyValue } from "../input/common";
|
||||
import { PropertyType } from "../input/property-type";
|
||||
|
||||
export const SecretTextProperty = Type.Composite([
|
||||
BasePieceAuthSchema,
|
||||
TPropertyValue(Type.Object({
|
||||
auth: Type.String()
|
||||
}), PropertyType.SECRET_TEXT)
|
||||
])
|
||||
|
||||
|
||||
export type SecretTextProperty<R extends boolean> =
|
||||
BasePieceAuthSchema<string> &
|
||||
TPropertyValue<
|
||||
string,
|
||||
PropertyType.SECRET_TEXT,
|
||||
R
|
||||
>;
|
||||
@@ -0,0 +1,72 @@
|
||||
import { InputProperty } from './input';
|
||||
import { PieceAuthProperty } from './authentication';
|
||||
import { TSchema, Type } from '@sinclair/typebox';
|
||||
import { PropertyType } from './input/property-type';
|
||||
import { DropdownState } from './input/dropdown/common';
|
||||
import { AUTHENTICATION_PROPERTY_NAME, isEmpty, isNil } from '@activepieces/shared';
|
||||
|
||||
// EXPORTED
|
||||
export { ApFile } from './input/file-property';
|
||||
export { DropdownProperty, MultiSelectDropdownProperty } from './input/dropdown/dropdown-prop';
|
||||
export { DynamicProperties, DynamicProp } from './input/dynamic-prop';
|
||||
export { PropertyType } from './input/property-type';
|
||||
export { Property } from './input';
|
||||
export { PieceAuth,getAuthPropertyForValue } from './authentication';
|
||||
export type { ExtractPieceAuthPropertyTypeForMethods } from './authentication';
|
||||
export { DynamicPropsValue } from './input/dynamic-prop';
|
||||
export { DropdownOption,DropdownState } from './input/dropdown/common';
|
||||
export { OAuth2PropertyValue } from './authentication/oauth2-prop';
|
||||
export { PieceAuthProperty, DEFAULT_CONNECTION_DISPLAY_NAME} from './authentication';
|
||||
export { ShortTextProperty } from './input/text-property';
|
||||
export { ArrayProperty, ArraySubProps } from './input/array-property';
|
||||
export { BasePropertySchema } from './input/common';
|
||||
export { CheckboxProperty } from './input/checkbox-property';
|
||||
export { DateTimeProperty } from './input/date-time-property';
|
||||
export { LongTextProperty } from './input/text-property';
|
||||
export { NumberProperty } from './input/number-property';
|
||||
export { ObjectProperty } from './input/object-property';
|
||||
export { OAuth2Props } from './authentication/oauth2-prop';
|
||||
export { OAuth2AuthorizationMethod } from './authentication/oauth2-prop';
|
||||
export { BasicAuthPropertyValue } from './authentication/basic-auth-prop';
|
||||
export { StaticMultiSelectDropdownProperty } from './input/dropdown/static-dropdown';
|
||||
export { StaticDropdownProperty } from './input/dropdown/static-dropdown';
|
||||
export * from './authentication/custom-auth-prop';
|
||||
export { OAuth2Property } from './authentication/oauth2-prop';
|
||||
export { FileProperty } from './input/file-property';
|
||||
export { BasicAuthProperty } from './authentication/basic-auth-prop';
|
||||
export { SecretTextProperty } from './authentication/secret-text-property'
|
||||
export { CustomAuthProperty } from './authentication/custom-auth-prop';
|
||||
|
||||
export { JsonProperty } from './input/json-property'
|
||||
export const PieceProperty = Type.Union([InputProperty, PieceAuthProperty])
|
||||
export type PieceProperty = InputProperty | PieceAuthProperty;
|
||||
export {CustomProperty} from './input/custom-property'
|
||||
export type {CustomPropertyCodeFunctionParams} from './input/custom-property'
|
||||
export const PiecePropertyMap = Type.Record(Type.String(), PieceProperty)
|
||||
export interface PiecePropertyMap {
|
||||
[name: string]: PieceProperty;
|
||||
}
|
||||
export type { InputProperty } from './input';
|
||||
export const InputPropertyMap = Type.Record(Type.String(), InputProperty)
|
||||
export interface InputPropertyMap {
|
||||
[name: string]: InputProperty;
|
||||
}
|
||||
export { piecePropertiesUtils } from './util';
|
||||
|
||||
export type PiecePropValueSchema<T extends PieceProperty> =
|
||||
T extends undefined
|
||||
? undefined
|
||||
: T extends { required: true }
|
||||
? T['valueSchema']
|
||||
: T['valueSchema'] | undefined;
|
||||
|
||||
export type StaticPropsValue<T extends PiecePropertyMap> = {
|
||||
[P in keyof T]: PiecePropValueSchema<T[P]>;
|
||||
};
|
||||
|
||||
|
||||
|
||||
export type ExecutePropsResult<T extends PropertyType.DROPDOWN | PropertyType.MULTI_SELECT_DROPDOWN | PropertyType.DYNAMIC> = {
|
||||
type: T
|
||||
options: T extends PropertyType.DROPDOWN ? DropdownState<unknown> : T extends PropertyType.MULTI_SELECT_DROPDOWN ? DropdownState<unknown> : InputPropertyMap
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { BasePropertySchema, TPropertyValue } from "./common";
|
||||
import { PropertyType } from "./property-type";
|
||||
import { LongTextProperty, ShortTextProperty } from "./text-property";
|
||||
import { StaticDropdownProperty, StaticMultiSelectDropdownProperty } from "./dropdown/static-dropdown";
|
||||
import { MultiSelectDropdownProperty } from "./dropdown/dropdown-prop";
|
||||
import { CheckboxProperty } from "./checkbox-property";
|
||||
import { NumberProperty } from "./number-property";
|
||||
import { FileProperty } from "./file-property";
|
||||
import { JsonProperty } from './json-property';
|
||||
import { ColorProperty } from "./color-property";
|
||||
import { DateTimeProperty } from './date-time-property';
|
||||
|
||||
export const ArraySubProps = Type.Record(Type.String(), Type.Union([
|
||||
ShortTextProperty,
|
||||
LongTextProperty,
|
||||
StaticDropdownProperty,
|
||||
MultiSelectDropdownProperty,
|
||||
StaticMultiSelectDropdownProperty,
|
||||
CheckboxProperty,
|
||||
NumberProperty,
|
||||
FileProperty,
|
||||
DateTimeProperty,
|
||||
]))
|
||||
|
||||
export const ArrayProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
Type.Object({
|
||||
properties: ArraySubProps
|
||||
}),
|
||||
TPropertyValue(Type.Array(Type.Unknown()), PropertyType.ARRAY)
|
||||
])
|
||||
|
||||
export type ArraySubProps<R extends boolean> = Record<
|
||||
string,
|
||||
| ShortTextProperty<R>
|
||||
| LongTextProperty<R>
|
||||
| StaticDropdownProperty<any, R>
|
||||
| MultiSelectDropdownProperty<any, R>
|
||||
| StaticMultiSelectDropdownProperty<any, R>
|
||||
| CheckboxProperty<R>
|
||||
| NumberProperty<R>
|
||||
| FileProperty<R>
|
||||
| JsonProperty<R>
|
||||
| ColorProperty<R>
|
||||
| DateTimeProperty<R>
|
||||
>;
|
||||
|
||||
export type ArrayProperty<R extends boolean> = BasePropertySchema &
|
||||
{
|
||||
properties?: ArraySubProps<R>;
|
||||
} & TPropertyValue<unknown[], PropertyType.ARRAY, R>;
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { BasePropertySchema, TPropertyValue } from "./common";
|
||||
import { PropertyType } from "./property-type";
|
||||
|
||||
export const CheckboxProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
TPropertyValue(Type.Boolean(), PropertyType.CHECKBOX)
|
||||
])
|
||||
|
||||
export type CheckboxProperty<R extends boolean> = BasePropertySchema &
|
||||
TPropertyValue<boolean, PropertyType.CHECKBOX, R>;
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { BasePropertySchema, TPropertyValue } from "./common";
|
||||
import { PropertyType } from "./property-type";
|
||||
|
||||
export const ColorProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
TPropertyValue(Type.String(), PropertyType.COLOR)
|
||||
])
|
||||
|
||||
|
||||
export type ColorProperty<R extends boolean> = BasePropertySchema &
|
||||
TPropertyValue<string, PropertyType.COLOR, R>;
|
||||
@@ -0,0 +1,57 @@
|
||||
import { Static, TObject, TSchema, Type } from "@sinclair/typebox";
|
||||
import { ApFile } from "./file-property";
|
||||
import { PropertyType } from "./property-type";
|
||||
|
||||
|
||||
|
||||
export const BasePropertySchema = Type.Object({
|
||||
displayName: Type.String(),
|
||||
description: Type.Optional(Type.String())
|
||||
})
|
||||
|
||||
export type BasePropertySchema = Static<typeof BasePropertySchema>
|
||||
|
||||
export const TPropertyValue = <T extends TSchema, U extends PropertyType>(T: T, propertyType: U): TObject => Type.Object({
|
||||
type: Type.Literal(propertyType),
|
||||
required: Type.Boolean(),
|
||||
defaultValue: Type.Optional(Type.Any()),
|
||||
})
|
||||
|
||||
export type TPropertyValue<
|
||||
T,
|
||||
U extends PropertyType,
|
||||
REQUIRED extends boolean
|
||||
> = {
|
||||
valueSchema: T;
|
||||
type: U;
|
||||
required: REQUIRED;
|
||||
// TODO this should be T or undefined
|
||||
defaultValue?: U extends PropertyType.ARRAY
|
||||
? unknown[]
|
||||
: U extends PropertyType.JSON
|
||||
? object
|
||||
: U extends PropertyType.CHECKBOX
|
||||
? boolean
|
||||
: U extends PropertyType.LONG_TEXT
|
||||
? string
|
||||
: U extends PropertyType.SHORT_TEXT
|
||||
? string
|
||||
: U extends PropertyType.NUMBER
|
||||
? number
|
||||
: U extends PropertyType.DROPDOWN
|
||||
? unknown
|
||||
: U extends PropertyType.MULTI_SELECT_DROPDOWN
|
||||
? unknown[]
|
||||
: U extends PropertyType.STATIC_MULTI_SELECT_DROPDOWN
|
||||
? unknown[]
|
||||
: U extends PropertyType.STATIC_DROPDOWN
|
||||
? unknown
|
||||
: U extends PropertyType.DATE_TIME
|
||||
? string
|
||||
: U extends PropertyType.FILE
|
||||
? ApFile
|
||||
: U extends PropertyType.COLOR
|
||||
? string
|
||||
: unknown;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { BasePropertySchema, TPropertyValue } from "./common";
|
||||
import { PropertyType } from "./property-type";
|
||||
|
||||
|
||||
// Code should be a valid javascript function that takes a single argument which is an object
|
||||
/*
|
||||
(ctx: {containerId:string, value: unknown, onChange: (value: unknown) => void, isEmbeded: boolean, projectId:string}) => void
|
||||
*/
|
||||
export const CustomProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
TPropertyValue(Type.Unknown(), PropertyType.CUSTOM),
|
||||
Type.Object({
|
||||
code: Type.String(),
|
||||
})
|
||||
])
|
||||
|
||||
export type CustomProperty<R extends boolean> = BasePropertySchema &
|
||||
TPropertyValue<unknown, PropertyType.CUSTOM, R> & {
|
||||
code:string;
|
||||
}
|
||||
|
||||
export type CustomPropertyCodeFunctionParams =
|
||||
{
|
||||
containerId:string,
|
||||
value: unknown,
|
||||
onChange: (value: unknown) => void,
|
||||
isEmbeded: boolean,
|
||||
projectId:string,
|
||||
property: Pick<CustomProperty<boolean>, 'displayName' | 'description' | 'required'>,
|
||||
disabled: boolean
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { BasePropertySchema, TPropertyValue } from "./common";
|
||||
import { PropertyType } from "./property-type";
|
||||
|
||||
export const DateTimeProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
TPropertyValue(Type.String(), PropertyType.DATE_TIME)
|
||||
])
|
||||
|
||||
export type DateTimeProperty<R extends boolean> = BasePropertySchema &
|
||||
TPropertyValue<string, PropertyType.DATE_TIME, R>;
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
|
||||
|
||||
export const DropdownOption = Type.Object({
|
||||
label: Type.String(),
|
||||
value: Type.Unknown(),
|
||||
})
|
||||
|
||||
export type DropdownOption<T> = {
|
||||
label: string;
|
||||
value: T;
|
||||
}
|
||||
|
||||
export const DropdownState = Type.Object({
|
||||
disabled: Type.Optional(Type.Boolean()),
|
||||
placeholder: Type.Optional(Type.String()),
|
||||
options: Type.Array(DropdownOption)
|
||||
})
|
||||
|
||||
export type DropdownState<T> = {
|
||||
disabled?: boolean;
|
||||
placeholder?: string;
|
||||
options: DropdownOption<T>[];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { BasePropertySchema, TPropertyValue } from "../common";
|
||||
import { DropdownState } from "./common";
|
||||
import { AppConnectionValueForAuthProperty, PropertyContext } from "../../../context";
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { PropertyType } from "../property-type";
|
||||
import { PieceAuthProperty } from "../../authentication";
|
||||
|
||||
type DynamicDropdownOptions<T, PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = undefined> = (
|
||||
propsValue: Record<string, unknown> & {
|
||||
auth?: PieceAuth extends undefined ? undefined : AppConnectionValueForAuthProperty<Exclude<PieceAuth, undefined>>;
|
||||
},
|
||||
ctx: PropertyContext,
|
||||
) => Promise<DropdownState<T>>;
|
||||
|
||||
export const DropdownProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
TPropertyValue(Type.Unknown(), PropertyType.DROPDOWN),
|
||||
Type.Object({
|
||||
refreshers: Type.Array(Type.String()),
|
||||
}),
|
||||
]);
|
||||
|
||||
export type DropdownProperty<T, R extends boolean, PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = undefined> = BasePropertySchema & {
|
||||
/**
|
||||
* A dummy property used to infer {@code PieceAuth} type
|
||||
*/
|
||||
auth: PieceAuth;
|
||||
refreshers: string[];
|
||||
refreshOnSearch?: boolean;
|
||||
options: DynamicDropdownOptions<T, PieceAuth>;
|
||||
} & TPropertyValue<T, PropertyType.DROPDOWN, R>;
|
||||
|
||||
|
||||
export const MultiSelectDropdownProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
TPropertyValue(Type.Array(Type.Unknown()), PropertyType.MULTI_SELECT_DROPDOWN),
|
||||
Type.Object({
|
||||
refreshers: Type.Array(Type.String()),
|
||||
}),
|
||||
]);
|
||||
|
||||
export type MultiSelectDropdownProperty<
|
||||
T,
|
||||
R extends boolean,
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = undefined
|
||||
> = BasePropertySchema & {
|
||||
/**
|
||||
* A dummy property used to infer {@code PieceAuth} type
|
||||
*/
|
||||
auth: PieceAuth;
|
||||
refreshers: string[];
|
||||
refreshOnSearch?: boolean;
|
||||
options: DynamicDropdownOptions<T, PieceAuth>;
|
||||
} & TPropertyValue<
|
||||
T[],
|
||||
PropertyType.MULTI_SELECT_DROPDOWN,
|
||||
R
|
||||
>;
|
||||
@@ -0,0 +1,39 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { BasePropertySchema, TPropertyValue } from "../common";
|
||||
import { DropdownState } from "./common";
|
||||
import { PropertyType } from "../property-type";
|
||||
|
||||
export const StaticDropdownProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
Type.Object({
|
||||
options: DropdownState
|
||||
}),
|
||||
TPropertyValue(Type.Unknown(), PropertyType.STATIC_DROPDOWN)
|
||||
])
|
||||
|
||||
export type StaticDropdownProperty<
|
||||
T,
|
||||
R extends boolean
|
||||
> = BasePropertySchema & {
|
||||
options: DropdownState<T>;
|
||||
} & TPropertyValue<T, PropertyType.STATIC_DROPDOWN, R>;
|
||||
|
||||
|
||||
export const StaticMultiSelectDropdownProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
Type.Object({
|
||||
options: DropdownState
|
||||
}),
|
||||
TPropertyValue(Type.Array(Type.Unknown()), PropertyType.STATIC_MULTI_SELECT_DROPDOWN)
|
||||
])
|
||||
|
||||
export type StaticMultiSelectDropdownProperty<
|
||||
T,
|
||||
R extends boolean
|
||||
> = BasePropertySchema & {
|
||||
options: DropdownState<T>;
|
||||
} & TPropertyValue<
|
||||
T[],
|
||||
PropertyType.STATIC_MULTI_SELECT_DROPDOWN,
|
||||
R
|
||||
>;
|
||||
@@ -0,0 +1,56 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { StaticDropdownProperty, StaticMultiSelectDropdownProperty } from "./dropdown/static-dropdown";
|
||||
import { ShortTextProperty } from "./text-property";
|
||||
import { BasePropertySchema, TPropertyValue } from "./common";
|
||||
import { AppConnectionValueForAuthProperty, PropertyContext } from "../../context";
|
||||
import { PropertyType } from "./property-type";
|
||||
import { JsonProperty } from "./json-property";
|
||||
import { ArrayProperty } from "./array-property";
|
||||
import { ExtractPieceAuthPropertyTypeForMethods, InputPropertyMap, PieceAuthProperty } from "..";
|
||||
|
||||
export const DynamicProp = Type.Union([
|
||||
ShortTextProperty,
|
||||
StaticDropdownProperty,
|
||||
JsonProperty,
|
||||
ArrayProperty,
|
||||
StaticMultiSelectDropdownProperty,
|
||||
])
|
||||
|
||||
export type DynamicProp =
|
||||
| ShortTextProperty<boolean>
|
||||
| StaticDropdownProperty<any, boolean>
|
||||
| JsonProperty<boolean>
|
||||
| ArrayProperty<boolean>
|
||||
| StaticMultiSelectDropdownProperty<any, boolean>;
|
||||
|
||||
export const DynamicPropsValue = Type.Record(Type.String(), DynamicProp);
|
||||
|
||||
export type DynamicPropsValue = Record<string, DynamicProp['valueSchema']>;
|
||||
|
||||
export const DynamicProperties = Type.Composite([
|
||||
Type.Object({
|
||||
refreshers: Type.Array(Type.String()),
|
||||
}),
|
||||
BasePropertySchema,
|
||||
TPropertyValue(Type.Unknown(), PropertyType.DYNAMIC),
|
||||
])
|
||||
|
||||
export type DynamicProperties<R extends boolean, PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = undefined> = BasePropertySchema &
|
||||
{
|
||||
//dummy property to define auth property value inside props value
|
||||
auth: PieceAuth
|
||||
props: DynamicPropertiesOptions<PieceAuth>
|
||||
refreshers: string[];
|
||||
} &
|
||||
TPropertyValue<
|
||||
DynamicPropsValue,
|
||||
PropertyType.DYNAMIC,
|
||||
R
|
||||
>;
|
||||
|
||||
type DynamicPropertiesOptions<PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = undefined> = (
|
||||
propsValue: Record<string, unknown> & {
|
||||
auth?: AppConnectionValueForAuthProperty<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>>;
|
||||
},
|
||||
ctx: PropertyContext,
|
||||
) => Promise<InputPropertyMap>;
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { BasePropertySchema, TPropertyValue } from "./common";
|
||||
import { PropertyType } from "./property-type";
|
||||
|
||||
export class ApFile {
|
||||
constructor(
|
||||
public filename: string,
|
||||
public data: Buffer,
|
||||
public extension?: string
|
||||
) { }
|
||||
|
||||
get base64(): string {
|
||||
return this.data.toString('base64');
|
||||
}
|
||||
}
|
||||
|
||||
export const FileProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
TPropertyValue(Type.Unknown(), PropertyType.FILE)
|
||||
])
|
||||
|
||||
export type FileProperty<R extends boolean> = BasePropertySchema &
|
||||
TPropertyValue<ApFile, PropertyType.FILE, R>;
|
||||
@@ -0,0 +1,271 @@
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { ArrayProperty } from './array-property';
|
||||
import { CheckboxProperty } from './checkbox-property';
|
||||
import { DateTimeProperty } from './date-time-property';
|
||||
import {
|
||||
DropdownProperty,
|
||||
MultiSelectDropdownProperty,
|
||||
} from './dropdown/dropdown-prop';
|
||||
import {
|
||||
StaticDropdownProperty,
|
||||
StaticMultiSelectDropdownProperty,
|
||||
} from './dropdown/static-dropdown';
|
||||
import { DynamicProperties } from './dynamic-prop';
|
||||
import { FileProperty } from './file-property';
|
||||
import { JsonProperty } from './json-property';
|
||||
import { MarkDownProperty } from './markdown-property';
|
||||
import { MarkdownVariant } from '@activepieces/shared';
|
||||
import { NumberProperty } from './number-property';
|
||||
import { ObjectProperty } from './object-property';
|
||||
import { PropertyType } from './property-type';
|
||||
import { LongTextProperty, ShortTextProperty } from './text-property';
|
||||
import { CustomProperty, CustomPropertyCodeFunctionParams } from './custom-property';
|
||||
import { ColorProperty } from './color-property';
|
||||
import { PieceAuthProperty } from '../authentication';
|
||||
|
||||
export const InputProperty = Type.Union([
|
||||
ShortTextProperty,
|
||||
LongTextProperty,
|
||||
MarkDownProperty,
|
||||
CheckboxProperty,
|
||||
StaticDropdownProperty,
|
||||
StaticMultiSelectDropdownProperty,
|
||||
DropdownProperty,
|
||||
MultiSelectDropdownProperty,
|
||||
DynamicProperties,
|
||||
NumberProperty,
|
||||
ArrayProperty,
|
||||
ObjectProperty,
|
||||
JsonProperty,
|
||||
DateTimeProperty,
|
||||
FileProperty,
|
||||
ColorProperty,
|
||||
]);
|
||||
|
||||
export type InputProperty =
|
||||
| ShortTextProperty<boolean>
|
||||
| LongTextProperty<boolean>
|
||||
| MarkDownProperty
|
||||
| CheckboxProperty<boolean>
|
||||
| DropdownProperty<any, boolean, PieceAuthProperty | undefined | PieceAuthProperty[]>
|
||||
| StaticDropdownProperty<any, boolean>
|
||||
| NumberProperty<boolean>
|
||||
| ArrayProperty<boolean>
|
||||
| ObjectProperty<boolean>
|
||||
| JsonProperty<boolean>
|
||||
| MultiSelectDropdownProperty<unknown, boolean, PieceAuthProperty | undefined | PieceAuthProperty[]>
|
||||
| StaticMultiSelectDropdownProperty<unknown, boolean>
|
||||
| DynamicProperties<boolean, PieceAuthProperty | PieceAuthProperty[] | undefined>
|
||||
| DateTimeProperty<boolean>
|
||||
| FileProperty<boolean>
|
||||
| CustomProperty<boolean>
|
||||
| ColorProperty<boolean>;
|
||||
|
||||
|
||||
type Properties<T> = Omit<
|
||||
T,
|
||||
'valueSchema' | 'type' | 'defaultValidators' | 'defaultProcessors'
|
||||
>;
|
||||
|
||||
export const Property = {
|
||||
ShortText<R extends boolean>(
|
||||
request: Properties<ShortTextProperty<R>>
|
||||
): R extends true ? ShortTextProperty<true> : ShortTextProperty<false> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.SHORT_TEXT,
|
||||
} as unknown as R extends true
|
||||
? ShortTextProperty<true>
|
||||
: ShortTextProperty<false>;
|
||||
},
|
||||
Checkbox<R extends boolean>(
|
||||
request: Properties<CheckboxProperty<R>>
|
||||
): R extends true ? CheckboxProperty<true> : CheckboxProperty<false> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.CHECKBOX,
|
||||
} as unknown as R extends true
|
||||
? CheckboxProperty<true>
|
||||
: CheckboxProperty<false>;
|
||||
},
|
||||
LongText<R extends boolean>(
|
||||
request: Properties<LongTextProperty<R>>
|
||||
): R extends true ? LongTextProperty<true> : LongTextProperty<false> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.LONG_TEXT,
|
||||
} as unknown as R extends true
|
||||
? LongTextProperty<true>
|
||||
: LongTextProperty<false>;
|
||||
},
|
||||
MarkDown(request: {
|
||||
value: string;
|
||||
variant?: MarkdownVariant;
|
||||
}): MarkDownProperty {
|
||||
return {
|
||||
displayName: 'Markdown',
|
||||
required: false,
|
||||
description: request.value,
|
||||
type: PropertyType.MARKDOWN,
|
||||
valueSchema: undefined as never,
|
||||
variant: request.variant ?? MarkdownVariant.INFO,
|
||||
};
|
||||
},
|
||||
Number<R extends boolean>(
|
||||
request: Properties<NumberProperty<R>>
|
||||
): R extends true ? NumberProperty<true> : NumberProperty<false> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.NUMBER,
|
||||
} as unknown as R extends true
|
||||
? NumberProperty<true>
|
||||
: NumberProperty<false>;
|
||||
},
|
||||
|
||||
Json<R extends boolean>(
|
||||
request: Properties<JsonProperty<R>>
|
||||
): R extends true ? JsonProperty<true> : JsonProperty<false> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.JSON,
|
||||
} as unknown as R extends true ? JsonProperty<true> : JsonProperty<false>;
|
||||
},
|
||||
Array<R extends boolean>(
|
||||
request: Properties<ArrayProperty<R>>
|
||||
): R extends true ? ArrayProperty<true> : ArrayProperty<false> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.ARRAY,
|
||||
} as unknown as R extends true ? ArrayProperty<true> : ArrayProperty<false>;
|
||||
},
|
||||
Object<R extends boolean>(
|
||||
request: Properties<ObjectProperty<R>>
|
||||
): R extends true ? ObjectProperty<true> : ObjectProperty<false> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.OBJECT,
|
||||
} as unknown as R extends true
|
||||
? ObjectProperty<true>
|
||||
: ObjectProperty<false>;
|
||||
},
|
||||
Dropdown<T, R extends boolean = boolean, PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = undefined>(
|
||||
request: Properties<DropdownProperty<T, R, PieceAuth>>
|
||||
): R extends true ? DropdownProperty<T, true, PieceAuth> : DropdownProperty<T, false, PieceAuth> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.DROPDOWN,
|
||||
} as unknown as R extends true
|
||||
? DropdownProperty<T, true, PieceAuth>
|
||||
: DropdownProperty<T, false, PieceAuth>;
|
||||
},
|
||||
StaticDropdown<T, R extends boolean = boolean>(
|
||||
request: Properties<StaticDropdownProperty<T, R>>
|
||||
): R extends true
|
||||
? StaticDropdownProperty<T, true>
|
||||
: StaticDropdownProperty<T, false> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.STATIC_DROPDOWN,
|
||||
} as unknown as R extends true
|
||||
? StaticDropdownProperty<T, true>
|
||||
: StaticDropdownProperty<T, false>;
|
||||
},
|
||||
MultiSelectDropdown<T, R extends boolean = boolean, PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = undefined>(
|
||||
request: Properties<MultiSelectDropdownProperty<T, R, PieceAuth>>
|
||||
): R extends true
|
||||
? MultiSelectDropdownProperty<T, true, PieceAuth>
|
||||
: MultiSelectDropdownProperty<T, false, PieceAuth> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.MULTI_SELECT_DROPDOWN,
|
||||
} as unknown as R extends true
|
||||
? MultiSelectDropdownProperty<T, true, PieceAuth>
|
||||
: MultiSelectDropdownProperty<T, false, PieceAuth>;
|
||||
},
|
||||
DynamicProperties<R extends boolean = boolean, PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = undefined>(
|
||||
request: Properties<DynamicProperties<R,PieceAuth>>
|
||||
): R extends true ? DynamicProperties<true, PieceAuth> : DynamicProperties<false, PieceAuth> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.DYNAMIC,
|
||||
} as unknown as R extends true
|
||||
? DynamicProperties<true, PieceAuth>
|
||||
: DynamicProperties<false, PieceAuth>;
|
||||
},
|
||||
StaticMultiSelectDropdown<T, R extends boolean = boolean>(
|
||||
request: Properties<StaticMultiSelectDropdownProperty<T, R>>
|
||||
): R extends true
|
||||
? StaticMultiSelectDropdownProperty<T, true>
|
||||
: StaticMultiSelectDropdownProperty<T, false> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.STATIC_MULTI_SELECT_DROPDOWN,
|
||||
} as unknown as R extends true
|
||||
? StaticMultiSelectDropdownProperty<T, true>
|
||||
: StaticMultiSelectDropdownProperty<T, false>;
|
||||
},
|
||||
DateTime<R extends boolean>(
|
||||
request: Properties<DateTimeProperty<R>>
|
||||
): R extends true ? DateTimeProperty<true> : DateTimeProperty<false> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.DATE_TIME,
|
||||
} as unknown as R extends true
|
||||
? DateTimeProperty<true>
|
||||
: DateTimeProperty<false>;
|
||||
},
|
||||
File<R extends boolean>(
|
||||
request: Properties<FileProperty<R>>
|
||||
): R extends true ? FileProperty<true> : FileProperty<false> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.FILE,
|
||||
} as unknown as R extends true ? FileProperty<true> : FileProperty<false>;
|
||||
},
|
||||
Custom<R extends boolean>(
|
||||
request: Omit<Properties<CustomProperty<R>>, 'code'> & {
|
||||
/**
|
||||
* This is designed to be self-contained and operates independently of any
|
||||
* external libraries or imported dependencies. All necessary logic and
|
||||
* functionality are implemented within this function itself.
|
||||
*
|
||||
* You can return a cleanup function that will be called when the component is unmounted in the frontend.
|
||||
* */
|
||||
code: ((ctx: CustomPropertyCodeFunctionParams) => (()=>void) | void)
|
||||
}
|
||||
): R extends true ? CustomProperty<true> : CustomProperty<false> {
|
||||
const code = request.code.toString();
|
||||
return {
|
||||
...request,
|
||||
code,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.CUSTOM,
|
||||
} as unknown as R extends true ? CustomProperty<true> : CustomProperty<false>;
|
||||
},
|
||||
Color<R extends boolean>(
|
||||
request: Properties<ColorProperty<R>>
|
||||
): R extends true ? ColorProperty<true> : ColorProperty<false> {
|
||||
return {
|
||||
...request,
|
||||
valueSchema: undefined,
|
||||
type: PropertyType.COLOR,
|
||||
} as unknown as R extends true
|
||||
? ColorProperty<true>
|
||||
: ColorProperty<false>;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { BasePropertySchema, TPropertyValue } from "./common";
|
||||
import { PropertyType } from "./property-type";
|
||||
|
||||
export const JsonProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
TPropertyValue(
|
||||
Type.Union([Type.Record(Type.String(), Type.Unknown())]),
|
||||
PropertyType.JSON,
|
||||
),
|
||||
]);
|
||||
export type JsonProperty<R extends boolean> = BasePropertySchema &
|
||||
TPropertyValue<
|
||||
Record<string, unknown>,
|
||||
PropertyType.JSON,
|
||||
R
|
||||
>;
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { BasePropertySchema, TPropertyValue } from './common';
|
||||
import { PropertyType } from './property-type';
|
||||
import { MarkdownVariant } from '@activepieces/shared';
|
||||
|
||||
export const MarkDownProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
TPropertyValue(Type.Void(), PropertyType.MARKDOWN),
|
||||
]);
|
||||
|
||||
export type MarkDownProperty = BasePropertySchema &
|
||||
TPropertyValue<
|
||||
undefined,
|
||||
PropertyType.MARKDOWN,
|
||||
false
|
||||
> & {
|
||||
variant?: MarkdownVariant;
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { BasePropertySchema, TPropertyValue } from "./common";
|
||||
import { PropertyType } from "./property-type";
|
||||
|
||||
export const NumberProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
TPropertyValue(Type.Number(), PropertyType.NUMBER)
|
||||
])
|
||||
|
||||
export type NumberProperty<R extends boolean> = BasePropertySchema &
|
||||
TPropertyValue<number, PropertyType.NUMBER, R>;
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { BasePropertySchema, TPropertyValue } from "./common";
|
||||
import { PropertyType } from "./property-type";
|
||||
|
||||
export const ObjectProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
TPropertyValue(
|
||||
Type.Record(Type.String(), Type.Unknown()),
|
||||
PropertyType.OBJECT,
|
||||
)
|
||||
])
|
||||
|
||||
export type ObjectProperty<R extends boolean> = BasePropertySchema &
|
||||
TPropertyValue<
|
||||
Record<string, unknown>,
|
||||
PropertyType.OBJECT,
|
||||
R
|
||||
>;
|
||||
@@ -0,0 +1,23 @@
|
||||
export enum PropertyType {
|
||||
SHORT_TEXT = 'SHORT_TEXT',
|
||||
LONG_TEXT = 'LONG_TEXT',
|
||||
MARKDOWN = 'MARKDOWN',
|
||||
DROPDOWN = 'DROPDOWN',
|
||||
STATIC_DROPDOWN = 'STATIC_DROPDOWN',
|
||||
NUMBER = 'NUMBER',
|
||||
CHECKBOX = 'CHECKBOX',
|
||||
OAUTH2 = 'OAUTH2',
|
||||
SECRET_TEXT = 'SECRET_TEXT',
|
||||
ARRAY = 'ARRAY',
|
||||
OBJECT = 'OBJECT',
|
||||
BASIC_AUTH = 'BASIC_AUTH',
|
||||
JSON = 'JSON',
|
||||
MULTI_SELECT_DROPDOWN = 'MULTI_SELECT_DROPDOWN',
|
||||
STATIC_MULTI_SELECT_DROPDOWN = 'STATIC_MULTI_SELECT_DROPDOWN',
|
||||
DYNAMIC = 'DYNAMIC',
|
||||
CUSTOM_AUTH = 'CUSTOM_AUTH',
|
||||
DATE_TIME = 'DATE_TIME',
|
||||
FILE = 'FILE',
|
||||
CUSTOM = 'CUSTOM',
|
||||
COLOR = 'COLOR',
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { BasePropertySchema, TPropertyValue } from "./common";
|
||||
import { PropertyType } from "./property-type";
|
||||
|
||||
|
||||
export const ShortTextProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
TPropertyValue(Type.String(), PropertyType.SHORT_TEXT)
|
||||
])
|
||||
|
||||
|
||||
export type ShortTextProperty<R extends boolean> = BasePropertySchema &
|
||||
TPropertyValue<string, PropertyType.SHORT_TEXT, R>;
|
||||
|
||||
|
||||
export const LongTextProperty = Type.Composite([
|
||||
BasePropertySchema,
|
||||
TPropertyValue(Type.String(), PropertyType.LONG_TEXT)
|
||||
])
|
||||
|
||||
export type LongTextProperty<R extends boolean> = BasePropertySchema &
|
||||
TPropertyValue<string, PropertyType.LONG_TEXT, R>;
|
||||
@@ -0,0 +1,131 @@
|
||||
import { PiecePropertyMap } from ".";
|
||||
import { PieceAuthProperty } from "./authentication";
|
||||
import { PropertyType } from "./input/property-type";
|
||||
import { Type, TSchema } from "@sinclair/typebox";
|
||||
import { AUTHENTICATION_PROPERTY_NAME, isEmpty, isNil } from "@activepieces/shared";
|
||||
|
||||
function buildSchema(props: PiecePropertyMap, auth: PieceAuthProperty | PieceAuthProperty[] | undefined, requireAuth: boolean | undefined = true) {
|
||||
const entries = Object.entries(props);
|
||||
const nullableType = [Type.Null(), Type.Undefined()];
|
||||
const nonNullableUnknownPropType = Type.Not(
|
||||
Type.Union(nullableType),
|
||||
Type.Unknown(),
|
||||
);
|
||||
const propsSchema: Record<string, TSchema> = {};
|
||||
for (const [name, property] of entries) {
|
||||
switch (property.type) {
|
||||
case PropertyType.MARKDOWN:
|
||||
propsSchema[name] = Type.Optional(
|
||||
Type.Union([Type.Null(), Type.Undefined(), Type.Never(), Type.Unknown()]),
|
||||
);
|
||||
break;
|
||||
case PropertyType.DATE_TIME:
|
||||
case PropertyType.SHORT_TEXT:
|
||||
case PropertyType.LONG_TEXT:
|
||||
case PropertyType.COLOR:
|
||||
case PropertyType.FILE:
|
||||
propsSchema[name] = Type.String({
|
||||
minLength: property.required ? 1 : undefined,
|
||||
});
|
||||
break;
|
||||
case PropertyType.CHECKBOX:
|
||||
propsSchema[name] = Type.Union([
|
||||
Type.Boolean({ defaultValue: false }),
|
||||
Type.String({}),
|
||||
]);
|
||||
break;
|
||||
case PropertyType.NUMBER:
|
||||
propsSchema[name] = Type.Union([
|
||||
Type.String({
|
||||
minLength: property.required ? 1 : undefined,
|
||||
}),
|
||||
Type.Number(),
|
||||
]);
|
||||
break;
|
||||
case PropertyType.STATIC_DROPDOWN:
|
||||
case PropertyType.DROPDOWN:
|
||||
propsSchema[name] = nonNullableUnknownPropType;
|
||||
break;
|
||||
case PropertyType.BASIC_AUTH:
|
||||
case PropertyType.CUSTOM_AUTH:
|
||||
case PropertyType.SECRET_TEXT:
|
||||
case PropertyType.OAUTH2:
|
||||
break;
|
||||
case PropertyType.ARRAY: {
|
||||
const arrayItemSchema = isNil(property.properties)
|
||||
? Type.String({
|
||||
minLength: property.required ? 1 : undefined,
|
||||
})
|
||||
: buildSchema(property.properties,undefined);
|
||||
propsSchema[name] = Type.Union([
|
||||
Type.Array(arrayItemSchema, {
|
||||
minItems: property.required ? 1 : undefined,
|
||||
}),
|
||||
//for inline items mode
|
||||
Type.Record(Type.String(), Type.Unknown()),
|
||||
//for normal dynamic input mode
|
||||
Type.String({
|
||||
minLength: property.required ? 1 : undefined,
|
||||
}),
|
||||
]);
|
||||
break;
|
||||
}
|
||||
case PropertyType.OBJECT:
|
||||
propsSchema[name] = Type.Union([
|
||||
Type.Record(Type.String(), Type.Any()),
|
||||
Type.String({
|
||||
minLength: property.required ? 1 : undefined,
|
||||
}),
|
||||
]);
|
||||
break;
|
||||
case PropertyType.JSON:
|
||||
propsSchema[name] = Type.Union([
|
||||
Type.Record(Type.String(), Type.Any()),
|
||||
Type.Array(Type.Any()),
|
||||
Type.String({
|
||||
minLength: property.required ? 1 : undefined,
|
||||
}),
|
||||
]);
|
||||
break;
|
||||
case PropertyType.MULTI_SELECT_DROPDOWN:
|
||||
case PropertyType.STATIC_MULTI_SELECT_DROPDOWN:
|
||||
propsSchema[name] = Type.Union([
|
||||
Type.Array(Type.Any(), {
|
||||
minItems: property.required ? 1 : undefined,
|
||||
}),
|
||||
Type.String({
|
||||
minLength: property.required ? 1 : undefined,
|
||||
}),
|
||||
]);
|
||||
break;
|
||||
case PropertyType.DYNAMIC:
|
||||
propsSchema[name] = Type.Record(Type.String(), Type.Any());
|
||||
break;
|
||||
case PropertyType.CUSTOM:
|
||||
propsSchema[name] = Type.Unknown();
|
||||
break;
|
||||
}
|
||||
|
||||
//optional array is checked against its children
|
||||
if (!property.required && property.type !== PropertyType.ARRAY) {
|
||||
propsSchema[name] = Type.Optional(
|
||||
Type.Union(
|
||||
isEmpty(propsSchema[name])
|
||||
? [Type.Any(), ...nullableType]
|
||||
: [propsSchema[name], ...nullableType],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
if(auth && requireAuth)
|
||||
{
|
||||
propsSchema[AUTHENTICATION_PROPERTY_NAME] = Type.String({
|
||||
minLength: 1
|
||||
})
|
||||
}
|
||||
return Type.Object(propsSchema);
|
||||
}
|
||||
|
||||
export const piecePropertiesUtils = {
|
||||
buildSchema
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { OnStartContext, TestOrRunHookContext, TriggerHookContext } from '../context';
|
||||
import { TriggerBase } from '../piece-metadata';
|
||||
import { InputPropertyMap } from '../property';
|
||||
import { ExtractPieceAuthPropertyTypeForMethods, PieceAuthProperty } from '../property/authentication';
|
||||
import { isNil, TriggerStrategy, TriggerTestStrategy, WebhookHandshakeConfiguration, WebhookHandshakeStrategy } from '@activepieces/shared';
|
||||
export { TriggerStrategy }
|
||||
|
||||
export const DEDUPE_KEY_PROPERTY = '_dedupe_key'
|
||||
|
||||
|
||||
|
||||
export enum WebhookRenewStrategy {
|
||||
CRON = 'CRON',
|
||||
NONE = 'NONE',
|
||||
}
|
||||
|
||||
type OnStartRunner<PieceAuth extends PieceAuthProperty | undefined, TriggerProps extends InputPropertyMap> = (ctx: OnStartContext<PieceAuth, TriggerProps>) => Promise<unknown | void>
|
||||
|
||||
|
||||
|
||||
export const WebhookRenewConfiguration = Type.Union([
|
||||
Type.Object({
|
||||
strategy: Type.Literal(WebhookRenewStrategy.CRON),
|
||||
cronExpression: Type.String(),
|
||||
}),
|
||||
Type.Object({
|
||||
strategy: Type.Literal(WebhookRenewStrategy.NONE),
|
||||
}),
|
||||
])
|
||||
export type WebhookRenewConfiguration = Static<typeof WebhookRenewConfiguration>
|
||||
|
||||
export interface WebhookResponse {
|
||||
status: number,
|
||||
body?: any,
|
||||
headers?: Record<string, string>
|
||||
}
|
||||
|
||||
type BaseTriggerParams<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined,
|
||||
TriggerProps extends InputPropertyMap,
|
||||
TS extends TriggerStrategy,
|
||||
> = {
|
||||
name: string
|
||||
displayName: string
|
||||
description: string
|
||||
requireAuth?: boolean
|
||||
auth?: PieceAuth
|
||||
props: TriggerProps
|
||||
type: TS
|
||||
onEnable: (context: TriggerHookContext<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, TriggerProps, TS>) => Promise<void>
|
||||
onDisable: (context: TriggerHookContext<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, TriggerProps, TS>) => Promise<void>
|
||||
run: (context: TestOrRunHookContext<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, TriggerProps, TS>) => Promise<unknown[]>
|
||||
test?: (context: TestOrRunHookContext<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, TriggerProps, TS>) => Promise<unknown[]>,
|
||||
onStart?: OnStartRunner<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, TriggerProps>,
|
||||
sampleData: unknown
|
||||
}
|
||||
|
||||
type WebhookTriggerParams<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined,
|
||||
TriggerProps extends InputPropertyMap,
|
||||
TS extends TriggerStrategy,
|
||||
> = BaseTriggerParams<PieceAuth, TriggerProps, TS> & {
|
||||
handshakeConfiguration?: WebhookHandshakeConfiguration
|
||||
onHandshake?: (context: TriggerHookContext<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, TriggerProps, TS>) => Promise<WebhookResponse>,
|
||||
renewConfiguration?: WebhookRenewConfiguration
|
||||
onRenew?(context: TriggerHookContext<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, TriggerProps, TS>): Promise<void>,
|
||||
}
|
||||
|
||||
type CreateTriggerParams<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined,
|
||||
TriggerProps extends InputPropertyMap,
|
||||
TS extends TriggerStrategy,
|
||||
> = TS extends TriggerStrategy.WEBHOOK
|
||||
? WebhookTriggerParams<PieceAuth, TriggerProps, TS>
|
||||
: BaseTriggerParams<PieceAuth, TriggerProps, TS>
|
||||
|
||||
export class ITrigger<
|
||||
TS extends TriggerStrategy,
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined,
|
||||
TriggerProps extends InputPropertyMap,
|
||||
> implements TriggerBase {
|
||||
constructor(
|
||||
public readonly name: string,
|
||||
public readonly displayName: string,
|
||||
public readonly description: string,
|
||||
public readonly requireAuth: boolean,
|
||||
public readonly props: TriggerProps,
|
||||
public readonly type: TS,
|
||||
public readonly handshakeConfiguration: WebhookHandshakeConfiguration,
|
||||
public readonly onHandshake: (ctx: TriggerHookContext<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, TriggerProps, TS>) => Promise<WebhookResponse>,
|
||||
public readonly renewConfiguration: WebhookRenewConfiguration,
|
||||
public readonly onRenew: (ctx: TriggerHookContext<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, TriggerProps, TS>) => Promise<void>,
|
||||
public readonly onEnable: (ctx: TriggerHookContext<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, TriggerProps, TS>) => Promise<void>,
|
||||
public readonly onDisable: (ctx: TriggerHookContext<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, TriggerProps, TS>) => Promise<void>,
|
||||
public readonly onStart: OnStartRunner<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, TriggerProps>,
|
||||
public readonly run: (ctx: TestOrRunHookContext<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, TriggerProps, TS>) => Promise<unknown[]>,
|
||||
public readonly test: (ctx: TestOrRunHookContext<ExtractPieceAuthPropertyTypeForMethods<PieceAuth>, TriggerProps, TS>) => Promise<unknown[]>,
|
||||
public readonly sampleData: unknown,
|
||||
public readonly testStrategy: TriggerTestStrategy,
|
||||
) { }
|
||||
}
|
||||
|
||||
export type Trigger<
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined = any,
|
||||
TriggerProps extends InputPropertyMap = any,
|
||||
S extends TriggerStrategy = any,
|
||||
> = ITrigger<S, PieceAuth, TriggerProps>
|
||||
|
||||
// TODO refactor and extract common logic
|
||||
export const createTrigger = <
|
||||
TS extends TriggerStrategy,
|
||||
PieceAuth extends PieceAuthProperty | PieceAuthProperty[] | undefined ,
|
||||
TriggerProps extends InputPropertyMap,
|
||||
>(params: CreateTriggerParams<PieceAuth, TriggerProps, TS>) => {
|
||||
switch (params.type) {
|
||||
case TriggerStrategy.WEBHOOK:
|
||||
return new ITrigger(
|
||||
params.name,
|
||||
params.displayName,
|
||||
params.description,
|
||||
params.requireAuth ?? true,
|
||||
params.props,
|
||||
params.type,
|
||||
params.handshakeConfiguration ?? { strategy: WebhookHandshakeStrategy.NONE },
|
||||
params.onHandshake ?? (async () => ({ status: 200 })),
|
||||
params.renewConfiguration ?? { strategy: WebhookRenewStrategy.NONE },
|
||||
params.onRenew ?? (async () => Promise.resolve()),
|
||||
params.onEnable,
|
||||
params.onDisable,
|
||||
params.onStart ?? (async () => Promise.resolve()),
|
||||
params.run,
|
||||
params.test ?? (() => Promise.resolve([params.sampleData])),
|
||||
params.sampleData,
|
||||
params.test ? TriggerTestStrategy.TEST_FUNCTION : TriggerTestStrategy.SIMULATION,
|
||||
)
|
||||
case TriggerStrategy.POLLING:
|
||||
return new ITrigger(
|
||||
params.name,
|
||||
params.displayName,
|
||||
params.description,
|
||||
params.requireAuth ?? true,
|
||||
params.props,
|
||||
params.type,
|
||||
{ strategy: WebhookHandshakeStrategy.NONE },
|
||||
async () => ({ status: 200 }),
|
||||
{ strategy: WebhookRenewStrategy.NONE },
|
||||
(async () => Promise.resolve()),
|
||||
params.onEnable,
|
||||
params.onDisable,
|
||||
params.onStart ?? (async () => Promise.resolve()),
|
||||
params.run,
|
||||
params.test ?? (() => Promise.resolve([params.sampleData])),
|
||||
params.sampleData,
|
||||
TriggerTestStrategy.TEST_FUNCTION,
|
||||
)
|
||||
case TriggerStrategy.APP_WEBHOOK:
|
||||
return new ITrigger(
|
||||
params.name,
|
||||
params.displayName,
|
||||
params.description,
|
||||
params.requireAuth ?? true,
|
||||
params.props,
|
||||
params.type,
|
||||
{ strategy: WebhookHandshakeStrategy.NONE },
|
||||
async () => ({ status: 200 }),
|
||||
{ strategy: WebhookRenewStrategy.NONE },
|
||||
(async () => Promise.resolve()),
|
||||
params.onEnable,
|
||||
params.onDisable,
|
||||
params.onStart ?? (async () => Promise.resolve()),
|
||||
params.run,
|
||||
params.test ?? (() => Promise.resolve([params.sampleData])),
|
||||
params.sampleData,
|
||||
(isNil(params.sampleData) && isNil(params.test)) ? TriggerTestStrategy.SIMULATION : TriggerTestStrategy.TEST_FUNCTION,
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user