@mostajs/aop-engine 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.
package/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # @mostajs/aop-engine
2
+
3
+ **Auteur** : Dr Hamid MADANI <drmdh@msn.com> · AGPL-3.0-or-later
4
+
5
+ Moteur de **veille multi-client** : câble `@mostajs/aop-scheduler` → hub `@mostajs/trigger` → **livraison au client** (notification, seam injecté). Compose scheduler + clients/veilles + notify. Stack `mosta-aop-stack`.
package/llms.txt ADDED
@@ -0,0 +1,10 @@
1
+ # @mostajs/aop-engine — fiche LLM
2
+ > Moteur de veille MULTI-CLIENT : câble aop-scheduler → hub @mostajs/trigger → LIVRAISON au client (notification).
3
+
4
+ ## EXPORTS
5
+ createVeilleEngine({ ingestion, tenders, veilles(aop-clients), clients(aop-clients), hub(@mostajs/trigger), notify?, audit?, now }) -> { runVeille(scrapers,filters), hub, scheduler }
6
+ createFakeHub() (./src/fake-hub.js) — hub minimal pour tests ; en prod createTriggerHub() de @mostajs/trigger.
7
+
8
+ ## FLUX
9
+ runVeille -> scheduler (ingère+matche veilles) -> hub.fire(aop:tender:matched) -> réaction enregistrée: résout client -> notify.send -> stats++.
10
+ Stack mosta-aop-stack. notify = seam (@mostajs/notifications/mailer).
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@mostajs/aop-engine",
3
+ "version": "0.1.0",
4
+ "description": "Moteur de veille multi-client : câble aop-scheduler → hub @mostajs/trigger → livraison au client (notification). Composition transverse.",
5
+ "author": "Dr Hamid MADANI <drmdh@msn.com>",
6
+ "license": "AGPL-3.0-or-later",
7
+ "type": "module",
8
+ "main": "src/index.js",
9
+ "exports": {
10
+ ".": "./src/index.js"
11
+ },
12
+ "files": [
13
+ "src",
14
+ "README.md",
15
+ "llms.txt"
16
+ ],
17
+ "dependencies": {
18
+ "@mostajs/aop-scheduler": "^0.1.0"
19
+ },
20
+ "peerDependencies": {
21
+ "@mostajs/trigger": "*"
22
+ },
23
+ "peerDependenciesMeta": {
24
+ "@mostajs/trigger": {
25
+ "optional": true
26
+ }
27
+ },
28
+ "devDependencies": {
29
+ "@mostajs/mjs-unit": "^0.3.0"
30
+ },
31
+ "scripts": {
32
+ "test": "node test-scripts/unit/aop-engine.test.mjs && node examples/run.mjs"
33
+ }
34
+ }
@@ -0,0 +1,8 @@
1
+ // Hub minimal compatible @mostajs/trigger pour TESTS/exemples (define + fire pondéré). En prod : createTriggerHub().
2
+ export function createFakeHub() {
3
+ const handlers = [];
4
+ return {
5
+ define: (def) => { handlers.push(def); return def; },
6
+ fire: async (event, ctx) => { for (const h of handlers.filter((d) => d.on === event).sort((a, b) => (a.weight || 0) - (b.weight || 0))) { if (!h.when || h.when(ctx)) await h.do(ctx); } },
7
+ };
8
+ }
package/src/index.js ADDED
@@ -0,0 +1,46 @@
1
+ // @mostajs/aop-engine — moteur de veille multi-client : câble aop-scheduler → hub @mostajs/trigger →
2
+ // LIVRAISON au client (notification). Compose scheduler + hub(trigger) + notify(seam) + clients/veilles/tenders.
3
+ // @author Dr Hamid MADANI <drmdh@msn.com> · AGPL-3.0-or-later
4
+ import { createScheduler } from '@mostajs/aop-scheduler';
5
+
6
+ /**
7
+ * @param {object} deps
8
+ * @param {object} deps.ingestion service @mostajs/aop-ingestion
9
+ * @param {object} deps.tenders service @mostajs/aop-core
10
+ * @param {object} deps.veilles service @mostajs/aop-clients createVeilles (= interface alerts du scheduler)
11
+ * @param {object} deps.clients service @mostajs/aop-clients createClients
12
+ * @param {object} deps.hub hub @mostajs/trigger (createTriggerHub) — REQUIS (define/fire)
13
+ * @param {{ send(msg):Promise }} [deps.notify] seam de notification (@mostajs/notifications/mailer)
14
+ * @param {{ record(ev) }} [deps.audit]
15
+ * @param {() => Date} [deps.now]
16
+ */
17
+ export function createVeilleEngine({ ingestion, tenders, veilles, clients, hub, notify = null, audit = null, now = () => new Date() } = {}) {
18
+ if (!hub?.define) throw new Error('aop-engine: hub @mostajs/trigger requis (createTriggerHub)');
19
+ const scheduler = createScheduler({ ingestion, tenders, alerts: veilles, hub, now });
20
+
21
+ // RÉACTION : un AO matche une veille → résoudre le client → livrer (notifier) + tracer + stats.
22
+ hub.define({
23
+ on: 'aop:tender:matched', weight: 10,
24
+ do: async (ctx) => {
25
+ const veille = await veilles.get(ctx.alertId || ctx.veilleId); if (!veille) return;
26
+ const client = veille.clientId ? await clients.get(veille.clientId) : null;
27
+ const tender = await tenders.get(ctx.tenderId);
28
+ const channels = veille.notifications?.channels || client?.notifyChannels || ['email'];
29
+ if (notify?.send && client?.contactEmail) {
30
+ await notify.send({ to: client.contactEmail, channels, subject: `Veille « ${veille.name} » — nouvel appel d'offres`,
31
+ body: `${tender?.title || ''} (score ${ctx.score})`, meta: { clientId: client.id, veilleId: veille.id, tenderId: ctx.tenderId, score: ctx.score } });
32
+ }
33
+ await veilles.update(veille.id, { stats: { ...(veille.stats || {}), matchCount: (veille.stats?.matchCount || 0) + 1 } });
34
+ audit?.record?.({ type: 'aop.match.delivered', clientId: client?.id, veilleId: veille.id, tenderId: ctx.tenderId, score: ctx.score });
35
+ },
36
+ });
37
+
38
+ return {
39
+ hub, scheduler,
40
+ /** Lance un cycle de veille (ingestion → matching veilles → trigger → livraison clients). */
41
+ runVeille: (scrapers, filters) => scheduler.runVeille(scrapers, filters),
42
+ };
43
+ }
44
+ export default { createVeilleEngine };
45
+
46
+ export { createFakeHub } from './fake-hub.js';