7415 serverless functions update environment variables in a dedicated tab in settings functions not a env file (#7939)
   
This commit is contained in:
@ -3,7 +3,7 @@ import { ID, InputType } from '@nestjs/graphql';
|
||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||
|
||||
@InputType()
|
||||
export class DeleteServerlessFunctionInput {
|
||||
export class ServerlessFunctionIdInput {
|
||||
@IDField(() => ID, { description: 'The id of the function.' })
|
||||
id!: string;
|
||||
}
|
||||
@ -11,6 +11,7 @@ import {
|
||||
QueryOptions,
|
||||
} from '@ptc-org/nestjs-query-graphql';
|
||||
import {
|
||||
IsArray,
|
||||
IsDateString,
|
||||
IsEnum,
|
||||
IsNotEmpty,
|
||||
@ -59,6 +60,10 @@ export class ServerlessFunctionDTO {
|
||||
@Field({ nullable: true })
|
||||
latestVersion: string;
|
||||
|
||||
@IsArray()
|
||||
@Field(() => [String], { nullable: false })
|
||||
publishedVersions: string[];
|
||||
|
||||
@IsEnum(ServerlessFunctionSyncStatus)
|
||||
@IsNotEmpty()
|
||||
@Field(() => ServerlessFunctionSyncStatus)
|
||||
|
||||
@ -29,6 +29,9 @@ export class ServerlessFunctionEntity {
|
||||
@Column({ nullable: true })
|
||||
latestVersion: string;
|
||||
|
||||
@Column({ nullable: false, type: 'jsonb', default: [] })
|
||||
publishedVersions: string[];
|
||||
|
||||
@Column({ nullable: false, default: ServerlessFunctionRuntime.NODE18 })
|
||||
runtime: ServerlessFunctionRuntime;
|
||||
|
||||
|
||||
@ -1,55 +1,23 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { SortDirection } from '@ptc-org/nestjs-query-core';
|
||||
import {
|
||||
NestjsQueryGraphQLModule,
|
||||
PagingStrategies,
|
||||
} from '@ptc-org/nestjs-query-graphql';
|
||||
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
||||
|
||||
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||
import { FileUploadModule } from 'src/engine/core-modules/file/file-upload/file-upload.module';
|
||||
import { FileModule } from 'src/engine/core-modules/file/file.module';
|
||||
import { ServerlessModule } from 'src/engine/core-modules/serverless/serverless.module';
|
||||
import { ThrottlerModule } from 'src/engine/core-modules/throttler/throttler.module';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { ServerlessFunctionDTO } from 'src/engine/metadata-modules/serverless-function/dtos/serverless-function.dto';
|
||||
import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity';
|
||||
import { ServerlessFunctionResolver } from 'src/engine/metadata-modules/serverless-function/serverless-function.resolver';
|
||||
import { ServerlessFunctionService } from 'src/engine/metadata-modules/serverless-function/serverless-function.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
NestjsQueryGraphQLModule.forFeature({
|
||||
imports: [
|
||||
FileUploadModule,
|
||||
NestjsQueryTypeOrmModule.forFeature(
|
||||
[ServerlessFunctionEntity],
|
||||
'metadata',
|
||||
),
|
||||
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
||||
FileModule,
|
||||
ThrottlerModule,
|
||||
],
|
||||
services: [ServerlessFunctionService],
|
||||
resolvers: [
|
||||
{
|
||||
EntityClass: ServerlessFunctionEntity,
|
||||
DTOClass: ServerlessFunctionDTO,
|
||||
ServiceClass: ServerlessFunctionService,
|
||||
pagingStrategy: PagingStrategies.CURSOR,
|
||||
read: {
|
||||
defaultSort: [{ field: 'id', direction: SortDirection.DESC }],
|
||||
},
|
||||
create: { disabled: true },
|
||||
update: { disabled: true },
|
||||
delete: { disabled: true },
|
||||
guards: [WorkspaceAuthGuard],
|
||||
},
|
||||
],
|
||||
}),
|
||||
ServerlessModule,
|
||||
FileUploadModule,
|
||||
NestjsQueryTypeOrmModule.forFeature([ServerlessFunctionEntity], 'metadata'),
|
||||
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
||||
FileModule,
|
||||
ThrottlerModule,
|
||||
],
|
||||
providers: [ServerlessFunctionService, ServerlessFunctionResolver],
|
||||
exports: [ServerlessFunctionService],
|
||||
|
||||
@ -11,7 +11,7 @@ import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { CreateServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/create-serverless-function.input';
|
||||
import { DeleteServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/delete-serverless-function.input';
|
||||
import { ServerlessFunctionIdInput } from 'src/engine/metadata-modules/serverless-function/dtos/serverless-function-id.input';
|
||||
import { ExecuteServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/execute-serverless-function.input';
|
||||
import { GetServerlessFunctionSourceCodeInput } from 'src/engine/metadata-modules/serverless-function/dtos/get-serverless-function-source-code.input';
|
||||
import { PublishServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/publish-serverless-function.input';
|
||||
@ -50,6 +50,39 @@ export class ServerlessFunctionResolver {
|
||||
}
|
||||
}
|
||||
|
||||
@Query(() => ServerlessFunctionDTO)
|
||||
async findOneServerlessFunction(
|
||||
@Args('input') { id }: ServerlessFunctionIdInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
try {
|
||||
await this.checkFeatureFlag(workspaceId);
|
||||
|
||||
return (
|
||||
await this.serverlessFunctionService.findManyServerlessFunctions({
|
||||
id,
|
||||
})
|
||||
)?.[0];
|
||||
} catch (error) {
|
||||
serverlessFunctionGraphQLApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Query(() => [ServerlessFunctionDTO])
|
||||
async findManyServerlessFunctions(
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
try {
|
||||
await this.checkFeatureFlag(workspaceId);
|
||||
|
||||
return await this.serverlessFunctionService.findManyServerlessFunctions({
|
||||
workspaceId,
|
||||
});
|
||||
} catch (error) {
|
||||
serverlessFunctionGraphQLApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Query(() => graphqlTypeJson)
|
||||
async getAvailablePackages(@AuthWorkspace() { id: workspaceId }: Workspace) {
|
||||
try {
|
||||
@ -81,7 +114,7 @@ export class ServerlessFunctionResolver {
|
||||
|
||||
@Mutation(() => ServerlessFunctionDTO)
|
||||
async deleteOneServerlessFunction(
|
||||
@Args('input') input: DeleteServerlessFunctionInput,
|
||||
@Args('input') input: ServerlessFunctionIdInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
try {
|
||||
|
||||
@ -3,7 +3,6 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { basename, dirname, join } from 'path';
|
||||
|
||||
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
||||
import deepEqual from 'deep-equal';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
@ -34,7 +33,7 @@ import {
|
||||
import { isDefined } from 'src/utils/is-defined';
|
||||
|
||||
@Injectable()
|
||||
export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFunctionEntity> {
|
||||
export class ServerlessFunctionService {
|
||||
constructor(
|
||||
private readonly fileStorageService: FileStorageService,
|
||||
private readonly serverlessService: ServerlessService,
|
||||
@ -42,8 +41,10 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun
|
||||
private readonly serverlessFunctionRepository: Repository<ServerlessFunctionEntity>,
|
||||
private readonly throttlerService: ThrottlerService,
|
||||
private readonly environmentService: EnvironmentService,
|
||||
) {
|
||||
super(serverlessFunctionRepository);
|
||||
) {}
|
||||
|
||||
async findManyServerlessFunctions(where) {
|
||||
return this.serverlessFunctionRepository.findBy(where);
|
||||
}
|
||||
|
||||
async getServerlessFunctionSourceCode(
|
||||
@ -51,12 +52,11 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun
|
||||
id: string,
|
||||
version: string,
|
||||
): Promise<{ [filePath: string]: string } | undefined> {
|
||||
const serverlessFunction = await this.serverlessFunctionRepository.findOne({
|
||||
where: {
|
||||
const serverlessFunction =
|
||||
await this.serverlessFunctionRepository.findOneBy({
|
||||
id,
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
if (!serverlessFunction) {
|
||||
throw new ServerlessFunctionException(
|
||||
@ -101,12 +101,12 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun
|
||||
): Promise<ServerlessExecuteResult> {
|
||||
await this.throttleExecution(workspaceId);
|
||||
|
||||
const functionToExecute = await this.serverlessFunctionRepository.findOne({
|
||||
where: {
|
||||
const functionToExecute = await this.serverlessFunctionRepository.findOneBy(
|
||||
{
|
||||
id,
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
);
|
||||
|
||||
if (!functionToExecute) {
|
||||
throw new ServerlessFunctionException(
|
||||
@ -120,9 +120,7 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun
|
||||
|
||||
async publishOneServerlessFunction(id: string, workspaceId: string) {
|
||||
const existingServerlessFunction =
|
||||
await this.serverlessFunctionRepository.findOne({
|
||||
where: { id, workspaceId },
|
||||
});
|
||||
await this.serverlessFunctionRepository.findOneBy({ id, workspaceId });
|
||||
|
||||
if (!existingServerlessFunction) {
|
||||
throw new ServerlessFunctionException(
|
||||
@ -154,17 +152,29 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun
|
||||
existingServerlessFunction,
|
||||
);
|
||||
|
||||
await super.updateOne(existingServerlessFunction.id, {
|
||||
latestVersion: newVersion,
|
||||
});
|
||||
const newPublishedVersions = [
|
||||
...existingServerlessFunction.publishedVersions,
|
||||
newVersion,
|
||||
];
|
||||
|
||||
return await this.findById(existingServerlessFunction.id);
|
||||
await this.serverlessFunctionRepository.update(
|
||||
existingServerlessFunction.id,
|
||||
{
|
||||
latestVersion: newVersion,
|
||||
publishedVersions: newPublishedVersions,
|
||||
},
|
||||
);
|
||||
|
||||
return this.serverlessFunctionRepository.findOneBy({
|
||||
id: existingServerlessFunction.id,
|
||||
});
|
||||
}
|
||||
|
||||
async deleteOneServerlessFunction(id: string, workspaceId: string) {
|
||||
const existingServerlessFunction =
|
||||
await this.serverlessFunctionRepository.findOne({
|
||||
where: { id, workspaceId },
|
||||
await this.serverlessFunctionRepository.findOneBy({
|
||||
id,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
if (!existingServerlessFunction) {
|
||||
@ -174,7 +184,7 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun
|
||||
);
|
||||
}
|
||||
|
||||
await super.deleteOne(id);
|
||||
await this.serverlessFunctionRepository.delete(id);
|
||||
|
||||
await this.serverlessService.delete(existingServerlessFunction);
|
||||
|
||||
@ -192,8 +202,9 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun
|
||||
workspaceId: string,
|
||||
) {
|
||||
const existingServerlessFunction =
|
||||
await this.serverlessFunctionRepository.findOne({
|
||||
where: { id: serverlessFunctionInput.id, workspaceId },
|
||||
await this.serverlessFunctionRepository.findOneBy({
|
||||
id: serverlessFunctionInput.id,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
if (!existingServerlessFunction) {
|
||||
@ -203,11 +214,14 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun
|
||||
);
|
||||
}
|
||||
|
||||
await super.updateOne(existingServerlessFunction.id, {
|
||||
name: serverlessFunctionInput.name,
|
||||
description: serverlessFunctionInput.description,
|
||||
syncStatus: ServerlessFunctionSyncStatus.NOT_READY,
|
||||
});
|
||||
await this.serverlessFunctionRepository.update(
|
||||
existingServerlessFunction.id,
|
||||
{
|
||||
name: serverlessFunctionInput.name,
|
||||
description: serverlessFunctionInput.description,
|
||||
syncStatus: ServerlessFunctionSyncStatus.NOT_READY,
|
||||
},
|
||||
);
|
||||
|
||||
const fileFolder = getServerlessFolder({
|
||||
serverlessFunction: existingServerlessFunction,
|
||||
@ -224,11 +238,16 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun
|
||||
}
|
||||
|
||||
await this.serverlessService.build(existingServerlessFunction, 'draft');
|
||||
await super.updateOne(existingServerlessFunction.id, {
|
||||
syncStatus: ServerlessFunctionSyncStatus.READY,
|
||||
});
|
||||
await this.serverlessFunctionRepository.update(
|
||||
existingServerlessFunction.id,
|
||||
{
|
||||
syncStatus: ServerlessFunctionSyncStatus.READY,
|
||||
},
|
||||
);
|
||||
|
||||
return await this.findById(existingServerlessFunction.id);
|
||||
return this.serverlessFunctionRepository.findOneBy({
|
||||
id: existingServerlessFunction.id,
|
||||
});
|
||||
}
|
||||
|
||||
async getAvailablePackages() {
|
||||
@ -255,11 +274,15 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun
|
||||
serverlessFunctionInput: CreateServerlessFunctionInput,
|
||||
workspaceId: string,
|
||||
) {
|
||||
const createdServerlessFunction = await super.createOne({
|
||||
...serverlessFunctionInput,
|
||||
workspaceId,
|
||||
layerVersion: LAST_LAYER_VERSION,
|
||||
});
|
||||
const serverlessFunctionToCreate =
|
||||
await this.serverlessFunctionRepository.create({
|
||||
...serverlessFunctionInput,
|
||||
workspaceId,
|
||||
layerVersion: LAST_LAYER_VERSION,
|
||||
});
|
||||
|
||||
const createdServerlessFunction =
|
||||
await this.serverlessFunctionRepository.save(serverlessFunctionToCreate);
|
||||
|
||||
const draftFileFolder = getServerlessFolder({
|
||||
serverlessFunction: createdServerlessFunction,
|
||||
@ -277,7 +300,9 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun
|
||||
|
||||
await this.serverlessService.build(createdServerlessFunction, 'draft');
|
||||
|
||||
return await this.findById(createdServerlessFunction.id);
|
||||
return this.serverlessFunctionRepository.findOneBy({
|
||||
id: createdServerlessFunction.id,
|
||||
});
|
||||
}
|
||||
|
||||
private async throttleExecution(workspaceId: string) {
|
||||
|
||||
Reference in New Issue
Block a user