diff --git a/packages/twenty-apps/hello-world/package.json b/packages/twenty-apps/hello-world/package.json index 1e8141e3016..33888defe51 100644 --- a/packages/twenty-apps/hello-world/package.json +++ b/packages/twenty-apps/hello-world/package.json @@ -1,6 +1,6 @@ { - "name": "hello-world", - "version": "0.1.0", + "name": "@twentyhq/hello-world", + "version": "0.2.2", "license": "MIT", "engines": { "node": "^24.5.0", diff --git a/packages/twenty-apps/hello-world/yarn.lock b/packages/twenty-apps/hello-world/yarn.lock index 67087601951..d84e9c64885 100644 --- a/packages/twenty-apps/hello-world/yarn.lock +++ b/packages/twenty-apps/hello-world/yarn.lock @@ -1591,6 +1591,22 @@ __metadata: languageName: node linkType: hard +"@twentyhq/hello-world@workspace:.": + version: 0.0.0-use.local + resolution: "@twentyhq/hello-world@workspace:." + dependencies: + "@types/node": "npm:^24.7.2" + "@types/react": "npm:^18.2.0" + eslint: "npm:^9.32.0" + react: "npm:^18.2.0" + twenty-sdk: "npm:0.6.3" + typescript: "npm:^5.9.3" + typescript-eslint: "npm:^8.50.0" + vite-tsconfig-paths: "npm:^4.2.1" + vitest: "npm:^3.1.1" + languageName: unknown + linkType: soft + "@types/chai@npm:^5.2.2": version: 5.2.3 resolution: "@types/chai@npm:5.2.3" @@ -1604,7 +1620,7 @@ __metadata: "@types/deep-eql@npm:*": version: 4.0.2 resolution: "@types/deep-eql@npm:4.0.2" - checksum: 10c0/bf3f811843117900d7084b9d0c852da9a044d12eb40e6de73b552598a6843c21291a8a381b0532644574beecd5e3491c5ff3a0365ab86b15d59862c025384844 + checksum: 10c0-bf3f811843117900d7084b9d0c852da9a044d12eb40e6de73b552598a6843c21291a8a381b0532644574beecd5e3491c5ff3a0365ab86b15d59862c025384844 languageName: node linkType: hard @@ -4676,22 +4692,6 @@ __metadata: languageName: node linkType: hard -"hello-world@workspace:.": - version: 0.0.0-use.local - resolution: "hello-world@workspace:." - dependencies: - "@types/node": "npm:^24.7.2" - "@types/react": "npm:^18.2.0" - eslint: "npm:^9.32.0" - react: "npm:^18.2.0" - twenty-sdk: "npm:0.6.3" - typescript: "npm:^5.9.3" - typescript-eslint: "npm:^8.50.0" - vite-tsconfig-paths: "npm:^4.2.1" - vitest: "npm:^3.1.1" - languageName: unknown - linkType: soft - "hoist-non-react-statics@npm:^3.3.1": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index aefa4a3c9ec..99663c9de55 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -316,6 +316,12 @@ export type ApiKeyToken = { token: Scalars['String']; }; +export enum AppRegistrationSourceType { + LOCAL = 'LOCAL', + NPM = 'NPM', + TARBALL = 'TARBALL' +} + export type AppToken = { __typename?: 'AppToken'; createdAt: Scalars['DateTime']; @@ -328,12 +334,14 @@ export type AppToken = { export type Application = { __typename?: 'Application'; agents: Array; + applicationRegistration?: Maybe; + applicationRegistrationId?: Maybe; applicationVariables: Array; availablePackages: Scalars['JSON']; canBeUninstalled: Scalars['Boolean']; defaultLogicFunctionRole?: Maybe; defaultRoleId?: Maybe; - description: Scalars['String']; + description?: Maybe; id: Scalars['UUID']; logicFunctions: Array; name: Scalars['String']; @@ -342,7 +350,7 @@ export type Application = { packageJsonFileId?: Maybe; settingsCustomTabFrontComponentId?: Maybe; universalIdentifier: Scalars['String']; - version: Scalars['String']; + version?: Maybe; yarnLockChecksum?: Maybe; yarnLockFileId?: Maybe; }; @@ -353,11 +361,15 @@ export type ApplicationRegistration = { createdAt: Scalars['DateTime']; description?: Maybe; id: Scalars['UUID']; + isFeatured: Scalars['Boolean']; + latestAvailableVersion?: Maybe; logoUrl?: Maybe; name: Scalars['String']; oAuthClientId: Scalars['String']; oAuthRedirectUris: Array; oAuthScopes: Array; + sourcePackage?: Maybe; + sourceType: AppRegistrationSourceType; termsUrl?: Maybe; universalIdentifier: Scalars['String']; updatedAt: Scalars['DateTime']; @@ -371,6 +383,13 @@ export type ApplicationRegistrationStats = { versionDistribution: Array; }; +export type ApplicationRegistrationSummary = { + __typename?: 'ApplicationRegistrationSummary'; + id: Scalars['UUID']; + latestAvailableVersion?: Maybe; + sourceType: AppRegistrationSourceType; +}; + export type ApplicationRegistrationVariable = { __typename?: 'ApplicationRegistrationVariable'; createdAt: Scalars['DateTime']; @@ -1772,6 +1791,7 @@ export type File = { export enum FileFolder { AgentChat = 'AgentChat', + AppTarball = 'AppTarball', Attachment = 'Attachment', BuiltFrontComponent = 'BuiltFrontComponent', BuiltLogicFunction = 'BuiltLogicFunction', @@ -2218,6 +2238,7 @@ export type MarketplaceApp = { objects: Array; providers: Array; screenshots: Array; + sourcePackage?: Maybe; termsUrl?: Maybe; version: Scalars['String']; websiteUrl?: Maybe; @@ -2432,6 +2453,7 @@ export type Mutation = { initiateOTPProvisioningForAuthenticatedUser: InitiateTwoFactorAuthenticationProvisioning; installApplication: Scalars['Boolean']; installMarketplaceApp: Scalars['Boolean']; + installNpmApp: Scalars['Boolean']; removeQueryFromEventStream: Scalars['Boolean']; removeRoleFromAgent: Scalars['Boolean']; renewApplicationToken: ApplicationTokenPair; @@ -2490,7 +2512,9 @@ export type Mutation = { updateWorkspace: Workspace; updateWorkspaceFeatureFlag: Scalars['Boolean']; updateWorkspaceMemberRole: WorkspaceMember; + upgradeApplication: Scalars['Boolean']; uploadAIChatFile: FileWithSignedUrl; + uploadAppTarball: ApplicationRegistration; uploadApplicationFile: File; uploadFilesFieldFile: FileWithSignedUrl; uploadFilesFieldFileByUniversalIdentifier: FileWithSignedUrl; @@ -3019,6 +3043,18 @@ export type MutationInstallApplicationArgs = { }; +export type MutationInstallMarketplaceAppArgs = { + universalIdentifier: Scalars['String']; + version?: InputMaybe; +}; + + +export type MutationInstallNpmAppArgs = { + packageName: Scalars['String']; + version?: InputMaybe; +}; + + export type MutationRemoveQueryFromEventStreamArgs = { input: RemoveQueryFromEventStreamInput; }; @@ -3324,11 +3360,23 @@ export type MutationUpdateWorkspaceMemberRoleArgs = { }; +export type MutationUpgradeApplicationArgs = { + appRegistrationId: Scalars['String']; + targetVersion: Scalars['String']; +}; + + export type MutationUploadAiChatFileArgs = { file: Scalars['Upload']; }; +export type MutationUploadAppTarballArgs = { + file: Scalars['Upload']; + universalIdentifier?: InputMaybe; +}; + + export type MutationUploadApplicationFileArgs = { applicationUniversalIdentifier: Scalars['String']; file: Scalars['Upload']; @@ -5765,19 +5813,19 @@ export type UpdateOneApplicationVariableMutationVariables = Exact<{ export type UpdateOneApplicationVariableMutation = { __typename?: 'Mutation', updateOneApplicationVariable: boolean }; -export type ApplicationFieldsFragment = { __typename?: 'Application', id: string, name: string, description: string, version: string, universalIdentifier: string, canBeUninstalled: boolean, defaultRoleId?: string | null, settingsCustomTabFrontComponentId?: string | null, availablePackages: any, applicationVariables: Array<{ __typename?: 'ApplicationVariable', id: string, key: string, value: string, description: string, isSecret: boolean }>, agents: Array<{ __typename?: 'Agent', id: string, name: string, label: string, description?: string | null, icon?: string | null, prompt: string, modelId: string, responseFormat?: any | null, roleId?: string | null, isCustom: boolean, modelConfiguration?: any | null, evaluationInputs: Array, applicationId?: string | null, createdAt: string, updatedAt: string }>, objects: Array<{ __typename?: 'Object', id: string, universalIdentifier: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, isUIReadOnly: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, applicationId: string, shortcut?: string | null, isLabelSyncedWithName: boolean, isSearchable: boolean, duplicateCriteria?: Array> | null, indexMetadataList: Array<{ __typename?: 'Index', id: string, createdAt: string, updatedAt: string, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, isCustom?: boolean | null, indexFieldMetadataList: Array<{ __typename?: 'IndexField', id: string, fieldMetadataId: string, createdAt: string, updatedAt: string, order: number }> }>, fieldsList: Array<{ __typename?: 'Field', id: string, universalIdentifier: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isUIReadOnly?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: string, updatedAt: string, defaultValue?: any | null, options?: any | null, settings?: any | null, isLabelSyncedWithName?: boolean | null, morphId?: string | null, applicationId: string, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null }> }>, logicFunctions: Array<{ __typename?: 'LogicFunction', id: string, name: string, description?: string | null, runtime: string, timeoutSeconds: number, sourceHandlerPath: string, handlerName: string, toolInputSchema?: any | null, isTool: boolean, cronTriggerSettings?: any | null, databaseEventTriggerSettings?: any | null, httpRouteTriggerSettings?: any | null, applicationId?: string | null, createdAt: string, updatedAt: string }> }; +export type ApplicationFieldsFragment = { __typename?: 'Application', id: string, name: string, description?: string | null, version?: string | null, universalIdentifier: string, applicationRegistrationId?: string | null, canBeUninstalled: boolean, defaultRoleId?: string | null, settingsCustomTabFrontComponentId?: string | null, availablePackages: any, applicationRegistration?: { __typename?: 'ApplicationRegistrationSummary', id: string, latestAvailableVersion?: string | null, sourceType: AppRegistrationSourceType } | null, applicationVariables: Array<{ __typename?: 'ApplicationVariable', id: string, key: string, value: string, description: string, isSecret: boolean }>, agents: Array<{ __typename?: 'Agent', id: string, name: string, label: string, description?: string | null, icon?: string | null, prompt: string, modelId: string, responseFormat?: any | null, roleId?: string | null, isCustom: boolean, modelConfiguration?: any | null, evaluationInputs: Array, applicationId?: string | null, createdAt: string, updatedAt: string }>, objects: Array<{ __typename?: 'Object', id: string, universalIdentifier: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, isUIReadOnly: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, applicationId: string, shortcut?: string | null, isLabelSyncedWithName: boolean, isSearchable: boolean, duplicateCriteria?: Array> | null, indexMetadataList: Array<{ __typename?: 'Index', id: string, createdAt: string, updatedAt: string, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, isCustom?: boolean | null, indexFieldMetadataList: Array<{ __typename?: 'IndexField', id: string, fieldMetadataId: string, createdAt: string, updatedAt: string, order: number }> }>, fieldsList: Array<{ __typename?: 'Field', id: string, universalIdentifier: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isUIReadOnly?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: string, updatedAt: string, defaultValue?: any | null, options?: any | null, settings?: any | null, isLabelSyncedWithName?: boolean | null, morphId?: string | null, applicationId: string, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null }> }>, logicFunctions: Array<{ __typename?: 'LogicFunction', id: string, name: string, description?: string | null, runtime: string, timeoutSeconds: number, sourceHandlerPath: string, handlerName: string, toolInputSchema?: any | null, isTool: boolean, cronTriggerSettings?: any | null, databaseEventTriggerSettings?: any | null, httpRouteTriggerSettings?: any | null, applicationId?: string | null, createdAt: string, updatedAt: string }> }; export type FindManyApplicationsQueryVariables = Exact<{ [key: string]: never; }>; -export type FindManyApplicationsQuery = { __typename?: 'Query', findManyApplications: Array<{ __typename?: 'Application', id: string, name: string, description: string, version: string }> }; +export type FindManyApplicationsQuery = { __typename?: 'Query', findManyApplications: Array<{ __typename?: 'Application', id: string, name: string, description?: string | null, version?: string | null, applicationRegistrationId?: string | null, applicationRegistration?: { __typename?: 'ApplicationRegistrationSummary', id: string, latestAvailableVersion?: string | null, sourceType: AppRegistrationSourceType } | null }> }; export type FindOneApplicationQueryVariables = Exact<{ id: Scalars['UUID']; }>; -export type FindOneApplicationQuery = { __typename?: 'Query', findOneApplication: { __typename?: 'Application', id: string, name: string, description: string, version: string, universalIdentifier: string, canBeUninstalled: boolean, defaultRoleId?: string | null, settingsCustomTabFrontComponentId?: string | null, availablePackages: any, applicationVariables: Array<{ __typename?: 'ApplicationVariable', id: string, key: string, value: string, description: string, isSecret: boolean }>, agents: Array<{ __typename?: 'Agent', id: string, name: string, label: string, description?: string | null, icon?: string | null, prompt: string, modelId: string, responseFormat?: any | null, roleId?: string | null, isCustom: boolean, modelConfiguration?: any | null, evaluationInputs: Array, applicationId?: string | null, createdAt: string, updatedAt: string }>, objects: Array<{ __typename?: 'Object', id: string, universalIdentifier: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, isUIReadOnly: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, applicationId: string, shortcut?: string | null, isLabelSyncedWithName: boolean, isSearchable: boolean, duplicateCriteria?: Array> | null, indexMetadataList: Array<{ __typename?: 'Index', id: string, createdAt: string, updatedAt: string, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, isCustom?: boolean | null, indexFieldMetadataList: Array<{ __typename?: 'IndexField', id: string, fieldMetadataId: string, createdAt: string, updatedAt: string, order: number }> }>, fieldsList: Array<{ __typename?: 'Field', id: string, universalIdentifier: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isUIReadOnly?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: string, updatedAt: string, defaultValue?: any | null, options?: any | null, settings?: any | null, isLabelSyncedWithName?: boolean | null, morphId?: string | null, applicationId: string, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null }> }>, logicFunctions: Array<{ __typename?: 'LogicFunction', id: string, name: string, description?: string | null, runtime: string, timeoutSeconds: number, sourceHandlerPath: string, handlerName: string, toolInputSchema?: any | null, isTool: boolean, cronTriggerSettings?: any | null, databaseEventTriggerSettings?: any | null, httpRouteTriggerSettings?: any | null, applicationId?: string | null, createdAt: string, updatedAt: string }> } }; +export type FindOneApplicationQuery = { __typename?: 'Query', findOneApplication: { __typename?: 'Application', id: string, name: string, description?: string | null, version?: string | null, universalIdentifier: string, applicationRegistrationId?: string | null, canBeUninstalled: boolean, defaultRoleId?: string | null, settingsCustomTabFrontComponentId?: string | null, availablePackages: any, applicationRegistration?: { __typename?: 'ApplicationRegistrationSummary', id: string, latestAvailableVersion?: string | null, sourceType: AppRegistrationSourceType } | null, applicationVariables: Array<{ __typename?: 'ApplicationVariable', id: string, key: string, value: string, description: string, isSecret: boolean }>, agents: Array<{ __typename?: 'Agent', id: string, name: string, label: string, description?: string | null, icon?: string | null, prompt: string, modelId: string, responseFormat?: any | null, roleId?: string | null, isCustom: boolean, modelConfiguration?: any | null, evaluationInputs: Array, applicationId?: string | null, createdAt: string, updatedAt: string }>, objects: Array<{ __typename?: 'Object', id: string, universalIdentifier: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, isUIReadOnly: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, applicationId: string, shortcut?: string | null, isLabelSyncedWithName: boolean, isSearchable: boolean, duplicateCriteria?: Array> | null, indexMetadataList: Array<{ __typename?: 'Index', id: string, createdAt: string, updatedAt: string, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, isCustom?: boolean | null, indexFieldMetadataList: Array<{ __typename?: 'IndexField', id: string, fieldMetadataId: string, createdAt: string, updatedAt: string, order: number }> }>, fieldsList: Array<{ __typename?: 'Field', id: string, universalIdentifier: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isUIReadOnly?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: string, updatedAt: string, defaultValue?: any | null, options?: any | null, settings?: any | null, isLabelSyncedWithName?: boolean | null, morphId?: string | null, applicationId: string, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null }> }>, logicFunctions: Array<{ __typename?: 'LogicFunction', id: string, name: string, description?: string | null, runtime: string, timeoutSeconds: number, sourceHandlerPath: string, handlerName: string, toolInputSchema?: any | null, isTool: boolean, cronTriggerSettings?: any | null, databaseEventTriggerSettings?: any | null, httpRouteTriggerSettings?: any | null, applicationId?: string | null, createdAt: string, updatedAt: string }> } }; export type AuthTokenFragmentFragment = { __typename?: 'AuthToken', token: string, expiresAt: string }; @@ -6172,12 +6220,44 @@ export type GetLogicFunctionSourceCodeQueryVariables = Exact<{ export type GetLogicFunctionSourceCodeQuery = { __typename?: 'Query', getLogicFunctionSourceCode?: string | null }; -export type MarketplaceAppFieldsFragment = { __typename?: 'MarketplaceApp', id: string, name: string, description: string, icon: string, version: string, author: string, category: string, logo?: string | null, screenshots: Array, aboutDescription: string, providers: Array, websiteUrl?: string | null, termsUrl?: string | null, objects: Array<{ __typename?: 'MarketplaceAppObject', universalIdentifier: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, fields: Array<{ __typename?: 'MarketplaceAppField', universalIdentifier?: string | null, name: string, type: string, label: string, description?: string | null, icon?: string | null }> }>, fields: Array<{ __typename?: 'MarketplaceAppField', name: string, type: string, label: string, description?: string | null, icon?: string | null, objectUniversalIdentifier?: string | null }>, logicFunctions: Array<{ __typename?: 'MarketplaceAppLogicFunction', name: string, description?: string | null, timeoutSeconds?: number | null }>, frontComponents: Array<{ __typename?: 'MarketplaceAppFrontComponent', name: string, description?: string | null }>, defaultRole?: { __typename?: 'MarketplaceAppDefaultRole', id: string, label: string, description?: string | null, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean, canUpdateAllSettings: boolean, canAccessAllTools: boolean, permissionFlags: Array, objectPermissions: Array<{ __typename?: 'MarketplaceAppRoleObjectPermission', objectUniversalIdentifier: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null }>, fieldPermissions: Array<{ __typename?: 'MarketplaceAppRoleFieldPermission', objectUniversalIdentifier: string, fieldUniversalIdentifier: string, canReadFieldValue?: boolean | null, canUpdateFieldValue?: boolean | null }> } | null }; +export type MarketplaceAppFieldsFragment = { __typename?: 'MarketplaceApp', id: string, name: string, description: string, icon: string, version: string, author: string, category: string, logo?: string | null, screenshots: Array, aboutDescription: string, providers: Array, websiteUrl?: string | null, termsUrl?: string | null, sourcePackage?: string | null, objects: Array<{ __typename?: 'MarketplaceAppObject', universalIdentifier: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, fields: Array<{ __typename?: 'MarketplaceAppField', universalIdentifier?: string | null, name: string, type: string, label: string, description?: string | null, icon?: string | null }> }>, fields: Array<{ __typename?: 'MarketplaceAppField', name: string, type: string, label: string, description?: string | null, icon?: string | null, objectUniversalIdentifier?: string | null }>, logicFunctions: Array<{ __typename?: 'MarketplaceAppLogicFunction', name: string, description?: string | null, timeoutSeconds?: number | null }>, frontComponents: Array<{ __typename?: 'MarketplaceAppFrontComponent', name: string, description?: string | null }>, defaultRole?: { __typename?: 'MarketplaceAppDefaultRole', id: string, label: string, description?: string | null, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean, canUpdateAllSettings: boolean, canAccessAllTools: boolean, permissionFlags: Array, objectPermissions: Array<{ __typename?: 'MarketplaceAppRoleObjectPermission', objectUniversalIdentifier: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null }>, fieldPermissions: Array<{ __typename?: 'MarketplaceAppRoleFieldPermission', objectUniversalIdentifier: string, fieldUniversalIdentifier: string, canReadFieldValue?: boolean | null, canUpdateFieldValue?: boolean | null }> } | null }; + +export type InstallMarketplaceAppMutationVariables = Exact<{ + universalIdentifier: Scalars['String']; + version?: InputMaybe; +}>; + + +export type InstallMarketplaceAppMutation = { __typename?: 'Mutation', installMarketplaceApp: boolean }; + +export type InstallNpmAppMutationVariables = Exact<{ + packageName: Scalars['String']; + version?: InputMaybe; +}>; + + +export type InstallNpmAppMutation = { __typename?: 'Mutation', installNpmApp: boolean }; + +export type UpgradeApplicationMutationVariables = Exact<{ + appRegistrationId: Scalars['String']; + targetVersion: Scalars['String']; +}>; + + +export type UpgradeApplicationMutation = { __typename?: 'Mutation', upgradeApplication: boolean }; + +export type UploadAppTarballMutationVariables = Exact<{ + file: Scalars['Upload']; + universalIdentifier?: InputMaybe; +}>; + + +export type UploadAppTarballMutation = { __typename?: 'Mutation', uploadAppTarball: { __typename?: 'ApplicationRegistration', id: string, universalIdentifier: string, name: string } }; export type FindManyMarketplaceAppsQueryVariables = Exact<{ [key: string]: never; }>; -export type FindManyMarketplaceAppsQuery = { __typename?: 'Query', findManyMarketplaceApps: Array<{ __typename?: 'MarketplaceApp', id: string, name: string, description: string, icon: string, version: string, author: string, category: string, logo?: string | null, screenshots: Array, aboutDescription: string, providers: Array, websiteUrl?: string | null, termsUrl?: string | null, objects: Array<{ __typename?: 'MarketplaceAppObject', universalIdentifier: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, fields: Array<{ __typename?: 'MarketplaceAppField', universalIdentifier?: string | null, name: string, type: string, label: string, description?: string | null, icon?: string | null }> }>, fields: Array<{ __typename?: 'MarketplaceAppField', name: string, type: string, label: string, description?: string | null, icon?: string | null, objectUniversalIdentifier?: string | null }>, logicFunctions: Array<{ __typename?: 'MarketplaceAppLogicFunction', name: string, description?: string | null, timeoutSeconds?: number | null }>, frontComponents: Array<{ __typename?: 'MarketplaceAppFrontComponent', name: string, description?: string | null }>, defaultRole?: { __typename?: 'MarketplaceAppDefaultRole', id: string, label: string, description?: string | null, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean, canUpdateAllSettings: boolean, canAccessAllTools: boolean, permissionFlags: Array, objectPermissions: Array<{ __typename?: 'MarketplaceAppRoleObjectPermission', objectUniversalIdentifier: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null }>, fieldPermissions: Array<{ __typename?: 'MarketplaceAppRoleFieldPermission', objectUniversalIdentifier: string, fieldUniversalIdentifier: string, canReadFieldValue?: boolean | null, canUpdateFieldValue?: boolean | null }> } | null }> }; +export type FindManyMarketplaceAppsQuery = { __typename?: 'Query', findManyMarketplaceApps: Array<{ __typename?: 'MarketplaceApp', id: string, name: string, description: string, icon: string, version: string, author: string, category: string, logo?: string | null, screenshots: Array, aboutDescription: string, providers: Array, websiteUrl?: string | null, termsUrl?: string | null, sourcePackage?: string | null, objects: Array<{ __typename?: 'MarketplaceAppObject', universalIdentifier: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, fields: Array<{ __typename?: 'MarketplaceAppField', universalIdentifier?: string | null, name: string, type: string, label: string, description?: string | null, icon?: string | null }> }>, fields: Array<{ __typename?: 'MarketplaceAppField', name: string, type: string, label: string, description?: string | null, icon?: string | null, objectUniversalIdentifier?: string | null }>, logicFunctions: Array<{ __typename?: 'MarketplaceAppLogicFunction', name: string, description?: string | null, timeoutSeconds?: number | null }>, frontComponents: Array<{ __typename?: 'MarketplaceAppFrontComponent', name: string, description?: string | null }>, defaultRole?: { __typename?: 'MarketplaceAppDefaultRole', id: string, label: string, description?: string | null, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean, canUpdateAllSettings: boolean, canAccessAllTools: boolean, permissionFlags: Array, objectPermissions: Array<{ __typename?: 'MarketplaceAppRoleObjectPermission', objectUniversalIdentifier: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null }>, fieldPermissions: Array<{ __typename?: 'MarketplaceAppRoleFieldPermission', objectUniversalIdentifier: string, fieldUniversalIdentifier: string, canReadFieldValue?: boolean | null, canUpdateFieldValue?: boolean | null }> } | null }> }; export type NavigationMenuItemFieldsFragment = { __typename?: 'NavigationMenuItem', id: string, userWorkspaceId?: string | null, targetRecordId?: string | null, targetObjectMetadataId?: string | null, viewId?: string | null, folderId?: string | null, name?: string | null, link?: string | null, icon?: string | null, color?: string | null, position: number, applicationId?: string | null, createdAt: string, updatedAt: string }; @@ -6464,7 +6544,7 @@ export type GetSystemHealthStatusQueryVariables = Exact<{ [key: string]: never; export type GetSystemHealthStatusQuery = { __typename?: 'Query', getSystemHealthStatus: { __typename?: 'SystemHealth', services: Array<{ __typename?: 'SystemHealthService', id: HealthIndicatorId, label: string, status: AdminPanelHealthServiceStatus }> } }; -export type ApplicationRegistrationFragmentFragment = { __typename?: 'ApplicationRegistration', id: string, universalIdentifier: string, name: string, description?: string | null, logoUrl?: string | null, author?: string | null, oAuthClientId: string, oAuthRedirectUris: Array, oAuthScopes: Array, websiteUrl?: string | null, termsUrl?: string | null, createdAt: string, updatedAt: string }; +export type ApplicationRegistrationFragmentFragment = { __typename?: 'ApplicationRegistration', id: string, universalIdentifier: string, name: string, description?: string | null, logoUrl?: string | null, author?: string | null, oAuthClientId: string, oAuthRedirectUris: Array, oAuthScopes: Array, sourceType: AppRegistrationSourceType, sourcePackage?: string | null, latestAvailableVersion?: string | null, websiteUrl?: string | null, termsUrl?: string | null, createdAt: string, updatedAt: string }; export type DeleteApplicationRegistrationMutationVariables = Exact<{ id: Scalars['String']; @@ -6485,7 +6565,7 @@ export type UpdateApplicationRegistrationMutationVariables = Exact<{ }>; -export type UpdateApplicationRegistrationMutation = { __typename?: 'Mutation', updateApplicationRegistration: { __typename?: 'ApplicationRegistration', id: string, universalIdentifier: string, name: string, description?: string | null, logoUrl?: string | null, author?: string | null, oAuthClientId: string, oAuthRedirectUris: Array, oAuthScopes: Array, websiteUrl?: string | null, termsUrl?: string | null, createdAt: string, updatedAt: string } }; +export type UpdateApplicationRegistrationMutation = { __typename?: 'Mutation', updateApplicationRegistration: { __typename?: 'ApplicationRegistration', id: string, universalIdentifier: string, name: string, description?: string | null, logoUrl?: string | null, author?: string | null, oAuthClientId: string, oAuthRedirectUris: Array, oAuthScopes: Array, sourceType: AppRegistrationSourceType, sourcePackage?: string | null, latestAvailableVersion?: string | null, websiteUrl?: string | null, termsUrl?: string | null, createdAt: string, updatedAt: string } }; export type UpdateApplicationRegistrationVariableMutationVariables = Exact<{ input: UpdateApplicationRegistrationVariableInput; @@ -6518,14 +6598,14 @@ export type FindApplicationRegistrationVariablesQuery = { __typename?: 'Query', export type FindManyApplicationRegistrationsQueryVariables = Exact<{ [key: string]: never; }>; -export type FindManyApplicationRegistrationsQuery = { __typename?: 'Query', findManyApplicationRegistrations: Array<{ __typename?: 'ApplicationRegistration', id: string, universalIdentifier: string, name: string, description?: string | null, logoUrl?: string | null, author?: string | null, oAuthClientId: string, oAuthRedirectUris: Array, oAuthScopes: Array, websiteUrl?: string | null, termsUrl?: string | null, createdAt: string, updatedAt: string }> }; +export type FindManyApplicationRegistrationsQuery = { __typename?: 'Query', findManyApplicationRegistrations: Array<{ __typename?: 'ApplicationRegistration', id: string, universalIdentifier: string, name: string, description?: string | null, logoUrl?: string | null, author?: string | null, oAuthClientId: string, oAuthRedirectUris: Array, oAuthScopes: Array, sourceType: AppRegistrationSourceType, sourcePackage?: string | null, latestAvailableVersion?: string | null, websiteUrl?: string | null, termsUrl?: string | null, createdAt: string, updatedAt: string }> }; export type FindOneApplicationRegistrationQueryVariables = Exact<{ id: Scalars['String']; }>; -export type FindOneApplicationRegistrationQuery = { __typename?: 'Query', findOneApplicationRegistration: { __typename?: 'ApplicationRegistration', id: string, universalIdentifier: string, name: string, description?: string | null, logoUrl?: string | null, author?: string | null, oAuthClientId: string, oAuthRedirectUris: Array, oAuthScopes: Array, websiteUrl?: string | null, termsUrl?: string | null, createdAt: string, updatedAt: string } }; +export type FindOneApplicationRegistrationQuery = { __typename?: 'Query', findOneApplicationRegistration: { __typename?: 'ApplicationRegistration', id: string, universalIdentifier: string, name: string, description?: string | null, logoUrl?: string | null, author?: string | null, oAuthClientId: string, oAuthRedirectUris: Array, oAuthScopes: Array, sourceType: AppRegistrationSourceType, sourcePackage?: string | null, latestAvailableVersion?: string | null, websiteUrl?: string | null, termsUrl?: string | null, createdAt: string, updatedAt: string } }; export type UninstallApplicationMutationVariables = Exact<{ universalIdentifier: Scalars['String']; @@ -7422,6 +7502,12 @@ export const ApplicationFieldsFragmentDoc = gql` description version universalIdentifier + applicationRegistrationId + applicationRegistration { + id + latestAvailableVersion + sourceType + } canBeUninstalled defaultRoleId settingsCustomTabFrontComponentId @@ -7790,6 +7876,7 @@ export const MarketplaceAppFieldsFragmentDoc = gql` name description } + sourcePackage defaultRole { id label @@ -7856,6 +7943,9 @@ export const ApplicationRegistrationFragmentFragmentDoc = gql` oAuthClientId oAuthRedirectUris oAuthScopes + sourceType + sourcePackage + latestAvailableVersion websiteUrl termsUrl createdAt @@ -9283,6 +9373,12 @@ export const FindManyApplicationsDocument = gql` name description version + applicationRegistrationId + applicationRegistration { + id + latestAvailableVersion + sourceType + } } } `; @@ -11329,6 +11425,144 @@ export function useGetLogicFunctionSourceCodeLazyQuery(baseOptions?: Apollo.Lazy export type GetLogicFunctionSourceCodeQueryHookResult = ReturnType; export type GetLogicFunctionSourceCodeLazyQueryHookResult = ReturnType; export type GetLogicFunctionSourceCodeQueryResult = Apollo.QueryResult; +export const InstallMarketplaceAppDocument = gql` + mutation InstallMarketplaceApp($universalIdentifier: String!, $version: String) { + installMarketplaceApp( + universalIdentifier: $universalIdentifier + version: $version + ) +} + `; +export type InstallMarketplaceAppMutationFn = Apollo.MutationFunction; + +/** + * __useInstallMarketplaceAppMutation__ + * + * To run a mutation, you first call `useInstallMarketplaceAppMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useInstallMarketplaceAppMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [installMarketplaceAppMutation, { data, loading, error }] = useInstallMarketplaceAppMutation({ + * variables: { + * universalIdentifier: // value for 'universalIdentifier' + * version: // value for 'version' + * }, + * }); + */ +export function useInstallMarketplaceAppMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(InstallMarketplaceAppDocument, options); + } +export type InstallMarketplaceAppMutationHookResult = ReturnType; +export type InstallMarketplaceAppMutationResult = Apollo.MutationResult; +export type InstallMarketplaceAppMutationOptions = Apollo.BaseMutationOptions; +export const InstallNpmAppDocument = gql` + mutation InstallNpmApp($packageName: String!, $version: String) { + installNpmApp(packageName: $packageName, version: $version) +} + `; +export type InstallNpmAppMutationFn = Apollo.MutationFunction; + +/** + * __useInstallNpmAppMutation__ + * + * To run a mutation, you first call `useInstallNpmAppMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useInstallNpmAppMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [installNpmAppMutation, { data, loading, error }] = useInstallNpmAppMutation({ + * variables: { + * packageName: // value for 'packageName' + * version: // value for 'version' + * }, + * }); + */ +export function useInstallNpmAppMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(InstallNpmAppDocument, options); + } +export type InstallNpmAppMutationHookResult = ReturnType; +export type InstallNpmAppMutationResult = Apollo.MutationResult; +export type InstallNpmAppMutationOptions = Apollo.BaseMutationOptions; +export const UpgradeApplicationDocument = gql` + mutation UpgradeApplication($appRegistrationId: String!, $targetVersion: String!) { + upgradeApplication( + appRegistrationId: $appRegistrationId + targetVersion: $targetVersion + ) +} + `; +export type UpgradeApplicationMutationFn = Apollo.MutationFunction; + +/** + * __useUpgradeApplicationMutation__ + * + * To run a mutation, you first call `useUpgradeApplicationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpgradeApplicationMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [upgradeApplicationMutation, { data, loading, error }] = useUpgradeApplicationMutation({ + * variables: { + * appRegistrationId: // value for 'appRegistrationId' + * targetVersion: // value for 'targetVersion' + * }, + * }); + */ +export function useUpgradeApplicationMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UpgradeApplicationDocument, options); + } +export type UpgradeApplicationMutationHookResult = ReturnType; +export type UpgradeApplicationMutationResult = Apollo.MutationResult; +export type UpgradeApplicationMutationOptions = Apollo.BaseMutationOptions; +export const UploadAppTarballDocument = gql` + mutation UploadAppTarball($file: Upload!, $universalIdentifier: String) { + uploadAppTarball(file: $file, universalIdentifier: $universalIdentifier) { + id + universalIdentifier + name + } +} + `; +export type UploadAppTarballMutationFn = Apollo.MutationFunction; + +/** + * __useUploadAppTarballMutation__ + * + * To run a mutation, you first call `useUploadAppTarballMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUploadAppTarballMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [uploadAppTarballMutation, { data, loading, error }] = useUploadAppTarballMutation({ + * variables: { + * file: // value for 'file' + * universalIdentifier: // value for 'universalIdentifier' + * }, + * }); + */ +export function useUploadAppTarballMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UploadAppTarballDocument, options); + } +export type UploadAppTarballMutationHookResult = ReturnType; +export type UploadAppTarballMutationResult = Apollo.MutationResult; +export type UploadAppTarballMutationOptions = Apollo.BaseMutationOptions; export const FindManyMarketplaceAppsDocument = gql` query FindManyMarketplaceApps { findManyMarketplaceApps { diff --git a/packages/twenty-front/src/modules/applications/graphql/fragments/applicationFragment.ts b/packages/twenty-front/src/modules/applications/graphql/fragments/applicationFragment.ts index 882e253fb4b..126e174c6ec 100644 --- a/packages/twenty-front/src/modules/applications/graphql/fragments/applicationFragment.ts +++ b/packages/twenty-front/src/modules/applications/graphql/fragments/applicationFragment.ts @@ -13,6 +13,12 @@ export const APPLICATION_FRAGMENT = gql` description version universalIdentifier + applicationRegistrationId + applicationRegistration { + id + latestAvailableVersion + sourceType + } canBeUninstalled defaultRoleId settingsCustomTabFrontComponentId diff --git a/packages/twenty-front/src/modules/applications/graphql/queries/findManyApplications.ts b/packages/twenty-front/src/modules/applications/graphql/queries/findManyApplications.ts index ceb1ba708fd..5144c9c928b 100644 --- a/packages/twenty-front/src/modules/applications/graphql/queries/findManyApplications.ts +++ b/packages/twenty-front/src/modules/applications/graphql/queries/findManyApplications.ts @@ -7,6 +7,12 @@ export const FIND_MANY_APPLICATIONS = gql` name description version + applicationRegistrationId + applicationRegistration { + id + latestAvailableVersion + sourceType + } } } `; diff --git a/packages/twenty-front/src/modules/marketplace/graphql/fragments/marketplaceAppFragment.ts b/packages/twenty-front/src/modules/marketplace/graphql/fragments/marketplaceAppFragment.ts index d4e6f625389..6ebbe4afdb1 100644 --- a/packages/twenty-front/src/modules/marketplace/graphql/fragments/marketplaceAppFragment.ts +++ b/packages/twenty-front/src/modules/marketplace/graphql/fragments/marketplaceAppFragment.ts @@ -49,6 +49,7 @@ export const MARKETPLACE_APP_FRAGMENT = gql` name description } + sourcePackage defaultRole { id label diff --git a/packages/twenty-front/src/modules/marketplace/graphql/mutations/installMarketplaceApp.ts b/packages/twenty-front/src/modules/marketplace/graphql/mutations/installMarketplaceApp.ts index 223be5ab51d..aba1aaf25bc 100644 --- a/packages/twenty-front/src/modules/marketplace/graphql/mutations/installMarketplaceApp.ts +++ b/packages/twenty-front/src/modules/marketplace/graphql/mutations/installMarketplaceApp.ts @@ -1,7 +1,13 @@ import gql from 'graphql-tag'; export const INSTALL_MARKETPLACE_APP = gql` - mutation InstallMarketplaceApp() { - installMarketplaceApp() + mutation InstallMarketplaceApp( + $universalIdentifier: String! + $version: String + ) { + installMarketplaceApp( + universalIdentifier: $universalIdentifier + version: $version + ) } `; diff --git a/packages/twenty-front/src/modules/marketplace/graphql/mutations/installNpmApp.ts b/packages/twenty-front/src/modules/marketplace/graphql/mutations/installNpmApp.ts new file mode 100644 index 00000000000..575a7dea763 --- /dev/null +++ b/packages/twenty-front/src/modules/marketplace/graphql/mutations/installNpmApp.ts @@ -0,0 +1,7 @@ +import gql from 'graphql-tag'; + +export const INSTALL_NPM_APP = gql` + mutation InstallNpmApp($packageName: String!, $version: String) { + installNpmApp(packageName: $packageName, version: $version) + } +`; diff --git a/packages/twenty-front/src/modules/marketplace/graphql/mutations/upgradeApplication.ts b/packages/twenty-front/src/modules/marketplace/graphql/mutations/upgradeApplication.ts new file mode 100644 index 00000000000..fd2eb6d883b --- /dev/null +++ b/packages/twenty-front/src/modules/marketplace/graphql/mutations/upgradeApplication.ts @@ -0,0 +1,13 @@ +import gql from 'graphql-tag'; + +export const UPGRADE_APPLICATION = gql` + mutation UpgradeApplication( + $appRegistrationId: String! + $targetVersion: String! + ) { + upgradeApplication( + appRegistrationId: $appRegistrationId + targetVersion: $targetVersion + ) + } +`; diff --git a/packages/twenty-front/src/modules/marketplace/graphql/mutations/uploadAppTarball.ts b/packages/twenty-front/src/modules/marketplace/graphql/mutations/uploadAppTarball.ts new file mode 100644 index 00000000000..05d3911683a --- /dev/null +++ b/packages/twenty-front/src/modules/marketplace/graphql/mutations/uploadAppTarball.ts @@ -0,0 +1,11 @@ +import { gql } from '@apollo/client'; + +export const UPLOAD_APP_TARBALL = gql` + mutation UploadAppTarball($file: Upload!, $universalIdentifier: String) { + uploadAppTarball(file: $file, universalIdentifier: $universalIdentifier) { + id + universalIdentifier + name + } + } +`; diff --git a/packages/twenty-front/src/modules/marketplace/hooks/useInstallApp.ts b/packages/twenty-front/src/modules/marketplace/hooks/useInstallApp.ts new file mode 100644 index 00000000000..31570c632fd --- /dev/null +++ b/packages/twenty-front/src/modules/marketplace/hooks/useInstallApp.ts @@ -0,0 +1,41 @@ +import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; +import { t } from '@lingui/core/macro'; +import { useState } from 'react'; +import { isDefined } from 'twenty-shared/utils'; + +export const useInstallApp = >( + mutationFn: (options: { + variables: TVariables; + }) => Promise<{ data?: Record | null }>, +) => { + const { enqueueErrorSnackBar, enqueueSuccessSnackBar } = useSnackBar(); + const [isInstalling, setIsInstalling] = useState(false); + + const install = async (variables: TVariables) => { + setIsInstalling(true); + + try { + const result = await mutationFn({ variables }); + + if (isDefined(result.data)) { + enqueueSuccessSnackBar({ + message: t`Application installed successfully.`, + }); + + return true; + } + + return false; + } catch { + enqueueErrorSnackBar({ + message: t`Failed to install the application.`, + }); + + return false; + } finally { + setIsInstalling(false); + } + }; + + return { install, isInstalling }; +}; diff --git a/packages/twenty-front/src/modules/marketplace/hooks/useInstallMarketplaceApp.ts b/packages/twenty-front/src/modules/marketplace/hooks/useInstallMarketplaceApp.ts index c629422f20a..a69c63c05b3 100644 --- a/packages/twenty-front/src/modules/marketplace/hooks/useInstallMarketplaceApp.ts +++ b/packages/twenty-front/src/modules/marketplace/hooks/useInstallMarketplaceApp.ts @@ -1,9 +1,11 @@ -export const useInstallMarketplaceApp = () => { - const install = async () => { - return true; - }; +import { useInstallApp } from '~/modules/marketplace/hooks/useInstallApp'; +import { useInstallMarketplaceAppMutation } from '~/generated-metadata/graphql'; - return { - install, - }; +export const useInstallMarketplaceApp = () => { + const [installMarketplaceAppMutation] = useInstallMarketplaceAppMutation(); + + return useInstallApp<{ + universalIdentifier: string; + version?: string; + }>(installMarketplaceAppMutation); }; diff --git a/packages/twenty-front/src/modules/marketplace/hooks/useInstallNpmApp.ts b/packages/twenty-front/src/modules/marketplace/hooks/useInstallNpmApp.ts new file mode 100644 index 00000000000..9168b8a596f --- /dev/null +++ b/packages/twenty-front/src/modules/marketplace/hooks/useInstallNpmApp.ts @@ -0,0 +1,13 @@ +import { useMutation } from '@apollo/client'; + +import { useInstallApp } from '~/modules/marketplace/hooks/useInstallApp'; +import { INSTALL_NPM_APP } from '~/modules/marketplace/graphql/mutations/installNpmApp'; + +export const useInstallNpmApp = () => { + const [installNpmAppMutation] = useMutation(INSTALL_NPM_APP); + + return useInstallApp<{ + packageName: string; + version?: string; + }>(installNpmAppMutation); +}; diff --git a/packages/twenty-front/src/pages/settings/applications/hooks/useMarketplaceApps.ts b/packages/twenty-front/src/modules/marketplace/hooks/useMarketplaceApps.ts similarity index 100% rename from packages/twenty-front/src/pages/settings/applications/hooks/useMarketplaceApps.ts rename to packages/twenty-front/src/modules/marketplace/hooks/useMarketplaceApps.ts diff --git a/packages/twenty-front/src/modules/marketplace/hooks/useUpgradeApplication.ts b/packages/twenty-front/src/modules/marketplace/hooks/useUpgradeApplication.ts new file mode 100644 index 00000000000..af1ff1e9027 --- /dev/null +++ b/packages/twenty-front/src/modules/marketplace/hooks/useUpgradeApplication.ts @@ -0,0 +1,44 @@ +import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; +import { t } from '@lingui/core/macro'; +import { useState } from 'react'; +import { isDefined } from 'twenty-shared/utils'; +import { useUpgradeApplicationMutation } from '~/generated-metadata/graphql'; + +export const useUpgradeApplication = () => { + const { enqueueErrorSnackBar, enqueueSuccessSnackBar } = useSnackBar(); + const [upgradeApplicationMutation] = useUpgradeApplicationMutation(); + const [isUpgrading, setIsUpgrading] = useState(false); + + const upgrade = async (params: { + appRegistrationId: string; + targetVersion: string; + }) => { + setIsUpgrading(true); + + try { + const result = await upgradeApplicationMutation({ + variables: params, + }); + + if (isDefined(result.data)) { + enqueueSuccessSnackBar({ + message: t`Application upgraded successfully.`, + }); + + return true; + } + + return false; + } catch { + enqueueErrorSnackBar({ + message: t`Failed to upgrade the application.`, + }); + + return false; + } finally { + setIsUpgrading(false); + } + }; + + return { upgrade, isUpgrading }; +}; diff --git a/packages/twenty-front/src/modules/marketplace/hooks/useUploadAppTarball.ts b/packages/twenty-front/src/modules/marketplace/hooks/useUploadAppTarball.ts new file mode 100644 index 00000000000..dc96f5713d5 --- /dev/null +++ b/packages/twenty-front/src/modules/marketplace/hooks/useUploadAppTarball.ts @@ -0,0 +1,54 @@ +import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; +import { useMutation } from '@apollo/client'; +import { t } from '@lingui/core/macro'; +import { useState } from 'react'; +import { isDefined } from 'twenty-shared/utils'; +import { UPLOAD_APP_TARBALL } from '~/modules/marketplace/graphql/mutations/uploadAppTarball'; + +type UploadResult = + | { + success: true; + universalIdentifier: string; + } + | { + success: false; + }; + +export const useUploadAppTarball = () => { + const [uploadAppTarball] = useMutation(UPLOAD_APP_TARBALL); + const { enqueueErrorSnackBar } = useSnackBar(); + const [isUploading, setIsUploading] = useState(false); + + const upload = async (file: File): Promise => { + setIsUploading(true); + + try { + const result = await uploadAppTarball({ + variables: { file }, + }); + + const registration = result.data?.uploadAppTarball; + + if (!isDefined(registration?.universalIdentifier)) { + enqueueErrorSnackBar({ message: t`Upload failed.` }); + + return { success: false }; + } + + return { + success: true, + universalIdentifier: registration.universalIdentifier, + }; + } catch { + enqueueErrorSnackBar({ + message: t`Failed to upload tarball.`, + }); + + return { success: false }; + } finally { + setIsUploading(false); + } + }; + + return { upload, isUploading }; +}; diff --git a/packages/twenty-front/src/modules/settings/application-registrations/graphql/fragments/applicationRegistrationFragment.ts b/packages/twenty-front/src/modules/settings/application-registrations/graphql/fragments/applicationRegistrationFragment.ts index e9756655e61..f129e72cecb 100644 --- a/packages/twenty-front/src/modules/settings/application-registrations/graphql/fragments/applicationRegistrationFragment.ts +++ b/packages/twenty-front/src/modules/settings/application-registrations/graphql/fragments/applicationRegistrationFragment.ts @@ -11,6 +11,9 @@ export const APPLICATION_REGISTRATION_FRAGMENT = gql` oAuthClientId oAuthRedirectUris oAuthScopes + sourceType + sourcePackage + latestAvailableVersion websiteUrl termsUrl createdAt diff --git a/packages/twenty-front/src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx b/packages/twenty-front/src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx index 038c0d9f89a..96fb23b0d16 100644 --- a/packages/twenty-front/src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx +++ b/packages/twenty-front/src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx @@ -28,7 +28,7 @@ import { Button } from 'twenty-ui/input'; import { Section } from 'twenty-ui/layout'; import { themeCssVariables } from 'twenty-ui/theme-constants'; import { PermissionFlagType } from '~/generated-metadata/graphql'; -import { useMarketplaceApps } from '~/pages/settings/applications/hooks/useMarketplaceApps'; +import { useMarketplaceApps } from '~/modules/marketplace/hooks/useMarketplaceApps'; import { SettingsApplicationPermissionsTab } from '~/pages/settings/applications/tabs/SettingsApplicationPermissionsTab'; import { SettingsAvailableApplicationDetailContentTab } from '~/pages/settings/applications/tabs/SettingsAvailableApplicationDetailContentTab'; @@ -248,7 +248,7 @@ export const SettingsAvailableApplicationDetails = () => { const [selectedScreenshotIndex, setSelectedScreenshotIndex] = useState(0); const { data: marketplaceApps } = useMarketplaceApps(); - const { install } = useInstallMarketplaceApp(); + const { install, isInstalling } = useInstallMarketplaceApp(); const canInstallMarketplaceApps = useHasPermissionFlag( PermissionFlagType.MARKETPLACE_APPS, ); @@ -259,7 +259,9 @@ export const SettingsAvailableApplicationDetails = () => { const handleInstall = async () => { if (isDefined(application)) { - await install(); + await install({ + universalIdentifier: application.id, + }); } }; @@ -460,10 +462,11 @@ export const SettingsAvailableApplicationDetails = () => { {canInstallMarketplaceApps && (