Compare commits

...

8 Commits

Author SHA1 Message Date
7baf747972 1.0.8 2024-04-01 02:58:27 +02:00
4a17a1073e fix(core): update 2024-04-01 02:58:27 +02:00
8997ded81d 1.0.7 2024-03-19 18:37:25 +01:00
f177d8e9ab fix(core): update 2024-03-19 18:37:24 +01:00
808a9cc856 1.0.6 2024-02-16 20:47:25 +01:00
be1c8d1164 fix(core): update 2024-02-16 20:47:25 +01:00
2ecb2f3aa0 1.0.5 2024-02-16 20:42:26 +01:00
01dcdebda5 fix(core): update 2024-02-16 20:42:26 +01:00
23 changed files with 2344 additions and 1662 deletions

View File

@ -1,6 +1,7 @@
{
"name": "@serve.zone/platformservice",
"version": "1.0.4",
"private": true,
"version": "1.0.8",
"description": "contains the platformservice container with mail, sms, letter, ai services.",
"main": "dist_ts/index.js",
"typings": "dist_ts/index.d.ts",
@ -9,22 +10,24 @@
"license": "MIT",
"scripts": {
"test": "(tstest test/)",
"start": "(node --max_old_space_size=100 ./cli.js)",
"start": "(node --max_old_space_size=250 ./cli.js)",
"startTs": "(node cli.ts.js)",
"build": "(tsbuild --web --allowimplicitany)"
"localPublish": ""
},
"devDependencies": {
"@git.zone/tsbuild": "^2.1.17",
"@git.zone/tsrun": "^1.2.8",
"@git.zone/tstest": "^1.0.28",
"@git.zone/tstest": "^1.0.88",
"@git.zone/tswatch": "^2.0.1",
"@push.rocks/tapbundle": "^5.0.3"
"@push.rocks/tapbundle": "^5.0.22"
},
"dependencies": {
"@api.global/typedrequest": "^3.0.4",
"@api.global/typedserver": "^3.0.20",
"@anthropic-ai/sdk": "^0.18.0",
"@api.global/typedrequest": "^3.0.19",
"@api.global/typedserver": "^3.0.27",
"@api.global/typedsocket": "^3.0.0",
"@apiclient.xyz/cloudflare": "^6.0.3",
"@apiclient.xyz/letterxpress": "^1.0.17",
"@push.rocks/projectinfo": "^5.0.1",
"@push.rocks/qenv": "^6.0.5",
"@push.rocks/smartdata": "^5.0.7",
@ -36,10 +39,11 @@
"@push.rocks/smartrequest": "^2.0.21",
"@push.rocks/smartrx": "^3.0.7",
"@push.rocks/smartstate": "^2.0.0",
"@serve.zone/interfaces": "^1.0.34",
"@tsclass/tsclass": "^4.0.51",
"@serve.zone/interfaces": "^1.0.47",
"@tsclass/tsclass": "^4.0.52",
"mailauth": "^4.6.5",
"mailparser": "^3.6.7",
"mailparser": "^3.6.9",
"openai": "^4.29.2",
"uuid": "^9.0.1"
}
}

3656
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

5
test/test.ts Normal file
View File

@ -0,0 +1,5 @@
import { tap, expect } from '@push.rocks/tapbundle';
tap.test('should create a platform service', async () => {});
tap.start();

View File

@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@serve.zone/platformservice',
version: '1.0.4',
version: '1.0.8',
description: 'contains the platformservice container with mail, sms, letter, ai services.'
}

View File

@ -0,0 +1,50 @@
import * as plugins from './aibridge.plugins.js';
import * as paths from './aibridge.paths.js';
import { AiBridgeDb } from './aibridge.classes.aibridgedb.js';
import { OpenAiBridge } from './aibridge.classes.openaibridge.js';
export class AiBridge {
public projectinfo: plugins.projectinfo.ProjectInfo;
public serverInstance: plugins.loleServiceserver.ServiceServer;
public serviceQenv = new plugins.qenv.Qenv('./', './.nogit');
public aibridgeDb: AiBridgeDb;
public openAiBridge: OpenAiBridge;
public typedrouter = new plugins.typedrequest.TypedRouter();
public async start() {
this.aibridgeDb = new AiBridgeDb(this);
await this.aibridgeDb.start();
this.projectinfo = new plugins.projectinfo.ProjectInfo(paths.packageDir);
this.openAiBridge = new OpenAiBridge(this);
await this.openAiBridge.start();
// server
this.serverInstance = new plugins.loleServiceserver.ServiceServer({
serviceDomain: 'aibridge.lossless.one',
serviceName: 'aibridge',
serviceVersion: this.projectinfo.npm.version,
addCustomRoutes: async (serverArg) => {
// any custom route configs go here
},
});
// lets implemenet the actual typedrequest functions
this.typedrouter.addTypedHandler<plugins.lointAiBridge.requests.IReq_Chat>(new plugins.typedrequest.TypedHandler('chat', async reqArg => {
const resultChat = await this.openAiBridge.chat(reqArg.chat.systemMessage, reqArg.chat.messages[reqArg.chat.messages.length - 1].content, reqArg.chat.messages);
return {
chat: reqArg.chat,
latestMessage: resultChat.message.content,
}
}))
await this.serverInstance.start();
this.serverInstance.typedServer.typedrouter.addTypedRouter(this.typedrouter);
}
public async stop() {
await this.serverInstance.stop();
await this.aibridgeDb.stop();
}
}

