Prodress Connection fertig implementiert
This commit is contained in:
parent
7e892e8c42
commit
b1f264424c
@ -1,8 +1,6 @@
|
|||||||
import {app, BrowserWindow} from 'electron';
|
import {app, BrowserWindow} from 'electron';
|
||||||
import {Socket} from 'net';
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import {R2RequestErweiterungsdaten, R2RequestKopfdaten, Request, RequestLeser} from '@prodress/pdr2com';
|
import {ProdressConnection} from './pdr2com/connection.js';
|
||||||
import {ProdressRequest} from './pdr2com/wrapper.js';
|
|
||||||
|
|
||||||
const APPLICATION_PATH = path.join(app.getAppPath(), '/dist-svelte/index.html');
|
const APPLICATION_PATH = path.join(app.getAppPath(), '/dist-svelte/index.html');
|
||||||
|
|
||||||
@ -14,23 +12,39 @@ app.on('ready', async () => {
|
|||||||
mainWindow.loadFile(APPLICATION_PATH);
|
mainWindow.loadFile(APPLICATION_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const req = new ProdressConnection(
|
||||||
const socket = new Socket();
|
{
|
||||||
socket.connect(4788, 'localhost');
|
port: 4788,
|
||||||
|
host: 'localhost',
|
||||||
const test = new ProdressRequest('db', 'handler', 'aktion', {});
|
database: 'test',
|
||||||
test.schreibeText('HalloWelt 2355435');
|
handler: 'Shopify',
|
||||||
socket.on('connect', () => {
|
action: 'artikelSync',
|
||||||
console.log('verbunden');
|
},
|
||||||
test.sende(socket);
|
[['string', 'HalloWelt']],
|
||||||
});
|
[
|
||||||
const r2reader = new RequestLeser();
|
['line1', 'string'],
|
||||||
socket.on('data', (data: Buffer) => {
|
['line2', 'string'],
|
||||||
r2reader.verarbeiteDaten(data);
|
],
|
||||||
});
|
);
|
||||||
const r2request = await r2reader.leseRequest();
|
const res = await req.handleRequest();
|
||||||
console.log(r2request.nächsterText());
|
console.log(res);
|
||||||
} catch (error) {
|
// try {
|
||||||
console.error(error);
|
// const socket = new Socket();
|
||||||
}
|
// socket.connect(4788, 'localhost');
|
||||||
|
//
|
||||||
|
// const test = new ProdressRequest('db', 'handler', 'aktion');
|
||||||
|
// test.schreibeText('HalloWelt 2355435');
|
||||||
|
// socket.on('connect', () => {
|
||||||
|
// console.log('verbunden');
|
||||||
|
// test.sende(socket);
|
||||||
|
// });
|
||||||
|
// const r2reader = new RequestLeser();
|
||||||
|
// socket.on('data', (data: Buffer) => {
|
||||||
|
// r2reader.verarbeiteDaten(data);
|
||||||
|
// });
|
||||||
|
// const r2request = await r2reader.leseRequest();
|
||||||
|
// console.log(r2request.nächsterText());
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error(error);
|
||||||
|
// }
|
||||||
});
|
});
|
||||||
|
|||||||
139
src/electron/pdr2com/connection.ts
Normal file
139
src/electron/pdr2com/connection.ts
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
import {RequestLeser as ProdressListener, type R2AnfrageBlaupause} from '@prodress/pdr2com';
|
||||||
|
import {type ResponseTupel, type ResponseObject, ProdressRequest, type RequestTupel} from './wrapper.js';
|
||||||
|
import {Socket} from 'node:net';
|
||||||
|
|
||||||
|
export interface ProdressHeader {
|
||||||
|
port?: number;
|
||||||
|
host?: string;
|
||||||
|
database: string;
|
||||||
|
handler: string;
|
||||||
|
action: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo move to nyi utils file
|
||||||
|
function stringifyError(error: Error): string {
|
||||||
|
const {message, stack} = error;
|
||||||
|
|
||||||
|
return JSON.stringify(
|
||||||
|
{
|
||||||
|
message,
|
||||||
|
stack,
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ProdressConnection {
|
||||||
|
public static readonly TIMEOUT = 30_000;
|
||||||
|
|
||||||
|
private port: number;
|
||||||
|
private host: string;
|
||||||
|
private socket: Socket;
|
||||||
|
private request: ProdressRequest;
|
||||||
|
private listener: ProdressListener;
|
||||||
|
private requestTupelList: RequestTupel[];
|
||||||
|
private responseTupelList: ResponseTupel[];
|
||||||
|
|
||||||
|
public constructor(header: ProdressHeader, requestTupelList: RequestTupel[], responseTupelList: ResponseTupel[]) {
|
||||||
|
this.port = header.port ?? 4788;
|
||||||
|
this.host = header.host ?? 'localhost';
|
||||||
|
this.socket = new Socket();
|
||||||
|
this.request = new ProdressRequest(header.database, header.handler, header.action);
|
||||||
|
this.listener = new ProdressListener();
|
||||||
|
this.requestTupelList = requestTupelList;
|
||||||
|
this.responseTupelList = responseTupelList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async handleRequest(): Promise<string> {
|
||||||
|
let response: string = '';
|
||||||
|
const responseAsPromise = new Promise<string>((resolve) => {
|
||||||
|
this.socket.once('finished', () => {
|
||||||
|
if (!this.socket.destroyed) {
|
||||||
|
this.socket.destroy();
|
||||||
|
}
|
||||||
|
resolve(response);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.setTimeout(ProdressConnection.TIMEOUT);
|
||||||
|
this.socket.connect(this.port, this.host);
|
||||||
|
|
||||||
|
this.socket.once('connect', () => {
|
||||||
|
try {
|
||||||
|
this.request.writeEntries(this.requestTupelList);
|
||||||
|
this.request.sende(this.socket);
|
||||||
|
} catch (error) {
|
||||||
|
response = stringifyError(error as Error);
|
||||||
|
this.finished();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// @todo Rework Error Message
|
||||||
|
this.socket.on('timeout', () => {
|
||||||
|
const timeoutError = new Error('timeout');
|
||||||
|
response = stringifyError(timeoutError);
|
||||||
|
this.finished();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on('error', (error: Error) => {
|
||||||
|
response = stringifyError(error);
|
||||||
|
this.finished();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on('data', (data: Buffer) => {
|
||||||
|
this.listener.verarbeiteDaten(data);
|
||||||
|
this.socket.emit('dataRecieved');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.once('dataRecieved', async () => {
|
||||||
|
try {
|
||||||
|
const incomingResponse = await this.listener.leseRequest();
|
||||||
|
const responseObject = this.readResponse(incomingResponse);
|
||||||
|
response = JSON.stringify(responseObject, null, 2);
|
||||||
|
this.finished();
|
||||||
|
} catch (error) {
|
||||||
|
response = stringifyError(error as Error);
|
||||||
|
this.finished();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return responseAsPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
private finished(): void {
|
||||||
|
this.socket.emit('finished');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reads the Reponse based on the provided responseTupelList and creates a ResponseObject
|
||||||
|
* @param responseInstance The Listener Instance of the active TCP Socket
|
||||||
|
* @returns ResponseObject
|
||||||
|
*/
|
||||||
|
private readResponse(responseInstance: R2AnfrageBlaupause): ResponseObject {
|
||||||
|
const response: ResponseObject = {};
|
||||||
|
|
||||||
|
for (const tupel of this.responseTupelList) {
|
||||||
|
const [key, type] = tupel;
|
||||||
|
switch (type) {
|
||||||
|
case 'string':
|
||||||
|
response[key] = responseInstance.nächsterText();
|
||||||
|
break;
|
||||||
|
case 'integer':
|
||||||
|
response[key] = responseInstance.nächsteGanzzahl();
|
||||||
|
break;
|
||||||
|
case 'float':
|
||||||
|
response[key] = responseInstance.nächsteDezimalzahl();
|
||||||
|
break;
|
||||||
|
case 'date':
|
||||||
|
response[key] = responseInstance.nächstesDatum();
|
||||||
|
break;
|
||||||
|
case 'date_time':
|
||||||
|
//@todo missing method in lib
|
||||||
|
response[key] = responseInstance.nächstesDatum();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,32 +8,18 @@ export interface DataTypeConversion {
|
|||||||
date_time: () => Date | null;
|
date_time: () => Date | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReponseSchema {
|
export interface ResponseObject {
|
||||||
readonly [key: string]: keyof DataTypeConversion;
|
[key: string]: ReturnType<DataTypeConversion[keyof DataTypeConversion]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ResponseTupel = [string, keyof DataTypeConversion];
|
||||||
|
|
||||||
export type RequestTupel = {
|
export type RequestTupel = {
|
||||||
[K in keyof DataTypeConversion]: [K, NonNullable<ReturnType<DataTypeConversion[K]>>];
|
[K in keyof DataTypeConversion]: [K, NonNullable<ReturnType<DataTypeConversion[K]>>];
|
||||||
}[keyof DataTypeConversion];
|
}[keyof DataTypeConversion];
|
||||||
|
|
||||||
export class ProdressRequest extends Request {
|
export class ProdressRequest extends Request {
|
||||||
/**
|
public constructor(db: string, handler: string, action: string) {
|
||||||
* Mapping of a datatype to the correspondig read method
|
|
||||||
*/
|
|
||||||
public readonly responseSchemaConversion: DataTypeConversion = {
|
|
||||||
string: this.nächsterText,
|
|
||||||
integer: this.nächsteGanzzahl,
|
|
||||||
float: this.nächsteDezimalzahl,
|
|
||||||
date: this.nächstesDatum,
|
|
||||||
date_time: this.nächstesDatumMitZeit,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Definition of the Reponse
|
|
||||||
*/
|
|
||||||
public readonly responseSchema: ReponseSchema;
|
|
||||||
|
|
||||||
public constructor(db: string, handler: string, action: string, responseSchema: ReponseSchema) {
|
|
||||||
super(
|
super(
|
||||||
{
|
{
|
||||||
interneProtokollVersion: 1,
|
interneProtokollVersion: 1,
|
||||||
@ -55,6 +41,40 @@ export class ProdressRequest extends Request {
|
|||||||
maximalePaketgröße: 0,
|
maximalePaketgröße: 0,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
this.responseSchema = responseSchema;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* writes entries based on the provided requestTupelList into the request
|
||||||
|
* @param requestTupelList
|
||||||
|
*/
|
||||||
|
public writeEntries(requestTupelList: RequestTupel[]): void {
|
||||||
|
for (const tupel of requestTupelList) {
|
||||||
|
this.writeEntry(tupel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* writes an entry based on the provided requestTupel into the request
|
||||||
|
* @param requestTupel
|
||||||
|
*/
|
||||||
|
public writeEntry(requestTupel: RequestTupel): void {
|
||||||
|
const [type, value] = requestTupel;
|
||||||
|
switch (type) {
|
||||||
|
case 'string':
|
||||||
|
this.schreibeText(value);
|
||||||
|
break;
|
||||||
|
case 'integer':
|
||||||
|
this.schreibeGanzzahl(value);
|
||||||
|
break;
|
||||||
|
case 'float':
|
||||||
|
this.schreibeDezimalzahl(value);
|
||||||
|
break;
|
||||||
|
case 'date':
|
||||||
|
this.schreibeDatum(value);
|
||||||
|
break;
|
||||||
|
case 'date_time':
|
||||||
|
this.schreibeDatumMitZeit(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,12 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
// require strict types (null-save)
|
|
||||||
"strict": true,
|
"strict": true,
|
||||||
// tell TypeScript to generate ESM Syntax
|
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
// tell TypeScript to require ESM Syntax as input (including .js file imports)
|
|
||||||
"module": "NodeNext",
|
"module": "NodeNext",
|
||||||
// define where to put generated JS
|
"moduleResolution": "NodeNext",
|
||||||
|
"esModuleInterop": true,
|
||||||
"outDir": "../../dist-electron",
|
"outDir": "../../dist-electron",
|
||||||
// ignore errors from dependencies
|
"skipLibCheck": true
|
||||||
"skipLibCheck": true,
|
|
||||||
// add global types
|
|
||||||
//"types": ["../../types"]
|
//"types": ["../../types"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user