@nodefony/orm-core 10.0.0-alpha.1
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/LICENSE +544 -0
- package/README.md +131 -0
- package/dist/index.js +22 -0
- package/dist/nodefony/interfaces/IEntity.js +1 -0
- package/dist/nodefony/interfaces/IOrm.js +1 -0
- package/dist/nodefony/interfaces/IOrmFlow.js +1 -0
- package/dist/nodefony/interfaces/IOrmGraph.js +1 -0
- package/dist/nodefony/interfaces/IOrmMigrations.js +12 -0
- package/dist/nodefony/interfaces/IOrmProbe.js +1 -0
- package/dist/nodefony/interfaces/IPage.js +1 -0
- package/dist/nodefony/interfaces/IRepository.js +1 -0
- package/dist/nodefony/interfaces/ITransaction.js +1 -0
- package/dist/nodefony/interfaces/index.js +1 -0
- package/dist/nodefony/src/AbstractCrudService.js +199 -0
- package/dist/nodefony/src/ConnectionMonitor.js +181 -0
- package/dist/nodefony/src/Entity.js +42 -0
- package/dist/nodefony/src/EntityRegistry.js +109 -0
- package/dist/nodefony/src/Orm.js +297 -0
- package/dist/nodefony/src/OrmAdminApi.js +491 -0
- package/dist/nodefony/src/OrmRegistry.js +75 -0
- package/dist/nodefony/src/QueryFlowMonitor.js +128 -0
- package/dist/nodefony/src/buildOrmLeanHealth.js +54 -0
- package/dist/nodefony/src/criteria.js +176 -0
- package/dist/nodefony/src/decorators/entitiesDecorator.js +67 -0
- package/dist/nodefony/src/decorators/entityDecorator.js +51 -0
- package/dist/nodefony/src/decorators/index.js +5 -0
- package/dist/nodefony/src/decorators/metadataStore.js +38 -0
- package/dist/nodefony/src/decorators/repositoryDecorator.js +35 -0
- package/dist/nodefony/src/defineEntity.js +27 -0
- package/dist/nodefony/src/errors.js +76 -0
- package/dist/nodefony/src/ormWiring.js +78 -0
- package/dist/nodefony/src/paginate.js +55 -0
- package/dist/nodefony/src/readOptions.js +52 -0
- package/dist/nodefony/src/serviceWiring.js +1 -0
- package/dist/types/index.d.ts +39 -0
- package/dist/types/nodefony/interfaces/IEntity.d.ts +65 -0
- package/dist/types/nodefony/interfaces/IOrm.d.ts +136 -0
- package/dist/types/nodefony/interfaces/IOrmFlow.d.ts +71 -0
- package/dist/types/nodefony/interfaces/IOrmGraph.d.ts +165 -0
- package/dist/types/nodefony/interfaces/IOrmMigrations.d.ts +145 -0
- package/dist/types/nodefony/interfaces/IOrmProbe.d.ts +70 -0
- package/dist/types/nodefony/interfaces/IPage.d.ts +24 -0
- package/dist/types/nodefony/interfaces/IRepository.d.ts +369 -0
- package/dist/types/nodefony/interfaces/ITransaction.d.ts +31 -0
- package/dist/types/nodefony/interfaces/index.d.ts +7 -0
- package/dist/types/nodefony/src/AbstractCrudService.d.ts +158 -0
- package/dist/types/nodefony/src/ConnectionMonitor.d.ts +86 -0
- package/dist/types/nodefony/src/Entity.d.ts +44 -0
- package/dist/types/nodefony/src/EntityRegistry.d.ts +60 -0
- package/dist/types/nodefony/src/Orm.d.ts +197 -0
- package/dist/types/nodefony/src/OrmAdminApi.d.ts +84 -0
- package/dist/types/nodefony/src/OrmRegistry.d.ts +58 -0
- package/dist/types/nodefony/src/QueryFlowMonitor.d.ts +53 -0
- package/dist/types/nodefony/src/buildOrmLeanHealth.d.ts +15 -0
- package/dist/types/nodefony/src/criteria.d.ts +131 -0
- package/dist/types/nodefony/src/decorators/entitiesDecorator.d.ts +48 -0
- package/dist/types/nodefony/src/decorators/entityDecorator.d.ts +49 -0
- package/dist/types/nodefony/src/decorators/index.d.ts +10 -0
- package/dist/types/nodefony/src/decorators/metadataStore.d.ts +54 -0
- package/dist/types/nodefony/src/decorators/repositoryDecorator.d.ts +30 -0
- package/dist/types/nodefony/src/defineEntity.d.ts +43 -0
- package/dist/types/nodefony/src/errors.d.ts +62 -0
- package/dist/types/nodefony/src/ormWiring.d.ts +48 -0
- package/dist/types/nodefony/src/paginate.d.ts +43 -0
- package/dist/types/nodefony/src/readOptions.d.ts +21 -0
- package/dist/types/nodefony/src/serviceWiring.d.ts +24 -0
- package/docs/index.md +791 -0
- package/docs/tutorial-entity.md +577 -0
- package/package.json +73 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { ormRegistry } from "./OrmRegistry.js";
|
|
2
|
+
import { connectionMonitor } from "./ConnectionMonitor.js";
|
|
3
|
+
import { Service } from "nodefony";
|
|
4
|
+
import { performance } from "node:perf_hooks";
|
|
5
|
+
//#region nodefony/src/Orm.ts
|
|
6
|
+
/**
|
|
7
|
+
* Période du battement, réglable par l'environnement (`0` le désactive).
|
|
8
|
+
*
|
|
9
|
+
* Lue UNE fois au chargement du module : un connecteur ne la relit pas à
|
|
10
|
+
* chaque construction, et un déploiement qui veut un battement plus serré
|
|
11
|
+
* — ou aucun — n'a pas à toucher au code de l'application.
|
|
12
|
+
*/
|
|
13
|
+
const HEARTBEAT_MS_DEFAULT = (() => {
|
|
14
|
+
const brut = process.env.NF_ORM_HEARTBEAT_MS;
|
|
15
|
+
if (brut === void 0) return 3e4;
|
|
16
|
+
const n = Number.parseInt(brut, 10);
|
|
17
|
+
return Number.isFinite(n) && n >= 0 ? n : 3e4;
|
|
18
|
+
})();
|
|
19
|
+
/**
|
|
20
|
+
* Classe de base abstraite de tout ORM Nodefony — câble {@link Service} (DI,
|
|
21
|
+
* Syslog, bus d'événements) et le contrat {@link IOrm}, et s'auto-enregistre
|
|
22
|
+
* dans le {@link ormRegistry} process-wide à la construction.
|
|
23
|
+
*
|
|
24
|
+
* Les drivers concrets (`@nodefony/mongoose`, `@nodefony/drizzle`...)
|
|
25
|
+
* implémentent les opérations bas niveau ({@link Orm.onConnect}, `disconnect`,
|
|
26
|
+
* `getRepository`, `transaction`, `getNativeConnection`). La connexion passe par
|
|
27
|
+
* la template method {@link Orm.connect} qui émet l'événement `onOrmReady` une
|
|
28
|
+
* fois le driver connecté — garantissant que tous les ORM signalent leur
|
|
29
|
+
* disponibilité de façon homogène (avant le `onReady` du Kernel).
|
|
30
|
+
*
|
|
31
|
+
* @typeParam — aucun ; les types natifs du driver transitent via les génériques
|
|
32
|
+
* des méthodes ({@link IRepository}, {@link ITransaction}, native connection).
|
|
33
|
+
*/
|
|
34
|
+
var Orm = class extends Service {
|
|
35
|
+
/**
|
|
36
|
+
* État de vie de la connexion — source UNIQUE de `isConnected()`.
|
|
37
|
+
*
|
|
38
|
+
* `protected` et non `#privé` : `disconnect()` est implémenté par chaque
|
|
39
|
+
* adapter et doit pouvoir le remettre à `false`.
|
|
40
|
+
*/
|
|
41
|
+
alive = false;
|
|
42
|
+
/**
|
|
43
|
+
* Une perte est-elle EN SOUFFRANCE, c'est-à-dire constatée et pas encore
|
|
44
|
+
* réparée ?
|
|
45
|
+
*
|
|
46
|
+
* Sans ce drapeau, l'idempotence de {@link Orm.connectionRestored} reposait
|
|
47
|
+
* sur le seul `alive` — et `alive` vaut encore `false` PENDANT
|
|
48
|
+
* l'établissement, puisqu'il n'est posé qu'au retour de `onConnect()`. Or un
|
|
49
|
+
* adapter câble ses écoutes AVANT son premier échange (il le doit : ce
|
|
50
|
+
* premier échange peut échouer), si bien que le client initial émettait un
|
|
51
|
+
* signal de « retour » que rien n'arrêtait : **chaque boot comptait une
|
|
52
|
+
* reconnexion et annonçait `onOrmRestored` avant même `onOrmReady`**
|
|
53
|
+
* (mesuré : `reconnectCount = 1` sur un connecteur qui vient de naître).
|
|
54
|
+
* Une reprise n'a de sens que s'il y a eu une perte : c'est ce que ce
|
|
55
|
+
* drapeau exprime, et il rend la garde vraie à tout instant du cycle de vie.
|
|
56
|
+
*/
|
|
57
|
+
#lostPending = false;
|
|
58
|
+
/**
|
|
59
|
+
* **Ce que cet adapter sait VRAIMENT de l'état de sa connexion** — déclaré,
|
|
60
|
+
* jamais supposé.
|
|
61
|
+
*
|
|
62
|
+
* `"events"` : le driver signale les pertes et les reprises, l'adapter les
|
|
63
|
+
* traduit ; `isConnected()` est un CONSTAT.
|
|
64
|
+
* `"assumed"` : rien ne signale quoi que ce soit (base embarquée, driver
|
|
65
|
+
* muet) ; `isConnected()` dit seulement « la connexion a été établie et
|
|
66
|
+
* n'a pas été fermée » — une supposition.
|
|
67
|
+
*
|
|
68
|
+
* **Le défaut est `"assumed"`, et il n'est pas abstrait — délibérément.**
|
|
69
|
+
* Le rendre obligatoire forcerait chaque adapter à répondre, mais casserait
|
|
70
|
+
* la compilation de tout adapter existant : ajouter un ORM deviendrait une
|
|
71
|
+
* rupture. Le défaut prudent protège aussi bien de l'oubli, parce qu'il dit
|
|
72
|
+
* la VÉRITÉ sur un adapter qui n'a rien câblé — il ne sait pas. Ce qu'il
|
|
73
|
+
* faut empêcher, ce n'est pas le silence : c'est qu'un silence se fasse
|
|
74
|
+
* passer pour un constat.
|
|
75
|
+
*/
|
|
76
|
+
get liveness() {
|
|
77
|
+
return "assumed";
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* @param name - clé unique de l'ORM dans le {@link ormRegistry}.
|
|
81
|
+
* @param container - container DI hérité (Kernel) ou nouveau si omis.
|
|
82
|
+
* @param notificationsCenter - bus d'événements partagé, `false` pour aucun.
|
|
83
|
+
* @param options - options de service.
|
|
84
|
+
* @throws si un ORM du même `name` est déjà enregistré.
|
|
85
|
+
*/
|
|
86
|
+
constructor(name, container, notificationsCenter, options) {
|
|
87
|
+
super(name, container, notificationsCenter, options);
|
|
88
|
+
ormRegistry.register(this.name, this);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Connecte le driver puis émet `onOrmReady`.
|
|
92
|
+
*
|
|
93
|
+
* Template method : ne pas surcharger — implémenter {@link Orm.onConnect}.
|
|
94
|
+
* Instrumente le {@link connectionMonitor} (latence + reconnexion en cas de
|
|
95
|
+
* succès, erreur de connexion en cas d'échec).
|
|
96
|
+
*/
|
|
97
|
+
async connect() {
|
|
98
|
+
this.#lostPending = false;
|
|
99
|
+
const t0 = performance.now();
|
|
100
|
+
try {
|
|
101
|
+
await this.onConnect();
|
|
102
|
+
this.alive = true;
|
|
103
|
+
connectionMonitor.recordConnect(this.name, performance.now() - t0);
|
|
104
|
+
this.startHeartbeat();
|
|
105
|
+
} catch (e) {
|
|
106
|
+
this.alive = false;
|
|
107
|
+
connectionMonitor.recordError(this.name, e instanceof Error ? e.message : String(e));
|
|
108
|
+
throw e;
|
|
109
|
+
}
|
|
110
|
+
this.fire("onOrmReady", this);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* **Le driver a PERDU la connexion** — à appeler par l'adapter depuis
|
|
114
|
+
* l'événement natif de son driver (`pool.on("error")` côté `pg`,
|
|
115
|
+
* `connection.on("disconnected")` côté Mongoose…).
|
|
116
|
+
*
|
|
117
|
+
* Idempotent : un driver émet souvent plusieurs erreurs pour une seule
|
|
118
|
+
* coupure (une par connexion du pool). Seule la PREMIÈRE bascule l'état,
|
|
119
|
+
* compte l'incident et émet `onOrmLost` — sinon un pool de 10 connexions
|
|
120
|
+
* ferait dix fois le tour du framework pour un seul serveur tombé.
|
|
121
|
+
*
|
|
122
|
+
* @param reason - cause lisible, sans credential (elle est journalisée).
|
|
123
|
+
*/
|
|
124
|
+
connectionLost(reason) {
|
|
125
|
+
connectionMonitor.recordError(this.name, reason);
|
|
126
|
+
if (!this.alive) return;
|
|
127
|
+
this.alive = false;
|
|
128
|
+
this.#lostPending = true;
|
|
129
|
+
connectionMonitor.recordLost(this.name);
|
|
130
|
+
this.log(`connexion perdue : ${reason}`, "WARNING");
|
|
131
|
+
this.fire("onOrmLost", this, reason);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* **Le driver a RÉTABLI la connexion** — à appeler par l'adapter depuis
|
|
135
|
+
* l'événement natif correspondant (`pool.on("connect")`, `reconnected`…).
|
|
136
|
+
*
|
|
137
|
+
* **Une reprise n'existe que s'il y a eu une perte.** `pg` émet `connect` et
|
|
138
|
+
* `acquire` à chaque client pris au pool, y compris quand rien n'est tombé,
|
|
139
|
+
* et y compris pendant l'établissement initial : sans cette condition, un
|
|
140
|
+
* pool qui grandit sous la charge — ou simplement une application qui
|
|
141
|
+
* démarre — compterait des reconnexions imaginaires.
|
|
142
|
+
*/
|
|
143
|
+
connectionRestored() {
|
|
144
|
+
if (this.alive || !this.#lostPending) return;
|
|
145
|
+
this.alive = true;
|
|
146
|
+
this.#lostPending = false;
|
|
147
|
+
connectionMonitor.recordReconnect(this.name);
|
|
148
|
+
this.log("connexion rétablie", "INFO");
|
|
149
|
+
this.fire("onOrmRestored", this);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Période du battement de cœur, en millisecondes. `0` le désactive.
|
|
153
|
+
*
|
|
154
|
+
* **Pourquoi le framework doit fournir ça** : le driver MongoDB surveille ses
|
|
155
|
+
* serveurs en permanence (SDAM) et sait donc qu'une base est tombée même sans
|
|
156
|
+
* le moindre trafic. `pg` et `mysql2` n'ont RIEN de tel — ils n'apprennent
|
|
157
|
+
* l'état du serveur que par leurs requêtes. Mesuré : sur ces deux dialectes,
|
|
158
|
+
* une coupure survenue pendant qu'une requête était en vol, ou un serveur
|
|
159
|
+
* simplement GELÉ (qui ne ferme rien), n'émettent aucun événement : l'état
|
|
160
|
+
* restait « connecté » indéfiniment. Un battement comble cette asymétrie —
|
|
161
|
+
* il ne réinvente rien, il donne aux drivers muets ce que Mongo a déjà.
|
|
162
|
+
*
|
|
163
|
+
* Pourquoi pas une instrumentation des requêtes : son coût croît avec le
|
|
164
|
+
* trafic, pour une information qui ne change qu'aux rares instants de panne ;
|
|
165
|
+
* et il faudrait distinguer une erreur de connexion d'une contrainte violée.
|
|
166
|
+
* Ici le coût est CONSTANT et connu d'avance : une requête légère par période.
|
|
167
|
+
*/
|
|
168
|
+
heartbeatMs = HEARTBEAT_MS_DEFAULT;
|
|
169
|
+
/**
|
|
170
|
+
* Délai au-delà duquel un battement sans réponse vaut une PERTE.
|
|
171
|
+
*
|
|
172
|
+
* Sans lui, le battement ne sert à rien contre le cas qui l'a justifié :
|
|
173
|
+
* une base GELÉE ne ferme rien et ne répond pas, donc `ping()` PEND — et
|
|
174
|
+
* le battement pendait avec elle, indéfiniment, sans jamais conclure
|
|
175
|
+
* (mesuré : 30 s de gel, aucune détection). Une sonde doit avoir sa
|
|
176
|
+
* propre montre, sinon elle hérite de la panne qu'elle est censée voir.
|
|
177
|
+
*/
|
|
178
|
+
heartbeatTimeoutMs = 5e3;
|
|
179
|
+
/** Minuterie du battement — `null` tant qu'il ne bat pas (aucun coût). */
|
|
180
|
+
#heartbeat = null;
|
|
181
|
+
/** Un battement est-il en vol ? Évite qu'un ping lent en déclenche un autre. */
|
|
182
|
+
#beating = false;
|
|
183
|
+
/**
|
|
184
|
+
* Démarre le battement si l'adapter sait répondre à un `ping()` et que la
|
|
185
|
+
* période n'est pas nulle. Idempotent.
|
|
186
|
+
*
|
|
187
|
+
* La minuterie est `unref()` : elle ne doit JAMAIS retenir le process en vie
|
|
188
|
+
* — un banc, un script CLI ou un test qui se termine ne doit pas attendre le
|
|
189
|
+
* prochain battement pour rendre la main.
|
|
190
|
+
*/
|
|
191
|
+
startHeartbeat() {
|
|
192
|
+
if (this.#heartbeat !== null || this.heartbeatMs <= 0) return;
|
|
193
|
+
if (typeof this.ping !== "function") return;
|
|
194
|
+
const timer = setInterval(() => {
|
|
195
|
+
this.#beat();
|
|
196
|
+
}, this.heartbeatMs);
|
|
197
|
+
timer.unref?.();
|
|
198
|
+
this.#heartbeat = timer;
|
|
199
|
+
}
|
|
200
|
+
/** Arrête le battement et libère la minuterie. Idempotent. */
|
|
201
|
+
stopHeartbeat() {
|
|
202
|
+
if (this.#heartbeat !== null) {
|
|
203
|
+
clearInterval(this.#heartbeat);
|
|
204
|
+
this.#heartbeat = null;
|
|
205
|
+
}
|
|
206
|
+
this.#beating = false;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* **Bat MAINTENANT**, sans attendre la fin de la période.
|
|
210
|
+
*
|
|
211
|
+
* À appeler par un adapter dont le driver émet un signal SUSPECT mais pas
|
|
212
|
+
* concluant — typiquement la fermeture du socket d'une connexion du pool :
|
|
213
|
+
* elle arrive aussi bien pour un serveur tombé que pour une connexion
|
|
214
|
+
* inactive recyclée, et l'adapter ne peut pas les distinguer. Plutôt que de
|
|
215
|
+
* trancher à sa place — ce qui inscrirait de faux incidents à chaque
|
|
216
|
+
* recyclage — il délègue ici : le battement fait la seule chose qui tranche,
|
|
217
|
+
* une requête, et met l'état à jour selon la réponse.
|
|
218
|
+
*
|
|
219
|
+
* Sans cette porte, un dialecte muet reste marqué connecté jusqu'au battement
|
|
220
|
+
* suivant : 30 s par défaut, là où `pg` bascule en millisecondes. C'est une
|
|
221
|
+
* asymétrie de détection entre deux dialectes de production, pas un réglage.
|
|
222
|
+
*
|
|
223
|
+
* Ne coûte rien quand rien ne va mal : la garde `#beating` écarte les
|
|
224
|
+
* battements concurrents, donc un pool dont dix connexions tombent d'un coup
|
|
225
|
+
* ne sonde qu'une fois. Ne rétablit ni ne perd quoi que ce soit après un
|
|
226
|
+
* `disconnect()` — `#beat` y voit un arrêt volontaire et s'abstient.
|
|
227
|
+
*/
|
|
228
|
+
beatNow() {
|
|
229
|
+
this.#beat();
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Un battement : sonde la base et met l'état à jour.
|
|
233
|
+
*
|
|
234
|
+
* Ne fait RIEN si un battement précédent n'a pas rendu la main — sur une base
|
|
235
|
+
* gelée, le ping peut pendre longtemps, et empiler les sondes ne ferait
|
|
236
|
+
* qu'empiler des connexions sur un serveur déjà en difficulté.
|
|
237
|
+
*/
|
|
238
|
+
async #beat() {
|
|
239
|
+
if (!this.alive && !this.#lostPending) {
|
|
240
|
+
this.stopHeartbeat();
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (this.#beating) return;
|
|
244
|
+
this.#beating = true;
|
|
245
|
+
let watchdog = null;
|
|
246
|
+
try {
|
|
247
|
+
await Promise.race([this.ping?.() ?? Promise.resolve(), new Promise((_, rejeter) => {
|
|
248
|
+
watchdog = setTimeout(() => {
|
|
249
|
+
rejeter(/* @__PURE__ */ new Error(`aucune réponse en ${this.heartbeatTimeoutMs} ms`));
|
|
250
|
+
}, this.heartbeatTimeoutMs);
|
|
251
|
+
watchdog.unref?.();
|
|
252
|
+
})]);
|
|
253
|
+
this.connectionRestored();
|
|
254
|
+
} catch (e) {
|
|
255
|
+
this.connectionLost(`battement : ${e instanceof Error ? e.message : String(e)}`);
|
|
256
|
+
} finally {
|
|
257
|
+
if (watchdog !== null) clearTimeout(watchdog);
|
|
258
|
+
this.#beating = false;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Indique si la connexion est active — **implémentation UNIQUE**, portée par
|
|
263
|
+
* la classe de base et non par chaque adapter.
|
|
264
|
+
*
|
|
265
|
+
* C'est délibéré : tant que chaque adapter portait son propre booléen posé à
|
|
266
|
+
* la connexion, aucun ne le remettait à `false` quand le serveur tombait —
|
|
267
|
+
* la santé ORM répondait « connecté » en pleine coupure. L'état vit ici, et
|
|
268
|
+
* il n'a que trois sources : `connect()`, `disconnect()`, et les deux
|
|
269
|
+
* signaux que l'adapter traduit depuis son driver.
|
|
270
|
+
*/
|
|
271
|
+
isConnected() {
|
|
272
|
+
return this.alive;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Décrit les colonnes d'une entité pour le graphe canonique. Défaut : `[]`
|
|
276
|
+
* (relations seules dans l'ERD). Les adapters surchargent avec l'introspection
|
|
277
|
+
* native (Drizzle `getTableConfig`, Mongoose paths).
|
|
278
|
+
*
|
|
279
|
+
* @param _name - nom logique de l'entité.
|
|
280
|
+
* @returns colonnes normalisées.
|
|
281
|
+
*/
|
|
282
|
+
describeEntity(_name) {
|
|
283
|
+
return [];
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Décrit la connexion sous-jacente (driver + cible). Défaut : driver vide
|
|
287
|
+
* (inconnu). Les adapters surchargent (Drizzle → `sqlite` + fichier, etc.).
|
|
288
|
+
* Ne DOIT jamais exposer de credential.
|
|
289
|
+
*
|
|
290
|
+
* @returns infos de connexion (driver vide si non renseigné).
|
|
291
|
+
*/
|
|
292
|
+
describeConnection() {
|
|
293
|
+
return { driver: "" };
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
//#endregion
|
|
297
|
+
export { Orm };
|