diff --git a/packages/twenty-front/src/generated-metadata/gql.ts b/packages/twenty-front/src/generated-metadata/gql.ts index 25ca29826..8d2ccc337 100644 --- a/packages/twenty-front/src/generated-metadata/gql.ts +++ b/packages/twenty-front/src/generated-metadata/gql.ts @@ -13,7 +13,7 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ * Therefore it is highly recommended to use the babel or swc plugin for production. */ const documents = { - "\n fragment RemoteServerFields on RemoteServer {\n id\n createdAt\n foreignDataWrapperId\n foreignDataWrapperOptions\n foreignDataWrapperType\n userMappingOptions {\n username\n }\n updatedAt\n schema\n }\n": types.RemoteServerFieldsFragmentDoc, + "\n fragment RemoteServerFields on RemoteServer {\n id\n createdAt\n foreignDataWrapperId\n foreignDataWrapperOptions\n foreignDataWrapperType\n userMappingOptions {\n user\n }\n updatedAt\n schema\n }\n": types.RemoteServerFieldsFragmentDoc, "\n fragment RemoteTableFields on RemoteTable {\n id\n name\n schema\n status\n }\n": types.RemoteTableFieldsFragmentDoc, "\n \n mutation createServer($input: CreateRemoteServerInput!) {\n createOneRemoteServer(input: $input) {\n ...RemoteServerFields\n }\n }\n": types.CreateServerDocument, "\n mutation deleteServer($input: RemoteServerIdInput!) {\n deleteOneRemoteServer(input: $input) {\n id\n }\n }\n": types.DeleteServerDocument, @@ -50,7 +50,7 @@ export function graphql(source: string): unknown; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n fragment RemoteServerFields on RemoteServer {\n id\n createdAt\n foreignDataWrapperId\n foreignDataWrapperOptions\n foreignDataWrapperType\n userMappingOptions {\n username\n }\n updatedAt\n schema\n }\n"): (typeof documents)["\n fragment RemoteServerFields on RemoteServer {\n id\n createdAt\n foreignDataWrapperId\n foreignDataWrapperOptions\n foreignDataWrapperType\n userMappingOptions {\n username\n }\n updatedAt\n schema\n }\n"]; +export function graphql(source: "\n fragment RemoteServerFields on RemoteServer {\n id\n createdAt\n foreignDataWrapperId\n foreignDataWrapperOptions\n foreignDataWrapperType\n userMappingOptions {\n user\n }\n updatedAt\n schema\n }\n"): (typeof documents)["\n fragment RemoteServerFields on RemoteServer {\n id\n createdAt\n foreignDataWrapperId\n foreignDataWrapperOptions\n foreignDataWrapperType\n userMappingOptions {\n user\n }\n updatedAt\n schema\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 8cc496114..591d37e4a 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -799,7 +799,7 @@ export type RemoteServer = { id: Scalars['ID']['output']; schema?: Maybe; updatedAt: Scalars['DateTime']['output']; - userMappingOptions?: Maybe; + userMappingOptions?: Maybe; }; export type RemoteServerIdInput = { @@ -815,7 +815,7 @@ export type RemoteTable = { __typename?: 'RemoteTable'; id?: Maybe; name: Scalars['String']['output']; - schema: Scalars['String']['output']; + schema?: Maybe; status: RemoteTableStatus; }; @@ -1057,17 +1057,17 @@ export type UserExists = { export type UserMappingOptions = { password?: InputMaybe; - username?: InputMaybe; + user?: InputMaybe; }; export type UserMappingOptionsUpdateInput = { password?: InputMaybe; - username?: InputMaybe; + user?: InputMaybe; }; -export type UserMappingOptionsUsername = { - __typename?: 'UserMappingOptionsUsername'; - username?: Maybe; +export type UserMappingOptionsUser = { + __typename?: 'UserMappingOptionsUser'; + user?: Maybe; }; export type UserWorkspace = { @@ -1253,16 +1253,16 @@ export type RelationEdge = { node: Relation; }; -export type RemoteServerFieldsFragment = { __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, userMappingOptions?: { __typename?: 'UserMappingOptionsUsername', username?: string | null } | null }; +export type RemoteServerFieldsFragment = { __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, userMappingOptions?: { __typename?: 'UserMappingOptionsUser', user?: string | null } | null }; -export type RemoteTableFieldsFragment = { __typename?: 'RemoteTable', id?: any | null, name: string, schema: string, status: RemoteTableStatus }; +export type RemoteTableFieldsFragment = { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus }; export type CreateServerMutationVariables = Exact<{ input: CreateRemoteServerInput; }>; -export type CreateServerMutation = { __typename?: 'Mutation', createOneRemoteServer: { __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, userMappingOptions?: { __typename?: 'UserMappingOptionsUsername', username?: string | null } | null } }; +export type CreateServerMutation = { __typename?: 'Mutation', createOneRemoteServer: { __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, userMappingOptions?: { __typename?: 'UserMappingOptionsUser', user?: string | null } | null } }; export type DeleteServerMutationVariables = Exact<{ input: RemoteServerIdInput; @@ -1276,42 +1276,42 @@ export type SyncRemoteTableMutationVariables = Exact<{ }>; -export type SyncRemoteTableMutation = { __typename?: 'Mutation', syncRemoteTable: { __typename?: 'RemoteTable', id?: any | null, name: string, schema: string, status: RemoteTableStatus } }; +export type SyncRemoteTableMutation = { __typename?: 'Mutation', syncRemoteTable: { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus } }; export type UnsyncRemoteTableMutationVariables = Exact<{ input: RemoteTableInput; }>; -export type UnsyncRemoteTableMutation = { __typename?: 'Mutation', unsyncRemoteTable: { __typename?: 'RemoteTable', id?: any | null, name: string, schema: string, status: RemoteTableStatus } }; +export type UnsyncRemoteTableMutation = { __typename?: 'Mutation', unsyncRemoteTable: { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus } }; export type UpdateServerMutationVariables = Exact<{ input: UpdateRemoteServerInput; }>; -export type UpdateServerMutation = { __typename?: 'Mutation', updateOneRemoteServer: { __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, userMappingOptions?: { __typename?: 'UserMappingOptionsUsername', username?: string | null } | null } }; +export type UpdateServerMutation = { __typename?: 'Mutation', updateOneRemoteServer: { __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, userMappingOptions?: { __typename?: 'UserMappingOptionsUser', user?: string | null } | null } }; export type GetManyDatabaseConnectionsQueryVariables = Exact<{ input: RemoteServerTypeInput; }>; -export type GetManyDatabaseConnectionsQuery = { __typename?: 'Query', findManyRemoteServersByType: Array<{ __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, userMappingOptions?: { __typename?: 'UserMappingOptionsUsername', username?: string | null } | null }> }; +export type GetManyDatabaseConnectionsQuery = { __typename?: 'Query', findManyRemoteServersByType: Array<{ __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, userMappingOptions?: { __typename?: 'UserMappingOptionsUser', user?: string | null } | null }> }; export type GetManyRemoteTablesQueryVariables = Exact<{ input: RemoteServerIdInput; }>; -export type GetManyRemoteTablesQuery = { __typename?: 'Query', findAvailableRemoteTablesByServerId: Array<{ __typename?: 'RemoteTable', id?: any | null, name: string, schema: string, status: RemoteTableStatus }> }; +export type GetManyRemoteTablesQuery = { __typename?: 'Query', findAvailableRemoteTablesByServerId: Array<{ __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus }> }; export type GetOneDatabaseConnectionQueryVariables = Exact<{ input: RemoteServerIdInput; }>; -export type GetOneDatabaseConnectionQuery = { __typename?: 'Query', findOneRemoteServerById: { __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, userMappingOptions?: { __typename?: 'UserMappingOptionsUsername', username?: string | null } | null } }; +export type GetOneDatabaseConnectionQuery = { __typename?: 'Query', findOneRemoteServerById: { __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, userMappingOptions?: { __typename?: 'UserMappingOptionsUser', user?: string | null } | null } }; export type CreateOneObjectMetadataItemMutationVariables = Exact<{ input: CreateOneObjectInput; @@ -1372,16 +1372,16 @@ export type ObjectMetadataItemsQueryVariables = Exact<{ export type ObjectMetadataItemsQuery = { __typename?: 'Query', objects: { __typename?: 'ObjectConnection', edges: Array<{ __typename?: 'objectEdge', node: { __typename?: 'object', id: any, dataSourceId: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, createdAt: any, updatedAt: any, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, fields: { __typename?: 'ObjectFieldsConnection', edges: Array<{ __typename?: 'fieldEdge', node: { __typename?: 'field', id: any, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isNullable?: boolean | null, createdAt: any, updatedAt: any, defaultValue?: any | null, options?: any | null, fromRelationMetadata?: { __typename?: 'relation', id: any, relationType: RelationMetadataType, toFieldMetadataId: string, toObjectMetadata: { __typename?: 'object', id: any, dataSourceId: string, nameSingular: string, namePlural: string, isSystem: boolean, isRemote: boolean } } | null, toRelationMetadata?: { __typename?: 'relation', id: any, relationType: RelationMetadataType, fromFieldMetadataId: string, fromObjectMetadata: { __typename?: 'object', id: any, dataSourceId: string, nameSingular: string, namePlural: string, isSystem: boolean, isRemote: boolean } } | null, relationDefinition?: { __typename?: 'RelationDefinition', direction: RelationDefinitionType, sourceObjectMetadata: { __typename?: 'object', id: any, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'field', id: any, name: string }, targetObjectMetadata: { __typename?: 'object', id: any, nameSingular: string, namePlural: string }, targetFieldMetadata: { __typename?: 'field', id: any, name: string } } | null } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } }; -export const RemoteServerFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteServerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperId"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperOptions"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperType"}},{"kind":"Field","name":{"kind":"Name","value":"userMappingOptions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"username"}}]}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}}]}}]} as unknown as DocumentNode; +export const RemoteServerFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteServerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperId"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperOptions"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperType"}},{"kind":"Field","name":{"kind":"Name","value":"userMappingOptions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"}}]}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}}]}}]} as unknown as DocumentNode; export const RemoteTableFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteTableFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteTable"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]} as unknown as DocumentNode; -export const CreateServerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"createServer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateRemoteServerInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneRemoteServer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"RemoteServerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteServerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperId"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperOptions"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperType"}},{"kind":"Field","name":{"kind":"Name","value":"userMappingOptions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"username"}}]}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}}]}}]} as unknown as DocumentNode; +export const CreateServerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"createServer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateRemoteServerInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneRemoteServer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"RemoteServerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteServerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperId"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperOptions"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperType"}},{"kind":"Field","name":{"kind":"Name","value":"userMappingOptions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"}}]}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}}]}}]} as unknown as DocumentNode; export const DeleteServerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"deleteServer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServerIdInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOneRemoteServer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode; export const SyncRemoteTableDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"syncRemoteTable"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteTableInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"syncRemoteTable"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"RemoteTableFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteTableFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteTable"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]} as unknown as DocumentNode; export const UnsyncRemoteTableDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"unsyncRemoteTable"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteTableInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"unsyncRemoteTable"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"RemoteTableFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteTableFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteTable"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]} as unknown as DocumentNode; -export const UpdateServerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"updateServer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateRemoteServerInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateOneRemoteServer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"RemoteServerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteServerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperId"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperOptions"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperType"}},{"kind":"Field","name":{"kind":"Name","value":"userMappingOptions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"username"}}]}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}}]}}]} as unknown as DocumentNode; -export const GetManyDatabaseConnectionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetManyDatabaseConnections"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServerTypeInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findManyRemoteServersByType"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"RemoteServerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteServerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperId"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperOptions"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperType"}},{"kind":"Field","name":{"kind":"Name","value":"userMappingOptions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"username"}}]}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}}]}}]} as unknown as DocumentNode; +export const UpdateServerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"updateServer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateRemoteServerInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateOneRemoteServer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"RemoteServerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteServerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperId"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperOptions"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperType"}},{"kind":"Field","name":{"kind":"Name","value":"userMappingOptions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"}}]}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}}]}}]} as unknown as DocumentNode; +export const GetManyDatabaseConnectionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetManyDatabaseConnections"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServerTypeInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findManyRemoteServersByType"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"RemoteServerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteServerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperId"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperOptions"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperType"}},{"kind":"Field","name":{"kind":"Name","value":"userMappingOptions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"}}]}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}}]}}]} as unknown as DocumentNode; export const GetManyRemoteTablesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetManyRemoteTables"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServerIdInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findAvailableRemoteTablesByServerId"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"RemoteTableFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteTableFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteTable"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]} as unknown as DocumentNode; -export const GetOneDatabaseConnectionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetOneDatabaseConnection"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServerIdInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findOneRemoteServerById"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"RemoteServerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteServerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperId"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperOptions"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperType"}},{"kind":"Field","name":{"kind":"Name","value":"userMappingOptions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"username"}}]}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}}]}}]} as unknown as DocumentNode; +export const GetOneDatabaseConnectionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetOneDatabaseConnection"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServerIdInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findOneRemoteServerById"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"RemoteServerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteServerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperId"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperOptions"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperType"}},{"kind":"Field","name":{"kind":"Name","value":"userMappingOptions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"}}]}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}}]}}]} as unknown as DocumentNode; export const CreateOneObjectMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneObjectMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateOneObjectInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifierFieldMetadataId"}}]}}]}}]} as unknown as DocumentNode; export const CreateOneFieldMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneFieldMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateOneFieldMetadataInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneField"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"defaultValue"}},{"kind":"Field","name":{"kind":"Name","value":"options"}}]}}]}}]} as unknown as DocumentNode; export const CreateOneRelationMetadataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneRelationMetadata"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateOneRelationInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneRelation"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"relationType"}},{"kind":"Field","name":{"kind":"Name","value":"fromObjectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"toObjectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"fromFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"toFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode; diff --git a/packages/twenty-front/src/generated/graphql.tsx b/packages/twenty-front/src/generated/graphql.tsx index 82c3f360a..decc9540e 100644 --- a/packages/twenty-front/src/generated/graphql.tsx +++ b/packages/twenty-front/src/generated/graphql.tsx @@ -577,14 +577,14 @@ export type RemoteServer = { id: Scalars['ID']; schema?: Maybe; updatedAt: Scalars['DateTime']; - userMappingOptions?: Maybe; + userMappingOptions?: Maybe; }; export type RemoteTable = { __typename?: 'RemoteTable'; id?: Maybe; name: Scalars['String']; - schema: Scalars['String']; + schema?: Maybe; status: RemoteTableStatus; }; @@ -772,9 +772,9 @@ export type UserExists = { exists: Scalars['Boolean']; }; -export type UserMappingOptionsUsername = { - __typename?: 'UserMappingOptionsUsername'; - username?: Maybe; +export type UserMappingOptionsUser = { + __typename?: 'UserMappingOptionsUser'; + user?: Maybe; }; export type UserWorkspace = { diff --git a/packages/twenty-front/src/modules/databases/graphql/fragments/databaseConnectionFragment.ts b/packages/twenty-front/src/modules/databases/graphql/fragments/databaseConnectionFragment.ts index 053aab769..67d81b3cd 100644 --- a/packages/twenty-front/src/modules/databases/graphql/fragments/databaseConnectionFragment.ts +++ b/packages/twenty-front/src/modules/databases/graphql/fragments/databaseConnectionFragment.ts @@ -8,7 +8,7 @@ export const DATABASE_CONNECTION_FRAGMENT = gql` foreignDataWrapperOptions foreignDataWrapperType userMappingOptions { - username + user } updatedAt schema diff --git a/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionForm.tsx b/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionForm.tsx index 1ecfd0d5a..91848ee6e 100644 --- a/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionForm.tsx +++ b/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionForm.tsx @@ -8,7 +8,7 @@ export const settingsIntegrationPostgreSQLConnectionFormSchema = z.object({ dbname: z.string().min(1), host: z.string().min(1), port: z.preprocess((val) => parseInt(val as string), z.number().positive()), - username: z.string().min(1), + user: z.string().min(1), password: z.string().min(1), schema: z.string().min(1), }); @@ -52,9 +52,9 @@ export const SettingsIntegrationPostgreSQLConnectionForm = ({ { name: 'host' as const, label: 'Host', placeholder: 'host' }, { name: 'port' as const, label: 'Port', placeholder: '5432' }, { - name: 'username' as const, - label: 'Username', - placeholder: 'username', + name: 'user' as const, + label: 'User', + placeholder: 'user', }, { name: 'password' as const, diff --git a/packages/twenty-front/src/modules/settings/integrations/database-connection/utils/editDatabaseConnection.ts b/packages/twenty-front/src/modules/settings/integrations/database-connection/utils/editDatabaseConnection.ts index d79c65d53..bcb9d6103 100644 --- a/packages/twenty-front/src/modules/settings/integrations/database-connection/utils/editDatabaseConnection.ts +++ b/packages/twenty-front/src/modules/settings/integrations/database-connection/utils/editDatabaseConnection.ts @@ -28,7 +28,7 @@ export const getFormDefaultValuesFromConnection = ({ dbname: connection.foreignDataWrapperOptions.dbname, host: connection.foreignDataWrapperOptions.host, port: connection.foreignDataWrapperOptions.port, - username: connection.userMappingOptions?.username || undefined, + user: connection.userMappingOptions?.user || undefined, schema: connection.schema || undefined, password: '', }; @@ -51,7 +51,7 @@ export const formatValuesForUpdate = ({ const formattedValues = { userMappingOptions: pickBy( { - username: formValues.username, + user: formValues.user, password: formValues.password, }, identity, diff --git a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx index 9a68e502a..f061f52a2 100644 --- a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx @@ -41,7 +41,7 @@ const createRemoteServerInputSchema = newConnectionSchema }, userMappingOptions: { password: values.password, - username: values.username, + user: values.user, }, schema: values.schema, })); diff --git a/packages/twenty-front/src/testing/mock-data/remote-servers.ts b/packages/twenty-front/src/testing/mock-data/remote-servers.ts index 295973d2f..f048392a0 100644 --- a/packages/twenty-front/src/testing/mock-data/remote-servers.ts +++ b/packages/twenty-front/src/testing/mock-data/remote-servers.ts @@ -12,7 +12,7 @@ export const mockedRemoteServers = [ foreignDataWrapperType: 'postgres_fdw', userMappingOptions: { __typename: 'UserMappingOptionsDTO', - username: 'twenty', + user: 'twenty', }, updatedAt: '2024-04-30T13:41:25.858Z', schema: 'public', diff --git a/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts b/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts index a8b6a89be..ad4a970b6 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts @@ -45,6 +45,11 @@ export const seedFeatureFlags = async ( workspaceId: workspaceId, value: true, }, + { + key: FeatureFlagKeys.IsStripeIntegrationEnabled, + workspaceId: workspaceId, + value: true, + }, ]) .execute(); }; diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/factories.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/factories.ts index db1255540..e10fab44e 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/factories.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/factories.ts @@ -1,4 +1,4 @@ -import { ForeignDataWrapperQueryFactory } from 'src/engine/api/graphql/workspace-query-builder/factories/foreign-data-wrapper-query.factory'; +import { ForeignDataWrapperServerQueryFactory } from 'src/engine/api/graphql/workspace-query-builder/factories/foreign-data-wrapper-server-query.factory'; import { ArgsAliasFactory } from './args-alias.factory'; import { ArgsStringFactory } from './args-string.factory'; @@ -30,5 +30,5 @@ export const workspaceQueryBuilderFactories = [ UpdateOneQueryFactory, UpdateManyQueryFactory, DeleteManyQueryFactory, - ForeignDataWrapperQueryFactory, + ForeignDataWrapperServerQueryFactory, ]; diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/foreign-data-wrapper-query.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/foreign-data-wrapper-query.factory.ts deleted file mode 100644 index 56f090349..000000000 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/foreign-data-wrapper-query.factory.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { isDefined } from 'class-validator'; - -import { - ForeignDataWrapperOptions, - RemoteServerType, -} from 'src/engine/metadata-modules/remote-server/remote-server.entity'; -import { UserMappingOptions } from 'src/engine/metadata-modules/remote-server/utils/user-mapping-options.utils'; - -@Injectable() -export class ForeignDataWrapperQueryFactory { - createForeignDataWrapper( - foreignDataWrapperId: string, - foreignDataWrapperType: RemoteServerType, - foreignDataWrapperOptions: ForeignDataWrapperOptions, - ) { - const [name, options] = this.buildNameAndOptionsFromType( - foreignDataWrapperType, - foreignDataWrapperOptions, - ); - - return `CREATE SERVER "${foreignDataWrapperId}" FOREIGN DATA WRAPPER ${name} OPTIONS (${options})`; - } - - updateForeignDataWrapper({ - foreignDataWrapperId, - foreignDataWrapperOptions, - }: { - foreignDataWrapperId: string; - foreignDataWrapperOptions: Partial< - ForeignDataWrapperOptions - >; - }) { - const options = this.buildUpdateOptions(foreignDataWrapperOptions); - - return `ALTER SERVER "${foreignDataWrapperId}" OPTIONS (${options})`; - } - - createUserMapping( - foreignDataWrapperId: string, - userMappingOptions: UserMappingOptions, - ) { - // CURRENT_USER works for now since we are using only one user. But if we switch to a user per workspace, we need to change this. - return `CREATE USER MAPPING IF NOT EXISTS FOR CURRENT_USER SERVER "${foreignDataWrapperId}" OPTIONS (user '${userMappingOptions.username}', password '${userMappingOptions.password}')`; - } - - updateUserMapping( - foreignDataWrapperId: string, - userMappingOptions: Partial, - ) { - const options = this.buildUpdateUserMappingOptions(userMappingOptions); - - // CURRENT_USER works for now since we are using only one user. But if we switch to a user per workspace, we need to change this. - return `ALTER USER MAPPING FOR CURRENT_USER SERVER "${foreignDataWrapperId}" OPTIONS (${options})`; - } - - private buildNameAndOptionsFromType( - type: RemoteServerType, - options: ForeignDataWrapperOptions, - ) { - switch (type) { - case RemoteServerType.POSTGRES_FDW: - return ['postgres_fdw', this.buildPostgresFDWQueryOptions(options)]; - default: - throw new Error('Foreign data wrapper type not supported'); - } - } - - private buildUpdateOptions( - options: Partial>, - ) { - const rawQuerySetStatements: string[] = []; - - Object.entries(options).forEach(([key, value]) => { - if (isDefined(value)) { - rawQuerySetStatements.push(`SET ${key} '${value}'`); - } - }); - - return rawQuerySetStatements.join(', '); - } - - private buildUpdateUserMappingOptions( - userMappingOptions?: Partial, - ) { - const setStatements: string[] = []; - - if (isDefined(userMappingOptions?.username)) { - setStatements.push(`SET user '${userMappingOptions?.username}'`); - } - - if (isDefined(userMappingOptions?.password)) { - setStatements.push(`SET password '${userMappingOptions?.password}'`); - } - - return setStatements.join(', '); - } - - private buildPostgresFDWQueryOptions( - foreignDataWrapperOptions: ForeignDataWrapperOptions, - ) { - return `dbname '${foreignDataWrapperOptions.dbname}', host '${foreignDataWrapperOptions.host}', port '${foreignDataWrapperOptions.port}'`; - } -} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/foreign-data-wrapper-server-query.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/foreign-data-wrapper-server-query.factory.ts new file mode 100644 index 000000000..13199d01e --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/foreign-data-wrapper-server-query.factory.ts @@ -0,0 +1,69 @@ +import { Injectable } from '@nestjs/common'; + +import { + ForeignDataWrapperOptions, + RemoteServerType, +} from 'src/engine/metadata-modules/remote-server/remote-server.entity'; +import { UserMappingOptions } from 'src/engine/metadata-modules/remote-server/types/user-mapping-options'; + +@Injectable() +export class ForeignDataWrapperServerQueryFactory { + createForeignDataWrapperServer( + foreignDataWrapperId: string, + foreignDataWrapperType: RemoteServerType, + foreignDataWrapperOptions: ForeignDataWrapperOptions, + ) { + const options = this.buildQueryOptions(foreignDataWrapperOptions, false); + + return `CREATE SERVER "${foreignDataWrapperId}" FOREIGN DATA WRAPPER ${foreignDataWrapperType} OPTIONS (${options})`; + } + + updateForeignDataWrapperServer({ + foreignDataWrapperId, + foreignDataWrapperOptions, + }: { + foreignDataWrapperId: string; + foreignDataWrapperOptions: Partial< + ForeignDataWrapperOptions + >; + }) { + const options = this.buildQueryOptions(foreignDataWrapperOptions, true); + + return `ALTER SERVER "${foreignDataWrapperId}" OPTIONS (${options})`; + } + + createUserMapping( + foreignDataWrapperId: string, + userMappingOptions: UserMappingOptions, + ) { + const options = this.buildQueryOptions(userMappingOptions, false); + + // CURRENT_USER works for now since we are using only one user. But if we switch to a user per workspace, we need to change this. + return `CREATE USER MAPPING IF NOT EXISTS FOR CURRENT_USER SERVER "${foreignDataWrapperId}" OPTIONS (${options})`; + } + + updateUserMapping( + foreignDataWrapperId: string, + userMappingOptions: Partial, + ) { + const options = this.buildQueryOptions(userMappingOptions, true); + + // CURRENT_USER works for now since we are using only one user. But if we switch to a user per workspace, we need to change this. + return `ALTER USER MAPPING FOR CURRENT_USER SERVER "${foreignDataWrapperId}" OPTIONS (${options})`; + } + + private buildQueryOptions( + options: + | ForeignDataWrapperOptions + | Partial> + | UserMappingOptions + | Partial, + isUpdate: boolean, + ) { + const prefix = isUpdate ? 'SET ' : ''; + + return Object.entries(options) + .map(([key, value]) => `${prefix}${key} '${value}'`) + .join(', '); + } +} diff --git a/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts b/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts index 396eb8572..566063005 100644 --- a/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts @@ -21,6 +21,7 @@ export enum FeatureFlagKeys { IsEventObjectEnabled = 'IS_EVENT_OBJECT_ENABLED', IsAirtableIntegrationEnabled = 'IS_AIRTABLE_INTEGRATION_ENABLED', IsPostgreSQLIntegrationEnabled = 'IS_POSTGRESQL_INTEGRATION_ENABLED', + IsStripeIntegrationEnabled = 'IS_STRIPE_INTEGRATION_ENABLED', IsMultiSelectEnabled = 'IS_MULTI_SELECT_ENABLED', } diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/dtos/create-remote-server.input.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/dtos/create-remote-server.input.ts index eb04e7ec4..be2ab5d81 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/dtos/create-remote-server.input.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/dtos/create-remote-server.input.ts @@ -7,7 +7,7 @@ import { ForeignDataWrapperOptions, RemoteServerType, } from 'src/engine/metadata-modules/remote-server/remote-server.entity'; -import { UserMappingOptions } from 'src/engine/metadata-modules/remote-server/utils/user-mapping-options.utils'; +import { UserMappingOptions } from 'src/engine/metadata-modules/remote-server/types/user-mapping-options'; @InputType() export class CreateRemoteServerInput { diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/dtos/update-remote-server.input.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/dtos/update-remote-server.input.ts index 2e01aae7b..567c25688 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/dtos/update-remote-server.input.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/dtos/update-remote-server.input.ts @@ -10,7 +10,7 @@ import { import { UserMappingOptions, UserMappingOptionsUpdateInput, -} from 'src/engine/metadata-modules/remote-server/utils/user-mapping-options.utils'; +} from 'src/engine/metadata-modules/remote-server/types/user-mapping-options'; @InputType() export class UpdateRemoteServerInput { diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/dtos/user-mapping-dto.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/dtos/user-mapping-dto.ts index b57f8bbb8..aff0739b6 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/dtos/user-mapping-dto.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/dtos/user-mapping-dto.ts @@ -2,9 +2,9 @@ import { ObjectType, Field } from '@nestjs/graphql'; import { IsOptional } from 'class-validator'; -@ObjectType('UserMappingOptionsUsername') +@ObjectType('UserMappingOptionsUser') export class UserMappingOptionsDTO { @IsOptional() @Field(() => String, { nullable: true }) - username: string; + user: string; } diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.entity.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.entity.ts index c579319e0..91493501b 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.entity.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.entity.ts @@ -10,11 +10,12 @@ import { } from 'typeorm'; import { RemoteTableEntity } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.entity'; -import { UserMappingOptions } from 'src/engine/metadata-modules/remote-server/utils/user-mapping-options.utils'; +import { UserMappingOptions } from 'src/engine/metadata-modules/remote-server/types/user-mapping-options'; import { DistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table'; export enum RemoteServerType { POSTGRES_FDW = 'postgres_fdw', + STRIPE_FDW = 'stripe_fdw', } type PostgresForeignDataWrapperOptions = { @@ -23,10 +24,17 @@ type PostgresForeignDataWrapperOptions = { dbname: string; }; +type StripeForeignDataWrapperOptions = { + api_key: string; +}; + export type ForeignDataWrapperOptions = T extends RemoteServerType.POSTGRES_FDW ? PostgresForeignDataWrapperOptions - : never; + : T extends RemoteServerType.STRIPE_FDW + ? StripeForeignDataWrapperOptions + : never; + @Entity('remoteServer') export class RemoteServerEntity { @PrimaryGeneratedColumn('uuid') diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.module.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.module.ts index bee0089f3..aa42a2490 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.module.ts @@ -1,7 +1,7 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { ForeignDataWrapperQueryFactory } from 'src/engine/api/graphql/workspace-query-builder/factories/foreign-data-wrapper-query.factory'; +import { ForeignDataWrapperServerQueryFactory } from 'src/engine/api/graphql/workspace-query-builder/factories/foreign-data-wrapper-server-query.factory'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { RemoteServerEntity } from 'src/engine/metadata-modules/remote-server/remote-server.entity'; import { RemoteServerResolver } from 'src/engine/metadata-modules/remote-server/remote-server.resolver'; @@ -19,7 +19,7 @@ import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/works providers: [ RemoteServerService, RemoteServerResolver, - ForeignDataWrapperQueryFactory, + ForeignDataWrapperServerQueryFactory, ], }) export class RemoteServerModule {} diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.service.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.service.ts index 07d05aa17..8c56e393d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.service.ts @@ -20,11 +20,11 @@ import { validateObjectAgainstInjections, validateStringAgainstInjections, } from 'src/engine/metadata-modules/remote-server/utils/validate-remote-server-input.utils'; -import { ForeignDataWrapperQueryFactory } from 'src/engine/api/graphql/workspace-query-builder/factories/foreign-data-wrapper-query.factory'; +import { ForeignDataWrapperServerQueryFactory } from 'src/engine/api/graphql/workspace-query-builder/factories/foreign-data-wrapper-server-query.factory'; import { RemoteTableService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.service'; import { UpdateRemoteServerInput } from 'src/engine/metadata-modules/remote-server/dtos/update-remote-server.input'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { updateRemoteServerRawQuery } from 'src/engine/metadata-modules/remote-server/utils/build-update-remote-server-raw-query.utils'; +import { buildUpdateRemoteServerRawQuery } from 'src/engine/metadata-modules/remote-server/utils/build-update-remote-server-raw-query.utils'; import { validateRemoteServerType } from 'src/engine/metadata-modules/remote-server/utils/validate-remote-server-type.util'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; @@ -38,7 +38,7 @@ export class RemoteServerService { @InjectDataSource('metadata') private readonly metadataDataSource: DataSource, private readonly environmentService: EnvironmentService, - private readonly foreignDataWrapperQueryFactory: ForeignDataWrapperQueryFactory, + private readonly foreignDataWrapperServerQueryFactory: ForeignDataWrapperServerQueryFactory, private readonly remoteTableService: RemoteTableService, private readonly workspaceDataSourceService: WorkspaceDataSourceService, @InjectRepository(FeatureFlagEntity, 'core') @@ -85,7 +85,7 @@ export class RemoteServerService { ); const foreignDataWrapperQuery = - this.foreignDataWrapperQueryFactory.createForeignDataWrapper( + this.foreignDataWrapperServerQueryFactory.createForeignDataWrapperServer( createdRemoteServer.foreignDataWrapperId, remoteServerInput.foreignDataWrapperType, remoteServerInput.foreignDataWrapperOptions, @@ -95,7 +95,7 @@ export class RemoteServerService { if (remoteServerInput.userMappingOptions) { const userMappingQuery = - this.foreignDataWrapperQueryFactory.createUserMapping( + this.foreignDataWrapperServerQueryFactory.createUserMapping( createdRemoteServer.foreignDataWrapperId, remoteServerInput.userMappingOptions, ); @@ -167,18 +167,20 @@ export class RemoteServerService { !isEmpty(partialRemoteServerWithUpdates.foreignDataWrapperOptions) ) { const foreignDataWrapperQuery = - this.foreignDataWrapperQueryFactory.updateForeignDataWrapper({ - foreignDataWrapperId, - foreignDataWrapperOptions: - partialRemoteServerWithUpdates.foreignDataWrapperOptions, - }); + this.foreignDataWrapperServerQueryFactory.updateForeignDataWrapperServer( + { + foreignDataWrapperId, + foreignDataWrapperOptions: + partialRemoteServerWithUpdates.foreignDataWrapperOptions, + }, + ); await entityManager.query(foreignDataWrapperQuery); } if (!isEmpty(partialRemoteServerWithUpdates.userMappingOptions)) { const userMappingQuery = - this.foreignDataWrapperQueryFactory.updateUserMapping( + this.foreignDataWrapperServerQueryFactory.updateUserMapping( foreignDataWrapperId, partialRemoteServerWithUpdates.userMappingOptions, ); @@ -254,7 +256,7 @@ export class RemoteServerService { Pick, 'workspaceId' | 'id'>, ): Promise> { const [parameters, rawQuery] = - updateRemoteServerRawQuery(remoteServerToUpdate); + buildUpdateRemoteServerRawQuery(remoteServerToUpdate); const updateResult = await this.workspaceDataSourceService.executeRawQuery( rawQuery, diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service.ts index 4be865409..9905da7a5 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service.ts @@ -11,6 +11,7 @@ import { import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; import { DistantTableColumn } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table-column'; import { DistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table'; +import { STRIPE_DISTANT_TABLES } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/util/stripe-distant-tables.util'; @Injectable() export class DistantTableService { @@ -27,7 +28,9 @@ export class DistantTableService { tableName: string, ): Promise { if (!remoteServer.availableTables) { - throw new Error('Remote server available tables are not defined'); + throw new BadRequestException( + 'Remote server available tables are not defined', + ); } return remoteServer.availableTables[tableName]; @@ -47,6 +50,20 @@ export class DistantTableService { private async createAvailableTables( remoteServer: RemoteServerEntity, workspaceId: string, + ): Promise { + if (remoteServer.schema) { + return this.createAvailableTablesFromDynamicSchema( + remoteServer, + workspaceId, + ); + } + + return this.createAvailableTablesFromStaticSchema(remoteServer); + } + + private async createAvailableTablesFromDynamicSchema( + remoteServer: RemoteServerEntity, + workspaceId: string, ): Promise { if (!remoteServer.schema) { throw new BadRequestException('Remote server schema is not defined'); @@ -99,4 +116,21 @@ export class DistantTableService { return availableTables; } + + private async createAvailableTablesFromStaticSchema( + remoteServer: RemoteServerEntity, + ): Promise { + switch (remoteServer.foreignDataWrapperType) { + case RemoteServerType.STRIPE_FDW: + this.remoteServerRepository.update(remoteServer.id, { + availableTables: STRIPE_DISTANT_TABLES, + }); + + return STRIPE_DISTANT_TABLES; + default: + throw new BadRequestException( + `Type ${remoteServer.foreignDataWrapperType} does not have a static schema.`, + ); + } + } } diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/util/stripe-distant-tables.util.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/util/stripe-distant-tables.util.ts new file mode 100644 index 000000000..93d98150d --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/util/stripe-distant-tables.util.ts @@ -0,0 +1,91 @@ +import { DistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table'; + +export const STRIPE_DISTANT_TABLES: DistantTables = { + balance_transactions: [ + { columnName: 'id', dataType: 'text', udtName: 'text' }, + { columnName: 'amount', dataType: 'bigint', udtName: 'int8' }, + { columnName: 'currency', dataType: 'text', udtName: 'text' }, + { columnName: 'description', dataType: 'text', udtName: 'text' }, + { columnName: 'fee', dataType: 'bigint', udtName: 'int8' }, + { columnName: 'net', dataType: 'bigint', udtName: 'int8' }, + { columnName: 'status', dataType: 'text', udtName: 'text' }, + { columnName: 'type', dataType: 'text', udtName: 'text' }, + { columnName: 'created', dataType: 'timestamp', udtName: 'timestamp' }, + ], + customers: [ + { columnName: 'id', dataType: 'text', udtName: 'text' }, + { columnName: 'email', dataType: 'text', udtName: 'text' }, + { columnName: 'name', dataType: 'text', udtName: 'text' }, + { columnName: 'description', dataType: 'text', udtName: 'text' }, + { columnName: 'created', dataType: 'timestamp', udtName: 'timestamp' }, + ], + disputes: [ + { columnName: 'id', dataType: 'text', udtName: 'text' }, + { columnName: 'amount', dataType: 'bigint', udtName: 'int8' }, + { columnName: 'currency', dataType: 'text', udtName: 'text' }, + { columnName: 'charge', dataType: 'text', udtName: 'text' }, + { columnName: 'payment_intent', dataType: 'text', udtName: 'text' }, + { columnName: 'reason', dataType: 'text', udtName: 'text' }, + { columnName: 'status', dataType: 'text', udtName: 'text' }, + { columnName: 'created', dataType: 'timestamp', udtName: 'timestamp' }, + ], + files: [ + { columnName: 'id', dataType: 'text', udtName: 'text' }, + { columnName: 'filename', dataType: 'text', udtName: 'text' }, + { columnName: 'purpose', dataType: 'text', udtName: 'text' }, + { columnName: 'title', dataType: 'text', udtName: 'text' }, + { columnName: 'size', dataType: 'bigint', udtName: 'int8' }, + { columnName: 'type', dataType: 'text', udtName: 'text' }, + { columnName: 'url', dataType: 'text', udtName: 'text' }, + { columnName: 'created', dataType: 'timestamp', udtName: 'timestamp' }, + { columnName: 'expires_at', dataType: 'timestamp', udtName: 'timestamp' }, + ], + file_links: [ + { columnName: 'id', dataType: 'text', udtName: 'text' }, + { columnName: 'file', dataType: 'text', udtName: 'text' }, + { columnName: 'url', dataType: 'text', udtName: 'text' }, + { columnName: 'created', dataType: 'timestamp', udtName: 'timestamp' }, + { columnName: 'expired', dataType: 'bool', udtName: 'boolean' }, + { columnName: 'expires_at', dataType: 'timestamp', udtName: 'timestamp' }, + ], + mandates: [ + { columnName: 'id', dataType: 'text', udtName: 'text' }, + { columnName: 'payment_method', dataType: 'text', udtName: 'text' }, + { columnName: 'status', dataType: 'text', udtName: 'text' }, + { columnName: 'type', dataType: 'text', udtName: 'text' }, + ], + payouts: [ + { columnName: 'id', dataType: 'text', udtName: 'text' }, + { columnName: 'amount', dataType: 'bigint', udtName: 'int8' }, + { columnName: 'currency', dataType: 'text', udtName: 'text' }, + { columnName: 'description', dataType: 'text', udtName: 'text' }, + { columnName: 'status', dataType: 'text', udtName: 'text' }, + { columnName: 'created', dataType: 'timestamp', udtName: 'timestamp' }, + ], + refunds: [ + { columnName: 'id', dataType: 'text', udtName: 'text' }, + { columnName: 'amount', dataType: 'bigint', udtName: 'int8' }, + { columnName: 'currency', dataType: 'text', udtName: 'text' }, + { columnName: 'charge', dataType: 'text', udtName: 'text' }, + { columnName: 'payment_intent', dataType: 'text', udtName: 'text' }, + { columnName: 'reason', dataType: 'text', udtName: 'text' }, + { columnName: 'status', dataType: 'text', udtName: 'text' }, + { columnName: 'created', dataType: 'timestamp', udtName: 'timestamp' }, + ], + topups: [ + { columnName: 'id', dataType: 'text', udtName: 'text' }, + { columnName: 'amount', dataType: 'bigint', udtName: 'int8' }, + { columnName: 'currency', dataType: 'text', udtName: 'text' }, + { columnName: 'description', dataType: 'text', udtName: 'text' }, + { columnName: 'status', dataType: 'text', udtName: 'text' }, + { columnName: 'created', dataType: 'timestamp', udtName: 'timestamp' }, + ], + transfers: [ + { columnName: 'id', dataType: 'text', udtName: 'text' }, + { columnName: 'amount', dataType: 'bigint', udtName: 'int8' }, + { columnName: 'currency', dataType: 'text', udtName: 'text' }, + { columnName: 'description', dataType: 'text', udtName: 'text' }, + { columnName: 'destination', dataType: 'text', udtName: 'text' }, + { columnName: 'created', dataType: 'timestamp', udtName: 'timestamp' }, + ], +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto.ts index 4c7fa5401..07dd57170 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto.ts @@ -1,7 +1,7 @@ import { ObjectType, Field, registerEnumType } from '@nestjs/graphql'; import { IDField } from '@ptc-org/nestjs-query-graphql'; -import { IsEnum } from 'class-validator'; +import { IsEnum, IsOptional } from 'class-validator'; import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; @@ -27,6 +27,7 @@ export class RemoteTableDTO { @Field(() => RemoteTableStatus) status: RemoteTableStatus; - @Field(() => String) + @IsOptional() + @Field(() => String, { nullable: true }) schema?: string; } diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.service.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.service.ts index ca098290a..ae2d34bcf 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.service.ts @@ -26,6 +26,7 @@ import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service'; import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util'; import { + ReferencedTable, WorkspaceMigrationForeignColumnDefinition, WorkspaceMigrationForeignTable, WorkspaceMigrationTableActionType, @@ -338,6 +339,11 @@ export class RemoteTableService { remoteServer: RemoteServerEntity, distantTableColumns: DistantTableColumn[], ) { + const referencedTable: ReferencedTable = this.buildReferencedTable( + remoteServer, + remoteTableInput, + ); + const workspaceMigration = await this.workspaceMigrationService.createCustomMigration( generateMigrationName(`create-foreign-table-${localTableName}`), @@ -355,8 +361,7 @@ export class RemoteTableService { distantColumnName: column.columnName, }) satisfies WorkspaceMigrationForeignColumnDefinition, ), - referencedTableName: remoteTableInput.name, - referencedTableSchema: remoteServer.schema, + referencedTable, foreignDataWrapperId: remoteServer.foreignDataWrapperId, } satisfies WorkspaceMigrationForeignTable, }, @@ -430,4 +435,21 @@ export class RemoteTableService { } } } + + private buildReferencedTable( + remoteServer: RemoteServerEntity, + remoteTableInput: RemoteTableInput, + ): ReferencedTable { + switch (remoteServer.foreignDataWrapperType) { + case RemoteServerType.POSTGRES_FDW: + return { + table_name: remoteTableInput.name, + schema_name: remoteServer.schema, + }; + case RemoteServerType.STRIPE_FDW: + return { object: remoteTableInput.name }; + default: + throw new BadRequestException('Foreign data wrapper not supported'); + } + } } diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util.ts index 4b18e072a..cdf403490 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util.ts @@ -7,6 +7,9 @@ export const mapUdtNameToFieldType = (udtName: string): FieldMetadataType => { case 'uuid': return FieldMetadataType.UUID; case 'varchar': + case 'text': + case 'bigint': + case 'int8': return FieldMetadataType.TEXT; case 'bool': return FieldMetadataType.BOOLEAN; diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/utils/user-mapping-options.utils.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/types/user-mapping-options.ts similarity index 92% rename from packages/twenty-server/src/engine/metadata-modules/remote-server/utils/user-mapping-options.utils.ts rename to packages/twenty-server/src/engine/metadata-modules/remote-server/types/user-mapping-options.ts index 9a7bc1006..a48fdee7f 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/utils/user-mapping-options.utils.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/types/user-mapping-options.ts @@ -7,7 +7,7 @@ import { IsOptional } from 'class-validator'; export class UserMappingOptions { @IsOptional() @Field(() => String, { nullable: true }) - username: string; + user: string; @IsOptional() @Field(() => String, { nullable: true }) @@ -18,7 +18,7 @@ export class UserMappingOptions { export class UserMappingOptionsUpdateInput { @IsOptional() @Field(() => String, { nullable: true }) - username?: string; + user?: string; @IsOptional() @Field(() => String, { nullable: true }) diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/utils/build-update-remote-server-raw-query.utils.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/utils/build-update-remote-server-raw-query.utils.ts index 89899770a..c4189e253 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/utils/build-update-remote-server-raw-query.utils.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/utils/build-update-remote-server-raw-query.utils.ts @@ -1,135 +1,43 @@ import { BadRequestException } from '@nestjs/common'; -import { isDefined } from 'class-validator'; - import { + ForeignDataWrapperOptions, RemoteServerEntity, RemoteServerType, } from 'src/engine/metadata-modules/remote-server/remote-server.entity'; -import { UserMappingOptions } from 'src/engine/metadata-modules/remote-server/utils/user-mapping-options.utils'; +import { UserMappingOptions } from 'src/engine/metadata-modules/remote-server/types/user-mapping-options'; export type DeepPartial = { [P in keyof T]?: DeepPartial; }; -const buildUserMappingOptionsQuery = ( - parameters: any[], - parametersPositions: object, - userMappingOptions: DeepPartial, -): string | null => { - const shouldUpdateUserMappingOptionsPassword = isDefined( - userMappingOptions?.password, - ); - - if (shouldUpdateUserMappingOptionsPassword) { - parameters.push(userMappingOptions?.password); - parametersPositions['password'] = parameters.length; - } - - const shouldUpdateUserMappingOptionsUsername = isDefined( - userMappingOptions?.username, - ); - - if (shouldUpdateUserMappingOptionsUsername) { - parameters.push(userMappingOptions?.username); - parametersPositions['username'] = parameters.length; - } - - if ( - shouldUpdateUserMappingOptionsPassword || - shouldUpdateUserMappingOptionsUsername - ) { - return `"userMappingOptions" = jsonb_set(${ - shouldUpdateUserMappingOptionsPassword && - shouldUpdateUserMappingOptionsUsername - ? `jsonb_set( - "userMappingOptions", - '{username}', - to_jsonb($${parametersPositions['username']}::text) - ), - '{password}', - to_jsonb($${parametersPositions['password']}::text) - ` - : shouldUpdateUserMappingOptionsPassword - ? `"userMappingOptions", - '{password}', - to_jsonb($${parametersPositions['password']}::text) - ` - : `"userMappingOptions", - '{username}', - to_jsonb($${parametersPositions['username']}::text) - ` - })`; - } - - return null; -}; - -// TO DO This only works for postgres_fdw type for now, lets make it more generic when we have a different type -export const updateRemoteServerRawQuery = ( +export const buildUpdateRemoteServerRawQuery = ( remoteServerToUpdate: DeepPartial> & Pick, 'workspaceId' | 'id'>, ): [any[], string] => { - const parameters: any[] = [remoteServerToUpdate.id]; - const parametersPositions = {}; - const options: string[] = []; + const [parameters, parametersPositions] = + buildParametersAndPositions(remoteServerToUpdate); + if (remoteServerToUpdate.userMappingOptions) { - const userMappingOptionsQuery = buildUserMappingOptionsQuery( - parameters, - parametersPositions, + const userMappingOptionsQuery = buildJsonRawQuery( remoteServerToUpdate.userMappingOptions, + parametersPositions, + 'userMappingOptions', ); - if (userMappingOptionsQuery) options.push(userMappingOptionsQuery); + options.push(userMappingOptionsQuery); } - const shouldUpdateFdwDbname = isDefined( - remoteServerToUpdate.foreignDataWrapperOptions?.dbname, - ); + if (remoteServerToUpdate.foreignDataWrapperOptions) { + const foreignDataWrapperOptionsQuery = buildJsonRawQuery( + remoteServerToUpdate.foreignDataWrapperOptions, + parametersPositions, + 'foreignDataWrapperOptions', + ); - if (shouldUpdateFdwDbname) { - parameters.push(remoteServerToUpdate?.foreignDataWrapperOptions?.dbname); - parametersPositions['dbname'] = parameters.length; - } - - const shouldUpdateFdwHost = isDefined( - remoteServerToUpdate.foreignDataWrapperOptions?.host, - ); - - if (shouldUpdateFdwHost) { - parameters.push(remoteServerToUpdate?.foreignDataWrapperOptions?.host); - parametersPositions['host'] = parameters.length; - } - - const shouldUpdateFdwPort = isDefined( - remoteServerToUpdate.foreignDataWrapperOptions?.port, - ); - - if (shouldUpdateFdwPort) { - parameters.push(remoteServerToUpdate?.foreignDataWrapperOptions?.port); - parametersPositions['port'] = parameters.length; - } - - if (shouldUpdateFdwDbname || shouldUpdateFdwHost || shouldUpdateFdwPort) { - const fwdOptionsQuery = `"foreignDataWrapperOptions" = jsonb_set(${ - shouldUpdateFdwDbname && shouldUpdateFdwHost && shouldUpdateFdwPort - ? `jsonb_set(jsonb_set("foreignDataWrapperOptions", '{dbname}', to_jsonb($${parametersPositions['dbname']}::text)), '{host}', to_jsonb($${parametersPositions['host']}::text)), '{port}', to_jsonb($${parametersPositions['port']}::text)` - : shouldUpdateFdwDbname && shouldUpdateFdwHost - ? `jsonb_set("foreignDataWrapperOptions", '{dbname}', to_jsonb($${parametersPositions['dbname']}::text)), '{host}', to_jsonb($${parametersPositions['host']}::text)` - : shouldUpdateFdwDbname && shouldUpdateFdwPort - ? `jsonb_set("foreignDataWrapperOptions", '{dbname}', to_jsonb($${parametersPositions['dbname']}::text)), '{port}', to_jsonb($${parametersPositions['port']}::text)` - : shouldUpdateFdwHost && shouldUpdateFdwPort - ? `jsonb_set("foreignDataWrapperOptions", '{host}', to_jsonb($${parametersPositions['host']}::text)), '{port}', to_jsonb($${parametersPositions['port']}::text)` - : shouldUpdateFdwDbname - ? `"foreignDataWrapperOptions", '{dbname}', to_jsonb($${parametersPositions['dbname']}::text)` - : shouldUpdateFdwHost - ? `"foreignDataWrapperOptions", '{host}', to_jsonb($${parametersPositions['host']}::text)` - : `"foreignDataWrapperOptions", '{port}', to_jsonb($${parametersPositions['port']}::text)` - })`; - - options.push(fwdOptionsQuery); + options.push(foreignDataWrapperOptionsQuery); } if (options.length < 1) { @@ -142,3 +50,57 @@ export const updateRemoteServerRawQuery = ( return [parameters, rawQuery]; }; + +const buildParametersAndPositions = ( + remoteServerToUpdate: DeepPartial> & + Pick, 'workspaceId' | 'id'>, +): [any[], object] => { + const parameters: any[] = [remoteServerToUpdate.id]; + const parametersPositions = {}; + + if (remoteServerToUpdate.userMappingOptions) { + Object.entries(remoteServerToUpdate.userMappingOptions).forEach( + ([key, value]) => { + parameters.push(value); + parametersPositions[key] = parameters.length; + }, + ); + } + + if (remoteServerToUpdate.foreignDataWrapperOptions) { + Object.entries(remoteServerToUpdate.foreignDataWrapperOptions).forEach( + ([key, value]) => { + parameters.push(value); + parametersPositions[key] = parameters.length; + }, + ); + } + + return [parameters, parametersPositions]; +}; + +const buildJsonRawQuery = ( + options: + | Partial + | Partial>, + parametersPositions: object, + objectName: string, +): string => { + const buildJsonSet = ( + opts: + | Partial + | Partial>, + ): string => { + const [[firstKey, _], ...followingOptions] = Object.entries(opts); + + let query = `jsonb_set("${objectName}", '{${firstKey}}', to_jsonb($${parametersPositions[firstKey]}::text))`; + + followingOptions.forEach(([key, _]) => { + query = `jsonb_set(${query}, '{${key}}', to_jsonb($${parametersPositions[key]}::text))`; + }); + + return query; + }; + + return `"${objectName}" = ${buildJsonSet(options)}`; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/utils/validate-remote-server-type.util.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/utils/validate-remote-server-type.util.ts index 36921e2d1..7a158e6a7 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/utils/validate-remote-server-type.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/utils/validate-remote-server-type.util.ts @@ -32,6 +32,8 @@ const getFeatureFlagKey = (remoteServerType: RemoteServerType) => { switch (remoteServerType) { case RemoteServerType.POSTGRES_FDW: return FeatureFlagKeys.IsPostgreSQLIntegrationEnabled; + case RemoteServerType.STRIPE_FDW: + return FeatureFlagKeys.IsStripeIntegrationEnabled; default: throw new BadRequestException( `Type ${remoteServerType} is not supported.`, diff --git a/packages/twenty-server/src/engine/metadata-modules/workspace-migration/workspace-migration.entity.ts b/packages/twenty-server/src/engine/metadata-modules/workspace-migration/workspace-migration.entity.ts index ad8068883..a524f1d98 100644 --- a/packages/twenty-server/src/engine/metadata-modules/workspace-migration/workspace-migration.entity.ts +++ b/packages/twenty-server/src/engine/metadata-modules/workspace-migration/workspace-migration.entity.ts @@ -67,10 +67,20 @@ export type WorkspaceMigrationForeignColumnDefinition = distantColumnName: string; }; +type ReferencedObject = { + object: string; +}; + +type ReferencedTableWithSchema = { + table_name: string; + schema_name: string; +}; + +export type ReferencedTable = ReferencedObject | ReferencedTableWithSchema; + export type WorkspaceMigrationForeignTable = { columns: WorkspaceMigrationForeignColumnDefinition[]; - referencedTableName: string; - referencedTableSchema: string; + referencedTable: ReferencedObject | ReferencedTableWithSchema; foreignDataWrapperId: string; }; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service.ts index 2f0991625..074bcae2a 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service.ts @@ -495,8 +495,14 @@ export class WorkspaceMigrationRunnerService { ) .join(', '); + let serverOptions = ''; + + Object.entries(foreignTable.referencedTable).forEach(([key, value]) => { + serverOptions += ` ${key} '${value}'`; + }); + await queryRunner.query( - `CREATE FOREIGN TABLE ${schemaName}."${name}" (${foreignTableColumns}) SERVER "${foreignTable.foreignDataWrapperId}" OPTIONS (schema_name '${foreignTable.referencedTableSchema}', table_name '${foreignTable.referencedTableName}')`, + `CREATE FOREIGN TABLE ${schemaName}."${name}" (${foreignTableColumns}) SERVER "${foreignTable.foreignDataWrapperId}" OPTIONS (${serverOptions})`, ); await queryRunner.query(` diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts index d1d6d3ef9..e34269b72 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts @@ -59,6 +59,7 @@ export class AddStandardIdCommand extends CommandRunner { IS_AIRTABLE_INTEGRATION_ENABLED: true, IS_POSTGRESQL_INTEGRATION_ENABLED: true, IS_MULTI_SELECT_ENABLED: false, + IS_STRIPE_INTEGRATION_ENABLED: false, }, ); const standardFieldMetadataCollection = this.standardFieldFactory.create( @@ -74,6 +75,7 @@ export class AddStandardIdCommand extends CommandRunner { IS_AIRTABLE_INTEGRATION_ENABLED: true, IS_POSTGRESQL_INTEGRATION_ENABLED: true, IS_MULTI_SELECT_ENABLED: false, + IS_STRIPE_INTEGRATION_ENABLED: false, }, );