gedcom-ts 2.1.0 → 2026.5.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.
Files changed (42) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/README.md +119 -14
  3. package/dist/commons/Act.d.ts +9 -2
  4. package/dist/commons/Person.d.ts +6 -1
  5. package/dist/commons/clonePrimitives.d.ts +17 -0
  6. package/dist/commons/gedcomEventTags.d.ts +7 -0
  7. package/dist/dataset/ReadGedEdit.d.ts +27 -0
  8. package/dist/dataset/cloneModels.d.ts +8 -0
  9. package/dist/dataset/graphOps.d.ts +29 -0
  10. package/dist/dataset/index.d.ts +9 -0
  11. package/dist/dataset/readGedCommands.d.ts +46 -0
  12. package/dist/dataset/readGedMutations.d.ts +12 -0
  13. package/dist/dataset/validation.d.ts +36 -0
  14. package/dist/edit/ActEdit.d.ts +8 -0
  15. package/dist/edit/ActMediaEdit.d.ts +21 -0
  16. package/dist/edit/ActsEdit.d.ts +18 -1
  17. package/dist/edit/GedcomExportOptionsEdit.d.ts +20 -0
  18. package/dist/edit/IndiAttributesEdit.d.ts +38 -0
  19. package/dist/edit/MultimediaFileEdit.d.ts +17 -0
  20. package/dist/edit/NameVariantsEdit.d.ts +43 -0
  21. package/dist/edit/NoteEdit.d.ts +18 -0
  22. package/dist/edit/NotesEdit.d.ts +11 -0
  23. package/dist/edit/PersonEdit.d.ts +20 -0
  24. package/dist/edit/PersonMediaEdit.d.ts +27 -0
  25. package/dist/edit/factories.d.ts +35 -0
  26. package/dist/edit/index.d.ts +14 -0
  27. package/dist/geocode/index.d.ts +3 -0
  28. package/dist/geocode/place-city-utils.d.ts +11 -0
  29. package/dist/geocode/place-clusters.d.ts +34 -0
  30. package/dist/geocode/place-geocode.d.ts +50 -0
  31. package/dist/import/PreservedRecordsBuffer.d.ts +21 -0
  32. package/dist/import/ReadGed.d.ts +6 -0
  33. package/dist/import/SplitedInformations.d.ts +7 -1
  34. package/dist/index.cjs +1 -1
  35. package/dist/index.d.ts +5 -3
  36. package/dist/index.mjs +1 -1
  37. package/dist/services/CitySearch.d.ts +4 -0
  38. package/dist/utils/gedcom/importGedcomNote.d.ts +17 -0
  39. package/dist/utils/gedcom/uriBasename.d.ts +2 -0
  40. package/dist/utils/multimedia/registerTrackedMedia.d.ts +10 -0
  41. package/dist/version.d.ts +1 -1
  42. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,97 @@ All notable changes of gedcom-ts
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ### Added
8
+
9
+ - **`src/geocode/`** : géocodage Nominatim (`GET /search?q=…&format=jsonv2`), contexte arbre (`inferGeocodeContext`), ranking (`rankGeocodeCandidates`), harmonisation des lieux (`findHarmonizationClusters`, `applyGeocodeCandidateToActs`), utilitaires ville (`normalizeCityKey`, `findCanonicalCityLabel`). `fetch` et `User-Agent` configurables pour les tests.
10
+
11
+ ### Changed
12
+
13
+ - **`getCityCoordinates`** : marqué `@deprecated` ; utilise la nouvelle API Nominatim (plus `search.php?city=` ni `XMLHttpRequest`).
14
+
15
+ ## [2026.5.0] - 2026-05-15
16
+
17
+ ### Versioning
18
+
19
+ À partir de cette release, le numéro de version du paquet npm et de **`GEDCOM_LIBRARY_VERSION`** (`src/version.ts`, exporté dans `HEAD`.`SOUR`.`VERS`) suit un schéma **CalVer** :
20
+
21
+ - format **`AAAA.M.micro`** (ex. **`2026.5.0`** = mai 2026, première publication de la série) ;
22
+ - remplace l’ancien **semver** (`2.1.0`, `2.0.x`, …) pour les releases applicatives ;
23
+ - la propriété `version` de `package.json` et `GEDCOM_LIBRARY_VERSION` doivent rester **identiques** (vérifié par `tests/version-package-sync.spec.ts`) ;
24
+ - les branches de release peuvent porter le même libellé (ex. `2026.5.0`).
25
+
26
+ Les entrées historiques du changelog conservent leurs numéros semver d’origine.
27
+
28
+ ### Highlights
29
+
30
+ - Nouvelle couche **`src/dataset/`** : mutations du graphe `ReadGed`, opérations famille, validation typée, commandes sûres (`try*` / `CommandResult`) et clones.
31
+ - Extension majeure de la **couche d’édition** (`*Edit`, factories, médias, variants de nom, attributs, options d’export).
32
+ - **Round-trip des notes sous actes** corrigé (import `2 NOTE` / `3 CONT` après `DATE`, ordre d’export `ActLine`).
33
+ - Refactor interne : médias centralisés, buffer des enregistrements préservés, `Person.clone` / `Act.clone`.
34
+
35
+ ### Added
36
+
37
+ #### Dataset (`src/dataset/`)
38
+
39
+ - **`readGedMutations`** : `addPersonToReadGed`, `removePersonFromReadGedByIndi` (mise à jour `mapPersons`, `persons`, lieux, `groupPartners`).
40
+ - **`ReadGedEdit`** / `editReadGed` : `addPerson`, `removePersonByIndi`, `preserved()` → `PreservedTopLevelEdit` (`append`, `insertAt`, `replaceAt`, `removeAt`, `clear`).
41
+ - **`graphOps`** : `nextFamilyId`, `createMarriageFamily`, `linkChildToFamily`, `unlinkChildFromFamily`, `removeFamilyReferencesFromDataset`.
42
+ - **`CreateUnionFamilyOptions`** : `eventTag` sur `createMarriageFamily` / `tryCreateMarriageFamily` (défaut `MARR` ; aussi `ENGA`, `MARB`, `MARC`, `MARL`, `MARS`, `EVEN` + `CreateActInit`, etc.) ; constante **`GEDCOM_7_PAIR_UNION_EVENT_TAGS`**.
43
+ - **`readGedCommands`** : `tryAddPersonToReadGed`, `tryRemovePersonFromReadGedByIndi`, `tryLinkChildToFamily`, `tryUnlinkChildFromFamily`, `tryCreateMarriageFamily` ; `validate*Command` ; **`CommandResult`** / `commandBlockingIssues`.
44
+ - **`validation`** : `ModelConsistencyIssue` avec `code`, `severity` (`error` | `warn`), `validatePerson` / `validateReadGed` ; options `checkMarrParticipants`, `checkDuplicateIndis`, `checkFamcWithoutSpouses`, `checkFamsWithoutSpouses`, `checkDuplicateFamsEntries`, `checkAncestorCycles` ; `assertPersonConsistent` / `assertReadGedConsistent` avec `failOn`.
45
+ - **`cloneModels`** : `clonePerson`, `cloneAct` (délèguent à `Person.clone` / `Act.clone`).
46
+
47
+ #### Import / modèle
48
+
49
+ - **`PreservedRecordsBuffer`** : encapsulation des blocs `0 …` préservés (`SplitGedcom` / `ReadGed.preservedTopLevelRecords`).
50
+ - **`ReadGed.rehydratePlacesFromActs()`** : reconstruction de `placesMap` après édition manuelle du graphe.
51
+ - **`importGedcomNote`** : `createNoteFromGedcomPayload`, `appendGedcomNoteSubline`, `isPersonLevelGedcomLine`, `isActLevelGedcomNoteLine`, `isGedcomNoteContinuationTag`.
52
+ - **`registerTrackedMedia`** : chemins relatifs uniques pour médias personne / acte.
53
+ - **`uriBasename`** : nom de fichier logique depuis une URI média.
54
+ - **`clonePrimitives`** : briques de copie profonde partagées (dates, lieux, notes, médias, variants, attributs).
55
+ - **`Person.clone(newIndi)`**, **`Act.clone()`** sur les classes domaine.
56
+
57
+ #### Fluent edit layer (extensions)
58
+
59
+ - **`factories`** : `createAct`, `createNote`, `createPersonStub`, `createPersonNameVariant`, `createIndiAttribute` (+ types `CreateActInit`, `CreatePersonStubInit`).
60
+ - **`NoteEdit`** / `editNote` ; **`NotesEdit`** : `addNew`, `insertNewAt`, `removeNote`, `indexOfNote`.
61
+ - **`ActMediaEdit`** / **`PersonMediaEdit`** / **`MultimediaFileEdit`** ; **`NameVariantsEdit`** / **`PersonNameVariantEdit`** ; **`IndiAttributesEdit`**.
62
+ - **`ActsEdit`** : `addNew`, `insertNewAt`, `removeAct`, `indexOfAct`.
63
+ - **`ActEdit`** : `notes()`, `multimedia()`, `clearNotes`, `clearMultimedia`.
64
+ - **`PersonEdit`** : `multimedia()`, `nameVariants()`, `attributes()`, `appendFams`, `removeFamsAt`, `removeFamsById`, etc.
65
+ - **`GedcomExportOptionsEdit`** / `editGedcomExportOptions` : `setExtraTopLevelRecords`, `setHeadCopyright`, `setHeadDestination`, `setHeadLanguageTag`, `setHeadSchemaTagDefs`, `clear*`.
66
+
67
+ #### Public API (`src/index.ts`)
68
+
69
+ - Réexport de tout le dataset, des commandes `try*`, des types de validation, `GEDCOM_7_PAIR_UNION_EVENT_TAGS`, `Gedcom7PairUnionEventTag`, `CreateUnionFamilyOptions`, `CommandResult`, etc.
70
+
71
+ #### Tests
72
+
73
+ - `tests/dataset/readGedCommands.spec.ts` : commandes et validations FAM optionnelles.
74
+ - `tests/edit/extendedLayer.spec.ts` : ReadGed, graphe, export options, clones, validation, `removeFamilyReferencesFromDataset`.
75
+ - `tests/edit/editApi.spec.ts` : facades étendues.
76
+ - `tests/commons/Person.spec.ts` / `Act.spec.ts` : notes d’acte (`2 NOTE` / `3 CONT`, ordre après `DATE`).
77
+ - `tests/export/GEDCOM.spec.ts` : round-trip ZIP avec note multi-lignes sous acte.
78
+ - `tests/utils/uriBasename.spec.ts`.
79
+
80
+ #### Documentation
81
+
82
+ - README : section **Dataset editing** (ReadGed, graphe, clones, validation, commandes) ; table `ReadGed` mise à jour (`rehydratePlacesFromActs`, plus de `addPerson` direct sur `ReadGed`).
83
+
84
+ ### Changed
85
+
86
+ - **`ReadGed`** : `addPerson` / `removePersonByIndi` retirés de la classe ; préférer `editReadGed` ou `addPersonToReadGed` / `removePersonFromReadGedByIndi`.
87
+ - **`Person.addMultimedia` / `addMultimediaFromUri`** et **`Act.addMultimedia` / `addMultimediaFromUri`** : délégation à `registerTrackedMedia`.
88
+ - **`SplitGedcom`** : liste préservée via `PreservedRecordsBuffer` au lieu d’un tableau interne brut.
89
+ - **`package.json`** / **`package-lock.json`** : version **`2026.5.0`** (CalVer).
90
+ - CI (`.gitlab-ci.yml`) : ajustements mineurs liés à la release.
91
+
92
+ ### Fixed
93
+
94
+ - **Notes d’acte au réimport** : `parsePersonLine` n’attache plus les `NOTE` de niveau 2 au individu ; `convertToActs` traite `2 NOTE` et `3 CONC`/`CONT` **avant** les blocs `pendingAfterDate` / `Plac` / `Sdate`, ce qui évite de perdre les `3 CONT` lorsque l’export place la note après `DATE` (`ActLine`).
95
+ - **`ReadGedEdit.addPerson`** : discrimination TypeScript correcte sur `CommandResult` (`r.ok === false`).
96
+ - Alignement **`GEDCOM_LIBRARY_VERSION`** ↔ **`package.json`** pour la série `2026.5.0`.
97
+
7
98
  ## [2.1.0] - 2026-05-13
