chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,300 @@
|
||||
import { z, IntegrationDefinitionProps, ActionDefinition } from '@botpress/sdk'
|
||||
import { linearIdsSchema, userProfileSchema, issueSchema } from './schemas'
|
||||
|
||||
const _channels = ['issue'] as const
|
||||
|
||||
export type Target = {
|
||||
displayName: string
|
||||
tags: { [key: string]: string }
|
||||
channel: (typeof _channels)[number]
|
||||
}
|
||||
|
||||
const findTarget = {
|
||||
title: 'Find Target',
|
||||
description: 'Find a target on Linear',
|
||||
input: {
|
||||
schema: z.object({
|
||||
query: z.string().min(2).title('Search query').describe('Issue title, description, or number'),
|
||||
channel: z.enum(['issue']).title('Channel').describe('The channel to search in'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
targets: z
|
||||
.array(
|
||||
z.object({
|
||||
displayName: z.string().title('Display Name').describe('The name of the issue'),
|
||||
tags: z.record(z.string()).title('Tags').describe('The tags applied to the issue'),
|
||||
channel: z.enum(['issue']).title('Channel').describe('The channel of the search result'),
|
||||
})
|
||||
)
|
||||
.title('Results')
|
||||
.describe('The list of issues found'),
|
||||
}),
|
||||
},
|
||||
} as const satisfies ActionDefinition
|
||||
|
||||
const getIssue = {
|
||||
title: 'Get Issue',
|
||||
description: 'Get an issue by its ID',
|
||||
input: {
|
||||
schema: z.object({
|
||||
issueId: z.string().title('Issue ID').describe('The issue ID on Linear. Ex: {{event.payload.linearIds.issueId}}'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: issueSchema.title('Issue').describe('The issue found'),
|
||||
},
|
||||
} as const satisfies ActionDefinition
|
||||
|
||||
const listIssues = {
|
||||
title: 'List Issues',
|
||||
description: 'List issues from Linear',
|
||||
input: {
|
||||
schema: z.object({
|
||||
count: z.number().optional().default(10).title('Fetch Amount').describe('The number of issues to return'),
|
||||
startCursor: z.string().optional().title('Start Cursor').describe('The cursor to start from'),
|
||||
teamId: z.string().optional().title('Team ID').describe('The team ID to filter by'),
|
||||
startDate: z.string().optional().title('Start Date').describe('Ignore issues created before this date'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
issues: z
|
||||
.array(issueSchema.extend({ linearIds: linearIdsSchema }))
|
||||
.title('Issues')
|
||||
.describe('The list of matching issues'),
|
||||
nextCursor: z.string().optional().title('Next Cursor').describe('The cursor to fetch the next page'),
|
||||
}),
|
||||
},
|
||||
} as const satisfies ActionDefinition
|
||||
|
||||
const userSchema = z.object({
|
||||
id: z.string().title('ID').describe('The user ID on Linear'),
|
||||
email: z.string().title('Email').describe("The user's email address"),
|
||||
name: z.string().title('Name').describe("The user's nickname"),
|
||||
displayName: z.string().title('Display Name').describe("The user's display name"),
|
||||
avatarUrl: z.string().optional().title('Avatar URL').describe('The URL of the user avatar'),
|
||||
description: z
|
||||
.string()
|
||||
.optional()
|
||||
.title('Description')
|
||||
.describe("The user's description, such as their title or bio"),
|
||||
lastSeen: z.string().optional().title('Last Seen').describe('The last time the user was seen'),
|
||||
updatedAt: z.string().datetime().title('Updated At').describe('The last time the user was updated'),
|
||||
})
|
||||
|
||||
const listUsers = {
|
||||
title: 'List Users',
|
||||
description: 'List users from Linear',
|
||||
input: {
|
||||
schema: z.object({
|
||||
count: z.number().optional().default(10).title('Fetch Amount').describe('The number of users to return'),
|
||||
startCursor: z.string().optional().title('Start Cursor').describe('The cursor to start from'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
users: z.array(userSchema).title('Users').describe('The list of matching users'),
|
||||
nextCursor: z.string().optional().title('Next Cursor').describe('The cursor to fetch the next page'),
|
||||
}),
|
||||
},
|
||||
} as const satisfies ActionDefinition
|
||||
|
||||
const listTeams = {
|
||||
title: 'List Teams',
|
||||
description: 'List teams from Linear',
|
||||
input: {
|
||||
schema: z.object({}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
teams: z
|
||||
.array(
|
||||
z.object({
|
||||
id: z.string().title('ID').describe('The unique identifier of the entity'),
|
||||
key: z.string().title('Key').describe("The team's key"),
|
||||
name: z.string().title('Name').describe("The team's name"),
|
||||
description: z.string().optional().title('Description').describe("The team's description"),
|
||||
icon: z.string().optional().title('Icon').describe('The icon of the team'),
|
||||
})
|
||||
)
|
||||
.title('Teams')
|
||||
.describe('The list of teams'),
|
||||
}),
|
||||
},
|
||||
} as const satisfies ActionDefinition
|
||||
|
||||
const listStates = {
|
||||
title: 'List States',
|
||||
description: 'List states from Linear',
|
||||
input: {
|
||||
schema: z.object({
|
||||
count: z.number().optional().default(10).title('Fetch Amount').describe('The number of states to return'),
|
||||
startCursor: z.string().optional().title('Start Cursor').describe('The cursor to start from'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
states: z
|
||||
.array(
|
||||
z.object({
|
||||
id: z.string().title('ID').describe('The unique identifier of the entity'),
|
||||
name: z.string().title('Name').describe("The state's name"),
|
||||
})
|
||||
)
|
||||
.title('States')
|
||||
.describe('The list of states'),
|
||||
nextCursor: z.string().optional().title('Next Cursor').describe('The cursor to fetch the next page'),
|
||||
}),
|
||||
},
|
||||
} as const satisfies ActionDefinition
|
||||
|
||||
const markAsDuplicate = {
|
||||
title: 'Mark Issue as Duplicate',
|
||||
description: 'Mark an issue as a duplicate of another',
|
||||
input: {
|
||||
schema: z.object({
|
||||
issueId: z.string().title('Issue ID').describe('The issue ID on Linear. Ex: {{event.payload.linearIds.issueId}}'),
|
||||
relatedIssueId: z.string().title('Related Issue ID').describe('The ID of the existing issue on Linear'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({}),
|
||||
},
|
||||
} as const satisfies ActionDefinition
|
||||
|
||||
const getUser = {
|
||||
title: 'Get User Profile',
|
||||
description: 'Get a user profile from Linear',
|
||||
input: {
|
||||
schema: z.object({
|
||||
linearUserId: z
|
||||
.string()
|
||||
.optional()
|
||||
.title('User ID')
|
||||
.describe(
|
||||
"The user's ID on Linear. Ex: {{event.payload.linearIds.creatorId}}. If omitted, returns the current user."
|
||||
),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: userProfileSchema.title('User').describe('The user profile'),
|
||||
},
|
||||
} as const satisfies ActionDefinition
|
||||
|
||||
const updateIssue = {
|
||||
title: 'Update Issue',
|
||||
description: 'Update an issue on Linear',
|
||||
input: {
|
||||
schema: z.object({
|
||||
issueId: z.string().title('Issue ID').describe('The issue ID on Linear. Example: {{event.payload.id}}'),
|
||||
priority: z.number().optional().title('Priority').describe('0 = none, 1 = urgent, 2 = high, 3 = medium, 4 = low'),
|
||||
teamName: z
|
||||
.string()
|
||||
.optional()
|
||||
.title('Move to team...')
|
||||
.describe('Type a name to change the assigned team of the issue'),
|
||||
labels: z
|
||||
.array(z.string())
|
||||
.optional()
|
||||
.title('Set labels')
|
||||
.describe('One or multiple labels to assign to this issue'),
|
||||
project: z.string().optional().title('Associate to project...').describe('A project to associate to this issue'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
issue: issueSchema.optional().title('Issue').describe('The updated issue'),
|
||||
}),
|
||||
},
|
||||
} as const satisfies ActionDefinition
|
||||
|
||||
const createIssue = {
|
||||
title: 'Create Issue',
|
||||
description: 'Create an issue on Linear',
|
||||
input: {
|
||||
schema: z.object({
|
||||
title: z.string().min(1).title('Title').describe("The issue's title"),
|
||||
description: z.string().title('Description').describe('The content of the issue'),
|
||||
priority: z.number().optional().title('Priority').describe('0 = none, 1 = urgent, 2 = high, 3 = medium, 4 = low'),
|
||||
teamName: z.string().title('Team Name').describe('Name of the team to assign the issue to'),
|
||||
labels: z.array(z.string()).optional().title('Labels').describe('One or multiple labels to assign to this issue'),
|
||||
project: z.string().optional().title('Project').describe('A project to associate to this issue'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
issue: issueSchema.title('Issue').describe('The created issue'),
|
||||
}),
|
||||
},
|
||||
} as const satisfies ActionDefinition
|
||||
|
||||
const deleteIssue = {
|
||||
title: 'Delete Issue',
|
||||
description: 'Delete an issue on Linear',
|
||||
input: {
|
||||
schema: z.object({
|
||||
id: z.string().title('Issue ID').describe('The issue ID on Linear. Ex: {{event.payload.linearIds.issueId}}'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({}),
|
||||
},
|
||||
} as const satisfies ActionDefinition
|
||||
|
||||
const sendRawGraphqlQuery = {
|
||||
title: 'Send Raw GraphQL Query',
|
||||
description: 'Send a raw GraphQL query to the linear API',
|
||||
input: {
|
||||
schema: z.object({
|
||||
query: z.string().title('Query').describe('The GraphQL query'),
|
||||
parameters: z
|
||||
.array(
|
||||
z.object({
|
||||
name: z.string().title('Name').describe('The parameter name'),
|
||||
value: z.any().title('Value').describe('The parameter value'),
|
||||
})
|
||||
)
|
||||
.optional()
|
||||
.title('Parameters')
|
||||
.describe('The query parameters'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
result: z.unknown().title('Result').describe('The query result'),
|
||||
}),
|
||||
},
|
||||
} as const satisfies ActionDefinition
|
||||
|
||||
const resolveComment = {
|
||||
title: 'Resolve Comment',
|
||||
description: 'Resolve a comment by id',
|
||||
input: {
|
||||
schema: z.object({
|
||||
id: z.string().title('ID').describe('The comment ID'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
success: z.boolean().title('Success').describe('Whether the operation was successful'),
|
||||
}),
|
||||
},
|
||||
} as const satisfies ActionDefinition
|
||||
|
||||
export const actions = {
|
||||
findTarget,
|
||||
listIssues,
|
||||
listTeams,
|
||||
listUsers,
|
||||
listStates,
|
||||
markAsDuplicate,
|
||||
getIssue,
|
||||
getUser,
|
||||
updateIssue,
|
||||
createIssue,
|
||||
deleteIssue,
|
||||
sendRawGraphqlQuery,
|
||||
resolveComment,
|
||||
} as const satisfies IntegrationDefinitionProps['actions']
|
||||
@@ -0,0 +1,30 @@
|
||||
import { EventDefinition, IntegrationDefinitionProps } from '@botpress/sdk'
|
||||
import { issueEventSchema, targets } from './schemas'
|
||||
|
||||
const issueCreated = {
|
||||
title: 'Issue Created',
|
||||
description: 'Triggered when an issue is created',
|
||||
schema: issueEventSchema.extend({
|
||||
targets: targets.title('Created Issue').describe('The issue that was created'),
|
||||
}),
|
||||
} as const satisfies EventDefinition
|
||||
|
||||
const issueUpdated = {
|
||||
title: 'Issue Updated',
|
||||
description: 'Triggered when an issue is updated',
|
||||
schema: issueEventSchema.extend({
|
||||
targets: targets.title('Updated Issue').describe('The issue that was updated'),
|
||||
}),
|
||||
} as const satisfies EventDefinition
|
||||
|
||||
const issueDeleted = {
|
||||
title: 'Issue Deleted',
|
||||
description: 'Triggered when an issue is deleted',
|
||||
schema: issueEventSchema.omit({ userId: true, conversationId: true }),
|
||||
} as const satisfies EventDefinition
|
||||
|
||||
export const events = {
|
||||
issueCreated,
|
||||
issueUpdated,
|
||||
issueDeleted,
|
||||
} as const satisfies IntegrationDefinitionProps['events']
|
||||
@@ -0,0 +1,102 @@
|
||||
import { z, IntegrationDefinitionProps, messages, ConfigurationDefinition } from '@botpress/sdk'
|
||||
import { issueSchema } from './schemas'
|
||||
|
||||
export { actions } from './actions'
|
||||
export { events } from './events'
|
||||
export { states } from './states'
|
||||
export * as schemas from './schemas'
|
||||
|
||||
export const configuration = {
|
||||
identifier: {
|
||||
linkTemplateScript: 'linkTemplate.vrl',
|
||||
},
|
||||
schema: z.object({
|
||||
displayName: z.string().optional().title('Display Name').describe('The name displayed in message transmissions'),
|
||||
avatarUrl: z.string().optional().title('Avatar URL').describe('The web address for the profile picture'),
|
||||
}),
|
||||
} as const satisfies ConfigurationDefinition
|
||||
|
||||
export const configurations = {
|
||||
apiKey: {
|
||||
title: 'API Key',
|
||||
description: 'Configure Linear with an API Key.',
|
||||
schema: z.object({
|
||||
apiKey: z.string().title('API Key').describe('The API key for Linear'),
|
||||
webhookSigningSecret: z
|
||||
.string()
|
||||
.secret()
|
||||
.optional()
|
||||
.title('Webhook Signing Secret (deprecated)')
|
||||
.describe(
|
||||
'The secret key for verifying incoming Linear webhook events if the webhook has been registered manually. ' +
|
||||
"If you don't provide this value, a webhook will be created automatically."
|
||||
),
|
||||
}),
|
||||
},
|
||||
} as const satisfies IntegrationDefinitionProps['configurations']
|
||||
|
||||
export const channels = {
|
||||
issue: {
|
||||
title: 'Issue',
|
||||
description: 'A linear issue',
|
||||
messages: { ...messages.defaults, markdown: messages.markdown, bloc: messages.markdownBloc },
|
||||
message: {
|
||||
tags: {
|
||||
id: {
|
||||
title: 'Comment ID',
|
||||
description: 'The ID of the comment on Linear',
|
||||
},
|
||||
},
|
||||
},
|
||||
conversation: {
|
||||
tags: {
|
||||
id: {
|
||||
title: 'Issue ID',
|
||||
description: 'The ID of the issue on Linear',
|
||||
},
|
||||
title: {
|
||||
title: 'Issue Title',
|
||||
description: 'The title of the issue',
|
||||
},
|
||||
url: {
|
||||
title: 'Issue URL',
|
||||
description: 'The URL of the issue on Linear',
|
||||
},
|
||||
parentId: {
|
||||
title: 'Parent Issue ID',
|
||||
description: 'The ID of the parent issue on Linear',
|
||||
},
|
||||
parentTitle: {
|
||||
title: 'Parent Issue Title',
|
||||
description: 'The title of the parent issue',
|
||||
},
|
||||
parentUrl: {
|
||||
title: 'Parent Issue URL',
|
||||
description: 'The URL of the parent issue on Linear',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const satisfies IntegrationDefinitionProps['channels']
|
||||
|
||||
export const user = {
|
||||
tags: {
|
||||
id: {
|
||||
title: 'User ID',
|
||||
description: 'The ID of the user on Linear',
|
||||
},
|
||||
},
|
||||
} as const satisfies IntegrationDefinitionProps['user']
|
||||
|
||||
export const entities = {
|
||||
issue: {
|
||||
title: 'Issue',
|
||||
description: 'A linear issue',
|
||||
schema: issueSchema,
|
||||
},
|
||||
issueConversation: {
|
||||
title: 'Issue Conversation',
|
||||
description: 'A conversation representing a linear issue',
|
||||
schema: z.object({ id: z.string().title('Issue ID').describe('The issue ID on Linear') }),
|
||||
},
|
||||
} as const satisfies IntegrationDefinitionProps['entities']
|
||||
@@ -0,0 +1,138 @@
|
||||
import { z } from '@botpress/sdk'
|
||||
import { User } from '@linear/sdk'
|
||||
import { assert, Equals } from 'tsafe/assert'
|
||||
|
||||
export const targets = z.object({
|
||||
issue: z
|
||||
.record(z.string().title('Issue').describe('The issue'))
|
||||
.optional()
|
||||
.title('Target Issue')
|
||||
.describe('The target issue on Linear'),
|
||||
})
|
||||
|
||||
type TransformDatesToStrings<T> = {
|
||||
[K in keyof T]: T[K] extends Date | undefined ? string : T[K]
|
||||
}
|
||||
|
||||
type LinearUserProfile = Pick<
|
||||
TransformDatesToStrings<User>,
|
||||
| 'admin'
|
||||
| 'archivedAt'
|
||||
| 'avatarUrl'
|
||||
| 'createdAt'
|
||||
| 'description'
|
||||
| 'displayName'
|
||||
| 'guest'
|
||||
| 'email'
|
||||
| 'isMe'
|
||||
| 'url'
|
||||
| 'timezone'
|
||||
| 'name'
|
||||
> & { linearId: string }
|
||||
|
||||
export const userProfileSchema = z.object({
|
||||
linearId: z.string().title('User ID').describe('Linear User ID'),
|
||||
admin: z.boolean().title('Is Admin?').describe('Indicates if the user is an admin of the organization'),
|
||||
archivedAt: z.string().datetime().optional().title('Archival Date').describe('Date when the user was archived'),
|
||||
avatarUrl: z.string().url().optional().title('Avatar URL').describe('The URL for the profile picture'),
|
||||
createdAt: z.string().datetime().title('Creation Date').describe('Date when the user was created'),
|
||||
description: z
|
||||
.string()
|
||||
.optional()
|
||||
.title('Description')
|
||||
.describe('A short description of the user, either its title or bio'),
|
||||
displayName: z
|
||||
.string()
|
||||
.title('Display Name')
|
||||
.describe("The user's display (nick) name. Unique within each organization"),
|
||||
guest: z
|
||||
.boolean()
|
||||
.title('Is Guest?')
|
||||
.describe('Whether the user is a guest in the workspace and limited to accessing a subset of teams'),
|
||||
email: z.string().title('Email').describe("The user's email address"),
|
||||
isMe: z.boolean().title('Is Self?').describe('Whether the user is the currently authenticated user'),
|
||||
url: z.string().title('Profile URL').describe("User's profile URL"),
|
||||
timezone: z.string().optional().title('Timezone').describe('The local timezone of the user'),
|
||||
name: z.string().title('Full Name').describe("The user's full name"),
|
||||
})
|
||||
|
||||
export const linearIdsSchema = z
|
||||
.object({
|
||||
creatorId: z
|
||||
.string()
|
||||
.optional()
|
||||
.title("Creator's User ID")
|
||||
.describe('The internal Linear User ID of the user who created the issue'),
|
||||
labelIds: z
|
||||
.array(z.string())
|
||||
.optional()
|
||||
.title('Label IDs')
|
||||
.describe('The internal Linear Label IDs associated with the issue'),
|
||||
issueId: z.string().title('Issue ID').describe('The internal Linear Issue ID'),
|
||||
teamId: z.string().optional().title('Team ID').describe('The internal Linear Team ID'),
|
||||
projectId: z.string().optional().title('Project ID').describe('The internal Linear Project ID'),
|
||||
assigneeId: z.string().optional().title('Assignee User ID').describe('The internal Linear Assignee ID'),
|
||||
subscriberIds: z
|
||||
.array(z.string())
|
||||
.optional()
|
||||
.title('Subscriber IDs')
|
||||
.describe('The internal Linear Subscriber User IDs'),
|
||||
})
|
||||
.describe('The Linear IDs of the referenced entities')
|
||||
|
||||
const commonIssueProperties = {
|
||||
title: z.string().title('Title').describe('The issue title on Linear, such as "Fix the bug'),
|
||||
number: z.number().title('Number').describe('The issue number on Linear, such as "123" in XXX-123'),
|
||||
createdAt: z.string().datetime().title('Created At').describe('The ISO date the issue was created'),
|
||||
updatedAt: z.string().datetime().title('Updated At').describe('The ISO date the issue was last updated'),
|
||||
identifier: z.string().title('Identifier').describe("Issue's human readable identifier (e.g. XXX-123)"),
|
||||
url: z.string().title('Issue URL').describe('The URL of the issue on Linear'),
|
||||
priority: z
|
||||
.number()
|
||||
.title('Priority')
|
||||
.describe('Priority of the issue, such as "1" for "Urgent", 0 for "No Priority"'),
|
||||
description: z
|
||||
.string()
|
||||
.optional()
|
||||
.title('Description')
|
||||
.describe('A markdown description of the issue. Images and videos are inlined using markdown links.'),
|
||||
}
|
||||
|
||||
export const issueSchema = z.object({
|
||||
...commonIssueProperties,
|
||||
id: z.string().title('Issue ID').describe('The issue ID on Linear'),
|
||||
estimate: z.number().optional().title('Points Estimate').describe('The estimate of the issue in points'),
|
||||
})
|
||||
|
||||
export const issueEventSchema = z.object({
|
||||
...commonIssueProperties,
|
||||
teamName: z
|
||||
.string()
|
||||
.optional()
|
||||
.title('Team Name')
|
||||
.describe('The name of the Linear team the issue currently belongs to, such as "Customer Support"'),
|
||||
teamKey: z
|
||||
.string()
|
||||
.optional()
|
||||
.title('Team Key')
|
||||
.describe('The key of the Linear team the issue currently belongs to, such as "XXX" in XXX-123'),
|
||||
status: z.string().title('Status').describe('The issue State name (such as "In Progress"'),
|
||||
statusColor: z.string().title('Status Color').describe('The issue State color (#000000 format)'),
|
||||
statusType: z.string().title('Status Type').describe('The issue State type'),
|
||||
labels: z
|
||||
.array(z.string().title('Label Name').describe('The name of the label'))
|
||||
.optional()
|
||||
.title('Applied Labels')
|
||||
.describe('Label names'),
|
||||
linearIds: linearIdsSchema.title('Linear IDs').describe('The Linear IDs of the referenced entities'),
|
||||
userId: z
|
||||
.string()
|
||||
.optional()
|
||||
.title('Botpress User ID')
|
||||
.describe(
|
||||
'The Botpress User ID of the individual who initiated the issue. If not provided, it indicates the issue was generated by the bot.'
|
||||
),
|
||||
conversationId: z.string().title('Botpress Conversation ID').describe('Botpress Conversation ID of the issue'),
|
||||
})
|
||||
|
||||
assert<Equals<z.infer<typeof userProfileSchema>, LinearUserProfile>>()
|
||||
@@ -0,0 +1,53 @@
|
||||
import { z, IntegrationDefinitionProps } from '@botpress/sdk'
|
||||
import { userProfileSchema } from './schemas'
|
||||
|
||||
const oauthCredentialsSchema = z.object({
|
||||
accessToken: z.string().title('Access Token').describe('The access token for Linear'),
|
||||
refreshToken: z.string().title('Refresh Token').describe('The refresh token needed when the access token expires'),
|
||||
expiresAt: z.string().title('Expires At').describe('The time when the access token expires'),
|
||||
})
|
||||
|
||||
export const states = {
|
||||
credentials: {
|
||||
type: 'integration',
|
||||
schema: oauthCredentialsSchema,
|
||||
},
|
||||
adminCredentials: {
|
||||
type: 'integration',
|
||||
schema: oauthCredentialsSchema.describe(
|
||||
'User-actor OAuth credentials used only for admin operations (webhook register/unregister)'
|
||||
),
|
||||
},
|
||||
environment: {
|
||||
type: 'integration',
|
||||
schema: z.object({
|
||||
env: z
|
||||
.enum(['preview', 'production'])
|
||||
.title('Environment')
|
||||
.describe('The environment where the integration is installed'),
|
||||
source: z.string().optional().title('Source').describe('The source of the OAuth request, eg: "desk"'),
|
||||
wizardPhase: z
|
||||
.enum(['admin', 'app'])
|
||||
.optional()
|
||||
.title('Wizard Phase')
|
||||
.describe('Which leg of the two-phase OAuth wizard is currently expected on /oauth callback'),
|
||||
runtimeActor: z
|
||||
.enum(['user', 'app'])
|
||||
.optional()
|
||||
.title('Runtime Actor')
|
||||
.describe('Which Linear OAuth actor type was used for the runtime credentials'),
|
||||
}),
|
||||
},
|
||||
|
||||
// TODO: delete these 2 states when the backend stop considering state deletion as breaking change
|
||||
configuration: {
|
||||
type: 'integration',
|
||||
schema: z.object({
|
||||
botUserId: z.string().optional().title('Bot User ID').describe('The ID of the bot user'),
|
||||
}),
|
||||
},
|
||||
profile: {
|
||||
type: 'user',
|
||||
schema: userProfileSchema,
|
||||
},
|
||||
} satisfies IntegrationDefinitionProps['states']
|
||||
Reference in New Issue
Block a user