View File

@ -0,0 +1,25 @@
import * as plugins from './aibridge.plugins.js';
import { AiBridge } from './aibridge.classes.aibridge.js';
export class AiBridgeDb {
public smartdataDb: plugins.smartdata.SmartdataDb;
public aibridgeRef: AiBridge;
constructor(aibridgeRefArg: AiBridge) {
this.aibridgeRef = aibridgeRefArg;
}
public async start() {
this.smartdataDb = new plugins.smartdata.SmartdataDb({
mongoDbUser: await this.aibridgeRef.serviceQenv.getEnvVarOnDemand('MONGO_DB_USER'),
mongoDbName: await this.aibridgeRef.serviceQenv.getEnvVarOnDemand('MONGO_DB_NAME'),
mongoDbPass: await this.aibridgeRef.serviceQenv.getEnvVarOnDemand('MONGO_DB_PASS'),
mongoDbUrl: await this.aibridgeRef.serviceQenv.getEnvVarOnDemand('MONGO_DB_URL'),
});
await this.smartdataDb.init();
}
public async stop() {
await this.smartdataDb.close();
}
}

View File

@ -0,0 +1,58 @@
import { AiBridge } from './aibridge.classes.aibridge.js';
import * as plugins from './aibridge.plugins.js';
import * as paths from './aibridge.paths.js';
export class OpenAiBridge {
public aiBridgeRef: AiBridge;
public openAiApiClient: plugins.openai.default;
constructor(aiBridgeRefArg: AiBridge) {
this.aiBridgeRef = aiBridgeRefArg;
}
public async start() {
const openAiToken = await this.aiBridgeRef.serviceQenv.getEnvVarOnDemand('OPENAI_TOKEN');
this.openAiApiClient = new plugins.openai.default({
apiKey: openAiToken,
dangerouslyAllowBrowser: true,
});
}
public async stop() {}
public async chat(
systemMessage: string,
userMessage: string,
messageHistory: {
role: 'assistant' | 'user';
content: string;
}[]
) {
const result = await this.openAiApiClient.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{ role: 'system', content: systemMessage },
...messageHistory,
{ role: 'user', content: userMessage },
],
});
return {
message: result.choices[0].message,
};
}
public async audio(messageArg: string) {
const done = plugins.smartpromise.defer();
const result = await this.openAiApiClient.audio.speech.create({
model: 'tts-1-hd',
input: messageArg,
voice: 'nova',
response_format: 'mp3',
speed: 1,
});
const stream = result.body.pipe(plugins.smartfile.fsStream.createWriteStream(plugins.path.join(paths.nogitDir, 'output.mp3')));
stream.on('finish', () => {
done.resolve();
});
return done.promise;
}
}

View File

@ -0,0 +1,16 @@
import * as plugins from './aibridge.plugins.js';
export const packageDir = plugins.path.join(
plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url),
'../'
);
export const assetsDir = plugins.path.join(
packageDir,
'./assets/'
);
export const nogitDir = plugins.path.join(
packageDir,
'./.nogit/'
);

View File

@ -0,0 +1,32 @@
// node native
import * as path from 'path';
export { path };
// @losslessone_private scope
import * as loleServiceserver from '@losslessone_private/lole-serviceserver';
import * as lointAiBridge from '@losslessone_private/loint-aibridge';
export { loleServiceserver, lointAiBridge };
// apiglobal scope
import * as typedrequest from '@api.global/typedrequest';
export {
typedrequest,
}
// pushrocks scope
import * as projectinfo from '@push.rocks/projectinfo';
import * as qenv from '@push.rocks/qenv';
import * as smartdata from '@push.rocks/smartdata';
import * as smartfile from '@push.rocks/smartfile';
import * as smartpath from '@push.rocks/smartpath';
import * as smartpromise from '@push.rocks/smartpromise';
export { projectinfo, qenv, smartdata, smartfile, smartpath, smartpromise };
// thirdparty scope
import * as antrophic from '@anthropic-ai/sdk';
import * as openai from 'openai';
export { antrophic as anthropic, openai };

17
ts/aibridge/index.ts Normal file
View File