8
99
 
9
100
  ### Highlights
package/README.md CHANGED
@@ -14,6 +14,7 @@ A graphical demo showcasing the public API (import a `.ged` / `.zip`, browse the
14
14
  ## Project
15
15
 
16
16
  - NPM package: [gedcom-ts](https://www.npmjs.com/package/gedcom-ts)
17
+ - **Versioning (CalVer)** : releases use **`AAAA.M.micro`** (e.g. `2026.5.0` = May 2026). The npm `version`, `GEDCOM_LIBRARY_VERSION` (export `HEAD`.`SOUR`.`VERS`), and release branches share the same label. Older changelog entries still refer to semver (`2.1.0`, …). See [CHANGELOG.md](CHANGELOG.md).
17
18
  - **GEDCOM 7 roadmap** (spec gedcom.io, coverage matrix, prioritized gaps): [docs/GEDCOM7-roadmap.md](docs/GEDCOM7-roadmap.md)
18
19
 
19
20
  ## Installation
@@ -118,6 +119,7 @@ Notable members:
118
119
  | `getChildrenOfFamily(familyId)` | Children of a single family. |
119
120
  | `groupPartners()` | Rebuilds `partnersMap` / `childsMap` after editing links. |
120
121
  | `generateUniqueIndi()` | Next free `INDI` number for new persons. |
122
+ | `rehydratePlacesFromActs()` | Rebuilds `placesMap` from act places (e.g. after manual graph edits). Use `editReadGed(readGed).addPerson(...)` to register persons so maps stay coherent. |
121
123
 
122
124
  ```ts
123
125
  import { ReadGed } from "gedcom-ts";
@@ -232,7 +234,7 @@ const occ = new IndiAttribute("OCCU", "Blacksmith", [
232
234
 
233
235
  #### `Act`, `Acts`, `TypeAct`, `ActConstructionOptions`
234
236
 
235
- `Act` models an individual or family event (BIRT, MARR, etc.). `Acts` is the ordered collection on a `Person`. `TypeAct` is the union of every supported GEDCOM 7 event tag (= `Gedcom7EventTag`).
237
+ `Act` models an individual or family event (BIRT, MARR, etc.). `Acts` is the ordered collection on a `Person`. `TypeAct` is the union of every supported GEDCOM 7 event tag (= `Gedcom7EventTag`). Event-level notes live on `act.notes` (`2 NOTE` / `3 CONT` in GEDCOM); they are distinct from `person.notes` (`1 NOTE` on `INDI`) and round-trip through ZIP export/import.
236
238
 
237
239
  ```ts
238
240
  import { Act, Acts, Identifier, type TypeAct } from "gedcom-ts";
@@ -267,9 +269,9 @@ const act = new Act(
267
269
  );
268
270
  ```
269
271
 
270
- #### `GEDCOM_7_ALL_EVENT_TAGS`, `GEDCOM_7_EVENT_SORT_ORDER`, `GEDCOM_7_EVENT_TAG_SET`, `Gedcom7EventTag`
272
+ #### `GEDCOM_7_ALL_EVENT_TAGS`, `GEDCOM_7_EVENT_SORT_ORDER`, `GEDCOM_7_EVENT_TAG_SET`, `GEDCOM_7_PAIR_UNION_EVENT_TAGS`, `Gedcom7EventTag`, `Gedcom7PairUnionEventTag`
271
273
 
272
- Canonical lists of GEDCOM 7 event tags (`INDIVIDUAL_EVENT_STRUCTURE` ∪ `FAMILY_EVENT_STRUCTURE`, LDS ordinances excluded). Use them to build UI selects or guard custom logic.
274
+ Canonical lists of GEDCOM 7 event tags (`INDIVIDUAL_EVENT_STRUCTURE` ∪ `FAMILY_EVENT_STRUCTURE`, LDS ordinances excluded). Use them to build UI selects or guard custom logic. `GEDCOM_7_PAIR_UNION_EVENT_TAGS` lists tags commonly used when creating a family union via `createMarriageFamily` (`ENGA`, `MARB`, `MARC`, `MARL`, `MARR`, `MARS`).
273
275
 
274
276
  ```ts
275
277
  import {
@@ -394,12 +396,78 @@ editDateAct(person.acts.list[0].dateAct!).setExactDate(1900, "JAN", 1);
394
396
 
395
397
  | Helper / class | Purpose |
396
398
  | --- | --- |
397
- | `editPerson(person)` / `PersonEdit` | identity (`setLastname`, `setFirstnames`, `setSex`, `setSosa`), links (`setFamc`, `setFams`, `clearFams`, `appendFams`), name variants (`setNameVariants`), attributes (`setAttributes`), entry points to `acts()` and `notes()`. |
398
- | `editActs(acts)` / `ActsEdit` | `add`, `replaceAt`, `removeAt`, `clear`, `sortByDate`, `at(index)`. |
399
- | `editAct(act)` / `ActEdit` | `setType`, `setIndis`, `setDateAct`, `setSdateAct`, `setPlace`, `setEvenDescription`, `setEvenTypeLabel`, `setEventPhrases` / `appendEventPhrase` / `clearEventPhrases`, plus `setPreservedPrefix` / `Suffix` helpers. |
399
+ | `editPerson(person)` / `PersonEdit` | Identity, `FAMS` / `FAMC` / `removeFams*`, `nameVariants()` / `attributes()` / `multimedia()`, bulk `clear*`, entry points to `acts()` and `notes()`. |
400
+ | `editActs(acts)` / `ActsEdit` | `add`, `addNew`, `insertAt`, `insertNewAt`, `replaceAt`, `removeAt`, `removeAct`, `removeLast`, `clear`, `sortByDate`, `at`, `indexOfAct`. |
401
+ | `editAct(act)` / `ActEdit` | `setType`, `setIndis`, dates, place, EVEN fields, preserved lines, `notes()`, `multimedia()`, `clearNotes`, `clearMultimedia`. |
400
402
  | `editDateAct(dateAct)` / `DateActEdit` | `clear`, `applyGedcomPayload`, `setExactDate`, `setQualified`, `setBetween`, `setFromTo`, `setTime`, `setDatePhrase` / `appendDatePhrase`, `setVerbatimPayload`. |
401
403
  | `editPlace(place)` / `PlaceEdit` | `setFromGedcom7Payload`, `setCity`, `setCounty`, `setState`, `setCountry`, `setPlacPhrase` / `appendPlacPhrase` / `clearPlacPhrase`, `setCoordinates` / `clearCoordinates` / `replaceCoordinateModel`, `clearStructured`. |
402
- | `editNotes(notes)` / `NotesEdit` | `add`, `replaceAt`, `removeAt`, `clear`. |
404
+ | `editNotes(notes)` / `NotesEdit` | `add`, `addNew`, `insertAt`, `insertNewAt`, `replaceAt`, `removeAt`, `removeNote`, `removeLast`, `clear`, `at`, `indexOfNote`. |
405
+
406
+ ### Dataset editing: `ReadGed`, graph, clone, export options, validation
407
+
408
+ Higher-level helpers complement the per-object edit facades:
409
+
410
+ ```ts
411
+ import type { GedcomExportOptions } from "gedcom-ts";
412
+ import {
413
+ createEmptyReadGed,
414
+ createPersonStub,
415
+ DateAct,
416
+ Sex,
417
+ editReadGed,
418
+ editGedcomExportOptions,
419
+ clonePerson,
420
+ cloneAct,
421
+ createMarriageFamily,
422
+ linkChildToFamily,
423
+ removeFamilyReferencesFromDataset,
424
+ addPersonToReadGed,
425
+ validateReadGed,
426
+ Identifier,
427
+ Act,
428
+ } from "gedcom-ts";
429
+
430
+ const readGed = createEmptyReadGed();
431
+ const p = createPersonStub(readGed.generateUniqueIndi(), { sex: Sex.M, firstnames: ["Jean"], lastname: "Dupont" });
432
+ editReadGed(readGed).addPerson(p);
433
+ p.acts.add(new Act(Identifier.BIRT, new DateAct("1900")));
434
+
435
+ editReadGed(readGed).preserved().append("0 @S42@ SOUR Custom");
436
+
437
+ const opts: GedcomExportOptions = {};
438
+ editGedcomExportOptions(opts)
439
+ .setHeadCopyright("© 2026")
440
+ .setExtraTopLevelRecords([...readGed.preservedTopLevelRecords]);
441
+
442
+ const twin = clonePerson(p, readGed.generateUniqueIndi());
443
+ const birthCopy = cloneAct(p.acts.list[0]!);
444
+
445
+ // const fam = createMarriageFamily(readGed, spouseA, spouseB, { dateAct: new DateAct("1 JAN 2000") }, { eventTag: Identifier.ENGA });
446
+ // linkChildToFamily(readGed, child, fam);
447
+ // removeFamilyReferencesFromDataset(readGed, fam);
448
+
449
+ validateReadGed(readGed, {
450
+ checkMarrParticipants: true,
451
+ checkFamcWithoutSpouses: true,
452
+ checkFamsWithoutSpouses: true,
453
+ checkDuplicateFamsEntries: true,
454
+ checkAncestorCycles: true,
455
+ });
456
+ ```
457
+
458
+ #### Commands (invariants before mutation)
459
+
460
+ `tryAddPersonToReadGed`, `tryRemovePersonFromReadGedByIndi`, `tryLinkChildToFamily`, `tryUnlinkChildFromFamily`, and `tryCreateMarriageFamily` return a `CommandResult` (`ok` + `issues` or `value` + optional `warnings`). `editReadGed(...).addPerson` uses these checks internally (throws on blocking errors). For UI or transactional flows, prefer the `try*` APIs and inspect `commandBlockingIssues`.
461
+
462
+ | Export | Role |
463
+ | --- | --- |
464
+ | `editReadGed(readGed)` / `ReadGedEdit` | `addPerson`, `removePersonByIndi`, `preserved()` → `PreservedTopLevelEdit` (`append`, `insertAt`, `replaceAt`, `removeAt`, `clear`) on `preservedTopLevelRecords`. Low-level helpers: `addPersonToReadGed`, `removePersonFromReadGedByIndi`. |
465
+ | `editGedcomExportOptions(opts)` / `GedcomExportOptionsEdit` | Fluent setters for `extraTopLevelRecords`, `headLanguageTag`, `headCopyright`, `headDestination`, `headSchemaTagDefs`. |
466
+ | `clonePerson(person, newIndi)` / `cloneAct(act)` / `person.clone` / `act.clone` | Deep copies for templates or undo stacks. |
467
+ | `nextFamilyId(persons)` | Next internal family id `F`. |
468
+ | `createMarriageFamily`, `linkChildToFamily`, `unlinkChildFromFamily`, `removeFamilyReferencesFromDataset` | Crée une `F` et des actes sur les deux conjoints. 5ᵉ argument : `{ eventTag }` (défaut `MARR`) pour `ENGA`, bans, contrat, `EVEN`+`CreateActInit`, etc. Voir `GEDCOM_7_PAIR_UNION_EVENT_TAGS`. |
469
+ | `validateReadGed`, `assertReadGedConsistent`, `validatePerson`, `assertPersonConsistent` | Typed `code` / `severity` (`error` \| `warn`). Options: `checkMarrParticipants`, `checkDuplicateIndis`, `checkFamcWithoutSpouses`, `checkFamsWithoutSpouses`, `checkDuplicateFamsEntries`, `checkAncestorCycles`. Assertions: `failOn` (default: `error`). |
470
+ | `tryAddPersonToReadGed`, `tryRemovePersonFromReadGedByIndi`, `tryLinkChildToFamily`, `tryUnlinkChildFromFamily`, `tryCreateMarriageFamily`, `commandBlockingIssues` | Command layer with `CommandResult` / `validate*Command` prechecks. |
403
471
 
404
472
  ### Utilities
405
473
 
@@ -424,18 +492,32 @@ import { remainingTypesAct, Acts } from "gedcom-ts";
424
492
  const available = remainingTypesAct(new Acts());
425
493
  ```
426
494
 
427
- #### `getCityCoordinates(cityName, callback)`
495
+ #### Geocoding (Nominatim)
428
496
 
429
- Queries OpenStreetMap’s Nominatim API and returns a list of candidate `Place` objects with coordinates. Browser-only (uses `XMLHttpRequest`).
497
+ Place search uses the official Nominatim endpoint `GET https://nominatim.openstreetmap.org/search` with `q`, `format=jsonv2`, and `addressdetails=1` (not the legacy `search.php?city=` API). A `User-Agent` header is required (`gedcom-ts/<version> (genealogy library)` by default).
430
498
 
431
499
  ```ts
432
- import { getCityCoordinates } from "gedcom-ts";
500
+ import {
501
+ inferGeocodeContext,
502
+ searchPlacesWithContext,
503
+ rankGeocodeCandidates,
504
+ findHarmonizationClusters,
505
+ applyGeocodeCandidateToActs,
506
+ } from "gedcom-ts";
433
507
 
434
- getCityCoordinates("Paris", (places) => {
435
- console.log(places[0]?.coordinate.latitude, places[0]?.coordinate.longitude);
436
- });
508
+ const context = inferGeocodeContext(ged);
509
+ const candidates = await searchPlacesWithContext("Valence", context);
510
+ // candidates are ranked (French tree → Valence FR before ES)
511
+
512
+ const clusters = findHarmonizationClusters(ged);
437
513
  ```
438
514
 
515
+ For tests or Node without a global `fetch`, pass `fetchFn` in options. Low-level API: `searchPlaces(query, { countryCodes, limit, userAgent, fetchFn })`.
516
+
517
+ #### `getCityCoordinates(cityName, callback)` (deprecated)
518
+
519
+ Legacy callback API; delegates to `searchPlaces` and maps results to `Place[]`. Prefer `searchPlaces` / `searchPlacesWithContext`.
520
+
439
521
  #### `resolveDatasetVersion(headerLines)` / `GedcomDatasetVersion`
440
522
 
441
523
  Inspects the lines of a `0 HEAD` block and returns `"7.0"`, `"5.5"` or `"unknown"`. Useful to branch UI behaviour for legacy datasets.
@@ -479,7 +561,7 @@ const primary = selectPrimaryNameVariant(person.nameVariants);
479
561
 
480
562
  #### `GEDCOM_LIBRARY_VERSION`
481
563
 
482
- The library version embedded in the exported `HEAD`.`SOUR`.`VERS`. Kept aligned with the `version` field of `package.json` (a test enforces it).
564
+ CalVer string embedded in the exported `HEAD`.`SOUR`.`VERS` (same value as `package.json` `version`, e.g. `2026.5.0`). A test (`version-package-sync`) enforces the match on every CI run.
483
565
 
484
566
  ```ts
485
567
  import { GEDCOM_LIBRARY_VERSION } from "gedcom-ts";
@@ -514,6 +596,29 @@ async function importModifyExport(file: File) {
514
596
  }
515
597
  ```
516
598
 
599
+ ## Development
600
+
601
+ ### Local scripts
602
+
603
+ | Script | Role |
604
+ | --- | --- |
605
+ | `npm run lint` | ESLint on the codebase |
606
+ | `npm run test` | Vitest test suite |
607
+ | `npm run build` | Production bundle + `.d.ts` |
608
+ | `npm run tgz` | `build` then `npm pack` (local `.tgz`) |
609
+
610
+ ### GitLab CI (`.gitlab-ci.yml`)
611
+
612
+ Every pipeline runs **`InstallDependencies`** (`npm ci`, `node_modules` artifact) — required by all other jobs.
613
+
614
+ | Job | When it runs |
615
+ | --- | --- |
616
+ | `InstallDependencies` | Always |
617
+ | `Lint`, `Test` | Merge requests and branch pushes (not on `master` after a merge commit titled `Merge…`) |
618
+ | `BuildTgz`, `PublishNpm` | Push to `master` after merge only (`Merge…` commit title) |
619
+
620
+ Typical flow: open an MR from a release branch (e.g. `2026.5.0`) → lint + test run there → after merge to `master`, only package build and npm publish run (quality checks are not repeated).
621
+
517
622
  ## Error handling
518
623
 
519
624
  ```ts
@@ -46,8 +46,13 @@ export declare class Act {
46
46
  * Suffixe `_1`, `_2`, … avant l’extension si le chemin est déjà pris sur cet acte.
47
47
  */
48
48
  addMultimedia(multimediaFile: MultimediaFile, ownerIndi?: number): void;
49
+ /**
50
+ * Média distant (URI) sans fichier local ; `ownerIndi` requis si {@link INDIS} est vide.
51
+ */
52
+ addMultimediaFromUri(sourceUri: string, ownerIndi?: number, objeXrefId?: number | null): void;
49
53
  removeMultimedia(index: number): void;
50
- private mediaRelativePathsInUse;
54
+ /** Copie profonde de l’acte (nouvelle instance, mêmes valeurs). */
55
+ clone(): Act;
51
56
  updateType(typeAct: TypeAct): void;
52
57
  addIndis(INDIS: number[]): void;
53
58
  updatePlace(place: Place | null): void;
@@ -72,7 +77,9 @@ export declare class Acts {
72
77
  export declare class ActsByExtraction extends Acts {
73
78
  extractActsInfo(lines: string[], INDIS: number[], mapFiles: Map<string, File>, objePayloadById?: ReadonlyMap<number, {
74
79
  sourceUri: string;
75
- }>, textualIndiXrefToIndi?: ReadonlyMap<string, number>): void;
80
+ }>, textualIndiXrefToIndi?: ReadonlyMap<string, number>, globalNotes?: Map<number, string[]>, importOptions?: {
81
+ notePointerToId?: ReadonlyMap<string, number>;
82
+ }): void;
76
83
  private convertToActs;
77
84
  private resolveTypeAct;
78
85
  }
@@ -51,8 +51,13 @@ export declare class Person {
51
51
  * Si le même nom existe déjà pour cet individu, suffixe `_1`, `_2`, etc. avant l’extension.
52
52
  */
53
53
  addMultimedia(multimediaFile: MultimediaFile): void;
54
+ /**
55
+ * Média distant (`FILE` / OBJE avec URI) sans fichier local : chemins relatifs uniques comme {@link addMultimedia}.
56
+ */
57
+ addMultimediaFromUri(sourceUri: string, objeXrefId?: number | null): void;
54
58
  deleteMultimedia(path: string): void;
55
- private mediaRelativePathsInUse;
59
+ /** Copie profonde avec un nouvel `INDI` (actes via {@link Act.clone}, notes, médias, variants, attributs). */
60
+ clone(newIndi: number): Person;
56
61
  private createFirstnamesAndLastnameJson;
57
62
  }
58
63
  export declare class TreePerson extends Person {
@@ -0,0 +1,17 @@
1
+ import { DateAct } from "./DateAct";
2
+ import { IndiAttribute } from "./IndiAttribute";
3
+ import { MultimediaFile, MultimediaFiles } from "./MultimediaFile";
4
+ import { Note, Notes } from "./Note";
5
+ import { PersonNameVariant } from "./PersonNameVariant";
6
+ import { Place } from "./Place";
7
+ export declare function cloneDateAct(d: DateAct): DateAct;
8
+ export declare function clonePlace(p: Place): Place;
9
+ export declare function cloneNote(note: Note): Note;
10
+ export declare function cloneNotesColl(notes: Notes): Notes;
11
+ export declare function cloneMultimediaFile(m: MultimediaFile): MultimediaFile;
12
+ export declare function cloneMultimediaBundle(files: readonly MultimediaFile[], relativePathRoot: string): {
13
+ files: MultimediaFiles;
14
+ map: Map<string, MultimediaFile>;
15
+ };
16
+ export declare function cloneNameVariant(v: PersonNameVariant): PersonNameVariant;
17
+ export declare function cloneAttribute(a: IndiAttribute): IndiAttribute;
@@ -5,6 +5,13 @@ import { Identifier } from "./Identifier.enum";
5
5
  */
6
6
  export declare const GEDCOM_7_ALL_EVENT_TAGS: readonly [Identifier.ADOP, Identifier.BAPM, Identifier.BARM, Identifier.BASM, Identifier.BIRT, Identifier.BLES, Identifier.BURI, Identifier.CENS, Identifier.CHR, Identifier.CHRA, Identifier.CONF, Identifier.CREM, Identifier.DEAT, Identifier.EMIG, Identifier.EVEN, Identifier.FCOM, Identifier.GRAD, Identifier.IMMI, Identifier.NATU, Identifier.ORDN, Identifier.PROB, Identifier.RETI, Identifier.WILL, Identifier.ANUL, Identifier.DIV, Identifier.DIVF, Identifier.ENGA, Identifier.MARB, Identifier.MARC, Identifier.MARL, Identifier.MARR, Identifier.MARS];
7
7
  export type Gedcom7EventTag = (typeof GEDCOM_7_ALL_EVENT_TAGS)[number];
8
+ /**
9
+ * Sous-ensemble des tags GEDCOM 7 typiquement utilisés pour lier deux personnes à une même famille `F`
10
+ * (fiançailles, bans, contrat, mariage, etc.). D’autres tags (`EVEN`, …) restent utilisables via
11
+ * {@link CreateUnionFamilyOptions.eventTag} s’ils figurent dans {@link GEDCOM_7_ALL_EVENT_TAGS}.
12
+ */
13
+ export declare const GEDCOM_7_PAIR_UNION_EVENT_TAGS: readonly [Identifier.ENGA, Identifier.MARB, Identifier.MARC, Identifier.MARL, Identifier.MARR, Identifier.MARS];
14
+ export type Gedcom7PairUnionEventTag = (typeof GEDCOM_7_PAIR_UNION_EVENT_TAGS)[number];
8
15
  /** Document order when two acts have no usable sortable date (`Acts.sortByDate`). */
9
16
  export declare const GEDCOM_7_EVENT_SORT_ORDER: readonly Gedcom7EventTag[];
10
17
  export declare const GEDCOM_7_EVENT_TAG_SET: ReadonlySet<string>;
@@ -0,0 +1,27 @@
1
+ import type { ReadGed } from "../import/ReadGed";
2
+ import type { Person } from "../commons/Person";
3
+ /**
4
+ * Édition des blocs `0 …` conservés pour round-trip (voir {@link ReadGed.preservedTopLevelRecords}).
5
+ */
6
+ export declare class PreservedTopLevelEdit {
7
+ private readonly target;
8
+ constructor(target: ReadGed);
9
+ get value(): ReadonlyArray<string>;
10
+ append(block: string): this;
11
+ insertAt(index: number, block: string): this;
12
+ replaceAt(index: number, block: string): this;
13
+ removeAt(index: number): this;
14
+ clear(): this;
15
+ }
16
+ /**
17
+ * Facade d’édition sur un {@link ReadGed} (personnes + enregistrements préservés).
18
+ */
19
+ export declare class ReadGedEdit {
20
+ private readonly target;
21
+ constructor(target: ReadGed);
22
+ get value(): ReadGed;
23
+ addPerson(person: Person): this;
24
+ removePersonByIndi(indi: number): boolean;
25
+ preserved(): PreservedTopLevelEdit;
26
+ }
27
+ export declare function editReadGed(readGed: ReadGed): ReadGedEdit;
@@ -0,0 +1,8 @@
1
+ import type { Act } from "../commons/Act";
2
+ import type { Person } from "../commons/Person";
3
+ /** Copie profonde d’un {@link Act} (nouvelle instance, mêmes valeurs). */
4
+ export declare function cloneAct(act: Act): Act;
5
+ /**
6
+ * Copie profonde d’une {@link Person} avec un nouvel `INDI` (identité, actes, notes, médias, variants, attributs).
7
+ */
8
+ export declare function clonePerson(person: Person, newIndi: number): Person;
@@ -0,0 +1,29 @@
1
+ import type { ReadGed } from "../import/ReadGed";
2
+ import type { TypeAct } from "../commons/Act";
3
+ import { Person } from "../commons/Person";
4
+ import type { CreateActInit } from "../edit/factories";
5
+ /** Prochain identifiant de famille `F` libre d'après les `FAMC` / `FAMS` du jeu. */
6
+ export declare function nextFamilyId(persons: readonly Person[]): number;
7
+ /** Rattache un enfant à une famille (`FAMC`). */
8
+ export declare function linkChildToFamily(readGed: ReadGed, child: Person, familyId: number): void;
9
+ /** Retire le rattachement `FAMC` d'un enfant. */
10
+ export declare function unlinkChildFromFamily(readGed: ReadGed, child: Person): void;
11
+ /**
12
+ * Retire toutes les références à une famille `familyId` : `FAMS` (toutes occurrences) et `FAMC` si égal.
13
+ * Puis {@link ReadGed.groupPartners}.
14
+ */
15
+ export declare function removeFamilyReferencesFromDataset(readGed: ReadGed, familyId: number): void;
16
+ export type CreateUnionFamilyOptions = {
17
+ /**
18
+ * Type d’acte créé sur chaque conjoint pour matérialiser l’union (défaut : {@link Identifier.MARR}).
19
+ * Doit appartenir à {@link GEDCOM_7_EVENT_TAG_SET} (ex. {@link Identifier.ENGA}, ou `EVEN` avec
20
+ * `CreateActInit.construction` pour une union civile / custom).
21
+ */
22
+ eventTag?: TypeAct;
23
+ };
24
+ /**
25
+ * Crée une famille `F` (nouvel id), rattache les deux conjoints en `FAMS` et ajoute le même type d’acte
26
+ * sur chacun (par défaut `MARR`). Voir {@link CreateUnionFamilyOptions} pour fiançailles, bans, etc.
27
+ * @returns l'identifiant interne de famille créé.
28
+ */
29
+ export declare function createMarriageFamily(readGed: ReadGed, spouseA: Person, spouseB: Person, init?: CreateActInit | null, unionOptions?: CreateUnionFamilyOptions | null): number;
@@ -0,0 +1,9 @@
1
+ export { addPersonToReadGed, removePersonFromReadGedByIndi } from "./readGedMutations";
2
+ export { commandBlockingIssues, tryAddPersonToReadGed, tryCreateMarriageFamily, tryLinkChildToFamily, tryRemovePersonFromReadGedByIndi, tryUnlinkChildFromFamily, validateAddPersonCommand, validateCreateMarriageCommand, validateLinkChildCommand, validateUnlinkChildCommand, } from "./readGedCommands";
3
+ export type { CommandFail, CommandOk, CommandResult } from "./readGedCommands";
4
+ export { createMarriageFamily, linkChildToFamily, nextFamilyId, removeFamilyReferencesFromDataset, unlinkChildFromFamily, } from "./graphOps";
5
+ export type { CreateUnionFamilyOptions } from "./graphOps";
6
+ export { PreservedTopLevelEdit, ReadGedEdit, editReadGed } from "./ReadGedEdit";
7
+ export { cloneAct, clonePerson } from "./cloneModels";
8
+ export { assertPersonConsistent, assertReadGedConsistent, validatePerson, validateReadGed, } from "./validation";
9
+ export type { AssertConsistencyOptions, ConsistencySeverity, ModelConsistencyIssue, ModelConsistencyIssueCode, ValidatePersonContext, ValidateReadGedOptions, } from "./validation";
@@ -0,0 +1,46 @@
1
+ import type { ReadGed } from "../import/ReadGed";
2
+ import type { Person } from "../commons/Person";
3
+ import type { CreateActInit } from "../edit/factories";
4
+ import { type CreateUnionFamilyOptions } from "./graphOps";
5
+ import type { ModelConsistencyIssue } from "./validation";
6
+ export type CommandOk<T = void> = {
7
+ ok: true;
8
+ value: T;
9
+ warnings?: ModelConsistencyIssue[];
10
+ };
11
+ export type CommandFail = {
12
+ ok: false;
13
+ issues: ModelConsistencyIssue[];
14
+ };
15
+ export type CommandResult<T = void> = CommandOk<T> | CommandFail;
16
+ /** Filtre les problèmes qui bloquent une commande (`severity === "error"`). */
17
+ export declare function commandBlockingIssues(issues: readonly ModelConsistencyIssue[]): ModelConsistencyIssue[];
18
+ /** Préconditions pour {@link tryAddPersonToReadGed} (sans effet de bord). */
19
+ export declare function validateAddPersonCommand(readGed: ReadGed, person: Person): ModelConsistencyIssue[];
20
+ /**
21
+ * Ajoute une personne au graphe après validation des préconditions.
22
+ * Effets en cas de succès : `mapPersons`, `persons`, lieux, `groupPartners()` (voir {@link addPersonToReadGed}).
23
+ */
24
+ export declare function tryAddPersonToReadGed(readGed: ReadGed, person: Person): CommandResult;
25
+ /**
26
+ * Retire une personne par `INDI`. Si absent, `ok: false` et aucune mutation.
27
+ */
28
+ export declare function tryRemovePersonFromReadGedByIndi(readGed: ReadGed, indi: number): CommandResult;
29
+ /** Préconditions pour rattacher un enfant à une famille. */
30
+ export declare function validateLinkChildCommand(readGed: ReadGed, child: Person, familyId: number): ModelConsistencyIssue[];
31
+ /**
32
+ * Rattache `child.FAMC = familyId` puis `groupPartners()`.
33
+ * Les avertissements (famille sans conjoints) n’empêchent pas la mutation ; ils sont renvoyés dans `warnings`.
34
+ */
35
+ export declare function tryLinkChildToFamily(readGed: ReadGed, child: Person, familyId: number): CommandResult;
36
+ /** Préconditions pour {@link tryUnlinkChildFromFamily}. */
37
+ export declare function validateUnlinkChildCommand(readGed: ReadGed, child: Person): ModelConsistencyIssue[];
38
+ /** Retire `FAMC` sur l’enfant puis `groupPartners()`. */
39
+ export declare function tryUnlinkChildFromFamily(readGed: ReadGed, child: Person): CommandResult;
40
+ /** Préconditions pour {@link tryCreateMarriageFamily}. */
41
+ export declare function validateCreateMarriageCommand(readGed: ReadGed, spouseA: Person, spouseB: Person): ModelConsistencyIssue[];
42
+ /**
43
+ * Crée une union (nouvel id `F`, actes MARR) après validation.
44
+ * @returns l’identifiant de famille en cas de succès.
45
+ */
46
+ export declare function tryCreateMarriageFamily(readGed: ReadGed, spouseA: Person, spouseB: Person, init?: CreateActInit | null, unionOptions?: CreateUnionFamilyOptions | null): CommandResult<number>;
@@ -0,0 +1,12 @@
1
+ import type { ReadGed } from "../import/ReadGed";
2
+ import { Person } from "../commons/Person";
3
+ /**
4
+ * Ajoute une personne au graphe (met à jour `mapPersons`, `persons`, lieux, `groupPartners`).
5
+ * Si `person.INDI` n’est pas défini, un nouvel identifiant unique est attribué.
6
+ */
7
+ export declare function addPersonToReadGed(readGed: ReadGed, person: Person): void;
8
+ /**
9
+ * Retire une personne par `INDI` et purge les références à cet `INDI` dans les actes et notes du jeu.
10
+ * @returns `false` si aucune personne ne correspond.
11
+ */
12
+ export declare function removePersonFromReadGedByIndi(readGed: ReadGed, indi: number): boolean;
@@ -0,0 +1,36 @@
1
+ import type { ReadGed } from "../import/ReadGed";
2
+ import { Person } from "../commons/Person";
3
+ export type ConsistencySeverity = "error" | "warn";
4
+ export type ModelConsistencyIssueCode = "person_missing_indi" | "act_unknown_indi" | "note_unknown_indi" | "marr_missing_spouse_indi" | "duplicate_indi_in_dataset" | "add_person_already_registered" | "add_person_indi_conflict" | "remove_person_not_found" | "link_child_indi_missing" | "link_child_not_bound_to_readged" | "link_child_family_has_no_spouses" | "unlink_child_indi_missing" | "unlink_child_not_bound_to_readged" | "marriage_spouses_same_person" | "marriage_spouses_same_indi" | "marriage_spouse_indi_missing" | "marriage_spouse_not_in_readged" | "famc_family_without_spouses" | "fams_family_without_spouses" | "fams_duplicate_family_id" | "famc_ancestor_cycle";
5
+ export type ModelConsistencyIssue = {
6
+ code: ModelConsistencyIssueCode;
7
+ severity: ConsistencySeverity;
8
+ message: string;
9
+ detail?: unknown;
10
+ };
11
+ export type ValidatePersonContext = {
12
+ knownIndis?: ReadonlySet<number>;
13
+ checkMarrParticipants?: boolean;
14
+ };
15
+ export type ValidateReadGedOptions = ValidatePersonContext & {
16
+ checkDuplicateIndis?: boolean;
17
+ /** `FAMC` pointant vers une famille sans entrée dans `partnersMap` ou liste vide. */
18
+ checkFamcWithoutSpouses?: boolean;
19
+ /** Chaque `FAMS` sans conjoints dans `partnersMap` (souvent import incomplet). */
20
+ checkFamsWithoutSpouses?: boolean;
21
+ /** Même identifiant de famille plusieurs fois dans `FAMS` d’une même personne. */
22
+ checkDuplicateFamsEntries?: boolean;
23
+ /** Cycle dans la remontée `FAMC` → parents (données impossibles biologiquement). */
24
+ checkAncestorCycles?: boolean;
25
+ };
26
+ export type AssertConsistencyOptions = {
27
+ failOn?: ConsistencySeverity;
28
+ };
29
+ /** Contrôles de base sur une personne (INDI, références d’actes). */
30
+ export declare function validatePerson(person: Person, context?: ValidatePersonContext): ModelConsistencyIssue[];
31
+ /** Agrège {@link validatePerson} pour toutes les personnes du graphe, plus les contrôles optionnels sur FAM. */
32
+ export declare function validateReadGed(readGed: ReadGed, options?: ValidateReadGedOptions): ModelConsistencyIssue[];
33
+ /** Lève une erreur si {@link validatePerson} retourne des problèmes selon `failOn` (défaut : seulement `error`). */
34
+ export declare function assertPersonConsistent(person: Person, context?: ValidatePersonContext & AssertConsistencyOptions): void;
35
+ /** Lève une erreur si {@link validateReadGed} retourne des problèmes selon `failOn` (défaut : seulement `error`). */
36
+ export declare function assertReadGedConsistent(readGed: ReadGed, options?: ValidateReadGedOptions & AssertConsistencyOptions): void;
@@ -1,6 +1,8 @@
1
1
  import { Act, type TypeAct } from "../commons/Act";
2
2
  import { DateAct } from "../commons/DateAct";
3
3
  import { Place } from "../commons/Place";
4
+ import { ActMediaEdit } from "./ActMediaEdit";
5
+ import { NotesEdit } from "./NotesEdit";
4
6
  /**
5
7
  * API d’édition cohérente autour d’un {@link Act} existant (mutation in-place).
6
8
  */
@@ -25,5 +27,11 @@ export declare class ActEdit {
25
27
  setPreservedSuffix(lines: readonly string[]): this;
26
28
  appendPreservedSuffixLine(line: string): this;
27
29
  clearPreservedSuffix(): this;
30
+ notes(): NotesEdit;
31
+ multimedia(): ActMediaEdit;
32
+ /** Supprime toutes les notes rattachées à l’acte. */
33
+ clearNotes(): this;
34
+ /** Supprime tous les médias rattachés à l’acte. */
35
+ clearMultimedia(): this;
28
36
  }
29
37
  export declare function editAct(act: Act): ActEdit;
@@ -0,0 +1,21 @@
1
+ import { MultimediaFile } from "../commons/MultimediaFile";
2
+ import type { Act } from "../commons/Act";
3
+ import { MultimediaFileEdit } from "./MultimediaFileEdit";
4
+ /**
5
+ * Médias rattachés à un {@link Act} : délègue à {@link Act.addMultimedia} / {@link Act.removeMultimedia}.
6
+ */
7
+ export declare class ActMediaEdit {
8
+ private readonly target;
9
+ constructor(target: Act);
10
+ get value(): Act;
11
+ /**
12
+ * Crée un {@link MultimediaFile} à partir d'un fichier local, l'ajoute et renvoie sa facade.
13
+ */
14
+ addNewFromFile(file: File, ownerIndi?: number): MultimediaFileEdit;
15
+ addNewFromUri(uri: string, ownerIndi?: number, objeXrefId?: number | null): MultimediaFileEdit;
16
+ add(multimediaFile: MultimediaFile, ownerIndi?: number): this;
17
+ removeAt(index: number): this;
18
+ clear(): this;
19
+ at(index: number): MultimediaFileEdit;
20
+ }
21
+ export declare function editActMedia(act: Act): ActMediaEdit;
@@ -1,5 +1,6 @@
1
- import { Acts } from "../commons/Act";
1
+ import { Act, Acts, type TypeAct } from "../commons/Act";
2
2
  import { ActEdit } from "./ActEdit";
3
+ import { type CreateActInit } from "./factories";
3
4
  /**
4
5
  * API d’édition cohérente autour d’un {@link Acts}.
5
6
  */
@@ -7,7 +8,23 @@ export declare class ActsEdit {
7
8
  private readonly target;
8
9
  constructor(target: Acts);
9
10
  get value(): Acts;
11
+ /**
12
+ * Crée un {@link Act}, l’ajoute en fin de liste et renvoie sa facade d’édition.
13
+ */
14
+ addNew(type: TypeAct, init?: CreateActInit | null): ActEdit;
10
15
  add(act: Parameters<Acts["add"]>[0]): this;
16
+ /** Insère un acte existant à la position donnée (0 = début). */
17
+ insertAt(index: number, act: Act): this;
18
+ /**
19
+ * Crée un acte et l’insère à la position donnée.
20
+ */
21
+ insertNewAt(index: number, type: TypeAct, init?: CreateActInit | null): ActEdit;
22
+ /** Supprime le dernier acte s’il en existe au moins un. */
23
+ removeLast(): this;
24
+ /** Index de l’acte par identité de référence, ou `-1`. */
25
+ indexOfAct(act: Act): number;
26
+ /** Retire l’acte s’il appartient à la liste ; @returns si une entrée a été supprimée. */
27
+ removeAct(act: Act): boolean;
11
28
  replaceAt(index: number, act: Parameters<Acts["updateFromIndex"]>[0]): this;
12
29
  removeAt(index: number): this;
13
30
  clear(): this;