@kogeet/scapin-core-agent 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ export default class AppSagent {
2
+ private EntryPoints;
3
+ listen(): void;
4
+ use(libName: string, entryPoints: Map<string, CallableFunction>): void;
5
+ getStepFunction(lib: string, fn: string): CallableFunction | null;
6
+ }
@@ -0,0 +1,30 @@
1
+ import wSocketIo from "./wsocket.io.js";
2
+ import { report } from "../index.js";
3
+ export default class AppSagent {
4
+ EntryPoints = new Map();
5
+ listen() {
6
+ wSocketIo.start();
7
+ }
8
+ use(libName, entryPoints) {
9
+ this.EntryPoints.set(libName, entryPoints);
10
+ }
11
+ getStepFunction(lib, fn) {
12
+ const library = this.EntryPoints.get(lib);
13
+ if (library) {
14
+ const stepFct = library.get(fn);
15
+ if (stepFct) {
16
+ return stepFct;
17
+ }
18
+ else {
19
+ // erreur : la fonction n'existe pas. Vérifier l'orthographe du nom
20
+ report.error(`The function '${fn}' does not exist. Check the spelling of the name`);
21
+ return null;
22
+ }
23
+ }
24
+ else {
25
+ // erreur : librairie n'existe pas. Vérifier l'orthographe du nom
26
+ report.error(`The library '${lib}' does not exist. Check the spelling of the name`);
27
+ return null;
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,15 @@
1
+ import { RunParamModel } from '../models/run.model.js';
2
+ import { varType } from '../models/parameter.model.js';
3
+ /**
4
+ * La classe **Context** stocke les variables utilisées lors du test
5
+ */
6
+ export default class Context {
7
+ idxStep: number;
8
+ private variables;
9
+ getVariable(varname: string): varType;
10
+ setVariable(varname: string, value: varType): void;
11
+ loadVariable(params: RunParamModel[]): void;
12
+ valorize(param: RunParamModel): void;
13
+ dump(): [string, varType][];
14
+ resetVariables(): void;
15
+ }
@@ -0,0 +1,53 @@
1
+ import { enumParamType } from '../models/parameter.model.js';
2
+ /**
3
+ * La classe **Context** stocke les variables utilisées lors du test
4
+ */
5
+ export default class Context {
6
+ idxStep = -1;
7
+ variables = new Map();
8
+ getVariable(varname) {
9
+ return this.variables.get(varname);
10
+ }
11
+ setVariable(varname, value) {
12
+ if (varname && varname.length) {
13
+ this.variables.set(varname, value);
14
+ }
15
+ }
16
+ loadVariable(params) {
17
+ const regex = /\$\w+/g;
18
+ params.forEach((p) => {
19
+ if (p && p.value && typeof p.value === 'string') {
20
+ const found = p.value.match(regex);
21
+ if (found) {
22
+ found.forEach((name) => {
23
+ if (!this.variables.has(name)) {
24
+ this.variables.set(name, undefined);
25
+ }
26
+ });
27
+ }
28
+ }
29
+ });
30
+ }
31
+ valorize(param) {
32
+ // console.log('Valorize input :', param)
33
+ const quot = param.type === enumParamType.textdata || param.type === enumParamType.options ? '"' : '';
34
+ if (param.type !== enumParamType.receipt && param.value && typeof param.value === 'string') {
35
+ const found = param.value.match(/\$\w+/g);
36
+ if (found) {
37
+ found.forEach((vname) => {
38
+ if (this.variables.has(vname)) {
39
+ const vvalue = this.variables.get(vname);
40
+ param.value = param.value.replace(vname, quot + vvalue + quot);
41
+ }
42
+ });
43
+ }
44
+ }
45
+ // console.log('Valorize output :', param)
46
+ }
47
+ dump() {
48
+ return [...this.variables.entries()];
49
+ }
50
+ resetVariables() {
51
+ this.variables.clear();
52
+ }
53
+ }
@@ -0,0 +1,15 @@
1
+ import { enumParamType } from '../models/parameter.model.js';
2
+ export declare class JisonParser {
3
+ error: string | null;
4
+ result: never | null;
5
+ private jparser;
6
+ constructor(grammar: unknown);
7
+ exec(exp: string): boolean | string;
8
+ static builder(type: enumParamType, options: string[]): JisonParser | null;
9
+ }
10
+ export declare class JisonSolver {
11
+ private jparser;
12
+ constructor(grammar: unknown);
13
+ exec(exp: string): string | null;
14
+ static builder(type: enumParamType, options: string[]): JisonSolver | null;
15
+ }
@@ -0,0 +1,82 @@
1
+ import { enumParamType } from '../models/parameter.model.js';
2
+ import { variableGrammar } from '../jison/variable.grammar.js';
3
+ import { logicalGrammar } from '../jison/logical.grammar.js';
4
+ import { stringGrammar } from '../jison/string.grammar.js';
5
+ import { calcGrammar } from '../jison/calc.grammar.js';
6
+ import { datetimeGrammar } from '../jison/datetime.grammar.js';
7
+ import { optionGrammar } from '../jison/option.grammar.js';
8
+ import pkg from "jison";
9
+ const { Parser } = pkg;
10
+ export class JisonParser {
11
+ error = null;
12
+ result = null;
13
+ jparser;
14
+ constructor(grammar) {
15
+ this.jparser = new Parser(grammar);
16
+ }
17
+ exec(exp) {
18
+ try {
19
+ this.jparser.parse(exp);
20
+ return true;
21
+ }
22
+ catch (e) {
23
+ const m = e.message.split('\n');
24
+ if (m.length >= 2 && m[2].match(/^-*\^$/)) {
25
+ const pos = m[2].length;
26
+ return pos > exp.length
27
+ ? 'Expression incomplete'
28
+ : `Syntax error near character '${exp.charAt(pos - 1)}' at position ${pos}`;
29
+ }
30
+ else {
31
+ return e.message;
32
+ }
33
+ }
34
+ }
35
+ static builder(type, options) {
36
+ const grammar = typeGrammar(type, false, options);
37
+ try {
38
+ return new JisonParser(grammar);
39
+ }
40
+ catch (e) {
41
+ return null;
42
+ }
43
+ }
44
+ }
45
+ export class JisonSolver {
46
+ jparser;
47
+ constructor(grammar) {
48
+ this.jparser = new Parser(grammar);
49
+ }
50
+ exec(exp) {
51
+ try {
52
+ const ret = this.jparser.parse(exp);
53
+ console.log(`Solve expression '${exp}' :`, ret);
54
+ return ret ? ret : null;
55
+ }
56
+ catch (e) {
57
+ const msg = e.message;
58
+ console.log(`Solve erreur expression '${exp}' :`, msg);
59
+ const errs = msg.split('\n');
60
+ throw errs.length > 1 ? errs[1] : errs[0];
61
+ }
62
+ }
63
+ static builder(type, options) {
64
+ const grammar = typeGrammar(type, true, options);
65
+ try {
66
+ return new JisonSolver(grammar);
67
+ }
68
+ catch (e) {
69
+ return null;
70
+ }
71
+ }
72
+ }
73
+ function typeGrammar(type, solve = false, options = []) {
74
+ switch (type) {
75
+ case enumParamType.receipt: return variableGrammar;
76
+ case enumParamType.booldata: return logicalGrammar(solve);
77
+ case enumParamType.textdata: return stringGrammar(solve);
78
+ case enumParamType.numbdata: return calcGrammar(solve);
79
+ case enumParamType.datetime: return datetimeGrammar(solve);
80
+ case enumParamType.options: return optionGrammar(solve, options);
81
+ }
82
+ }
@@ -0,0 +1,20 @@
1
+ import StepContext from './step.context.js';
2
+ export default class Report {
3
+ private oneStepLog;
4
+ private start;
5
+ private stepPos;
6
+ private oneStepReport;
7
+ private flagStopOnError;
8
+ stepStart(pos: number): void;
9
+ stepEnd(pass: boolean): void;
10
+ info(message: string): void;
11
+ warning(message: string): void;
12
+ error(message: string): void;
13
+ getJsonStepReport(stepCtx: StepContext | null): string;
14
+ getStepStatus(): number;
15
+ CountOneStepLog(): number;
16
+ setStopOnError(state: boolean): void;
17
+ getStopOnError(): boolean;
18
+ clearStepLog(): void;
19
+ private log;
20
+ }
@@ -0,0 +1,83 @@
1
+ import { logLevel, stepStatus } from '../models/run.model.js';
2
+ import { context } from "../index.js";
3
+ export default class Report {
4
+ oneStepLog = [];
5
+ start = 0;
6
+ stepPos = -1;
7
+ oneStepReport = null;
8
+ flagStopOnError = false;
9
+ stepStart(pos) {
10
+ this.oneStepLog = [];
11
+ this.start = Date.now();
12
+ this.stepPos = pos;
13
+ console.log(`----------------- step #${pos} ------------------------`);
14
+ }
15
+ stepEnd(pass) {
16
+ let hasCancelMessage = false;
17
+ this.oneStepLog.forEach(l => {
18
+ if (l.level !== logLevel.info) {
19
+ hasCancelMessage = true;
20
+ }
21
+ });
22
+ const status = hasCancelMessage ? stepStatus.cancel : (pass ? stepStatus.pass : stepStatus.fail);
23
+ this.oneStepReport = {
24
+ pos: this.stepPos,
25
+ runtime: Date.now() - this.start,
26
+ status,
27
+ messages: this.oneStepLog
28
+ };
29
+ const r = this.oneStepReport;
30
+ console.log(`status='${stepStatus.toString(r.status)}' runtime=${r.runtime}, ${r.messages && r.messages.length ? r.messages.length + ' messages' : 'no message'}`);
31
+ if (r.messages) {
32
+ for (const msg of r.messages) {
33
+ console.log(` => ${logLevel.toString(msg.level)} : ${msg.message}`);
34
+ }
35
+ }
36
+ console.log('-------------------------------------------------');
37
+ }
38
+ info(message) {
39
+ this.log(logLevel.info, message);
40
+ }
41
+ warning(message) {
42
+ this.log(logLevel.warning, message);
43
+ }
44
+ error(message) {
45
+ this.log(logLevel.error, message);
46
+ }
47
+ getJsonStepReport(stepCtx) {
48
+ try {
49
+ return JSON.stringify({
50
+ ctx: context.dump(),
51
+ logs: this.oneStepReport,
52
+ params: stepCtx ? stepCtx.getAllParams() : [],
53
+ flagStop: this.flagStopOnError
54
+ });
55
+ }
56
+ catch (e) {
57
+ return '{}';
58
+ }
59
+ }
60
+ getStepStatus() {
61
+ return this.oneStepReport && this.oneStepReport.status ? this.oneStepReport.status : 0;
62
+ }
63
+ CountOneStepLog() {
64
+ return this.oneStepLog.length;
65
+ }
66
+ setStopOnError(state) {
67
+ this.flagStopOnError = state;
68
+ }
69
+ getStopOnError() {
70
+ return this.flagStopOnError;
71
+ }
72
+ clearStepLog() {
73
+ this.oneStepLog = [];
74
+ }
75
+ log(level, message) {
76
+ const log = {
77
+ pos: this.stepPos,
78
+ level,
79
+ message
80
+ };
81
+ this.oneStepLog.push(log);
82
+ }
83
+ }
@@ -0,0 +1,10 @@
1
+ import StepContext from './step.context.js';
2
+ export default class RunStep {
3
+ /**
4
+ * Execute a step
5
+ * @param stepCtx
6
+ * @param lib
7
+ * @param fn
8
+ */
9
+ run(stepCtx: StepContext, lib: string, fn: string): Promise<boolean>;
10
+ }
@@ -0,0 +1,23 @@
1
+ import { report, sagent } from "../index.js";
2
+ export default class RunStep {
3
+ /**
4
+ * Execute a step
5
+ * @param stepCtx
6
+ * @param lib
7
+ * @param fn
8
+ */
9
+ async run(stepCtx, lib, fn) {
10
+ let retour = false;
11
+ const fct = sagent.getStepFunction(lib, fn);
12
+ if (fct) {
13
+ try {
14
+ retour = await fct(stepCtx);
15
+ }
16
+ catch (e) {
17
+ // erreur d'exécution de la fonction => codage
18
+ report.error(`Function execution error : ${e.message}`);
19
+ }
20
+ }
21
+ return retour;
22
+ }
23
+ }
@@ -0,0 +1,8 @@
1
+ import { RunDataStepModel } from '../models/run.model.js';
2
+ export declare class RunSteps {
3
+ private runstep;
4
+ private stepCtx;
5
+ stop: boolean;
6
+ run(data: RunDataStepModel[] | RunDataStepModel | undefined): Promise<void>;
7
+ private runAStep;
8
+ }
@@ -0,0 +1,47 @@
1
+ import RunStep from './runstep.js';
2
+ import StepContext from './step.context.js';
3
+ import wSocketIo from './wsocket.io.js';
4
+ import { context, report } from "../index.js";
5
+ export class RunSteps {
6
+ runstep;
7
+ stepCtx = null;
8
+ stop = false;
9
+ async run(data) {
10
+ this.runstep = new RunStep();
11
+ if (data) {
12
+ const rundata = !Array.isArray(data) ? [data] : data;
13
+ context.resetVariables();
14
+ for (const step of rundata) {
15
+ await this.runAStep(step);
16
+ // suppression de la prise en compte du stop si erreur parce qu'il fait bugger l'automatisation des campagnes
17
+ // if (stopIfError) {
18
+ // break
19
+ // }
20
+ if (this.stop) {
21
+ break;
22
+ }
23
+ }
24
+ wSocketIo.end();
25
+ }
26
+ else {
27
+ report.error('No steps data found');
28
+ wSocketIo.end();
29
+ }
30
+ }
31
+ async runAStep(step) {
32
+ let stepResult;
33
+ report.stepStart(step.pos);
34
+ try {
35
+ this.stepCtx = new StepContext(step);
36
+ stepResult = await this.runstep.run(this.stepCtx, step.lib, step.fn);
37
+ }
38
+ catch (e) {
39
+ report.warning('Unexpected error : ' + e.message);
40
+ stepResult = false;
41
+ }
42
+ report.stepEnd(stepResult);
43
+ // wsServer.send(report.getJsonStepReport(this.ctx, this.stepCtx))
44
+ wSocketIo.report(report.getJsonStepReport(this.stepCtx), report.getStepStatus());
45
+ return report.getStopOnError();
46
+ }
47
+ }
@@ -0,0 +1,23 @@
1
+ import { RunDataStepModel, RunParamModel } from '../models/run.model.js';
2
+ import { varType } from '../models/parameter.model.js';
3
+ /**
4
+ * La classe **StepContext** gère les paramètres.
5
+ *
6
+ * Il y a 2 types de paramètres.
7
+ * - les paramètres des étapes de test. Ils sont représentés par la propriété params.
8
+ * - les paramètres de configuration des accessoires et les clés de mapping. Ils sont représentés par la propriété config
9
+ */
10
+ export default class StepContext {
11
+ istoy: boolean;
12
+ private readonly params;
13
+ private readonly config;
14
+ readonly toolid: string | null;
15
+ constructor(step: RunDataStepModel);
16
+ getAllParams(): RunParamModel[];
17
+ getAllConfigs(): RunParamModel[];
18
+ getParam(key: string, defaut?: varType): varType;
19
+ getStringParam(key: string, defaut?: string | undefined): string;
20
+ getConfig(key: string, defaut?: varType): varType;
21
+ private get;
22
+ private solveParams;
23
+ }
@@ -0,0 +1,78 @@
1
+ import { enumParamType } from '../models/parameter.model.js';
2
+ import { JisonSolver } from './jison.parser.js';
3
+ import { context, report } from "../index.js";
4
+ /**
5
+ * La classe **StepContext** gère les paramètres.
6
+ *
7
+ * Il y a 2 types de paramètres.
8
+ * - les paramètres des étapes de test. Ils sont représentés par la propriété params.
9
+ * - les paramètres de configuration des accessoires et les clés de mapping. Ils sont représentés par la propriété config
10
+ */
11
+ export default class StepContext {
12
+ istoy;
13
+ params;
14
+ config;
15
+ toolid;
16
+ constructor(step) {
17
+ this.params = step.parameters;
18
+ this.config = step.config;
19
+ this.istoy = step.istoy;
20
+ this.toolid = step.toolid ? step.toolid : null;
21
+ // Chargement si nécessaire des variables présentes dans les paramètres
22
+ context.loadVariable(this.params);
23
+ // Résolution des expressions
24
+ this.solveParams();
25
+ }
26
+ getAllParams() {
27
+ return this.params;
28
+ }
29
+ getAllConfigs() {
30
+ return this.config;
31
+ }
32
+ getParam(key, defaut = undefined) {
33
+ return this.get(this.params, key, defaut);
34
+ }
35
+ getStringParam(key, defaut = undefined) {
36
+ return this.getParam(key, defaut);
37
+ }
38
+ getConfig(key, defaut = undefined) {
39
+ return this.get(this.config, key, defaut);
40
+ }
41
+ get(P, key, defaut) {
42
+ const par = P.find((p) => p.key === key);
43
+ return par && typeof par.value !== 'undefined' ? par.value : defaut;
44
+ }
45
+ solveParams() {
46
+ this.params.map((param) => {
47
+ context.valorize(param);
48
+ if (param.value && param.type && param.options) {
49
+ const solver = JisonSolver.builder(param.type, param.options);
50
+ if (solver) {
51
+ const strSolveVal = solver.exec(param.value);
52
+ if (strSolveVal) {
53
+ switch (param.type) {
54
+ case enumParamType.booldata:
55
+ param.value = strSolveVal.toLowerCase() === 'true';
56
+ break;
57
+ case enumParamType.numbdata:
58
+ param.value = parseFloat(strSolveVal);
59
+ break;
60
+ case enumParamType.datetime:
61
+ param.value = Date.parse(strSolveVal);
62
+ break;
63
+ default:
64
+ param.value = strSolveVal;
65
+ }
66
+ }
67
+ else {
68
+ param.value = null;
69
+ }
70
+ }
71
+ else {
72
+ report.error(`Impossible to solve expression : ${param.value}`);
73
+ }
74
+ }
75
+ return param;
76
+ });
77
+ }
78
+ }
@@ -0,0 +1,20 @@
1
+ import { Socket } from "socket.io-client";
2
+ declare class WsocketIo {
3
+ ioClient: Socket | null;
4
+ private runsteps;
5
+ private connected;
6
+ private termId;
7
+ start(): void;
8
+ report(message: string, stepStatus: number): void;
9
+ /**
10
+ * Fin d'exécution d'un run
11
+ */
12
+ end(): void;
13
+ private onError;
14
+ private onRundata;
15
+ private onStatus;
16
+ private onPing;
17
+ private onStopRun;
18
+ }
19
+ declare const wSocketIo: WsocketIo;
20
+ export default wSocketIo;
@@ -0,0 +1,112 @@
1
+ import { io } from "socket.io-client";
2
+ import { RunSteps } from './runsteps.js';
3
+ import { report } from "../index.js";
4
+ const url = process.env.ScapinServerURL || 'https://scapin.loicg.com';
5
+ const scapinAgentId = process.env.ScapinAgentId;
6
+ class WsocketIo {
7
+ ioClient = null;
8
+ runsteps = null;
9
+ connected = true;
10
+ termId = '';
11
+ start() {
12
+ console.log(`Start websocket url = ${url}, activation key = ${scapinAgentId}`);
13
+ const t = scapinAgentId ? scapinAgentId.split('/') : '__';
14
+ if (t.length !== 2) {
15
+ console.log('/!\\ ScapinAgentId environment variable does not exist or is incorrectly formatted ');
16
+ console.log(' The good format is :');
17
+ console.log(' <account>/<terminalKey>');
18
+ console.log(' with :');
19
+ console.log(' - <account> Your account identifier ');
20
+ console.log(' - <terminalKey> The identification key of your terminal ');
21
+ this.ioClient = null;
22
+ return;
23
+ }
24
+ this.termId = t[1];
25
+ this.ioClient = io(`${url}`, {
26
+ autoConnect: true,
27
+ transports: ['websocket'],
28
+ path: `/jobrunner/${t[0]}/`,
29
+ query: { from: 'terminal', termId: this.termId }
30
+ });
31
+ if (this.ioClient.disconnected) {
32
+ // console.log('Terminal closed => connect it')
33
+ this.ioClient.connect();
34
+ }
35
+ this.ioClient.on('connected', (() => {
36
+ this.connected = true;
37
+ console.log(`Terminal ${scapinAgentId} is now connected to automation server!`);
38
+ }));
39
+ this.ioClient.on('connect_error', this.onError);
40
+ this.ioClient.on('data', this.onRundata);
41
+ this.ioClient.on('rundata', this.onRundata);
42
+ this.ioClient.on('status', this.onStatus);
43
+ this.ioClient.on('status-ping', this.onPing);
44
+ this.ioClient.on('stoprun', this.onStopRun);
45
+ // this.ioClient.on('reconnect_attempt', (n: number) => { console.log(`${n} tentative de reconnexion`)})
46
+ this.ioClient.on('reconnect', (n) => {
47
+ console.log(`${n} reconnexion réussies`);
48
+ });
49
+ // this.ioClient.on('reconnect_error', (err: Error) => { console.log(`reconnexion error :`, err)})
50
+ this.ioClient.on('offline', () => {
51
+ console.log('Db server offline');
52
+ });
53
+ }
54
+ report(message, stepStatus) {
55
+ if (this.ioClient) {
56
+ // console.log('emit report & step-status')
57
+ this.ioClient.emit('report', message);
58
+ this.ioClient.emit('step-status', stepStatus);
59
+ }
60
+ }
61
+ /**
62
+ * Fin d'exécution d'un run
63
+ */
64
+ end() {
65
+ if (this.ioClient) {
66
+ this.ioClient.emit('end');
67
+ }
68
+ this.runsteps = null;
69
+ report.clearStepLog();
70
+ }
71
+ onError = (err) => {
72
+ const msg = err.description ? err.description.message : '';
73
+ if (this.connected) {
74
+ if (msg.indexOf('ECONNREFUSED') > 0) {
75
+ this.connected = false;
76
+ console.log(`Automation server is currently offline`);
77
+ }
78
+ else {
79
+ console.log('Connection error :', err.message);
80
+ }
81
+ }
82
+ };
83
+ onRundata = async (stepsdata) => {
84
+ this.runsteps = new RunSteps();
85
+ try {
86
+ await this.runsteps.run(stepsdata);
87
+ }
88
+ catch (e) {
89
+ console.log('Unexpected error : ' + e.message);
90
+ wSocketIo.end();
91
+ }
92
+ };
93
+ onStatus = () => {
94
+ if (this.ioClient) {
95
+ this.ioClient.emit('status', this.runsteps ? 'busy' : 'available');
96
+ }
97
+ };
98
+ onPing = (ack) => {
99
+ console.log(`onPing termId:${this.termId}`);
100
+ ack(this.termId);
101
+ };
102
+ onStopRun = () => {
103
+ console.log('onStopRun');
104
+ if (this.runsteps) {
105
+ this.runsteps.stop = true;
106
+ }
107
+ this.runsteps = null;
108
+ report.clearStepLog();
109
+ };
110
+ }
111
+ const wSocketIo = new WsocketIo();
112
+ export default wSocketIo;
package/bin/index.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import AppSagent from "./core/app.sagent.js";
2
+ import Context from "./core/context.js";
3
+ import Report from "./core/report.js";
4
+ export declare const sagent: AppSagent;
5
+ export declare const context: Context;
6
+ export declare const report: Report;
package/bin/index.js ADDED
@@ -0,0 +1,7 @@
1
+ import AppSagent from "./core/app.sagent.js";
2
+ import Context from "./core/context.js";
3
+ import Report from "./core/report.js";
4
+ export const sagent = new AppSagent();
5
+ export const context = new Context();
6
+ export const report = new Report;
7
+ // sagent.listen()
@@ -0,0 +1,19 @@
1
+ export declare function calcGrammar(solve?: boolean): {
2
+ lex: {
3
+ rules: string[][];
4
+ };
5
+ operators: string[][];
6
+ bnf: {
7
+ expressions: string[][];
8
+ e: (string | {
9
+ prec: string;
10
+ })[][];
11
+ };
12
+ };
13
+ export declare const xxxGrammar: {
14
+ lex: {
15
+ rules: string[][];
16
+ };
17
+ operators: never[];
18
+ bnf: {};
19
+ };
@@ -0,0 +1,66 @@
1
+ /* tslint:disable:quotemark trailing-comma */
2
+ export function calcGrammar(solve = false) {
3
+ const varValue = solve ? 'return null' : '$$ = 0';
4
+ return {
5
+ lex: {
6
+ rules: [
7
+ // Saute les espaces
8
+ ['\\s+', '/* skip whitespace */'],
9
+ ['[0-9]+(?:\\.[0-9]+)?\\b', 'return `NUMBER`'],
10
+ ['\\$\\w+', 'return `VARIABLE`'],
11
+ ['\\*', 'return `*`'],
12
+ ['\\/', 'return `/`'],
13
+ ['-', 'return `-`'],
14
+ ['\\+', 'return `+`'],
15
+ ['\\^', 'return `^`'],
16
+ ['!', 'return `!`'],
17
+ ['%', 'return `%`'],
18
+ ['\\(', 'return `(`'],
19
+ ['\\)', 'return `)`'],
20
+ ['PI\\b', 'return `PI`'],
21
+ ['E\\b', 'return `E`'],
22
+ ['$', 'return `EOF`'],
23
+ ['=', 'return `BEGEXP`']
24
+ ]
25
+ },
26
+ operators: [
27
+ ['left', '+', '-'],
28
+ ['left', '*', '/'],
29
+ ['left', '^'],
30
+ ['right', '!'],
31
+ ['right', '%'],
32
+ ['left', 'UMINUS']
33
+ ],
34
+ bnf: {
35
+ expressions: [['BEGEXP e EOF', 'return $2'], ['NUMBER EOF', 'return $1']],
36
+ e: [
37
+ ['e + e', '$$ = $1+$3'],
38
+ ['e - e', '$$ = $1-$3'],
39
+ ['e * e', '$$ = $1*$3'],
40
+ ['e / e', '$$ = $1/$3'],
41
+ ['e ^ e', '$$ = Math.pow($1, $3)'],
42
+ ['e !', '$$ = (function(n) {if(n==0) return 1; return arguments.callee(n-1) * n})($1)'],
43
+ ['e - e %', '$$ = $e1-($e1*($e2/100))'],
44
+ ['e + e %', '$$ = $e1+($e1*($e2/100))'],
45
+ ['e * e %', '$$ = $e1*($e2/100)'],
46
+ ['( e % )', '$$ = $2/100'],
47
+ ['- e', '$$ = -$2', { prec: 'UMINUS' }],
48
+ ['( e )', '$$ = $2'],
49
+ ['NUMBER', '$$ = Number(yytext)'],
50
+ ['VARIABLE', varValue],
51
+ ['E', '$$ = Math.E'],
52
+ ['PI', '$$ = Math.PI']
53
+ ]
54
+ }
55
+ };
56
+ }
57
+ export const xxxGrammar = {
58
+ lex: {
59
+ rules: [
60
+ // Saute les espaces
61
+ ['\\s+', '/* skip whitespace */'],
62
+ ]
63
+ },
64
+ operators: [],
65
+ bnf: {}
66
+ };
@@ -0,0 +1,10 @@
1
+ export declare function datetimeGrammar(solve: boolean): {
2
+ lex: {
3
+ rules: string[][];
4
+ };
5
+ operators: never[];
6
+ bnf: {
7
+ expressions: string[][];
8
+ e: string[][];
9
+ };
10
+ };
@@ -0,0 +1,42 @@
1
+ export function datetimeGrammar(solve) {
2
+ const varValue = solve ? 'return null' : '$$ = ``';
3
+ return {
4
+ lex: {
5
+ rules: [
6
+ ['\\s+', '/* skip whitespace */'],
7
+ ['\\$\\w+', 'return `VARIABLE`'],
8
+ ['=', 'return `BEGEXP`'],
9
+ ['"', 'return `QUOT`'],
10
+ ['\/', 'return `/`'],
11
+ ['(0?[1-9]|1[012])', 'return `MM`'],
12
+ ['(0?[1-9]|[12][0-9]|3[01])', 'return `DD`'],
13
+ ['\\d\{4\}', 'return `YYYY`'],
14
+ ['NOW|now', 'return `NOW`'],
15
+ // ['0?[0-9]|[1][0-9]|2[01234]', 'return `HH`'],
16
+ // ['0?[0-9]|[12345][0-9]', 'return `0-59`'],
17
+ // ['\-', 'return `-`'],
18
+ // ['[12]\\d\\d\\d\\-(0?[1-9]|1[012])\\-(0?[1-9]|[12][0-9]|3[01])', 'return USDATE'],
19
+ // ['[1-9]+[Dd]', 'return `ADD`'],
20
+ // ['\+', 'return `+`'],
21
+ ['$', 'return `EOF`']
22
+ ]
23
+ },
24
+ operators: [],
25
+ bnf: {
26
+ expressions: [['BEGEXP e EOF', 'return $2']],
27
+ e: [
28
+ ['DD / e', '$$ = $1'],
29
+ ['e / YYYY', '$$ = $3'],
30
+ ['/ MM /', '$$ = $2'],
31
+ // ['YYYY - MM - DD', '$$ = new Date($e1, $e2, $e3)'],
32
+ // ['DD / MM / YYYY', '$$ = new Date($e3, $e2, $e1)'],
33
+ // ['HH : 0-59 : 0-59', '$$ = new Date(0, 0, 0, $e1, $e2, $e3)'],
34
+ // ['QUOT MM QUOT', '$$ = 0'],
35
+ ['NOW', '$$ = Date.now()'],
36
+ // ['e + ADD', '$$ = ``'],
37
+ // ['e + ADD', '$$ = {const ret = new Date($e1); return ret.setDate(ret.getDate() + parseInt($e2))}'],
38
+ ['VARIABLE', varValue]
39
+ ]
40
+ }
41
+ };
42
+ }
@@ -0,0 +1,10 @@
1
+ export declare function logicalGrammar(solve: boolean): {
2
+ lex: {
3
+ rules: string[][];
4
+ };
5
+ operators: string[][];
6
+ bnf: {
7
+ expressions: string[][];
8
+ e: string[][];
9
+ };
10
+ };
@@ -0,0 +1,39 @@
1
+ export function logicalGrammar(solve) {
2
+ const varValue = solve ? 'return null' : '$$ = 0';
3
+ return {
4
+ lex: {
5
+ // startConditions: {
6
+ // expression: 'return e',
7
+ // value: 'return v'
8
+ // },
9
+ rules: [
10
+ ['\\s+', '/* skip whitespace */'],
11
+ ['[0-9]+(?:\\.[0-9]+)?\\b', 'return `NUMBER`'],
12
+ ['\\$\\w+', 'return `VARIABLE`'],
13
+ ['TRUE|true|FALSE|false', 'return `BOOLEAN`'],
14
+ ['<=', 'return `INFEQ`'],
15
+ ['>=', 'return `SUPEQ`'],
16
+ ['<', 'return `INF`'],
17
+ ['>', 'return `SUP`'],
18
+ ['$', 'return `EOF`'],
19
+ ['=', 'return `BEGEXP`']
20
+ ]
21
+ },
22
+ operators: [
23
+ ['left', 'INF', 'SUP', 'INFEQ', 'SUPEQ'],
24
+ ['right', 'BEGEXP']
25
+ ],
26
+ bnf: {
27
+ expressions: [['BEGEXP e EOF', 'return $2'], ['BOOLEAN EOF', 'return $1']],
28
+ e: [
29
+ ['NUMBER', '$$ = Number(yytext)'],
30
+ ['VARIABLE', varValue],
31
+ ['BOOLEAN', '$$ = yytext === `TRUE` || yytext === `true`'],
32
+ ['e INF e', '$$ = $1<$3'],
33
+ ['e SUP e', '$$ = $1 > $3'],
34
+ ['e SUPEQ e', '$$ = $1 >= $3'],
35
+ ['e INFEQ e', '$$ = $1 <= $3'],
36
+ ]
37
+ }
38
+ };
39
+ }
@@ -0,0 +1,10 @@
1
+ export declare function optionGrammar(solve: boolean, options: string[]): {
2
+ lex: {
3
+ rules: string[][];
4
+ };
5
+ operators: never[];
6
+ bnf: {
7
+ expressions: string[][];
8
+ e: string[][];
9
+ };
10
+ };
@@ -0,0 +1,24 @@
1
+ export function optionGrammar(solve, options) {
2
+ const varValue = solve ? 'return null' : '$$ = ``';
3
+ const optValue = options.join('|');
4
+ return {
5
+ lex: {
6
+ rules: [
7
+ ['\\s+', '/* skip whitespace */'],
8
+ ['\\$\\w+', 'return `VARIABLE`'],
9
+ ['"', 'return `QUOT`'],
10
+ [optValue, 'return `OPTION`'],
11
+ ['$', 'return `EOF`'],
12
+ ['=', 'return `BEGEXP`']
13
+ ]
14
+ },
15
+ operators: [],
16
+ bnf: {
17
+ expressions: [['BEGEXP e EOF', 'return $2'], ['OPTION EOF', 'return $1']],
18
+ e: [
19
+ ['QUOT OPTION QUOT', '$$ = $2'],
20
+ ['VARIABLE', varValue]
21
+ ]
22
+ }
23
+ };
24
+ }
@@ -0,0 +1,10 @@
1
+ export declare function stringGrammar(solve: boolean): {
2
+ lex: {
3
+ rules: string[][];
4
+ };
5
+ operators: string[][];
6
+ bnf: {
7
+ expressions: string[][];
8
+ e: string[][];
9
+ };
10
+ };
@@ -0,0 +1,31 @@
1
+ /* tslint:disable:trailing-comma */
2
+ export function stringGrammar(solve) {
3
+ const varVariable = solve ? 'return null' : '$$ = ``';
4
+ return {
5
+ lex: {
6
+ rules: [
7
+ // Saute les espaces
8
+ ['\\s+', '/* skip whitespace */'],
9
+ ['\\$\\w+', 'return `VARIABLE`'],
10
+ ['_', 'return `SPACE`'],
11
+ ['"', 'return `QUOT`'],
12
+ ['\\&', 'return `&`'],
13
+ ['=', 'return `BEGEXP`'],
14
+ ['[^"]+', 'return `STRING`'],
15
+ ['$', 'return `EOF`'],
16
+ ]
17
+ },
18
+ operators: [
19
+ ['left', '&']
20
+ ],
21
+ bnf: {
22
+ expressions: [['BEGEXP e EOF', 'return $2'], ['STRING EOF', 'return $1']],
23
+ e: [
24
+ ['e & e', '$$ = `${$1}${$3}`'],
25
+ ['QUOT STRING QUOT', '$$ = $2'],
26
+ ['SPACE', '$$ = ` `'],
27
+ ['VARIABLE', varVariable]
28
+ ]
29
+ }
30
+ };
31
+ }
@@ -0,0 +1,9 @@
1
+ export declare const variableGrammar: {
2
+ lex: {
3
+ rules: string[][];
4
+ };
5
+ operators: never[];
6
+ bnf: {
7
+ expressions: string[][];
8
+ };
9
+ };
@@ -0,0 +1,14 @@
1
+ export const variableGrammar = {
2
+ lex: {
3
+ rules: [
4
+ // Saute les espaces
5
+ ['\\s+', '/* skip whitespace */'],
6
+ ['\\$\\w+', 'return `VARIABLE`'],
7
+ ['$', 'return `EOF`']
8
+ ]
9
+ },
10
+ operators: [],
11
+ bnf: {
12
+ expressions: [['VARIABLE EOF', 'return $1']]
13
+ }
14
+ };
@@ -0,0 +1,20 @@
1
+ export interface DescModel {
2
+ pos: number;
3
+ label: string;
4
+ type: enumParamType;
5
+ documentation?: string;
6
+ required: boolean;
7
+ options?: string[];
8
+ }
9
+ export interface SettingDescModel extends DescModel {
10
+ tid: string;
11
+ }
12
+ export declare enum enumParamType {
13
+ booldata = "Boolean",
14
+ numbdata = "Number",
15
+ textdata = "Text",
16
+ datetime = "DateTime",
17
+ receipt = "Variable",
18
+ options = "Options"
19
+ }
20
+ export type varType = string | number | boolean | null | undefined;
@@ -0,0 +1,14 @@
1
+ // Modèle de données des paramètres utilisés pour les libraries
2
+ // et pour la configuration des outils
3
+ // Enumération des types de paramètre
4
+ // receipt est spécifique aux paramètres d'action
5
+ // options est spécifique aux paramètres de configuration d'outils (tool's settings)
6
+ export var enumParamType;
7
+ (function (enumParamType) {
8
+ enumParamType["booldata"] = "Boolean";
9
+ enumParamType["numbdata"] = "Number";
10
+ enumParamType["textdata"] = "Text";
11
+ enumParamType["datetime"] = "DateTime";
12
+ enumParamType["receipt"] = "Variable";
13
+ enumParamType["options"] = "Options";
14
+ })(enumParamType || (enumParamType = {}));
@@ -0,0 +1,56 @@
1
+ import { enumParamType, varType } from './parameter.model.js';
2
+ export interface WsDataMessage {
3
+ logs: RunReportStep;
4
+ ctx: [string, varType][];
5
+ params: RunParamModel[];
6
+ }
7
+ export interface RunDataStepModel {
8
+ pos: number;
9
+ istoy: boolean;
10
+ lib: string;
11
+ fn: string;
12
+ parameters: RunParamModel[];
13
+ config: RunParamModel[];
14
+ toolid?: string;
15
+ }
16
+ export interface RunParamModel {
17
+ key: string;
18
+ value: varType;
19
+ type?: enumParamType;
20
+ options?: string[];
21
+ }
22
+ /**
23
+ * Log information interface
24
+ * - *pos* : step position or -1 if log message doesn't concern a step
25
+ * - *level* : 0 = information, 1 = warning, 2 = error
26
+ * - *message* : message text
27
+ */
28
+ export interface RunLog {
29
+ pos: number;
30
+ level: number;
31
+ message: string;
32
+ }
33
+ /**
34
+ * Step execution reporting
35
+ * - *pos* : step position
36
+ * - *runtime* : step execution duration
37
+ * - *status* : 0 = cancel, 1 = pass, 2 = fail
38
+ */
39
+ export interface RunReportStep {
40
+ pos?: number;
41
+ runtime?: number;
42
+ status?: number;
43
+ messages?: RunLog[];
44
+ }
45
+ export declare const stepStatus: Readonly<{
46
+ cancel: 0;
47
+ pass: 1;
48
+ fail: 2;
49
+ toString(n: number | undefined): "cancel" | "pass" | "fail" | "";
50
+ }>;
51
+ export declare const logLevel: Readonly<{
52
+ info: 0;
53
+ warning: 1;
54
+ error: 2;
55
+ toString(n: number | undefined): "" | "info" | "warning" | "error";
56
+ }>;
@@ -0,0 +1,26 @@
1
+ export const stepStatus = Object.freeze({
2
+ cancel: 0,
3
+ pass: 1,
4
+ fail: 2,
5
+ toString(n) {
6
+ switch (n) {
7
+ case 0: return 'cancel';
8
+ case 1: return 'pass';
9
+ case 2: return 'fail';
10
+ }
11
+ return '';
12
+ },
13
+ });
14
+ export const logLevel = Object.freeze({
15
+ info: 0,
16
+ warning: 1,
17
+ error: 2,
18
+ toString(n) {
19
+ switch (n) {
20
+ case 0: return 'info';
21
+ case 1: return 'warning';
22
+ case 2: return 'error';
23
+ }
24
+ return '';
25
+ },
26
+ });
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@kogeet/scapin-core-agent",
3
+ "version": "0.1.0",
4
+ "description": "Scapin Core Agent",
5
+ "author": "Loïc Griveau",
6
+ "license": "MIT",
7
+ "main": "bin/index.js",
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "engines": {
12
+ "node": "^18.17.1"
13
+ },
14
+ "np": {
15
+ "tests": false,
16
+ "message": "core-agent %s"
17
+ },
18
+ "scripts": {
19
+ "build": "tsc --sourceMap false --declaration true",
20
+ "sagentprod": "npm run build && node bin/index.js"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^20.8.8",
24
+ "@typescript-eslint/eslint-plugin": "^6.8.0",
25
+ "@typescript-eslint/parser": "^6.8.0",
26
+ "eslint": "^8.51.0",
27
+ "typescript": "^5.2.2"
28
+ },
29
+ "dependencies": {
30
+ "jison": "^0.4.18",
31
+ "socket.io-client": "^4.7.2"
32
+ },
33
+ "type": "module"
34
+ }