remove nestjs-query from app-token and drop unused createOneAppToken mutation (#22765)
## What Migrates `app-token` off `@ptc-org/nestjs-query` and removes the auto-generated `createOneAppToken` mutation, which was unused dead API surface. ## Why The `createOneAppToken` mutation was reachable only from the schema — no frontend query, SDK caller, or test used it. It was also non-functional (its input couldn't set the token `value`), a leftover from nestjs-query's default `create.one` being left enabled. Real app tokens (refresh, password-reset, email-verification, invitation, OAuth, enterprise) are all created directly via the repository in ~14 services, none of which touched this mutation. ## Notes - ⚠️ This removes `AppToken`, `createOneAppToken`, `CreateAppTokenInput`, and `CreateOneAppTokenInput` from the `/metadata` schema, so the **api-breaking-changes check will flag it** <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/22765?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
@@ -952,14 +952,6 @@ enum WorkspaceActivationStatus {
|
||||
SUSPENDED
|
||||
}
|
||||
|
||||
type AppToken {
|
||||
id: UUID!
|
||||
type: String!
|
||||
expiresAt: DateTime!
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
type User {
|
||||
id: UUID!
|
||||
firstName: String!
|
||||
@@ -3512,7 +3504,6 @@ type Mutation {
|
||||
createPublicDomain(domain: String!, applicationId: String!): PublicDomain!
|
||||
deletePublicDomain(domain: String!): Boolean!
|
||||
checkPublicDomainValidRecords(domain: String!): DomainValidRecords
|
||||
createOneAppToken(input: CreateOneAppTokenInput!): AppToken!
|
||||
createDevelopmentApplication(universalIdentifier: String!, name: String!): DevelopmentApplication!
|
||||
syncApplication(manifest: JSON!, dryRun: Boolean): WorkspaceMigration!
|
||||
uploadApplicationFile(file: Upload!, applicationUniversalIdentifier: String!, fileFolder: FileFolder!, filePath: String!): File!
|
||||
@@ -4682,15 +4673,6 @@ input UpdateLabPublicFeatureFlagInput {
|
||||
value: Boolean!
|
||||
}
|
||||
|
||||
input CreateOneAppTokenInput {
|
||||
"""The record to create"""
|
||||
appToken: CreateAppTokenInput!
|
||||
}
|
||||
|
||||
input CreateAppTokenInput {
|
||||
expiresAt: DateTime!
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
onEventSubscription(eventStreamId: String!): EventSubscription
|
||||
logicFunctionLogs(input: LogicFunctionLogsInput!): LogicFunctionLogs!
|
||||
|
||||
@@ -669,15 +669,6 @@ export type WorkspaceDiscoverability = 'PUBLIC' | 'MEMBERS_AND_INVITEES' | 'HIDD
|
||||
|
||||
export type WorkspaceActivationStatus = 'ONGOING_CREATION' | 'PENDING_CREATION' | 'ACTIVE' | 'INACTIVE' | 'SUSPENDED'
|
||||
|
||||
export interface AppToken {
|
||||
id: Scalars['UUID']
|
||||
type: Scalars['String']
|
||||
expiresAt: Scalars['DateTime']
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
__typename: 'AppToken'
|
||||
}
|
||||
|
||||
export interface User {
|
||||
id: Scalars['UUID']
|
||||
firstName: Scalars['String']
|
||||
@@ -3048,7 +3039,6 @@ export interface Mutation {
|
||||
createPublicDomain: PublicDomain
|
||||
deletePublicDomain: Scalars['Boolean']
|
||||
checkPublicDomainValidRecords?: DomainValidRecords
|
||||
createOneAppToken: AppToken
|
||||
createDevelopmentApplication: DevelopmentApplication
|
||||
syncApplication: WorkspaceMigration
|
||||
uploadApplicationFile: File
|
||||
@@ -3751,16 +3741,6 @@ export interface WorkspaceGenqlSelection{
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface AppTokenGenqlSelection{
|
||||
id?: boolean | number
|
||||
type?: boolean | number
|
||||
expiresAt?: boolean | number
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface UserGenqlSelection{
|
||||
id?: boolean | number
|
||||
firstName?: boolean | number
|
||||
@@ -6300,7 +6280,6 @@ export interface MutationGenqlSelection{
|
||||
createPublicDomain?: (PublicDomainGenqlSelection & { __args: {domain: Scalars['String'], applicationId: Scalars['String']} })
|
||||
deletePublicDomain?: { __args: {domain: Scalars['String']} }
|
||||
checkPublicDomainValidRecords?: (DomainValidRecordsGenqlSelection & { __args: {domain: Scalars['String']} })
|
||||
createOneAppToken?: (AppTokenGenqlSelection & { __args: {input: CreateOneAppTokenInput} })
|
||||
createDevelopmentApplication?: (DevelopmentApplicationGenqlSelection & { __args: {universalIdentifier: Scalars['String'], name: Scalars['String']} })
|
||||
syncApplication?: (WorkspaceMigrationGenqlSelection & { __args: {manifest: Scalars['JSON'], dryRun?: (Scalars['Boolean'] | null)} })
|
||||
uploadApplicationFile?: (FileGenqlSelection & { __args: {file: Scalars['Upload'], applicationUniversalIdentifier: Scalars['String'], fileFolder: FileFolder, filePath: Scalars['String']} })
|
||||
@@ -6689,12 +6668,6 @@ export interface ConnectionParametersInput {host: Scalars['String'],port: Scalar
|
||||
|
||||
export interface UpdateLabPublicFeatureFlagInput {publicFeatureFlag: Scalars['String'],value: Scalars['Boolean']}
|
||||
|
||||
export interface CreateOneAppTokenInput {
|
||||
/** The record to create */
|
||||
appToken: CreateAppTokenInput}
|
||||
|
||||
export interface CreateAppTokenInput {expiresAt: Scalars['DateTime']}
|
||||
|
||||
export interface SubscriptionGenqlSelection{
|
||||
onEventSubscription?: (EventSubscriptionGenqlSelection & { __args: {eventStreamId: Scalars['String']} })
|
||||
logicFunctionLogs?: (LogicFunctionLogsGenqlSelection & { __args: {input: LogicFunctionLogsInput} })
|
||||
@@ -7011,14 +6984,6 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
|
||||
|
||||
|
||||
|
||||
const AppToken_possibleTypes: string[] = ['AppToken']
|
||||
export const isAppToken = (obj?: { __typename?: any } | null): obj is AppToken => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isAppToken"')
|
||||
return AppToken_possibleTypes.includes(obj.__typename)
|
||||
}
|
||||
|
||||
|
||||
|
||||
const User_possibleTypes: string[] = ['User']
|
||||
export const isUser = (obj?: { __typename?: any } | null): obj is User => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isUser"')
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -279,15 +279,6 @@ export type AppConnection = {
|
||||
visibility: Scalars['String']['output'];
|
||||
};
|
||||
|
||||
export type AppToken = {
|
||||
__typename?: 'AppToken';
|
||||
createdAt: Scalars['DateTime']['output'];
|
||||
expiresAt: Scalars['DateTime']['output'];
|
||||
id: Scalars['UUID']['output'];
|
||||
type: Scalars['String']['output'];
|
||||
updatedAt: Scalars['DateTime']['output'];
|
||||
};
|
||||
|
||||
export type Application = {
|
||||
__typename?: 'Application';
|
||||
agents: Array<Agent>;
|
||||
@@ -1052,10 +1043,6 @@ export type CreateApiKeyInput = {
|
||||
roleId: Scalars['UUID']['input'];
|
||||
};
|
||||
|
||||
export type CreateAppTokenInput = {
|
||||
expiresAt: Scalars['DateTime']['input'];
|
||||
};
|
||||
|
||||
export type CreateApplicationRegistration = {
|
||||
__typename?: 'CreateApplicationRegistration';
|
||||
applicationRegistration: ApplicationRegistration;
|
||||
@@ -1225,11 +1212,6 @@ export type CreateObjectInput = {
|
||||
skipNameField?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
};
|
||||
|
||||
export type CreateOneAppTokenInput = {
|
||||
/** The record to create */
|
||||
appToken: CreateAppTokenInput;
|
||||
};
|
||||
|
||||
export type CreateOneFieldMetadataInput = {
|
||||
/** The record to create */
|
||||
field: CreateFieldInput;
|
||||
@@ -2557,7 +2539,6 @@ export type Mutation = {
|
||||
createOIDCIdentityProvider: SetupSso;
|
||||
createObjectEvent: Analytics;
|
||||
createOneAgent: Agent;
|
||||
createOneAppToken: AppToken;
|
||||
createOneField: Field;
|
||||
createOneIndex: Index;
|
||||
createOneLogicFunction: LogicFunction;
|
||||
@@ -2925,11 +2906,6 @@ export type MutationCreateOneAgentArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationCreateOneAppTokenArgs = {
|
||||
input: CreateOneAppTokenInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationCreateOneFieldArgs = {
|
||||
input: CreateOneFieldMetadataInput;
|
||||
};
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
import {
|
||||
type AutoResolverOpts,
|
||||
PagingStrategies,
|
||||
type ReadResolverOpts,
|
||||
} from '@ptc-org/nestjs-query-graphql';
|
||||
|
||||
import { AppTokenEntity } from 'src/engine/core-modules/app-token/app-token.entity';
|
||||
import { CreateAppTokenInput } from 'src/engine/core-modules/app-token/dtos/create-app-token.input';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
|
||||
export const appTokenAutoResolverOpts: AutoResolverOpts<
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
any,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
any,
|
||||
unknown,
|
||||
unknown,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
ReadResolverOpts<any>,
|
||||
PagingStrategies
|
||||
>[] = [
|
||||
{
|
||||
EntityClass: AppTokenEntity,
|
||||
DTOClass: AppTokenEntity,
|
||||
CreateDTOClass: CreateAppTokenInput,
|
||||
enableTotalCount: true,
|
||||
pagingStrategy: PagingStrategies.CURSOR,
|
||||
read: {
|
||||
many: { disabled: true },
|
||||
one: { disabled: true },
|
||||
},
|
||||
create: {
|
||||
many: { disabled: true },
|
||||
},
|
||||
update: {
|
||||
many: { disabled: true },
|
||||
one: { disabled: true },
|
||||
},
|
||||
delete: { many: { disabled: true }, one: { disabled: true } },
|
||||
guards: [WorkspaceAuthGuard],
|
||||
},
|
||||
];
|
||||
@@ -1,6 +1,3 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { BeforeCreateOne, IDField } from '@ptc-org/nestjs-query-graphql';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
BeforeInsert,
|
||||
@@ -15,8 +12,6 @@ import {
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { BeforeCreateOneAppToken } from 'src/engine/core-modules/app-token/hooks/before-create-one-app-token.hook';
|
||||
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
|
||||
@@ -32,10 +27,7 @@ export enum AppTokenType {
|
||||
}
|
||||
|
||||
@Entity({ name: 'appToken', schema: 'core' })
|
||||
@ObjectType('AppToken')
|
||||
@BeforeCreateOne(BeforeCreateOneAppToken)
|
||||
export class AppTokenEntity {
|
||||
@IDField(() => UUIDScalarType)
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@@ -57,14 +49,12 @@ export class AppTokenEntity {
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
workspaceId: string | null;
|
||||
|
||||
@Field()
|
||||
@Column({ nullable: false, type: 'text', default: AppTokenType.RefreshToken })
|
||||
type: AppTokenType;
|
||||
|
||||
@Column({ nullable: true, type: 'text' })
|
||||
value: string;
|
||||
|
||||
@Field()
|
||||
@Column({ type: 'timestamptz' })
|
||||
expiresAt: Date;
|
||||
|
||||
@@ -74,11 +64,9 @@ export class AppTokenEntity {
|
||||
@Column({ nullable: true, type: 'timestamptz' })
|
||||
revokedAt: Date | null;
|
||||
|
||||
@Field()
|
||||
@CreateDateColumn({ type: 'timestamptz' })
|
||||
createdAt: Date;
|
||||
|
||||
@Field()
|
||||
@UpdateDateColumn({ type: 'timestamptz' })
|
||||
updatedAt: Date;
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql';
|
||||
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
||||
|
||||
import { AppTokenEntity } from 'src/engine/core-modules/app-token/app-token.entity';
|
||||
import { appTokenAutoResolverOpts } from 'src/engine/core-modules/app-token/app-token.auto-resolver-opts';
|
||||
import { AppTokenService } from 'src/engine/core-modules/app-token/services/app-token.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
NestjsQueryGraphQLModule.forFeature({
|
||||
imports: [NestjsQueryTypeOrmModule.forFeature([AppTokenEntity])],
|
||||
services: [AppTokenService],
|
||||
resolvers: appTokenAutoResolverOpts,
|
||||
}),
|
||||
],
|
||||
})
|
||||
export class AppTokenModule {}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import { IsDate, IsNotEmpty } from 'class-validator';
|
||||
|
||||
@InputType()
|
||||
export class CreateAppTokenInput {
|
||||
@IsDate()
|
||||
@IsNotEmpty()
|
||||
@Field()
|
||||
expiresAt: Date;
|
||||
}
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
import {
|
||||
type BeforeCreateOneHook,
|
||||
type CreateOneInputType,
|
||||
} from '@ptc-org/nestjs-query-graphql';
|
||||
|
||||
import { type AppTokenEntity } from 'src/engine/core-modules/app-token/app-token.entity';
|
||||
|
||||
export class BeforeCreateOneAppToken<
|
||||
T extends AppTokenEntity,
|
||||
> implements BeforeCreateOneHook<T> {
|
||||
async run(
|
||||
instance: CreateOneInputType<T>,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
context: any,
|
||||
): Promise<CreateOneInputType<T>> {
|
||||
const userId = context?.req?.user?.id;
|
||||
|
||||
instance.input.userId = userId;
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
|
||||
import { AppTokenService } from 'src/engine/core-modules/app-token/services/app-token.service';
|
||||
import { AppTokenEntity } from 'src/engine/core-modules/app-token/app-token.entity';
|
||||
|
||||
describe('AppTokenService', () => {
|
||||
let service: AppTokenService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
AppTokenService,
|
||||
{
|
||||
provide: getRepositoryToken(AppTokenEntity),
|
||||
useValue: {
|
||||
manager: {
|
||||
connection: { driver: { options: { type: 'postgres' } } },
|
||||
},
|
||||
metadata: { columns: [] },
|
||||
},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get<AppTokenService>(AppTokenService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { AppTokenEntity } from 'src/engine/core-modules/app-token/app-token.entity';
|
||||
|
||||
export class AppTokenService extends TypeOrmQueryService<AppTokenEntity> {
|
||||
constructor(
|
||||
@InjectRepository(AppTokenEntity)
|
||||
private readonly appTokenRepository: Repository<AppTokenEntity>,
|
||||
) {
|
||||
super(appTokenRepository);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import { CoreEntityCacheModule } from 'src/engine/core-entity-cache/core-entity-
|
||||
import { ApiKeyEntity } from 'src/engine/core-modules/api-key/api-key.entity';
|
||||
import { ApiKeyModule } from 'src/engine/core-modules/api-key/api-key.module';
|
||||
import { AppTokenEntity } from 'src/engine/core-modules/app-token/app-token.entity';
|
||||
import { AppTokenService } from 'src/engine/core-modules/app-token/services/app-token.service';
|
||||
import { ApplicationRegistrationModule } from 'src/engine/core-modules/application/application-registration/application-registration.module';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { ConnectionProviderOAuthController } from 'src/engine/core-modules/application/connection-provider/connection-provider-oauth.controller';
|
||||
@@ -151,7 +150,6 @@ import { JwtAuthStrategy } from './strategies/jwt.auth.strategy';
|
||||
GoogleAPIScopesService,
|
||||
GoogleApisServiceAvailabilityService,
|
||||
MicrosoftAPIsService,
|
||||
AppTokenService,
|
||||
AccessTokenService,
|
||||
RefreshTokenService,
|
||||
LoginTokenService,
|
||||
|
||||
@@ -6,7 +6,6 @@ import { WorkspaceQueryRunnerModule } from 'src/engine/api/graphql/workspace-que
|
||||
import { ActorModule } from 'src/engine/core-modules/actor/actor.module';
|
||||
import { AdminPanelModule } from 'src/engine/core-modules/admin-panel/admin-panel.module';
|
||||
import { ApiKeyModule } from 'src/engine/core-modules/api-key/api-key.module';
|
||||
import { AppTokenModule } from 'src/engine/core-modules/app-token/app-token.module';
|
||||
import { ApplicationDevelopmentModule } from 'src/engine/core-modules/application/application-development/application-development.module';
|
||||
import { ApplicationInstallModule } from 'src/engine/core-modules/application/application-install/application-install.module';
|
||||
import { MarketplaceModule } from 'src/engine/core-modules/application/application-marketplace/marketplace.module';
|
||||
@@ -107,7 +106,6 @@ import { FileModule } from './file/file.module';
|
||||
ApplicationUpgradeModule,
|
||||
ApplicationDevelopmentModule,
|
||||
MarketplaceModule,
|
||||
AppTokenModule,
|
||||
TimelineMessagingModule,
|
||||
TimelineCalendarEventModule,
|
||||
UserModule,
|
||||
|
||||
Reference in New Issue
Block a user