@ -0,0 +1,17 @@
import { AiBridge } from './aibridge.classes.aibridge.js';
export {
AiBridge,
}
let aibridgeInstance: AiBridge;
export const runCli = async () => {
aibridgeInstance = new AiBridge();
await aibridgeInstance.start();
};
export const stop = async () => {
if (aibridgeInstance) {
await aibridgeInstance.stop();
}
};

View File

@ -1,6 +1,10 @@
import * as plugins from './plugins.js';
import * as paths from './paths.js';
import { PlatformServiceDb } from './classes.platformservicedb.js'
import { EmailService } from './email/email.classes.emailservice.js';
import { SmsService } from './sms/smsservice.js';
import { LetterService } from './letter/classes.letterservice.js';
import { MtaService } from './mta/mta.classes.mta.js';
export class SzPlatformService {
public projectinfo: plugins.projectinfo.ProjectInfo;
@ -10,9 +14,28 @@ export class SzPlatformService {
public typedserver: plugins.typedserver.TypedServer;
public typedrouter = new plugins.typedrequest.TypedRouter();
// SubServices
public emailService: EmailService;
public letterService: LetterService;
public mtaService: MtaService;
public smsService: SmsService;
public async start() {
this.platformserviceDb = new PlatformServiceDb(this);
this.projectinfo = new plugins.projectinfo.ProjectInfo(paths.packageDir);
// lets start the sub services
this.emailService = new EmailService(this);
this.letterService = new LetterService(this, {
letterxpressUser: await this.serviceQenv.getEnvVarOnDemand('LETTER_API_USER'),
letterxpressToken: await this.serviceQenv.getEnvVarOnDemand('LETTER_API_TOKEN')
});
this.mtaService = new MtaService(this);
this.smsService = new SmsService(this, {
apiGatewayApiToken: await this.serviceQenv.getEnvVarOnDemand('SMS_API_TOKEN'),
});
// lets start the server finally
this.typedserver = new plugins.typedserver.TypedServer({
cors: true,
});

View File

@ -6,6 +6,11 @@ import { ApiManager } from './email.classes.apimanager.js';
import { logger } from '../logger.js';
import type { SzPlatformService } from '../classes.platformservice.js';
export interface IEmailConstructorOptions {
mailgunApiKey: string;
}
export class EmailService {
public platformServiceRef: SzPlatformService;

View File

@ -0,0 +1,41 @@
import type { SzPlatformService } from '../classes.platformservice.js';
import * as plugins from '../plugins.js';
export interface ILetterConstructorOptions {
letterxpressUser: string;
letterxpressToken: string;
}
export class LetterService {
public platformServiceRef: SzPlatformService;
public options: ILetterConstructorOptions;
public letterxpressAccount: plugins.letterxpress.LetterXpressAccount;
public typedrouter = new plugins.typedrequest.TypedRouter();
constructor(platformServiceRefArg: SzPlatformService, optionsArg: ILetterConstructorOptions) {
this.platformServiceRef = platformServiceRefArg;
this.options = optionsArg;
this.platformServiceRef.typedrouter.addTypedRouter(this.typedrouter);
this.typedrouter.addTypedHandler<
plugins.servezoneInterfaces.platformservice.letter.IRequest_SendLetter
>(new plugins.typedrequest.TypedHandler('sendLetter', async dataArg => {
if(dataArg.needsCover) {
}
return {
processId: '',
}
}));
}
public async start() {
this.letterxpressAccount = new plugins.letterxpress.LetterXpressAccount({
username: this.options.letterxpressUser,
apiKey: this.options.letterxpressToken,
});
await this.letterxpressAccount.start();
}
public async stop() {}
}

0
ts/letter/index.ts Normal file
View File

View File

@ -2,7 +2,7 @@ import * as plugins from '../plugins.js';
import * as paths from '../paths.js';
import { Email } from './mta.classes.email.js';
import type { MTA } from './mta.classes.mta.js';
import type { MtaService } from './mta.classes.mta.js';
const readFile = plugins.util.promisify(plugins.fs.readFile);
const writeFile = plugins.util.promisify(plugins.fs.writeFile);
@ -16,7 +16,7 @@ export interface IKeyPaths {
export class DKIMCreator {
private keysDir: string;
constructor(metaRef: MTA, keysDir = paths.keysDir) {
constructor(metaRef: MtaService, keysDir = paths.keysDir) {
this.keysDir = keysDir;
}

View File

@ -1,10 +1,10 @@
import * as plugins from '../plugins.js';
import { MTA } from './mta.classes.mta.js';
import { MtaService } from './mta.classes.mta.js';
class DKIMVerifier {
public mtaRef: MTA;
public mtaRef: MtaService;
constructor(mtaRefArg: MTA) {
constructor(mtaRefArg: MtaService) {
this.mtaRef = mtaRefArg;
}

View File

@ -1,10 +1,10 @@
import type { MTA } from './mta.classes.mta.js';
import type { MtaService } from './mta.classes.mta.js';
import * as plugins from '../plugins.js';
export class DNSManager {
public mtaRef: MTA;
public mtaRef: MtaService;
constructor(mtaRefArg: MTA) {
constructor(mtaRefArg: MtaService) {
this.mtaRef = mtaRefArg;
}
}

View File

@ -2,15 +2,15 @@ import * as plugins from '../plugins.js';
import * as paths from '../paths.js';
import { Email } from './mta.classes.email.js';
import { EmailSignJob } from './mta.classes.emailsignjob.js';
import type { MTA } from './mta.classes.mta.js';
import type { MtaService } from './mta.classes.mta.js';
export class EmailSendJob {
mtaRef: MTA;
mtaRef: MtaService;
private email: Email;
private socket: plugins.net.Socket | plugins.tls.TLSSocket = null;
private mxRecord: string = null;
constructor(mtaRef: MTA, emailArg: Email) {
constructor(mtaRef: MtaService, emailArg: Email) {
this.email = emailArg;
this.mtaRef = mtaRef;
}

View File

@ -1,5 +1,5 @@
import * as plugins from '../plugins.js';
import type { MTA } from './mta.classes.mta.js';
import type { MtaService } from './mta.classes.mta.js';
interface Headers {
[key: string]: string;
@ -13,10 +13,10 @@ interface IEmailSignJobOptions {
}
export class EmailSignJob {
mtaRef: MTA;
mtaRef: MtaService;
jobOptions: IEmailSignJobOptions;
constructor(mtaRefArg: MTA, options: IEmailSignJobOptions) {
constructor(mtaRefArg: MtaService, options: IEmailSignJobOptions) {
this.mtaRef = mtaRefArg;
this.jobOptions = options;
}

View File

@ -6,14 +6,17 @@ import { DKIMCreator } from './mta.classes.dkimcreator.js';
import { DKIMVerifier } from './mta.classes.dkimverifier.js';
import { SMTPServer } from './mta.classes.smtpserver.js';
import { DNSManager } from './mta.classes.dnsmanager.js';
import type { SzPlatformService } from '../classes.platformservice.js';
export class MTA {
export class MtaService {
public platformServiceRef: SzPlatformService;
public server: SMTPServer;
public dkimCreator: DKIMCreator;
public dkimVerifier: DKIMVerifier;
public dnsManager: DNSManager;
constructor() {
constructor(platformServiceRefArg: SzPlatformService) {
this.platformServiceRef = platformServiceRefArg;
this.dkimCreator = new DKIMCreator(this);
this.dkimVerifier = new DKIMVerifier(this);
this.dnsManager = new DNSManager(this);

View File

@ -1,7 +1,7 @@
import * as plugins from '../plugins.js';
import * as paths from '../paths.js';
import { Email } from './mta.classes.email.js';
import type { MTA } from './mta.classes.mta.js';
import type { MtaService } from './mta.classes.mta.js';
export interface ISmtpServerOptions {
port: number;
@ -10,12 +10,12 @@ export interface ISmtpServerOptions {
}
export class SMTPServer {
public mtaRef: MTA;
public mtaRef: MtaService;
private smtpServerOptions: ISmtpServerOptions;
private server: plugins.net.Server;
private emailBufferStringMap: Map<plugins.net.Socket, string>;
constructor(mtaRefArg: MTA, optionsArg: ISmtpServerOptions) {
constructor(mtaRefArg: MtaService, optionsArg: ISmtpServerOptions) {
console.log('SMTPServer instance is being created...');
this.mtaRef = mtaRefArg;

View File

@ -49,6 +49,13 @@ import * as smartrx from '@push.rocks/smartrx';
export { projectinfo, qenv, smartdata, smartfile, smartlog, smartmail, smartpath, smartpromise, smartrequest, smartrx };
// apiclient.xyz scope
import * as letterxpress from '@apiclient.xyz/letterxpress';
export {
letterxpress,
}
// tsclass scope
import * as tsclass from '@tsclass/tsclass';

View File

@ -4,7 +4,7 @@ import { logger } from '../logger.js';
import type { SzPlatformService } from '../classes.platformservice.js';
export interface ISmsConstructorOptions {
apiToken: string;
apiGatewayApiToken: string;
}
export class SmsService {
@ -63,7 +63,7 @@ export class SmsService {
method: 'POST',
requestBody: JSON.stringify(payload),
headers: {
Authorization: `Basic ${Buffer.from(`${this.options.apiToken}:`).toString('base64')}`,
Authorization: `Basic ${Buffer.from(`${this.options.apiGatewayApiToken}:`).toString('base64')}`,
'Content-Type': 'application/json',
},
});