@nodefony/orm-core 10.0.0-beta.4 → 10.0.0-beta.5
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/docs/index.md +14 -13
- package/docs/tutorial-entity.md +30 -1
- package/package.json +3 -3
package/docs/index.md
CHANGED
|
@@ -734,19 +734,20 @@ deux, et pas de course).
|
|
|
734
734
|
|
|
735
735
|
## ⚠️ Pièges
|
|
736
736
|
|
|
737
|
-
| Symptôme
|
|
738
|
-
|
|
|
739
|
-
| « no entity registered under "X" » au premier appel
|
|
740
|
-
| La table n'existe pas alors que l'entité est déclarée
|
|
741
|
-
| « entity "User" exists on multiple connectors … specify one »
|
|
742
|
-
| Un filtre « champ vide » ne remonte jamais rien
|
|
743
|
-
| `UnknownCriteriaField` sur un champ qui existe « pourtant »
|
|
744
|
-
| `updateOne` rend `null` alors que la ligne a bien changé
|
|
745
|
-
| Un `upsert` écrase une valeur qui devait progresser
|
|
746
|
-
| Un objet de critère est pris pour une égalité (colonne JSON)
|
|
747
|
-
| `onOrmReady` ne part plus après un ajout dans l'adapter
|
|
748
|
-
| Une entité déclarée dans un module reste invisible
|
|
749
|
-
| Rien dans `flow` alors que la base travaille
|
|
737
|
+
| Symptôme | Cause | Correction |
|
|
738
|
+
| --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
739
|
+
| « no entity registered under "X" » au premier appel | l'entité n'a jamais été inscrite (fichier importé mais `defineEntity` est sans effet de bord) | l'ajouter à `@entities([...])` sur le module (`entitiesDecorator.ts#entities`) |
|
|
740
|
+
| La table n'existe pas alors que l'entité est déclarée | inscription faite à `onBoot` → course avec `connect()` | inscrire à `onRegister` — c'est ce que fait `entities()` (`entitiesDecorator.ts#entities`) |
|
|
741
|
+
| « entity "User" exists on multiple connectors … specify one » | la même entité vit sur plusieurs connecteurs | préciser le connecteur : `entityRegistry.get("User", "analytics")` (`EntityRegistry.ts#EntityRegistry.get`) |
|
|
742
|
+
| Un filtre « champ vide » ne remonte jamais rien | `colonne = NULL` est toujours faux en SQL | `{ champ: { $null: true } }` ou la valeur nue `{ champ: null }` (`IRepository.ts#FieldOperators.$null`) |
|
|
743
|
+
| `UnknownCriteriaField` sur un champ qui existe « pourtant » | faute de frappe, ou champ calculé absent du schéma | lire les champs connus dans le message ; pour du natif, passer par `getNativeConnection()` |
|
|
744
|
+
| `updateOne` rend `null` alors que la ligne a bien changé | ancien réflexe `UPDATE` + relecture (le critère porte sur le champ modifié) | utiliser `updateOne`, atomique par construction (`IRepository.ts#IRepository.updateOne`) |
|
|
745
|
+
| Un `upsert` écrase une valeur qui devait progresser | le `DO UPDATE` est inconditionnel (contrainte MySQL) | poser la condition **dans** la valeur : `{ seuil: { $max: v } }` (`IRepository.ts#UpdateOperators`) |
|
|
746
|
+
| Un objet de critère est pris pour une égalité (colonne JSON) | comportement **voulu** : une valeur n'est un filtre que si **toutes** ses clés sont des opérateurs | c'est la protection ; pour filtrer dedans, passer au natif (`criteria.ts#isFieldOperators`) |
|
|
747
|
+
| `onOrmReady` ne part plus après un ajout dans l'adapter | `connect()` a été surchargé | surcharger `onConnect()` (`Orm.ts#Orm.onConnect`), jamais `connect()` |
|
|
748
|
+
| Une entité déclarée dans un module reste invisible | le module embarque sa **propre copie** du registre (singleton dédoublé) | externaliser `@nodefony/orm-core` dans le `rolldown.config.ts` du module |
|
|
749
|
+
| Rien dans `flow` alors que la base travaille | la sonde est éteinte hors développement, ou le driver n'a pas de tap | `NF_ORM_FLOW=1` (`ormWiring.ts#resolveOrmFlowEnabled`) ; les deux drivers officiels ont un tap |
|
|
750
|
+
| Un champ vaut `null` dans la réponse alors que la colonne est remplie | repository maison : la fonction qui transforme une ligne en entité ne recopie pas cette colonne — rien ne lève, le champ optionnel reste vide | faire porter au mapping **chaque** champ exposé, et un test qui écrit une ligne complète puis compare tous les champs relus (`IRepository.ts#IRepository`) |
|
|
750
751
|
|
|
751
752
|
## 🧪 Tests & couverture
|
|
752
753
|
|
package/docs/tutorial-entity.md
CHANGED
|
@@ -23,6 +23,26 @@ source: "src/packages/@nodefony/orm-core/docs/tutorial-entity.md"
|
|
|
23
23
|
|
|
24
24
|
📍 [Documentation](../../../../../docs/index.md) › [ORM — le socle](index.md) › **Créer une entité**
|
|
25
25
|
|
|
26
|
+
## ⚡ Le geste — une commande
|
|
27
|
+
|
|
28
|
+
Dans une application, une entité ne s'écrit pas à la main : `create entity` pose tout ce que cette
|
|
29
|
+
page construit pas à pas, câblé et testé.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npx nodefony create entity Post title:string content:text views:int --route /api/posts
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Elle écrit la table (`nodefony/entity/Post.ts`), ses schémas de validation, un service CRUD, un
|
|
36
|
+
contrôleur REST dont les lectures répondent aussi par la socket, un test unitaire et un test e2e,
|
|
37
|
+
puis inscrit l'entité et le contrôleur dans `index.ts`. Si l'application versionne ses migrations
|
|
38
|
+
(toute application complète), elle écrit puis applique celle de la table à la base de
|
|
39
|
+
développement ; sinon, la table naît au prochain démarrage. Si la base ne répond pas, sa sortie donne la commande à
|
|
40
|
+
relancer (`npx nodefony orm:generate --name posts --apply`). Les options :
|
|
41
|
+
[le raccourci](#le-raccourci--nodefony-create-entity).
|
|
42
|
+
|
|
43
|
+
La suite de la page construit la même entité à la main : c'est ce qui permet de comprendre ce que
|
|
44
|
+
la commande écrit, et de le retoucher.
|
|
45
|
+
|
|
26
46
|
## 🧠 Schéma général
|
|
27
47
|
|
|
28
48
|
Trois objets s'emboîtent, toujours dans le même ordre. Le tutoriel les parcourt de gauche à
|
|
@@ -337,11 +357,14 @@ champs se déclarent en positionnels, façon Rails :
|
|
|
337
357
|
nodefony create entity Post title:string content:text views:int
|
|
338
358
|
# --id uuid7|uuid4|serial --soft-delete --no-timestamps
|
|
339
359
|
# --module <nom> --no-controller --connector <nom>
|
|
360
|
+
# --no-migrate (n'écrit pas la migration : la sortie la conseille)
|
|
340
361
|
```
|
|
341
362
|
|
|
342
363
|
Elle écrit le fichier d'entité (`nodefony/entity/Post.ts`), les schémas de validation, un service
|
|
343
364
|
CRUD, un controller REST + WebSocket et les tests — puis **câble elle-même** `@entities([...])` et
|
|
344
|
-
`@controllers([...])
|
|
365
|
+
`@controllers([...])`, et migre la table neuve quand l'application versionne son schéma — mais seulement si la migration ne touche
|
|
366
|
+
qu'elle : une autre entité modifiée en attente laisse le fichier écrit, NON appliqué, et la sortie
|
|
367
|
+
nomme les tables en trop. Le schéma vit alors dans son propre fichier, et le point d'entrée ne garde
|
|
345
368
|
que l'import plus la ligne du décorateur.
|
|
346
369
|
|
|
347
370
|
> [!WARNING]
|
|
@@ -379,6 +402,12 @@ apportent, jamais sur leur nom.
|
|
|
379
402
|
> **nombre** de lignes touchées. Un verbe unique masquerait cette différence de garantie, qui est
|
|
380
403
|
> précisément ce qu'on veut choisir en connaissance de cause.
|
|
381
404
|
|
|
405
|
+
**Une clé qui vaut `undefined` vaut une clé absente.** Les écritures du service CRUD acceptent
|
|
406
|
+
`PartialInput<T>` (`types/PartialInput.ts#PartialInput`) et retirent ces clés avant la persistance
|
|
407
|
+
(`AbstractCrudService.updateOne()`, `AbstractCrudService.ts#AbstractCrudService.updateOne`) : un champ
|
|
408
|
+
facultatif d'un schéma Zod (`.optional()`, `.partial()`) qui arrive `undefined` ne touche pas la
|
|
409
|
+
colonne. Pour la **vider**, écrire `null`.
|
|
410
|
+
|
|
382
411
|
Quelques usages, un par garantie :
|
|
383
412
|
|
|
384
413
|
```ts ignore
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodefony/orm-core",
|
|
3
|
-
"version": "10.0.0-beta.
|
|
3
|
+
"version": "10.0.0-beta.5",
|
|
4
4
|
"description": "Un contrat de dépôt de données pour Nodefony, plusieurs moteurs : interfaces, registre et classes de base pour le support multi-ORM",
|
|
5
5
|
"contributors": [],
|
|
6
6
|
"type": "module",
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
"esm"
|
|
38
38
|
],
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"nodefony": "^10.0.0-beta.
|
|
40
|
+
"nodefony": "^10.0.0-beta.5"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "26.6.5",
|
|
44
|
-
"nodefony": "^10.0.0-beta.
|
|
44
|
+
"nodefony": "^10.0.0-beta.5",
|
|
45
45
|
"vitest": "5.0.5"
|
|
46
46
|
},
|
|
47
47
|
"repository": {
|