sendEmail per CommandPattern

This commit is contained in:
clauspeterhuebner 2026-01-27 02:10:57 +01:00
parent 1d7d93aee6
commit 47e94c1671
22 changed files with 477 additions and 0 deletions

View File

@ -6,6 +6,7 @@ import { buildSchema } from 'type-graphql'
import { isAuthorized } from './directive/isAuthorized' import { isAuthorized } from './directive/isAuthorized'
import { AiChatResolver } from './resolver/AiChatResolver' import { AiChatResolver } from './resolver/AiChatResolver'
import { BalanceResolver } from './resolver/BalanceResolver' import { BalanceResolver } from './resolver/BalanceResolver'
import { CommandResolver } from 'core/src/graphql/resolver/CommandResolver'
import { CommunityResolver } from './resolver/CommunityResolver' import { CommunityResolver } from './resolver/CommunityResolver'
import { ContributionLinkResolver } from './resolver/ContributionLinkResolver' import { ContributionLinkResolver } from './resolver/ContributionLinkResolver'
import { ContributionMessageResolver } from './resolver/ContributionMessageResolver' import { ContributionMessageResolver } from './resolver/ContributionMessageResolver'
@ -25,6 +26,7 @@ export const schema = async (): Promise<GraphQLSchema> => {
resolvers: [ resolvers: [
AiChatResolver, AiChatResolver,
BalanceResolver, BalanceResolver,
CommandResolver,
CommunityResolver, CommunityResolver,
ContributionLinkResolver, ContributionLinkResolver,
ContributionMessageResolver, ContributionMessageResolver,

View File

@ -0,0 +1,15 @@
import { Command } from './Command';
export abstract class BaseCommand<T = any> implements Command<T> {
protected constructor(protected readonly params: any = {}) {}
abstract execute(): Promise<T>;
validate(): boolean {
return true; // Default implementation, override in subclasses
}
protected validateParams(requiredParams: string[]): boolean {
return requiredParams.every(param => this.params[param] !== undefined);
}
}

View File

@ -0,0 +1,4 @@
export interface Command<T = any> {
execute(): Promise<T>;
validate?(): boolean;
}

View File

@ -0,0 +1,68 @@
// core/src/command/CommandExecutor.ts
import { CommandJwtPayloadType } from 'shared';
import { interpretEncryptedTransferArgs } from '../graphql/logic/interpretEncryptedTransferArgs';
import { EncryptedTransferArgs } from '../graphql/model/EncryptedTransferArgs';
import { BaseCommand } from './BaseCommand';
import { Command } from './Command';
import { getLogger } from 'log4js';
import { LOG4JS_BASE_CATEGORY_NAME } from '../config/const';
import { CommandFactory } from './CommandFactory';
import { CommandResult } from '../graphql/model/CommandResult';
const createLogger = (method: string) =>
getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.command.CommandExecutor.${method}`)
export class CommandExecutor {
async executeCommand<T>(command: Command<T>): Promise<CommandResult> {
const methodLogger = createLogger(`executeCommand`)
try {
if (command.validate && !command.validate()) {
return { success: false, error: 'Command validation failed' };
}
methodLogger.debug(`executeCommand() executing command=${command.constructor.name}`)
const result = await command.execute();
methodLogger.debug(`executeCommand() executed result=${JSON.stringify(result)}`)
return { success: true, data: result };
} catch (error) {
methodLogger.error(`executeCommand() error=${error}`)
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error occurred'
};
}
}
async executeEncryptedCommand<T>(
encryptedArgs: EncryptedTransferArgs
): Promise<CommandResult> {
const methodLogger = createLogger(`executeEncryptedCommand`)
try {
// Decrypt the command data
const commandArgs = (await interpretEncryptedTransferArgs(encryptedArgs)) as CommandJwtPayloadType
if (!commandArgs) {
const errmsg = `invalid commandArgs payload of requesting community with publicKey=${encryptedArgs.publicKey}`
methodLogger.error(errmsg)
throw new Error(errmsg)
}
if (methodLogger.isDebugEnabled()) {
methodLogger.debug(`executeEncryptedCommand() commandArgs=${JSON.stringify(commandArgs)}`)
}
const command = CommandFactory.getInstance().createCommand(commandArgs.commandName, commandArgs.params);
// Execute the command
const result = await this.executeCommand(command);
if (methodLogger.isDebugEnabled()) {
methodLogger.debug(`executeCommand() result=${JSON.stringify(result)}`)
}
return result
} catch (error) {
methodLogger.error(`executeEncryptedCommand() error=${error}`)
const errorResult: CommandResult = {
success: false,
error: error instanceof Error ? error.message : 'Failed to process command'
};
return errorResult;
}
}
}

View File

@ -0,0 +1,28 @@
import { Command } from './Command';
import { BaseCommand } from './BaseCommand';
export class CommandFactory {
private static instance: CommandFactory;
private commands: Map<string, new (params: any) => Command> = new Map();
private constructor() {}
static getInstance(): CommandFactory {
if (!CommandFactory.instance) {
CommandFactory.instance = new CommandFactory();
}
return CommandFactory.instance;
}
registerCommand(name: string, commandClass: new (params: any) => Command): void {
this.commands.set(name, commandClass);
}
createCommand<T>(name: string, params: any = {}): Command<T> {
const CommandClass = this.commands.get(name);
if (!CommandClass) {
throw new Error(`Command ${name} not found`);
}
return new CommandClass(params) as Command<T>;
}
}

View File

@ -0,0 +1,24 @@
// core/src/command/CommandRegistry.ts
import { ICommand } from './CommandTypes';
export class CommandRegistry {
private static instance: CommandRegistry;
private commands: Map<string, new (params: any) => ICommand> = new Map();
private constructor() {}
static getInstance(): CommandRegistry {
if (!CommandRegistry.instance) {
CommandRegistry.instance = new CommandRegistry();
}
return CommandRegistry.instance;
}
static registerCommand(type: string, commandClass: new (params: any) => ICommand): void {
this.getInstance().commands.set(type, commandClass);
}
static getCommandClass(type: string): (new (params: any) => ICommand) | undefined {
return this.getInstance().commands.get(type);
}
}

View File

@ -0,0 +1,26 @@
// core/src/command/commands/ExampleCommand.ts
import { BaseCommand } from '../BaseCommand';
import { CommandRegistry } from '../CommandRegistry';
export interface ExampleCommandParams {
someData: string;
}
export class ExampleCommand extends BaseCommand<{ processed: boolean }> {
constructor(params: ExampleCommandParams) {
super('EXAMPLE_COMMAND', params);
}
validate(): boolean {
return !!this.params.someData;
}
async execute(): Promise<{ processed: boolean }> {
// Command implementation here
console.log('Executing ExampleCommand with data:', this.params.someData);
return { processed: true };
}
}
// Register the command
CommandRegistry.registerCommand('EXAMPLE_COMMAND', ExampleCommand);

View File

@ -0,0 +1,75 @@
import { BaseCommand } from '../BaseCommand';
import { sendTransactionReceivedEmail } from '../../emails/sendEmailVariants';
import { findForeignUserByUuids, findUserByIdentifier } from 'database';
import { LOG4JS_BASE_CATEGORY_NAME } from '../../config/const';
import { getLogger } from 'log4js';
const createLogger = (method: string) =>
getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.command.CommandExecutor.${method}`)
export class SendEmailCommand extends BaseCommand<{ success: boolean }> {
static readonly SEND_MAIL_COMMAND = 'SEND_MAIL_COMMAND';
constructor(params: {
mailType: string,
senderComUuid: string,
senderGradidoId: string,
receiverComUuid: string,
receiverGradidoId: string,
memo?: string,
amount?: number,
}) {
super(params);
}
validate(): boolean {
return this.validateParams(['mailType', 'senderComUuid', 'senderGradidoId', 'receiverComUuid', 'receiverGradidoId']);
}
async execute(): Promise<{ success: boolean }> {
const methodLogger = createLogger(`execute`)
if (!this.validate()) {
throw new Error('Invalid command parameters');
}
// find sender user
const senderUser = await findForeignUserByUuids(this.params.senderComUuid, this.params.senderGradidoId);
if (!senderUser) {
const errmsg = `Sender user not found: ${this.params.senderComUuid} ${this.params.senderGradidoId}`;
methodLogger.error(errmsg);
throw new Error(errmsg);
}
const recipientUser = await findUserByIdentifier(this.params.receiverGradidoId, this.params.receiverComUuid);
if (!recipientUser) {
const errmsg = `Recipient user not found: ${this.params.receiverComUuid} ${this.params.receiverGradidoId}`;
methodLogger.error(errmsg);
throw new Error(errmsg);
}
const emailParams = {
firstName: recipientUser.firstName,
lastName: recipientUser.lastName,
email: recipientUser.emailContact.email,
language: recipientUser.language,
senderFirstName: senderUser.firstName,
senderLastName: senderUser.lastName,
senderEmail: senderUser.emailContact?.email,
memo: this.params.memo || '',
transactionAmount: this.params.amount || 0,
};
switch(this.params.mailType) {
case 'sendTransactionReceivedEmail':
await sendTransactionReceivedEmail(emailParams);
break;
default:
throw new Error(`Unknown mail type: ${this.params.mailType}`);
}
try {
// Example: const result = await emailService.sendEmail(this.params);
return { success: true };
} catch (error) {
methodLogger.error('Error executing SendEmailCommand:', error);
throw error;
}
}
}

View File

@ -0,0 +1,11 @@
import { CommandFactory } from './CommandFactory';
import { SendEmailCommand } from './commands/SendEmailCommand';
// Import other commands...
export function initializeCommands(): void {
const factory = CommandFactory.getInstance();
// Register all commands
factory.registerCommand(SendEmailCommand.SEND_MAIL_COMMAND, SendEmailCommand);
// Register other commands...
}

View File

@ -0,0 +1,44 @@
import { EncryptedTransferArgs, ensureUrlEndsWithSlash } from 'core'
import { FederatedCommunity as DbFederatedCommunity } from 'database'
import { GraphQLClient } from 'graphql-request'
import { getLogger } from 'log4js'
import { LOG4JS_BASE_CATEGORY_NAME } from '../../../config/const'
import { sendCommand } from './query/sendCommand'
const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.federation.client.1_0.CommandClient`)
export class CommandClient {
dbCom: DbFederatedCommunity
endpoint: string
client: GraphQLClient
constructor(dbCom: DbFederatedCommunity) {
this.dbCom = dbCom
this.endpoint = ensureUrlEndsWithSlash(dbCom.endPoint).concat(dbCom.apiVersion).concat('/')
this.client = new GraphQLClient(this.endpoint, {
method: 'POST',
jsonSerializer: {
parse: JSON.parse,
stringify: JSON.stringify,
},
})
}
async sendCommand(args: EncryptedTransferArgs): Promise<boolean> {
logger.debug(`sendCommand at ${this.endpoint} for args:`, args)
try {
const { data } = await this.client.rawRequest<{ success: boolean }>(sendCommand, {
args,
})
if (!data?.success) {
logger.warn('sendCommand without response data from endpoint', this.endpoint)
return false
}
logger.debug('sendCommand successfully started with endpoint', this.endpoint)
return true
} catch (err) {
logger.error('error on sendCommand: ', err)
return false
}
}
}

View File

@ -0,0 +1,11 @@
import { gql } from 'graphql-request'
export const sendCommand = gql`
mutation ($args: EncryptedTransferArgs!) {
sendCommand(encryptedArgs: $args) {
success
data
error
}
}
`

View File

@ -0,0 +1,3 @@
import { CommandClient as V1_0_CommandClient } from 'core/src/federation/client/1_0/CommandClient'
export class CommandClient extends V1_0_CommandClient {}

View File

@ -0,0 +1,57 @@
import { ApiVersionType } from 'core'
import { FederatedCommunity as DbFederatedCommunity } from 'database'
import { CommandClient as V1_0_CommandClient } from './1_0/CommandClient'
import { CommandClient as V1_1_CommandClient } from './1_1/CommandClient'
type CommandClient = V1_0_CommandClient | V1_1_CommandClient
interface CommandClientInstance {
id: number
client: CommandClient
}
export class CommandClientFactory {
private static instanceArray: CommandClientInstance[] = []
/**
* The Singleton's constructor should always be private to prevent direct
* construction calls with the `new` operator.
*/
private constructor() {}
private static createCommandClient = (dbCom: DbFederatedCommunity) => {
switch (dbCom.apiVersion) {
case ApiVersionType.V1_0:
return new V1_0_CommandClient(dbCom)
case ApiVersionType.V1_1:
return new V1_1_CommandClient(dbCom)
default:
return null
}
}
/**
* The static method that controls the access to the singleton instance.
*
* This implementation let you subclass the Singleton class while keeping
* just one instance of each subclass around.
*/
public static getInstance(dbCom: DbFederatedCommunity): CommandClient | null {
const instance = CommandClientFactory.instanceArray.find(
(instance) => instance.id === dbCom.id,
)
if (instance) {
return instance.client
}
const client = CommandClientFactory.createCommandClient(dbCom)
if (client) {
CommandClientFactory.instanceArray.push({
id: dbCom.id,
client,
} as CommandClientInstance)
}
return client
}
}

View File

@ -0,0 +1,10 @@
import { getLogger } from 'log4js'
import { LOG4JS_BASE_CATEGORY_NAME } from '../../config/const'
const createLogger = (method: string) =>
getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.logic.processCommand.${method}`)
export async function processCommand(commandClass: string, commandMethod: string, commandArgs: string[]) {
const methodLogger = createLogger(`processCommand`)
methodLogger.info('processing a command...')
}

View File

@ -16,6 +16,7 @@ import { Decimal } from 'decimal.js-light'
// import { LogError } from '@server/LogError' // import { LogError } from '@server/LogError'
import { getLogger } from 'log4js' import { getLogger } from 'log4js'
import { import {
CommandJwtPayloadType,
encryptAndSign, encryptAndSign,
PendingTransactionState, PendingTransactionState,
SendCoinsJwtPayloadType, SendCoinsJwtPayloadType,
@ -30,6 +31,7 @@ import { SendCoinsResultLoggingView } from '../../federation/client/1_0/logging/
import { SendCoinsResult } from '../../federation/client/1_0/model/SendCoinsResult' import { SendCoinsResult } from '../../federation/client/1_0/model/SendCoinsResult'
import { SendCoinsClient as V1_0_SendCoinsClient } from '../../federation/client/1_0/SendCoinsClient' import { SendCoinsClient as V1_0_SendCoinsClient } from '../../federation/client/1_0/SendCoinsClient'
import { SendCoinsClientFactory } from '../../federation/client/SendCoinsClientFactory' import { SendCoinsClientFactory } from '../../federation/client/SendCoinsClientFactory'
import { CommandClientFactory } from '../../federation/client/CommandClientFactory'
import { TransactionTypeId } from '../../graphql/enum/TransactionTypeId' import { TransactionTypeId } from '../../graphql/enum/TransactionTypeId'
import { EncryptedTransferArgs } from '../../graphql/model/EncryptedTransferArgs' import { EncryptedTransferArgs } from '../../graphql/model/EncryptedTransferArgs'
import { calculateSenderBalance } from '../../util/calculateSenderBalance' import { calculateSenderBalance } from '../../util/calculateSenderBalance'
@ -37,6 +39,8 @@ import { fullName } from '../../util/utilities'
import { settlePendingSenderTransaction } from './settlePendingSenderTransaction' import { settlePendingSenderTransaction } from './settlePendingSenderTransaction'
import { storeForeignUser } from './storeForeignUser' import { storeForeignUser } from './storeForeignUser'
import { storeLinkAsRedeemed } from './storeLinkAsRedeemed' import { storeLinkAsRedeemed } from './storeLinkAsRedeemed'
import { V1_0_CommandClient } from '../..'
import { SendEmailCommand } from '../../command/commands/SendEmailCommand'
const createLogger = (method: string) => const createLogger = (method: string) =>
getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.util.processXComSendCoins.${method}`) getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.util.processXComSendCoins.${method}`)
@ -511,6 +515,36 @@ export async function processXComCommittingSendCoins(
sendCoinsResult.recipGradidoID = pendingTx.linkedUserGradidoID sendCoinsResult.recipGradidoID = pendingTx.linkedUserGradidoID
sendCoinsResult.recipAlias = recipient.recipAlias sendCoinsResult.recipAlias = recipient.recipAlias
} }
// ** after successfull settle of the pending transaction on sender side we have to send a trigger to the recipient community to send an email to the x-com-tx recipient
const cmdClient = CommandClientFactory.getInstance(receiverFCom)
if (cmdClient instanceof V1_0_CommandClient) {
const payload = new CommandJwtPayloadType(
handshakeID,
SendEmailCommand.SEND_MAIL_COMMAND,
SendEmailCommand.name,
[
JSON.stringify({
mailType: 'sendTransactionReceivedEmail',
senderComUuid: senderCom.communityUuid,
senderGradidoId: sender.gradidoID,
receiverComUuid: receiverCom.communityUuid,
receiverGradidoId: sendCoinsResult.recipGradidoID,
memo: pendingTx.memo,
amount: pendingTx.amount,
}),
])
const jws = await encryptAndSign(
payload,
senderCom.privateJwtKey!,
receiverCom.publicJwtKey!,
)
const args = new EncryptedTransferArgs()
args.publicKey = senderCom.publicKey.toString('hex')
args.jwt = jws
args.handshakeID = handshakeID
cmdClient.sendCommand(args)
}
} catch (err) { } catch (err) {
methodLogger.error( methodLogger.error(
`Error in writing sender pending transaction: ${JSON.stringify(err, null, 2)}`, `Error in writing sender pending transaction: ${JSON.stringify(err, null, 2)}`,

View File

@ -0,0 +1,13 @@
import { Field, ObjectType } from 'type-graphql'
@ObjectType()
export class CommandResult {
@Field(() => Boolean)
success: boolean;
@Field(() => String, { nullable: true })
data?: any;
@Field(() => String, { nullable: true })
error?: string;
}

View File

@ -0,0 +1,19 @@
// backend/src/graphql/resolver/CommandResolver.ts
import { Resolver, Mutation, Arg, Ctx } from 'type-graphql';
import { CommandExecutor } from '../../command/CommandExecutor';
import { CommandResult } from '../model/CommandResult';
@Resolver()
export class CommandResolver {
private commandExecutor = new CommandExecutor();
@Mutation(() => CommandResult)
async executeCommand(
@Arg('encryptedArgs', () => Object) encryptedArgs: any,
@Ctx() context: any
): Promise<CommandResult> {
// Convert to EncryptedTransferArgs if needed
const result = await this.commandExecutor.executeEncryptedCommand(encryptedArgs);
return result as unknown as CommandResult;
}
}

View File

@ -1,4 +1,7 @@
export * from './config/index' export * from './config/index'
export * from './command/CommandExecutor'
export * from './command/CommandFactory'
export * from './command/initCommands'
export * from './emails' export * from './emails'
export * from './federation/client/1_0/logging/SendCoinsArgsLogging.view' export * from './federation/client/1_0/logging/SendCoinsArgsLogging.view'
export * from './federation/client/1_0/logging/SendCoinsResultLogging.view' export * from './federation/client/1_0/logging/SendCoinsResultLogging.view'
@ -8,18 +11,24 @@ export * from './federation/client/1_0/query/revertSendCoins'
export * from './federation/client/1_0/query/revertSettledSendCoins' export * from './federation/client/1_0/query/revertSettledSendCoins'
export * from './federation/client/1_0/query/settleSendCoins' export * from './federation/client/1_0/query/settleSendCoins'
export * from './federation/client/1_0/query/voteForSendCoins' export * from './federation/client/1_0/query/voteForSendCoins'
export { CommandClient as V1_0_CommandClient } from './federation/client/1_0/CommandClient'
export { CommandClient as V1_1_CommandClient } from './federation/client/1_1/CommandClient'
export { SendCoinsClient as V1_0_SendCoinsClient } from './federation/client/1_0/SendCoinsClient' export { SendCoinsClient as V1_0_SendCoinsClient } from './federation/client/1_0/SendCoinsClient'
export { SendCoinsClient as V1_1_SendCoinsClient } from './federation/client/1_1/SendCoinsClient' export { SendCoinsClient as V1_1_SendCoinsClient } from './federation/client/1_1/SendCoinsClient'
export * from './federation/client/CommandClientFactory'
export * from './federation/client/SendCoinsClientFactory' export * from './federation/client/SendCoinsClientFactory'
export * from './federation/enum/apiVersionType' export * from './federation/enum/apiVersionType'
export * from './graphql/enum/TransactionTypeId' export * from './graphql/enum/TransactionTypeId'
export * from './graphql/logging/DecayLogging.view' export * from './graphql/logging/DecayLogging.view'
export * from './graphql/logic/interpretEncryptedTransferArgs' export * from './graphql/logic/interpretEncryptedTransferArgs'
export * from './graphql/logic/processCommand'
export * from './graphql/logic/processXComSendCoins' export * from './graphql/logic/processXComSendCoins'
export * from './graphql/logic/settlePendingSenderTransaction' export * from './graphql/logic/settlePendingSenderTransaction'
export * from './graphql/logic/storeForeignUser' export * from './graphql/logic/storeForeignUser'
export * from './graphql/model/CommandResult'
export * from './graphql/model/Decay' export * from './graphql/model/Decay'
export * from './graphql/model/EncryptedTransferArgs' export * from './graphql/model/EncryptedTransferArgs'
export * from './graphql/resolver/CommandResolver'
export * from './logic' export * from './logic'
export * from './util/calculateSenderBalance' export * from './util/calculateSenderBalance'
export * from './util/utilities' export * from './util/utilities'

View File

@ -1,5 +1,6 @@
import { NonEmptyArray } from 'type-graphql' import { NonEmptyArray } from 'type-graphql'
import { AuthenticationResolver } from './resolver/AuthenticationResolver' import { AuthenticationResolver } from './resolver/AuthenticationResolver'
import { CommandResolver } from 'core'
import { DisbursementResolver } from './resolver/DisbursementResolver' import { DisbursementResolver } from './resolver/DisbursementResolver'
import { PublicCommunityInfoResolver } from './resolver/PublicCommunityInfoResolver' import { PublicCommunityInfoResolver } from './resolver/PublicCommunityInfoResolver'
import { PublicKeyResolver } from './resolver/PublicKeyResolver' import { PublicKeyResolver } from './resolver/PublicKeyResolver'
@ -8,6 +9,7 @@ import { SendCoinsResolver } from './resolver/SendCoinsResolver'
export const getApiResolvers = (): NonEmptyArray<Function> => { export const getApiResolvers = (): NonEmptyArray<Function> => {
return [ return [
AuthenticationResolver, AuthenticationResolver,
CommandResolver,
DisbursementResolver, DisbursementResolver,
PublicCommunityInfoResolver, PublicCommunityInfoResolver,
PublicKeyResolver, PublicKeyResolver,

View File

@ -7,6 +7,7 @@ import { onShutdown, printServerCrashAsciiArt, ShutdownReason } from 'shared'
import { CONFIG } from './config' import { CONFIG } from './config'
import { LOG4JS_BASE_CATEGORY_NAME } from './config/const' import { LOG4JS_BASE_CATEGORY_NAME } from './config/const'
import { createServer } from './server/createServer' import { createServer } from './server/createServer'
import { initializeCommands } from 'core'
async function main() { async function main() {
const startTime = new Date() const startTime = new Date()
@ -44,6 +45,9 @@ async function main() {
} }
}) })
}) })
initializeCommands()
} }
main().catch((e) => { main().catch((e) => {

View File

@ -4,6 +4,7 @@ export * from './helper'
export * from './jwt/JWT' export * from './jwt/JWT'
export * from './jwt/payloadtypes/AuthenticationJwtPayloadType' export * from './jwt/payloadtypes/AuthenticationJwtPayloadType'
export * from './jwt/payloadtypes/AuthenticationResponseJwtPayloadType' export * from './jwt/payloadtypes/AuthenticationResponseJwtPayloadType'
export * from './jwt/payloadtypes/CommandJwtPayloadType'
export * from './jwt/payloadtypes/DisburseJwtPayloadType' export * from './jwt/payloadtypes/DisburseJwtPayloadType'
export * from './jwt/payloadtypes/EncryptedJWEJwtPayloadType' export * from './jwt/payloadtypes/EncryptedJWEJwtPayloadType'
export * from './jwt/payloadtypes/JwtPayloadType' export * from './jwt/payloadtypes/JwtPayloadType'

View File

@ -0,0 +1,17 @@
import { JwtPayloadType } from './JwtPayloadType'
export class CommandJwtPayloadType extends JwtPayloadType {
static COMMAND_TYPE = 'command'
commandName: string
commandClass: string
commandArgs: string[]
constructor(handshakeID: string, commandName: string, commandClass: string, commandArgs: string[]) {
super(handshakeID)
this.tokentype = CommandJwtPayloadType.COMMAND_TYPE
this.commandName = commandName
this.commandClass = commandClass
this.commandArgs = commandArgs
}
}