Add auto-upgrade-in-apps (#23001)
We need to auto upgrade application, lets add this column in application entity, and add an admin button to autoupgrade all applications to latest app registrration version manually <img width="1131" height="372" alt="image" src="https://github.com/user-attachments/assets/4e755abc-38ad-4895-a2e8-d55ee1948ac2" /> <img width="906" height="533" alt="image" src="https://github.com/user-attachments/assets/ce002057-0341-4581-bf9a-66ac2bd84a9b" />
This commit is contained in:
@@ -660,6 +660,7 @@ type Application {
|
||||
availablePackages: JSON!
|
||||
applicationRegistrationId: UUID
|
||||
canBeUninstalled: Boolean!
|
||||
autoUpgrade: Boolean!
|
||||
defaultRoleId: String
|
||||
settingsCustomTabFrontComponentId: UUID @deprecated(reason: "Custom settings tabs are no longer supported. This field is ignored.")
|
||||
defaultLogicFunctionRole: Role
|
||||
@@ -3376,6 +3377,7 @@ type Mutation {
|
||||
destroyViewGroup(input: DestroyViewGroupInput!): ViewGroup!
|
||||
installMarketplaceApp(universalIdentifier: String!, version: String): Boolean! @deprecated(reason: "Use installApplication instead")
|
||||
installApplication(universalIdentifier: String!, version: String): Application!
|
||||
updateApplication(id: UUID!, input: UpdateApplicationInput!): Application!
|
||||
uninstallApplication(universalIdentifier: String!): Boolean!
|
||||
syncMarketplaceCatalog: Boolean!
|
||||
createApplicationRegistration(input: CreateApplicationRegistrationInput!): CreateApplicationRegistration!
|
||||
@@ -4277,6 +4279,10 @@ input DestroyViewGroupInput {
|
||||
id: UUID!
|
||||
}
|
||||
|
||||
input UpdateApplicationInput {
|
||||
autoUpgrade: Boolean
|
||||
}
|
||||
|
||||
input CreateApplicationRegistrationInput {
|
||||
name: String!
|
||||
universalIdentifier: String
|
||||
|
||||
@@ -449,6 +449,7 @@ export interface Application {
|
||||
availablePackages: Scalars['JSON']
|
||||
applicationRegistrationId?: Scalars['UUID']
|
||||
canBeUninstalled: Scalars['Boolean']
|
||||
autoUpgrade: Scalars['Boolean']
|
||||
defaultRoleId?: Scalars['String']
|
||||
/** @deprecated Custom settings tabs are no longer supported. This field is ignored. */
|
||||
settingsCustomTabFrontComponentId?: Scalars['UUID']
|
||||
@@ -2924,6 +2925,7 @@ export interface Mutation {
|
||||
/** @deprecated Use installApplication instead */
|
||||
installMarketplaceApp: Scalars['Boolean']
|
||||
installApplication: Application
|
||||
updateApplication: Application
|
||||
uninstallApplication: Scalars['Boolean']
|
||||
syncMarketplaceCatalog: Scalars['Boolean']
|
||||
createApplicationRegistration: CreateApplicationRegistration
|
||||
@@ -3514,6 +3516,7 @@ export interface ApplicationGenqlSelection{
|
||||
availablePackages?: boolean | number
|
||||
applicationRegistrationId?: boolean | number
|
||||
canBeUninstalled?: boolean | number
|
||||
autoUpgrade?: boolean | number
|
||||
defaultRoleId?: boolean | number
|
||||
/** @deprecated Custom settings tabs are no longer supported. This field is ignored. */
|
||||
settingsCustomTabFrontComponentId?: boolean | number
|
||||
@@ -6139,6 +6142,7 @@ export interface MutationGenqlSelection{
|
||||
/** @deprecated Use installApplication instead */
|
||||
installMarketplaceApp?: { __args: {universalIdentifier: Scalars['String'], version?: (Scalars['String'] | null)} }
|
||||
installApplication?: (ApplicationGenqlSelection & { __args: {universalIdentifier: Scalars['String'], version?: (Scalars['String'] | null)} })
|
||||
updateApplication?: (ApplicationGenqlSelection & { __args: {id: Scalars['UUID'], input: UpdateApplicationInput} })
|
||||
uninstallApplication?: { __args: {universalIdentifier: Scalars['String']} }
|
||||
syncMarketplaceCatalog?: boolean | number
|
||||
createApplicationRegistration?: (CreateApplicationRegistrationGenqlSelection & { __args: {input: CreateApplicationRegistrationInput} })
|
||||
@@ -6520,6 +6524,8 @@ export interface DestroyViewGroupInput {
|
||||
/** The id of the view group to destroy. */
|
||||
id: Scalars['UUID']}
|
||||
|
||||
export interface UpdateApplicationInput {autoUpgrade?: (Scalars['Boolean'] | null)}
|
||||
|
||||
export interface CreateApplicationRegistrationInput {name: Scalars['String'],universalIdentifier?: (Scalars['String'] | null),oAuthRedirectUris?: (Scalars['String'][] | null),oAuthScopes?: (Scalars['String'][] | null)}
|
||||
|
||||
export interface UpdateApplicationRegistrationInput {id: Scalars['String'],update: UpdateApplicationRegistrationPayload}
|
||||
|
||||
@@ -82,7 +82,7 @@ export default {
|
||||
351,
|
||||
358,
|
||||
359,
|
||||
485
|
||||
486
|
||||
],
|
||||
"types": {
|
||||
"BillingProductDTO": {
|
||||
@@ -1277,6 +1277,9 @@ export default {
|
||||
"canBeUninstalled": [
|
||||
6
|
||||
],
|
||||
"autoUpgrade": [
|
||||
6
|
||||
],
|
||||
"defaultRoleId": [
|
||||
1
|
||||
],
|
||||
@@ -8099,6 +8102,19 @@ export default {
|
||||
]
|
||||
}
|
||||
],
|
||||
"updateApplication": [
|
||||
54,
|
||||
{
|
||||
"id": [
|
||||
3,
|
||||
"UUID!"
|
||||
],
|
||||
"input": [
|
||||
440,
|
||||
"UpdateApplicationInput!"
|
||||
]
|
||||
}
|
||||
],
|
||||
"uninstallApplication": [
|
||||
6,
|
||||
{
|
||||
@@ -8115,7 +8131,7 @@ export default {
|
||||
196,
|
||||
{
|
||||
"input": [
|
||||
440,
|
||||
441,
|
||||
"CreateApplicationRegistrationInput!"
|
||||
]
|
||||
}
|
||||
@@ -8124,7 +8140,7 @@ export default {
|
||||
8,
|
||||
{
|
||||
"input": [
|
||||
441,
|
||||
442,
|
||||
"UpdateApplicationRegistrationInput!"
|
||||
]
|
||||
}
|
||||
@@ -8151,7 +8167,7 @@ export default {
|
||||
5,
|
||||
{
|
||||
"input": [
|
||||
443,
|
||||
444,
|
||||
"CreateApplicationRegistrationVariableInput!"
|
||||
]
|
||||
}
|
||||
@@ -8160,7 +8176,7 @@ export default {
|
||||
5,
|
||||
{
|
||||
"input": [
|
||||
444,
|
||||
445,
|
||||
"UpdateApplicationRegistrationVariableInput!"
|
||||
]
|
||||
}
|
||||
@@ -8225,7 +8241,7 @@ export default {
|
||||
29,
|
||||
{
|
||||
"createRoleInput": [
|
||||
446,
|
||||
447,
|
||||
"CreateRoleInput!"
|
||||
]
|
||||
}
|
||||
@@ -8234,7 +8250,7 @@ export default {
|
||||
29,
|
||||
{
|
||||
"updateRoleInput": [
|
||||
447,
|
||||
448,
|
||||
"UpdateRoleInput!"
|
||||
]
|
||||
}
|
||||
@@ -8252,7 +8268,7 @@ export default {
|
||||
16,
|
||||
{
|
||||
"upsertObjectPermissionsInput": [
|
||||
449,
|
||||
450,
|
||||
"UpsertObjectPermissionsInput!"
|
||||
]
|
||||
}
|
||||
@@ -8261,7 +8277,7 @@ export default {
|
||||
27,
|
||||
{
|
||||
"upsertPermissionFlagsInput": [
|
||||
451,
|
||||
452,
|
||||
"UpsertPermissionFlagsInput!"
|
||||
]
|
||||
}
|
||||
@@ -8270,7 +8286,7 @@ export default {
|
||||
26,
|
||||
{
|
||||
"upsertFieldPermissionsInput": [
|
||||
452,
|
||||
453,
|
||||
"UpsertFieldPermissionsInput!"
|
||||
]
|
||||
}
|
||||
@@ -8279,7 +8295,7 @@ export default {
|
||||
233,
|
||||
{
|
||||
"input": [
|
||||
454,
|
||||
455,
|
||||
"UpsertRowLevelPermissionPredicatesInput!"
|
||||
]
|
||||
}
|
||||
@@ -8310,7 +8326,7 @@ export default {
|
||||
281,
|
||||
{
|
||||
"input": [
|
||||
457,
|
||||
458,
|
||||
"SendEmailViaDomainInput!"
|
||||
]
|
||||
}
|
||||
@@ -8319,7 +8335,7 @@ export default {
|
||||
283,
|
||||
{
|
||||
"input": [
|
||||
458,
|
||||
459,
|
||||
"SendMessageCampaignInput!"
|
||||
]
|
||||
}
|
||||
@@ -8328,7 +8344,7 @@ export default {
|
||||
284,
|
||||
{
|
||||
"input": [
|
||||
459,
|
||||
460,
|
||||
"CreateUnsubscribeTopicInput!"
|
||||
]
|
||||
}
|
||||
@@ -8337,7 +8353,7 @@ export default {
|
||||
284,
|
||||
{
|
||||
"input": [
|
||||
460,
|
||||
461,
|
||||
"UpdateUnsubscribeTopicInput!"
|
||||
]
|
||||
}
|
||||
@@ -8355,7 +8371,7 @@ export default {
|
||||
271,
|
||||
{
|
||||
"input": [
|
||||
461,
|
||||
462,
|
||||
"UpdateMessageChannelInput!"
|
||||
]
|
||||
}
|
||||
@@ -8364,7 +8380,7 @@ export default {
|
||||
279,
|
||||
{
|
||||
"input": [
|
||||
463,
|
||||
464,
|
||||
"CreateEmailGroupChannelInput!"
|
||||
]
|
||||
}
|
||||
@@ -8382,7 +8398,7 @@ export default {
|
||||
269,
|
||||
{
|
||||
"input": [
|
||||
464,
|
||||
465,
|
||||
"CreateEmailingDomainInput!"
|
||||
]
|
||||
}
|
||||
@@ -8418,7 +8434,7 @@ export default {
|
||||
296,
|
||||
{
|
||||
"input": [
|
||||
465,
|
||||
466,
|
||||
"RunAgentInput!"
|
||||
]
|
||||
}
|
||||
@@ -8427,7 +8443,7 @@ export default {
|
||||
293,
|
||||
{
|
||||
"input": [
|
||||
466,
|
||||
467,
|
||||
"CreateWebhookInput!"
|
||||
]
|
||||
}
|
||||
@@ -8436,7 +8452,7 @@ export default {
|
||||
293,
|
||||
{
|
||||
"input": [
|
||||
467,
|
||||
468,
|
||||
"UpdateWebhookInput!"
|
||||
]
|
||||
}
|
||||
@@ -8454,7 +8470,7 @@ export default {
|
||||
329,
|
||||
{
|
||||
"input": [
|
||||
469,
|
||||
470,
|
||||
"UpdateMessageFolderInput!"
|
||||
]
|
||||
}
|
||||
@@ -8463,7 +8479,7 @@ export default {
|
||||
329,
|
||||
{
|
||||
"input": [
|
||||
471,
|
||||
472,
|
||||
"UpdateMessageFoldersInput!"
|
||||
]
|
||||
}
|
||||
@@ -8472,7 +8488,7 @@ export default {
|
||||
324,
|
||||
{
|
||||
"input": [
|
||||
472,
|
||||
473,
|
||||
"UpdateCalendarChannelInput!"
|
||||
]
|
||||
}
|
||||
@@ -8502,7 +8518,7 @@ export default {
|
||||
1
|
||||
],
|
||||
"fileAttachments": [
|
||||
474,
|
||||
475,
|
||||
"[FileAttachmentInput!]"
|
||||
]
|
||||
}
|
||||
@@ -8531,7 +8547,7 @@ export default {
|
||||
"UUID!"
|
||||
],
|
||||
"answers": [
|
||||
475,
|
||||
476,
|
||||
"[AgentChatQuestionAnswerInput!]!"
|
||||
],
|
||||
"modelId": [
|
||||
@@ -8601,7 +8617,7 @@ export default {
|
||||
312,
|
||||
{
|
||||
"input": [
|
||||
476,
|
||||
477,
|
||||
"CreateSkillInput!"
|
||||
]
|
||||
}
|
||||
@@ -8610,7 +8626,7 @@ export default {
|
||||
312,
|
||||
{
|
||||
"input": [
|
||||
477,
|
||||
478,
|
||||
"UpdateSkillInput!"
|
||||
]
|
||||
}
|
||||
@@ -8668,7 +8684,7 @@ export default {
|
||||
246,
|
||||
{
|
||||
"input": [
|
||||
478,
|
||||
479,
|
||||
"GetAuthorizationUrlForSSOInput!"
|
||||
]
|
||||
}
|
||||
@@ -8834,7 +8850,7 @@ export default {
|
||||
249,
|
||||
{
|
||||
"input": [
|
||||
479
|
||||
480
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -8989,7 +9005,7 @@ export default {
|
||||
6,
|
||||
{
|
||||
"input": [
|
||||
480,
|
||||
481,
|
||||
"UpdateWorkspaceMemberSettingsInput!"
|
||||
]
|
||||
}
|
||||
@@ -9023,7 +9039,7 @@ export default {
|
||||
219,
|
||||
{
|
||||
"input": [
|
||||
481,
|
||||
482,
|
||||
"SetupOIDCSsoInput!"
|
||||
]
|
||||
}
|
||||
@@ -9032,7 +9048,7 @@ export default {
|
||||
219,
|
||||
{
|
||||
"input": [
|
||||
482,
|
||||
483,
|
||||
"SetupSAMLSsoInput!"
|
||||
]
|
||||
}
|
||||
@@ -9041,7 +9057,7 @@ export default {
|
||||
215,
|
||||
{
|
||||
"input": [
|
||||
483,
|
||||
484,
|
||||
"DeleteSsoInput!"
|
||||
]
|
||||
}
|
||||
@@ -9050,7 +9066,7 @@ export default {
|
||||
216,
|
||||
{
|
||||
"input": [
|
||||
484,
|
||||
485,
|
||||
"EditSsoInput!"
|
||||
]
|
||||
}
|
||||
@@ -9079,7 +9095,7 @@ export default {
|
||||
308,
|
||||
{
|
||||
"type": [
|
||||
485,
|
||||
486,
|
||||
"AnalyticsType!"
|
||||
],
|
||||
"name": [
|
||||
@@ -9119,7 +9135,7 @@ export default {
|
||||
298,
|
||||
{
|
||||
"input": [
|
||||
486,
|
||||
487,
|
||||
"CreateCalendarEventInput!"
|
||||
]
|
||||
}
|
||||
@@ -9128,7 +9144,7 @@ export default {
|
||||
307,
|
||||
{
|
||||
"input": [
|
||||
487,
|
||||
488,
|
||||
"SendEmailInput!"
|
||||
]
|
||||
}
|
||||
@@ -9150,7 +9166,7 @@ export default {
|
||||
"String!"
|
||||
],
|
||||
"connectionParameters": [
|
||||
489,
|
||||
490,
|
||||
"EmailAccountConnectionParameters!"
|
||||
],
|
||||
"id": [
|
||||
@@ -9162,7 +9178,7 @@ export default {
|
||||
167,
|
||||
{
|
||||
"input": [
|
||||
491,
|
||||
492,
|
||||
"UpdateLabPublicFeatureFlagInput!"
|
||||
]
|
||||
}
|
||||
@@ -11023,6 +11039,14 @@ export default {
|
||||
1
|
||||
]
|
||||
},
|
||||
"UpdateApplicationInput": {
|
||||
"autoUpgrade": [
|
||||
6
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
]
|
||||
},
|
||||
"CreateApplicationRegistrationInput": {
|
||||
"name": [
|
||||
1
|
||||
@@ -11045,7 +11069,7 @@ export default {
|
||||
1
|
||||
],
|
||||
"update": [
|
||||
442
|
||||
443
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
@@ -11099,7 +11123,7 @@ export default {
|
||||
1
|
||||
],
|
||||
"update": [
|
||||
445
|
||||
446
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
@@ -11165,7 +11189,7 @@ export default {
|
||||
},
|
||||
"UpdateRoleInput": {
|
||||
"update": [
|
||||
448
|
||||
449
|
||||
],
|
||||
"id": [
|
||||
3
|
||||
@@ -11220,7 +11244,7 @@ export default {
|
||||
3
|
||||
],
|
||||
"objectPermissions": [
|
||||
450
|
||||
451
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
@@ -11262,7 +11286,7 @@ export default {
|
||||
3
|
||||
],
|
||||
"fieldPermissions": [
|
||||
453
|
||||
454
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
@@ -11293,10 +11317,10 @@ export default {
|
||||
3
|
||||
],
|
||||
"predicates": [
|
||||
455
|
||||
456
|
||||
],
|
||||
"predicateGroups": [
|
||||
456
|
||||
457
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
@@ -11442,7 +11466,7 @@ export default {
|
||||
3
|
||||
],
|
||||
"update": [
|
||||
462
|
||||
463
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
@@ -11526,7 +11550,7 @@ export default {
|
||||
3
|
||||
],
|
||||
"update": [
|
||||
468
|
||||
469
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
@@ -11554,7 +11578,7 @@ export default {
|
||||
3
|
||||
],
|
||||
"update": [
|
||||
470
|
||||
471
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
@@ -11573,7 +11597,7 @@ export default {
|
||||
3
|
||||
],
|
||||
"update": [
|
||||
470
|
||||
471
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
@@ -11584,7 +11608,7 @@ export default {
|
||||
3
|
||||
],
|
||||
"update": [
|
||||
473
|
||||
474
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
@@ -11838,7 +11862,7 @@ export default {
|
||||
1
|
||||
],
|
||||
"files": [
|
||||
488
|
||||
489
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
@@ -11860,13 +11884,13 @@ export default {
|
||||
1
|
||||
],
|
||||
"IMAP": [
|
||||
490
|
||||
491
|
||||
],
|
||||
"SMTP": [
|
||||
490
|
||||
491
|
||||
],
|
||||
"CALDAV": [
|
||||
490
|
||||
491
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
@@ -11917,7 +11941,7 @@ export default {
|
||||
234,
|
||||
{
|
||||
"input": [
|
||||
493,
|
||||
494,
|
||||
"LogicFunctionLogsInput!"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ To release an update:
|
||||
|
||||
1. Bump the `version` field in your `package.json` (e.g. `1.2.3` → `1.2.4`, `1.3.0`, or `2.0.0`)
|
||||
2. Run `yarn twenty app:publish --private` (or `yarn twenty app:publish --private --remote production`)
|
||||
3. Workspaces that have the app installed will see the upgrade available in their settings
|
||||
3. Workspaces that have the app installed and enabled auto-upgrade for it (in the app's Settings tab) are upgraded automatically in the background; the others will see the upgrade available in their settings
|
||||
|
||||
<Note>
|
||||
Pre-release tags work as expected: bumping `1.0.0-rc.1` → `1.0.0-rc.2` is allowed, and a final release like `1.0.0` is correctly recognized as higher than `1.0.0-rc.5`. The version in `package.json` must itself be a valid semver string.
|
||||
|
||||
@@ -453,6 +453,7 @@ export type Mutation = {
|
||||
updateDatabaseConfigVariable: Scalars['Boolean']['output'];
|
||||
updateServerAdminAccess: ServerAdmin;
|
||||
updateWorkspaceFeatureFlag: Scalars['Boolean']['output'];
|
||||
upgradeRegistrationApplications: Scalars['Boolean']['output'];
|
||||
};
|
||||
|
||||
|
||||
@@ -579,6 +580,11 @@ export type MutationUpdateWorkspaceFeatureFlagArgs = {
|
||||
workspaceId: Scalars['UUID']['input'];
|
||||
};
|
||||
|
||||
|
||||
export type MutationUpgradeRegistrationApplicationsArgs = {
|
||||
applicationRegistrationId: Scalars['String']['input'];
|
||||
};
|
||||
|
||||
export type PaginatedApplicationRegistrations = {
|
||||
__typename?: 'PaginatedApplicationRegistrations';
|
||||
hasMore: Scalars['Boolean']['output'];
|
||||
@@ -1094,6 +1100,13 @@ export type UpdateAdminApplicationRegistrationVariableMutationVariables = Exact<
|
||||
|
||||
export type UpdateAdminApplicationRegistrationVariableMutation = { __typename?: 'Mutation', updateAdminApplicationRegistrationVariable: { __typename?: 'ApplicationRegistrationVariableDTO', id: string, key: string, description: string, isSecret: boolean, isRequired: boolean, isFilled: boolean, createdAt: string, updatedAt: string } };
|
||||
|
||||
export type UpgradeRegistrationApplicationsMutationVariables = Exact<{
|
||||
applicationRegistrationId: Scalars['String']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type UpgradeRegistrationApplicationsMutation = { __typename?: 'Mutation', upgradeRegistrationApplications: boolean };
|
||||
|
||||
export type FindAdminApplicationRegistrationInstalledWorkspacesQueryVariables = Exact<{
|
||||
input: FindApplicationRegistrationInstalledWorkspacesInput;
|
||||
}>;
|
||||
@@ -1363,6 +1376,7 @@ export const BackfillApplicationInstallationDocument = {"kind":"Document","defin
|
||||
export const SyncMarketplaceCatalogDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SyncMarketplaceCatalog"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"syncMarketplaceCatalog"}}]}}]} as unknown as DocumentNode<SyncMarketplaceCatalogMutation, SyncMarketplaceCatalogMutationVariables>;
|
||||
export const UpdateAdminApplicationRegistrationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateAdminApplicationRegistration"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateApplicationRegistrationInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateAdminApplicationRegistration"},"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":"ApplicationRegistrationFragment"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ApplicationRegistrationFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ApplicationRegistration"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"universalIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"logoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"galleryImagesUrls"}},{"kind":"Field","name":{"kind":"Name","value":"oAuthClientId"}},{"kind":"Field","name":{"kind":"Name","value":"oAuthRedirectUris"}},{"kind":"Field","name":{"kind":"Name","value":"oAuthScopes"}},{"kind":"Field","name":{"kind":"Name","value":"sourceType"}},{"kind":"Field","name":{"kind":"Name","value":"sourcePackage"}},{"kind":"Field","name":{"kind":"Name","value":"latestAvailableVersion"}},{"kind":"Field","name":{"kind":"Name","value":"isListed"}},{"kind":"Field","name":{"kind":"Name","value":"isVetted"}},{"kind":"Field","name":{"kind":"Name","value":"isPreInstalled"}},{"kind":"Field","name":{"kind":"Name","value":"isConfigured"}},{"kind":"Field","name":{"kind":"Name","value":"ownerWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<UpdateAdminApplicationRegistrationMutation, UpdateAdminApplicationRegistrationMutationVariables>;
|
||||
export const UpdateAdminApplicationRegistrationVariableDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateAdminApplicationRegistrationVariable"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateApplicationRegistrationVariableInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateAdminApplicationRegistrationVariable"},"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":"key"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"isSecret"}},{"kind":"Field","name":{"kind":"Name","value":"isRequired"}},{"kind":"Field","name":{"kind":"Name","value":"isFilled"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode<UpdateAdminApplicationRegistrationVariableMutation, UpdateAdminApplicationRegistrationVariableMutationVariables>;
|
||||
export const UpgradeRegistrationApplicationsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpgradeRegistrationApplications"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"applicationRegistrationId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"upgradeRegistrationApplications"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"applicationRegistrationId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"applicationRegistrationId"}}}]}]}}]} as unknown as DocumentNode<UpgradeRegistrationApplicationsMutation, UpgradeRegistrationApplicationsMutationVariables>;
|
||||
export const FindAdminApplicationRegistrationInstalledWorkspacesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindAdminApplicationRegistrationInstalledWorkspaces"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"FindApplicationRegistrationInstalledWorkspacesInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findAdminApplicationRegistrationInstalledWorkspaces"},"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":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"hasMore"}},{"kind":"Field","name":{"kind":"Name","value":"workspaces"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"version"}}]}}]}}]}}]} as unknown as DocumentNode<FindAdminApplicationRegistrationInstalledWorkspacesQuery, FindAdminApplicationRegistrationInstalledWorkspacesQueryVariables>;
|
||||
export const FindAdminApplicationRegistrationStatsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindAdminApplicationRegistrationStats"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findAdminApplicationRegistrationStats"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeInstalls"}},{"kind":"Field","name":{"kind":"Name","value":"mostInstalledVersion"}},{"kind":"Field","name":{"kind":"Name","value":"versionDistribution"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"count"}}]}}]}}]}}]} as unknown as DocumentNode<FindAdminApplicationRegistrationStatsQuery, FindAdminApplicationRegistrationStatsQueryVariables>;
|
||||
export const FindAdminApplicationRegistrationVariablesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindAdminApplicationRegistrationVariables"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"applicationRegistrationId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findAdminApplicationRegistrationVariables"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"applicationRegistrationId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"applicationRegistrationId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"isSecret"}},{"kind":"Field","name":{"kind":"Name","value":"isRequired"}},{"kind":"Field","name":{"kind":"Name","value":"isFilled"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"options"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode<FindAdminApplicationRegistrationVariablesQuery, FindAdminApplicationRegistrationVariablesQueryVariables>;
|
||||
|
||||
File diff suppressed because one or more lines are too long
+1
@@ -22,6 +22,7 @@ export const APPLICATION_FRAGMENT = gql`
|
||||
logoUrl
|
||||
}
|
||||
canBeUninstalled
|
||||
autoUpgrade
|
||||
defaultRoleId
|
||||
settingsCustomTabFrontComponentId
|
||||
availablePackages
|
||||
|
||||
+1
@@ -8,6 +8,7 @@ export const CUSTOM_WORKSPACE_APPLICATION_MOCK = {
|
||||
commandMenuItems: [],
|
||||
availablePackages: {},
|
||||
canBeUninstalled: false,
|
||||
autoUpgrade: false,
|
||||
description: 'workpace custom application',
|
||||
name: 'custom',
|
||||
objects: [],
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const UPGRADE_REGISTRATION_APPLICATIONS = gql`
|
||||
mutation UpgradeRegistrationApplications(
|
||||
$applicationRegistrationId: String!
|
||||
) {
|
||||
upgradeRegistrationApplications(
|
||||
applicationRegistrationId: $applicationRegistrationId
|
||||
)
|
||||
}
|
||||
`;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const UPDATE_APPLICATION = gql`
|
||||
mutation UpdateApplication($id: UUID!, $input: UpdateApplicationInput!) {
|
||||
updateApplication(id: $id, input: $input) {
|
||||
id
|
||||
autoUpgrade
|
||||
}
|
||||
}
|
||||
`;
|
||||
+5
@@ -30,6 +30,7 @@ describe('useComputeObjectAndFieldsContentForApplication', () => {
|
||||
name: 'Test App',
|
||||
logo: null,
|
||||
canBeUninstalled: true,
|
||||
autoUpgrade: false,
|
||||
availablePackages: {},
|
||||
applicationVariables: [],
|
||||
agents: [],
|
||||
@@ -60,6 +61,7 @@ describe('useComputeObjectAndFieldsContentForApplication', () => {
|
||||
name: 'Test App',
|
||||
logo: null,
|
||||
canBeUninstalled: true,
|
||||
autoUpgrade: false,
|
||||
availablePackages: {},
|
||||
applicationVariables: [],
|
||||
agents: [],
|
||||
@@ -88,6 +90,7 @@ describe('useComputeObjectAndFieldsContentForApplication', () => {
|
||||
name: 'Test App',
|
||||
logo: null,
|
||||
canBeUninstalled: true,
|
||||
autoUpgrade: false,
|
||||
availablePackages: {},
|
||||
applicationVariables: [],
|
||||
agents: [],
|
||||
@@ -117,6 +120,7 @@ describe('useComputeObjectAndFieldsContentForApplication', () => {
|
||||
name: 'Test App',
|
||||
logo: null,
|
||||
canBeUninstalled: true,
|
||||
autoUpgrade: false,
|
||||
availablePackages: {},
|
||||
applicationVariables: [],
|
||||
agents: [],
|
||||
@@ -274,6 +278,7 @@ describe('useComputeObjectAndFieldsContentForApplication', () => {
|
||||
name: 'Test App',
|
||||
logo: null,
|
||||
canBeUninstalled: true,
|
||||
autoUpgrade: false,
|
||||
availablePackages: {},
|
||||
applicationVariables: [],
|
||||
agents: [],
|
||||
|
||||
+4
-4
@@ -150,7 +150,7 @@ export const SettingsAdminApplicationRegistrationGeneralToggles = ({
|
||||
<StyledButtonWrapper id={BACKFILL_BUTTON_ID}>
|
||||
<Button
|
||||
Icon={IconReload}
|
||||
title={t`Install latest version on all workspaces`}
|
||||
title={t`Install on all workspaces`}
|
||||
variant="secondary"
|
||||
onClick={() => openModal(BACKFILL_INSTALLATION_MODAL_ID)}
|
||||
disabled={isBackfilling || !registration.isPreInstalled}
|
||||
@@ -169,10 +169,10 @@ export const SettingsAdminApplicationRegistrationGeneralToggles = ({
|
||||
</StyledBackfillContainer>
|
||||
<ConfirmationModal
|
||||
modalInstanceId={BACKFILL_INSTALLATION_MODAL_ID}
|
||||
title={t`Backfill installation`}
|
||||
subtitle={t`This will install the latest version of "${registration.name}" on all existing active and suspended workspaces, upgrading any workspace that already has an older version. It runs as a background job and may take a while. Continue?`}
|
||||
title={t`Install on all workspaces`}
|
||||
subtitle={t`This will install the latest version of "${registration.name}" on all existing active and suspended workspaces, including the ones that don't have it yet. It runs as a background job and may take a while. Continue?`}
|
||||
onConfirmClick={handleBackfill}
|
||||
confirmButtonText={t`Backfill`}
|
||||
confirmButtonText={t`Install`}
|
||||
confirmButtonAccent="blue"
|
||||
loading={isBackfilling}
|
||||
/>
|
||||
|
||||
+4
-1
@@ -235,7 +235,10 @@ export const SettingsApplicationDetails = () => {
|
||||
applicationHasHttpTriggeredFunctions(application);
|
||||
const canShowFunctionDomain = hasHttpTriggeredFunctions;
|
||||
const hasNothingToConfigure =
|
||||
!hasVariables && !hasConnectionProviders && !canShowFunctionDomain;
|
||||
!hasVariables &&
|
||||
!hasConnectionProviders &&
|
||||
!canShowFunctionDomain &&
|
||||
!isUpgradableApplicationSourceType(sourceType);
|
||||
|
||||
return {
|
||||
id: 'settings',
|
||||
|
||||
+68
-3
@@ -1,9 +1,27 @@
|
||||
import { useApolloAdminClient } from '@/settings/admin-panel/apollo/hooks/useApolloAdminClient';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useState } from 'react';
|
||||
import { IconRefresh } from 'twenty-ui/icon';
|
||||
import { Button } from 'twenty-ui/input';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
import { H2Title } from 'twenty-ui/typography';
|
||||
import { styled } from '@linaria/react';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { UpgradeRegistrationApplicationsDocument } from '~/generated-admin/graphql';
|
||||
import { type ApplicationRegistration } from '~/generated-metadata/graphql';
|
||||
import { SettingsApplicationRegistrationInstalledWorkspaces } from '~/pages/settings/applications/components/SettingsApplicationRegistrationInstalledWorkspaces';
|
||||
import { SettingsApplicationRegistrationInstallStats } from '~/pages/settings/applications/components/SettingsApplicationRegistrationInstallStats';
|
||||
import { H2Title } from 'twenty-ui/typography';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
|
||||
const StyledUpgradeContainer = styled.div`
|
||||
margin-top: ${themeCssVariables.spacing[6]};
|
||||
`;
|
||||
|
||||
const UPGRADE_INSTALLATIONS_MODAL_ID =
|
||||
'upgrade-registration-applications-modal';
|
||||
|
||||
export const SettingsApplicationRegistrationGeneralStats = ({
|
||||
registration,
|
||||
@@ -11,6 +29,35 @@ export const SettingsApplicationRegistrationGeneralStats = ({
|
||||
registration: ApplicationRegistration;
|
||||
}) => {
|
||||
const { t } = useLingui();
|
||||
const apolloAdminClient = useApolloAdminClient();
|
||||
const { enqueueSuccessSnackBar, enqueueErrorSnackBar } = useSnackBar();
|
||||
const { openModal, closeModal } = useModal();
|
||||
|
||||
const [isUpgrading, setIsUpgrading] = useState(false);
|
||||
|
||||
const [upgradeApplications] = useMutation(
|
||||
UpgradeRegistrationApplicationsDocument,
|
||||
{ client: apolloAdminClient },
|
||||
);
|
||||
|
||||
const handleUpgrade = async () => {
|
||||
setIsUpgrading(true);
|
||||
try {
|
||||
await upgradeApplications({
|
||||
variables: { applicationRegistrationId: registration.id },
|
||||
});
|
||||
enqueueSuccessSnackBar({
|
||||
message: t`Upgrade started. Existing installations will be upgraded to the latest version in the background.`,
|
||||
});
|
||||
} catch {
|
||||
enqueueErrorSnackBar({
|
||||
message: t`Failed to start upgrade`,
|
||||
});
|
||||
} finally {
|
||||
setIsUpgrading(false);
|
||||
closeModal(UPGRADE_INSTALLATIONS_MODAL_ID);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Section>
|
||||
@@ -24,6 +71,24 @@ export const SettingsApplicationRegistrationGeneralStats = ({
|
||||
<SettingsApplicationRegistrationInstalledWorkspaces
|
||||
registration={registration}
|
||||
/>
|
||||
<StyledUpgradeContainer>
|
||||
<Button
|
||||
Icon={IconRefresh}
|
||||
title={t`Upgrade existing installations`}
|
||||
variant="secondary"
|
||||
onClick={() => openModal(UPGRADE_INSTALLATIONS_MODAL_ID)}
|
||||
disabled={isUpgrading}
|
||||
/>
|
||||
</StyledUpgradeContainer>
|
||||
<ConfirmationModal
|
||||
modalInstanceId={UPGRADE_INSTALLATIONS_MODAL_ID}
|
||||
title={t`Upgrade existing installations`}
|
||||
subtitle={t`This will upgrade "${registration.name}" to its latest available version on every workspace that already has it installed. Workspaces without the app are not affected. It runs as a background job and may take a while. Continue?`}
|
||||
onConfirmClick={handleUpgrade}
|
||||
confirmButtonText={t`Upgrade`}
|
||||
confirmButtonAccent="blue"
|
||||
loading={isUpgrading}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
+1
@@ -37,6 +37,7 @@ const buildApplication = (variableValue: string): Application => ({
|
||||
applicationRegistrationId: null,
|
||||
applicationRegistration: null,
|
||||
canBeUninstalled: true,
|
||||
autoUpgrade: false,
|
||||
defaultRoleId: null,
|
||||
settingsCustomTabFrontComponentId: null,
|
||||
availablePackages: {},
|
||||
|
||||
+14
@@ -3,7 +3,9 @@ import { useUpdateOneApplicationVariable } from '~/pages/settings/applications/h
|
||||
import { SettingsApplicationConnectionsSection } from '~/pages/settings/applications/tabs/SettingsApplicationConnectionsSection';
|
||||
import { SettingsApplicationDetailEnvironmentVariablesTable } from '~/pages/settings/applications/tabs/SettingsApplicationDetailEnvironmentVariablesTable';
|
||||
import { SettingsApplicationFunctionDomainSection } from '~/pages/settings/applications/tabs/SettingsApplicationFunctionDomainSection';
|
||||
import { SettingsApplicationGeneralSection } from '~/pages/settings/applications/tabs/SettingsApplicationGeneralSection';
|
||||
import { applicationHasHttpTriggeredFunctions } from '~/pages/settings/applications/utils/applicationHasHttpTriggeredFunctions';
|
||||
import { isUpgradableApplicationSourceType } from '~/pages/settings/applications/utils/isUpgradableApplicationSourceType';
|
||||
|
||||
export const SettingsApplicationDetailSettingsTab = ({
|
||||
application,
|
||||
@@ -14,6 +16,8 @@ export const SettingsApplicationDetailSettingsTab = ({
|
||||
| 'id'
|
||||
| 'universalIdentifier'
|
||||
| 'canBeUninstalled'
|
||||
| 'autoUpgrade'
|
||||
| 'applicationRegistration'
|
||||
| 'logicFunctions'
|
||||
>;
|
||||
}) => {
|
||||
@@ -26,8 +30,18 @@ export const SettingsApplicationDetailSettingsTab = ({
|
||||
const hasHttpTriggeredFunctions =
|
||||
applicationHasHttpTriggeredFunctions(application);
|
||||
|
||||
const isUpgradable = isUpgradableApplicationSourceType(
|
||||
application?.applicationRegistration?.sourceType,
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{isUpgradable && application?.id && (
|
||||
<SettingsApplicationGeneralSection
|
||||
applicationId={application.id}
|
||||
autoUpgrade={application.autoUpgrade}
|
||||
/>
|
||||
)}
|
||||
{hasHttpTriggeredFunctions && application?.id && (
|
||||
<SettingsApplicationFunctionDomainSection
|
||||
applicationId={application.id}
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
import { SettingsOptionCardContentToggle } from '@/settings/components/SettingsOptions/SettingsOptionCardContentToggle';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { IconRefresh } from 'twenty-ui/icon';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
import { Card } from 'twenty-ui/surfaces';
|
||||
import { H2Title } from 'twenty-ui/typography';
|
||||
import { UpdateApplicationDocument } from '~/generated-metadata/graphql';
|
||||
|
||||
export const SettingsApplicationGeneralSection = ({
|
||||
applicationId,
|
||||
autoUpgrade,
|
||||
}: {
|
||||
applicationId: string;
|
||||
autoUpgrade: boolean;
|
||||
}) => {
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
|
||||
const [updateApplication] = useMutation(UpdateApplicationDocument);
|
||||
|
||||
const handleAutoUpgradeChange = async (checked: boolean) => {
|
||||
try {
|
||||
await updateApplication({
|
||||
variables: {
|
||||
id: applicationId,
|
||||
input: { autoUpgrade: checked },
|
||||
},
|
||||
});
|
||||
} catch {
|
||||
enqueueErrorSnackBar({
|
||||
message: t`Failed to update auto-upgrade setting.`,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<H2Title title={t`General`} />
|
||||
<Card rounded fullWidth>
|
||||
<SettingsOptionCardContentToggle
|
||||
Icon={IconRefresh}
|
||||
title={t`Auto-upgrade`}
|
||||
description={t`Automatically upgrade this application when a new version is published`}
|
||||
checked={autoUpgrade}
|
||||
onChange={handleAutoUpgradeChange}
|
||||
/>
|
||||
</Card>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import { QueryRunner } from 'typeorm';
|
||||
|
||||
import { RegisteredInstanceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-instance-command.decorator';
|
||||
import { FastInstanceCommand } from 'src/engine/core-modules/upgrade/interfaces/fast-instance-command.interface';
|
||||
|
||||
@RegisteredInstanceCommand('2.23.0', 1784297307235)
|
||||
export class AddAutoUpgradeToApplicationFastInstanceCommand implements FastInstanceCommand {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'ALTER TABLE "core"."application" ADD COLUMN IF NOT EXISTS "autoUpgrade" boolean NOT NULL DEFAULT false',
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'ALTER TABLE "core"."application" DROP COLUMN IF EXISTS "autoUpgrade"',
|
||||
);
|
||||
}
|
||||
}
|
||||
+2
@@ -113,6 +113,7 @@ import { AddLogoFileIdToApplicationRegistrationFastInstanceCommand } from './2-2
|
||||
import { AddCalendarEndFieldMetadataIdToViewFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-22/2-22-instance-command-fast-1783956795000-add-calendar-end-field-metadata-id-to-view';
|
||||
import { AddCreatedWorkspaceActivationStatusSlowInstanceCommand } from './2-22/2-22-instance-command-slow-1784106205000-add-created-workspace-activation-status';
|
||||
import { BackfillCreatedWorkspaceActivationStatusSlowInstanceCommand } from './2-23/2-23-instance-command-slow-1784286705000-backfill-created-workspace-activation-status';
|
||||
import { AddAutoUpgradeToApplicationFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-23/2-23-instance-command-fast-1784297307235-add-auto-upgrade-to-application';
|
||||
|
||||
export const INSTANCE_COMMANDS = [
|
||||
AddViewFieldGroupIdIndexOnViewFieldFastInstanceCommand,
|
||||
@@ -228,4 +229,5 @@ export const INSTANCE_COMMANDS = [
|
||||
AddCalendarEndFieldMetadataIdToViewFastInstanceCommand,
|
||||
AddCreatedWorkspaceActivationStatusSlowInstanceCommand,
|
||||
BackfillCreatedWorkspaceActivationStatusSlowInstanceCommand,
|
||||
AddAutoUpgradeToApplicationFastInstanceCommand,
|
||||
];
|
||||
|
||||
@@ -61,6 +61,10 @@ import {
|
||||
BACKFILL_APPLICATION_INSTALLATION_JOB_NAME,
|
||||
type BackfillApplicationInstallationJobData,
|
||||
} from 'src/engine/core-modules/application/jobs/backfill-application-installation.job-constants';
|
||||
import {
|
||||
UPGRADE_APPLICATIONS_JOB_NAME,
|
||||
type UpgradeApplicationsJobData,
|
||||
} from 'src/engine/core-modules/application/jobs/upgrade-applications.job-constants';
|
||||
import { AuthGraphqlApiExceptionFilter } from 'src/engine/core-modules/auth/filters/auth-graphql-api-exception.filter';
|
||||
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { AdminAiModelsDTO } from 'src/engine/core-modules/client-config/client-config.entity';
|
||||
@@ -545,6 +549,26 @@ export class AdminPanelResolver {
|
||||
return true;
|
||||
}
|
||||
|
||||
@UseGuards(AdminPanelGuard)
|
||||
@Mutation(() => Boolean)
|
||||
async upgradeRegistrationApplications(
|
||||
@Args('applicationRegistrationId') applicationRegistrationId: string,
|
||||
): Promise<boolean> {
|
||||
await this.applicationRegistrationService.findOneByIdGlobal(
|
||||
applicationRegistrationId,
|
||||
);
|
||||
|
||||
await this.workspaceQueueService.add<UpgradeApplicationsJobData>(
|
||||
UPGRADE_APPLICATIONS_JOB_NAME,
|
||||
{ applicationRegistrationId, onlyAutoUpgrade: false },
|
||||
{
|
||||
id: `${UPGRADE_APPLICATIONS_JOB_NAME}-${applicationRegistrationId}`,
|
||||
}, // Avoids triggering multiple pending jobs for the same app
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@UseGuards(AdminPanelGuard)
|
||||
@Query(() => GraphQLJSON)
|
||||
async getAiProviders(): Promise<Record<string, unknown>> {
|
||||
|
||||
+23
@@ -7,6 +7,8 @@ import {
|
||||
import { Args, Mutation, Query } from '@nestjs/graphql';
|
||||
|
||||
import { PermissionFlagType } from 'twenty-shared/constants';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { ApplicationExceptionFilter } from 'src/engine/core-modules/application/application-exception-filter';
|
||||
@@ -18,6 +20,7 @@ import { ApplicationException } from 'src/engine/core-modules/application/applic
|
||||
import { ApplicationRegistrationExceptionFilter } from 'src/engine/core-modules/application/application-registration/application-registration-exception-filter';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { ApplicationDTO } from 'src/engine/core-modules/application/dtos/application.dto';
|
||||
import { UpdateApplicationInput } from 'src/engine/core-modules/application/dtos/update-application.input';
|
||||
import { AuthGraphqlApiExceptionFilter } from 'src/engine/core-modules/auth/filters/auth-graphql-api-exception.filter';
|
||||
import { MetricsService } from 'src/engine/core-modules/metrics/metrics.service';
|
||||
import { MetricsKeys } from 'src/engine/core-modules/metrics/types/metrics-keys.type';
|
||||
@@ -128,6 +131,26 @@ export class ApplicationInstallResolver {
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => ApplicationDTO)
|
||||
@UseGuards(SettingsPermissionGuard(PermissionFlagType.APPLICATIONS))
|
||||
async updateApplication(
|
||||
@Args('id', { type: () => UUIDScalarType }) id: string,
|
||||
@Args('input') input: UpdateApplicationInput,
|
||||
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
|
||||
) {
|
||||
await this.applicationService.findOneApplicationOrThrow({
|
||||
id,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
return this.applicationService.update(id, {
|
||||
...(isDefined(input.autoUpgrade)
|
||||
? { autoUpgrade: input.autoUpgrade }
|
||||
: {}),
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => Boolean)
|
||||
@UseGuards(SettingsPermissionGuard(PermissionFlagType.APPLICATIONS))
|
||||
async uninstallApplication(
|
||||
|
||||
+1
@@ -161,6 +161,7 @@ export class ApplicationSyncService {
|
||||
defaultRole: null,
|
||||
settingsCustomTabFrontComponentId: null,
|
||||
canBeUninstalled: true,
|
||||
autoUpgrade: false,
|
||||
isSdkLayerStale: false,
|
||||
applicationRegistrationId: null,
|
||||
primaryPublicDomainId: null,
|
||||
|
||||
+6
@@ -10,6 +10,8 @@ import { ApplicationEntity } from 'src/engine/core-modules/application/applicati
|
||||
import { CacheLockService } from 'src/engine/core-modules/cache-lock/cache-lock.service';
|
||||
import { CoreEntityCacheService } from 'src/engine/core-entity-cache/services/core-entity-cache.service';
|
||||
import { ServerFileStorageService } from 'src/engine/core-modules/file-storage/services/server-file-storage.service';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
import { getQueueToken } from 'src/engine/core-modules/message-queue/utils/get-queue-token.util';
|
||||
import { MetricsService } from 'src/engine/core-modules/metrics/metrics.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
|
||||
@@ -95,6 +97,10 @@ describe('ApplicationRegistrationService - upsertFromCatalog', () => {
|
||||
provide: MetricsService,
|
||||
useValue: { incrementCounterBy: jest.fn() },
|
||||
},
|
||||
{
|
||||
provide: getQueueToken(MessageQueue.workspaceQueue),
|
||||
useValue: { add: jest.fn() },
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
|
||||
+31
@@ -35,8 +35,15 @@ import { ApplicationRegistrationSourceType } from 'src/engine/core-modules/appli
|
||||
import { buildRegistrationManifestUpdateFields } from 'src/engine/core-modules/application/application-registration/utils/build-registration-manifest-update-fields.util';
|
||||
import { fromManifestApplicationToDisplayFields } from 'src/engine/core-modules/application/application-registration/utils/from-manifest-application-to-display-fields.util';
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import {
|
||||
UPGRADE_APPLICATIONS_JOB_NAME,
|
||||
type UpgradeApplicationsJobData,
|
||||
} from 'src/engine/core-modules/application/jobs/upgrade-applications.job-constants';
|
||||
import { validateRedirectUri } from 'src/engine/core-modules/auth/utils/validate-redirect-uri.util';
|
||||
import { CacheLockService } from 'src/engine/core-modules/cache-lock/cache-lock.service';
|
||||
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
||||
import { ServerFileStorageService } from 'src/engine/core-modules/file-storage/services/server-file-storage.service';
|
||||
import { MetricsService } from 'src/engine/core-modules/metrics/metrics.service';
|
||||
import { MetricsKeys } from 'src/engine/core-modules/metrics/types/metrics-keys.type';
|
||||
@@ -115,8 +122,28 @@ export class ApplicationRegistrationService {
|
||||
private readonly cacheLockService: CacheLockService,
|
||||
private readonly coreEntityCacheService: CoreEntityCacheService,
|
||||
private readonly metricsService: MetricsService,
|
||||
@InjectMessageQueue(MessageQueue.workspaceQueue)
|
||||
private readonly workspaceQueueService: MessageQueueService,
|
||||
) {}
|
||||
|
||||
// Best-effort: a queue outage must not fail the publish flow that
|
||||
// triggered the upgrade.
|
||||
async enqueueAutoUpgradeApplications(
|
||||
applicationRegistrationId: string,
|
||||
): Promise<void> {
|
||||
try {
|
||||
await this.workspaceQueueService.add<UpgradeApplicationsJobData>(
|
||||
UPGRADE_APPLICATIONS_JOB_NAME,
|
||||
{ applicationRegistrationId, onlyAutoUpgrade: true },
|
||||
);
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Failed to enqueue auto-upgrade for registration ${applicationRegistrationId}`,
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async invalidateMarketplaceAppsCache(): Promise<void> {
|
||||
try {
|
||||
await this.coreEntityCacheService.invalidate(
|
||||
@@ -618,6 +645,8 @@ export class ApplicationRegistrationService {
|
||||
sourceType: params.sourceType,
|
||||
version: params.latestAvailableVersion,
|
||||
});
|
||||
|
||||
await this.enqueueAutoUpgradeApplications(existing.id);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -659,6 +688,8 @@ export class ApplicationRegistrationService {
|
||||
sourceType: params.sourceType,
|
||||
version: params.latestAvailableVersion,
|
||||
});
|
||||
|
||||
await this.enqueueAutoUpgradeApplications(existing.id);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
+6
@@ -135,6 +135,12 @@ export class ApplicationTarballService {
|
||||
sourceType: ApplicationRegistrationSourceType.TARBALL,
|
||||
version: incomingVersion,
|
||||
});
|
||||
|
||||
if (!isNewRegistration) {
|
||||
await this.applicationRegistrationService.enqueueAutoUpgradeApplications(
|
||||
appRegistration.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return this.appRegistrationRepository.findOneOrFail({
|
||||
|
||||
+5
-1
@@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationInstallModule } from 'src/engine/core-modules/application/application-install/application-install.module';
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { ApplicationRegistrationEntity } from 'src/engine/core-modules/application/application-registration/application-registration.entity';
|
||||
import { ApplicationRegistrationModule } from 'src/engine/core-modules/application/application-registration/application-registration.module';
|
||||
import { ApplicationUpgradeResolver } from 'src/engine/core-modules/application/application-upgrade/application-upgrade.resolver';
|
||||
@@ -14,7 +15,10 @@ import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permi
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([ApplicationRegistrationEntity]),
|
||||
TypeOrmModule.forFeature([
|
||||
ApplicationEntity,
|
||||
ApplicationRegistrationEntity,
|
||||
]),
|
||||
ApplicationInstallModule,
|
||||
ApplicationRegistrationModule,
|
||||
FeatureFlagModule,
|
||||
|
||||
+82
-1
@@ -2,10 +2,12 @@ import { Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import axios from 'axios';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { ApplicationInstallService } from 'src/engine/core-modules/application/application-install/application-install.service';
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { ApplicationRegistrationEntity } from 'src/engine/core-modules/application/application-registration/application-registration.entity';
|
||||
import { ApplicationRegistrationService } from 'src/engine/core-modules/application/application-registration/application-registration.service';
|
||||
import { ApplicationRegistrationSourceType } from 'src/engine/core-modules/application/application-registration/enums/application-registration-source-type.enum';
|
||||
@@ -19,6 +21,8 @@ const npmPackageMetadataSchema = z.object({
|
||||
version: z.string(),
|
||||
});
|
||||
|
||||
const UPGRADE_APPLICATIONS_BATCH_SIZE = 20;
|
||||
|
||||
@Injectable()
|
||||
export class ApplicationUpgradeService {
|
||||
private readonly logger = new Logger(ApplicationUpgradeService.name);
|
||||
@@ -26,6 +30,8 @@ export class ApplicationUpgradeService {
|
||||
constructor(
|
||||
@InjectRepository(ApplicationRegistrationEntity)
|
||||
private readonly appRegistrationRepository: Repository<ApplicationRegistrationEntity>,
|
||||
@InjectRepository(ApplicationEntity)
|
||||
private readonly applicationRepository: Repository<ApplicationEntity>,
|
||||
private readonly applicationInstallService: ApplicationInstallService,
|
||||
private readonly applicationRegistrationService: ApplicationRegistrationService,
|
||||
private readonly twentyConfigService: TwentyConfigService,
|
||||
@@ -79,6 +85,10 @@ export class ApplicationUpgradeService {
|
||||
sourceType: appRegistration.sourceType,
|
||||
version: parsed.data.version,
|
||||
});
|
||||
|
||||
await this.applicationRegistrationService.enqueueAutoUpgradeApplications(
|
||||
appRegistration.id,
|
||||
);
|
||||
}
|
||||
|
||||
return parsed.data.version;
|
||||
@@ -101,6 +111,63 @@ export class ApplicationUpgradeService {
|
||||
}
|
||||
}
|
||||
|
||||
async upgradeAllApplications({
|
||||
applicationRegistrationId,
|
||||
onlyAutoUpgrade = false,
|
||||
}: {
|
||||
applicationRegistrationId: string;
|
||||
onlyAutoUpgrade?: boolean;
|
||||
}): Promise<void> {
|
||||
const appRegistration = await this.appRegistrationRepository.findOneOrFail({
|
||||
where: { id: applicationRegistrationId },
|
||||
});
|
||||
|
||||
const targetVersion = appRegistration.latestAvailableVersion;
|
||||
|
||||
if (!isDefined(targetVersion)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const applications = await this.applicationRepository.find({
|
||||
where: {
|
||||
applicationRegistrationId,
|
||||
...(onlyAutoUpgrade ? { autoUpgrade: true } : {}),
|
||||
},
|
||||
});
|
||||
|
||||
const applicationsToUpgrade = applications.filter(
|
||||
(application) => application.version !== targetVersion,
|
||||
);
|
||||
|
||||
for (
|
||||
let batchStart = 0;
|
||||
batchStart < applicationsToUpgrade.length;
|
||||
batchStart += UPGRADE_APPLICATIONS_BATCH_SIZE
|
||||
) {
|
||||
const batch = applicationsToUpgrade.slice(
|
||||
batchStart,
|
||||
batchStart + UPGRADE_APPLICATIONS_BATCH_SIZE,
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
batch.map(async (application) => {
|
||||
try {
|
||||
await this.upgradeApplicationToVersion({
|
||||
appRegistration,
|
||||
targetVersion,
|
||||
workspaceId: application.workspaceId,
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Failed to upgrade application ${application.id} to version ${targetVersion} in workspace ${application.workspaceId}`,
|
||||
error,
|
||||
);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async upgradeApplication(params: {
|
||||
appRegistrationId: string;
|
||||
targetVersion: string;
|
||||
@@ -110,6 +177,20 @@ export class ApplicationUpgradeService {
|
||||
where: { id: params.appRegistrationId },
|
||||
});
|
||||
|
||||
return this.upgradeApplicationToVersion({
|
||||
appRegistration,
|
||||
targetVersion: params.targetVersion,
|
||||
workspaceId: params.workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
private async upgradeApplicationToVersion(params: {
|
||||
appRegistration: ApplicationRegistrationEntity;
|
||||
targetVersion: string;
|
||||
workspaceId: string;
|
||||
}): Promise<boolean> {
|
||||
const { appRegistration } = params;
|
||||
|
||||
// LOCAL apps are updated by dev sync and OAUTH_ONLY registrations have no
|
||||
// code artifacts.
|
||||
if (
|
||||
@@ -125,7 +206,7 @@ export class ApplicationUpgradeService {
|
||||
|
||||
try {
|
||||
return await this.applicationInstallService.installApplication({
|
||||
appRegistrationId: params.appRegistrationId,
|
||||
appRegistrationId: appRegistration.id,
|
||||
version: params.targetVersion,
|
||||
workspaceId: params.workspaceId,
|
||||
});
|
||||
|
||||
@@ -124,6 +124,13 @@ export class ApplicationEntity extends WorkspaceRelatedEntity {
|
||||
@Column({ nullable: false, type: 'boolean', default: true })
|
||||
canBeUninstalled: boolean;
|
||||
|
||||
@Column({ nullable: false, type: 'boolean', default: false })
|
||||
@WasIntroducedInUpgrade({
|
||||
upgradeCommandName:
|
||||
'2.23.0_AddAutoUpgradeToApplicationFastInstanceCommand_1784297307235',
|
||||
})
|
||||
autoUpgrade: boolean;
|
||||
|
||||
@Column({ nullable: false, type: 'boolean', default: false })
|
||||
isSdkLayerStale: boolean;
|
||||
|
||||
|
||||
@@ -86,6 +86,10 @@ export class ApplicationDTO {
|
||||
@IsBoolean()
|
||||
canBeUninstalled: boolean;
|
||||
|
||||
@Field(() => Boolean)
|
||||
@IsBoolean()
|
||||
autoUpgrade: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@Field({ nullable: true })
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import { IsBoolean, IsOptional } from 'class-validator';
|
||||
|
||||
@InputType()
|
||||
export class UpdateApplicationInput {
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@Field(() => Boolean, { nullable: true })
|
||||
autoUpgrade?: boolean;
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
export const UPGRADE_APPLICATIONS_JOB_NAME = 'UpgradeApplicationsJob';
|
||||
|
||||
export type UpgradeApplicationsJobData = {
|
||||
applicationRegistrationId: string;
|
||||
onlyAutoUpgrade: boolean;
|
||||
};
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { ApplicationUpgradeService } from 'src/engine/core-modules/application/application-upgrade/application-upgrade.service';
|
||||
import {
|
||||
UPGRADE_APPLICATIONS_JOB_NAME,
|
||||
type UpgradeApplicationsJobData,
|
||||
} from 'src/engine/core-modules/application/jobs/upgrade-applications.job-constants';
|
||||
import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator';
|
||||
import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
|
||||
@Processor(MessageQueue.workspaceQueue)
|
||||
export class UpgradeApplicationsJob {
|
||||
constructor(
|
||||
private readonly applicationUpgradeService: ApplicationUpgradeService,
|
||||
) {}
|
||||
|
||||
@Process(UPGRADE_APPLICATIONS_JOB_NAME)
|
||||
async handle(data: UpgradeApplicationsJobData): Promise<void> {
|
||||
await this.applicationUpgradeService.upgradeAllApplications({
|
||||
applicationRegistrationId: data.applicationRegistrationId,
|
||||
onlyAutoUpgrade: data.onlyAutoUpgrade,
|
||||
});
|
||||
}
|
||||
}
|
||||
+2
@@ -3,6 +3,7 @@ import { type FlatApplication } from 'src/engine/core-modules/application/types/
|
||||
|
||||
export const fromFlatApplicationToApplicationDto = ({
|
||||
canBeUninstalled,
|
||||
autoUpgrade,
|
||||
description,
|
||||
id,
|
||||
logo,
|
||||
@@ -18,6 +19,7 @@ export const fromFlatApplicationToApplicationDto = ({
|
||||
}: FlatApplication): ApplicationDTO => {
|
||||
return {
|
||||
canBeUninstalled,
|
||||
autoUpgrade,
|
||||
description: description ?? undefined,
|
||||
id,
|
||||
logo: logo ?? undefined,
|
||||
|
||||
@@ -14,7 +14,9 @@ import { BillingReminderCronJob } from 'src/engine/core-modules/billing/reminder
|
||||
import { StripeModule } from 'src/engine/core-modules/billing/stripe/stripe.module';
|
||||
import { ApplicationInstallModule } from 'src/engine/core-modules/application/application-install/application-install.module';
|
||||
import { ApplicationRegistrationModule } from 'src/engine/core-modules/application/application-registration/application-registration.module';
|
||||
import { ApplicationUpgradeModule } from 'src/engine/core-modules/application/application-upgrade/application-upgrade.module';
|
||||
import { BackfillApplicationInstallationJob } from 'src/engine/core-modules/application/jobs/backfill-application-installation.job';
|
||||
import { UpgradeApplicationsJob } from 'src/engine/core-modules/application/jobs/upgrade-applications.job';
|
||||
import { PreInstalledAppsModule } from 'src/engine/core-modules/application/pre-installed-apps/pre-installed-apps.module';
|
||||
import { InstallOnboardingAppsJob } from 'src/engine/core-modules/onboarding/jobs/install-onboarding-apps.job';
|
||||
import { OnboardingModule } from 'src/engine/core-modules/onboarding/onboarding.module';
|
||||
@@ -95,6 +97,7 @@ import { WorkflowModule } from 'src/modules/workflow/workflow.module';
|
||||
PreInstalledAppsModule,
|
||||
ApplicationInstallModule,
|
||||
ApplicationRegistrationModule,
|
||||
ApplicationUpgradeModule,
|
||||
OnboardingModule,
|
||||
BillingReminderModule,
|
||||
],
|
||||
@@ -112,6 +115,7 @@ import { WorkflowModule } from 'src/modules/workflow/workflow.module';
|
||||
UpdateWorkspaceMemberEmailJob,
|
||||
GenerateSdkClientJob,
|
||||
BackfillApplicationInstallationJob,
|
||||
UpgradeApplicationsJob,
|
||||
InstallOnboardingAppsJob,
|
||||
],
|
||||
})
|
||||
|
||||
+1
@@ -41,6 +41,7 @@ const MOCK_FLAT_APPLICATION: FlatApplication = {
|
||||
defaultRole: null,
|
||||
settingsCustomTabFrontComponentId: null,
|
||||
canBeUninstalled: false,
|
||||
autoUpgrade: false,
|
||||
applicationRegistrationId: null,
|
||||
primaryPublicDomainId: null,
|
||||
createdAt: new Date(),
|
||||
|
||||
+1
@@ -36,6 +36,7 @@ const MOCK_FLAT_APPLICATION: FlatApplication = {
|
||||
defaultRole: null,
|
||||
settingsCustomTabFrontComponentId: null,
|
||||
canBeUninstalled: false,
|
||||
autoUpgrade: false,
|
||||
applicationRegistrationId: null,
|
||||
primaryPublicDomainId: null,
|
||||
createdAt: new Date(),
|
||||
|
||||
Reference in New Issue
Block a user