1635 extensibilitytwenty cli app vars (#15143)

- Update twenty-cli to support application env variable definition
- Update twenty-server to create a new `core.applicationVariable` entity
to store env variables and provide env var when executing serverless
function
- Update twenty-front to support application environment variable value
setting

<img width="1044" height="660" alt="image"
src="https://github.com/user-attachments/assets/24c3d323-5370-4a80-8174-fc4653cc3c22"
/>

<img width="1178" height="662" alt="image"
src="https://github.com/user-attachments/assets/c124f423-8ed8-4246-ae5b-a9bd6672c7dc"
/>

<img width="1163" height="823" alt="image"
src="https://github.com/user-attachments/assets/fb7425a3-facc-4895-a5eb-8a8e278e0951"
/>

<img width="1087" height="696" alt="image"
src="https://github.com/user-attachments/assets/113da8a2-5590-433c-b1b3-5ed3137f24ca"
/>

<img width="1512" height="715" alt="image"
src="https://github.com/user-attachments/assets/1d2110b7-301d-4f21-a45c-ddd54d6e3391"
/>

<img width="1287" height="581" alt="image"
src="https://github.com/user-attachments/assets/353b16c6-0527-444c-87d6-51447a96cbc7"
/>
This commit is contained in:
martmull
2025-10-17 10:54:38 +02:00
committed by GitHub
parent 54baa47fbb
commit d2e7f2a910
58 changed files with 1305 additions and 359 deletions
@@ -28,6 +28,7 @@ import { FlatRouteTrigger } from 'src/engine/metadata-modules/route-trigger/type
import { ServerlessFunctionLayerService } from 'src/engine/metadata-modules/serverless-function-layer/serverless-function-layer.service';
import { ServerlessFunctionV2Service } from 'src/engine/metadata-modules/serverless-function/services/serverless-function-v2.service';
import { FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type';
import { ApplicationVariableService } from 'src/engine/core-modules/applicationVariable/application-variable.service';
@Injectable()
export class ApplicationSyncService {
@@ -35,6 +36,7 @@ export class ApplicationSyncService {
constructor(
private readonly applicationService: ApplicationService,
private readonly applicationVariableService: ApplicationVariableService,
private readonly serverlessFunctionLayerService: ServerlessFunctionLayerService,
private readonly objectMetadataServiceV2: ObjectMetadataServiceV2,
private readonly serverlessFunctionV2Service: ServerlessFunctionV2Service,
@@ -106,7 +108,7 @@ export class ApplicationSyncService {
workspaceId,
);
return await this.applicationService.create({
const application = await this.applicationService.create({
universalIdentifier: manifest.universalIdentifier,
name: manifest.name,
description: manifest.description,
@@ -115,6 +117,13 @@ export class ApplicationSyncService {
serverlessFunctionLayerId: serverlessFunctionLayer.id,
workspaceId,
});
await this.applicationVariableService.upsertManyApplicationVariables({
env: manifest.env,
applicationId: application.id,
});
return application;
}
await this.serverlessFunctionLayerService.update(
@@ -131,6 +140,11 @@ export class ApplicationSyncService {
version: manifest.version,
});
await this.applicationVariableService.upsertManyApplicationVariables({
env: manifest.env,
applicationId: application.id,
});
return application;
}
@@ -18,6 +18,7 @@ import { AgentEntity } from 'src/engine/metadata-modules/agent/agent.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { ServerlessFunctionLayerEntity } from 'src/engine/metadata-modules/serverless-function-layer/serverless-function-layer.entity';
import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity';
import { ApplicationVariable } from 'src/engine/core-modules/applicationVariable/application-variable.entity';
@Entity({ name: 'application', schema: 'core' })
@Index('IDX_APPLICATION_WORKSPACE_ID', ['workspaceId'])
@@ -86,6 +87,15 @@ export class ApplicationEntity {
})
objects: Relation<ObjectMetadataEntity[]>;
@OneToMany(
() => ApplicationVariable,
(applicationVariable) => applicationVariable.application,
{
onDelete: 'CASCADE',
},
)
applicationVariables: Relation<ApplicationVariable[]>;
@ManyToOne(() => Workspace, {
onDelete: 'CASCADE',
})
@@ -16,6 +16,7 @@ import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadat
import { RouteTriggerModule } from 'src/engine/metadata-modules/route-trigger/route-trigger.module';
import { ServerlessFunctionLayerModule } from 'src/engine/metadata-modules/serverless-function-layer/serverless-function-layer.module';
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
import { ApplicationVariableModule } from 'src/engine/core-modules/applicationVariable/application-variable.module';
@Module({
imports: [
@@ -24,6 +25,7 @@ import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless
ObjectMetadataModule,
DataSourceModule,
AgentModule,
ApplicationVariableModule,
ServerlessFunctionLayerModule,
ServerlessFunctionModule,
DatabaseEventTriggerModule,
@@ -25,7 +25,12 @@ export class ApplicationService {
): Promise<ApplicationEntity[]> {
return this.applicationRepository.find({
where: { workspaceId },
relations: ['serverlessFunctions', 'agents', 'objects'],
relations: [
'serverlessFunctions',
'agents',
'objects',
'applicationVariables',
],
});
}
@@ -35,7 +40,12 @@ export class ApplicationService {
): Promise<ApplicationEntity> {
const application = await this.applicationRepository.findOne({
where: { workspaceId, id: applicationId },
relations: ['serverlessFunctions', 'agents', 'objects'],
relations: [
'serverlessFunctions',
'agents',
'objects',
'applicationVariables',
],
});
if (!isDefined(application)) {
@@ -6,6 +6,7 @@ import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/
import { ServerlessFunctionDTO } from 'src/engine/metadata-modules/serverless-function/dtos/serverless-function.dto';
import { AgentDTO } from 'src/engine/metadata-modules/agent/dtos/agent.dto';
import { ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto';
import { ApplicationVariableDTO } from 'src/engine/core-modules/applicationVariable/dtos/application-variable.dto';
@ObjectType('Application')
export class ApplicationDTO {
@@ -22,6 +23,10 @@ export class ApplicationDTO {
@Field()
description: string;
@IsString()
@Field()
version: string;
@Field(() => [AgentDTO])
agents: AgentDTO[];
@@ -30,4 +35,7 @@ export class ApplicationDTO {
@Field(() => [ObjectMetadataDTO])
objects: ObjectMetadataDTO[];
@Field(() => [ApplicationVariableDTO])
applicationVariables: ApplicationVariableDTO[];
}
@@ -11,6 +11,15 @@ export type PackageJson = {
npm: string;
yarn: string;
};
env: Record<
string,
{
key: string;
value?: string;
description?: string;
isSecret: boolean;
}
>;
icon?: string;
version: string;
dependencies?: object;