@duplojs/agents-kit 0.1.0-beta.8 → 0.1.0-beta.9

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 (83) hide show
  1. package/docs/API/10-lang/10-common/10-asyncLoop.ts +4 -6
  2. package/docs/API/10-lang/10-common/10-asyncLoopAccumulator.ts +40 -0
  3. package/docs/API/10-lang/10-common/10-loop.ts +5 -7
  4. package/docs/API/10-lang/10-common/10-loopAccumulator.ts +35 -0
  5. package/docs/API/10-lang/10-common/10-loopAccumulatorFrom.ts +29 -0
  6. package/docs/API/10-lang/10-common/index.llms.md +14 -2
  7. package/docs/API/10-lang/10-generator/10-asyncLoop.ts +11 -20
  8. package/docs/API/10-lang/10-generator/10-asyncLoopAccumulator.ts +40 -0
  9. package/docs/API/10-lang/10-generator/10-loop.ts +11 -20
  10. package/docs/API/10-lang/10-generator/10-loopAccumulator.ts +33 -0
  11. package/docs/API/10-lang/10-generator/10-loopAccumulatorFrom.ts +30 -0
  12. package/docs/API/10-lang/10-generator/index.llms.md +14 -2
  13. package/docs/API/20-server/10-file/10-appendFile.ts +50 -0
  14. package/docs/API/20-server/10-file/10-appendTextFile.ts +49 -0
  15. package/docs/API/20-server/10-file/10-copy.ts +50 -0
  16. package/docs/API/20-server/10-file/10-createEntryInterface.ts +13 -0
  17. package/docs/API/20-server/10-file/10-createFileInterface.ts +22 -0
  18. package/docs/API/20-server/10-file/10-createFolderInterface.ts +20 -0
  19. package/docs/API/20-server/10-file/10-createUnknownEntryInterface.ts +13 -0
  20. package/docs/API/20-server/10-file/10-ensureDirectory.ts +39 -0
  21. package/docs/API/20-server/10-file/10-ensureFile.ts +40 -0
  22. package/docs/API/20-server/10-file/10-exists.ts +36 -0
  23. package/docs/API/20-server/10-file/10-link.ts +51 -0
  24. package/docs/API/20-server/10-file/10-linkStat.ts +37 -0
  25. package/docs/API/20-server/10-file/10-makeDirectory.ts +41 -0
  26. package/docs/API/20-server/10-file/10-makeTemporaryDirectory.ts +35 -0
  27. package/docs/API/20-server/10-file/10-makeTemporaryFile.ts +40 -0
  28. package/docs/API/20-server/10-file/10-move.ts +51 -0
  29. package/docs/API/20-server/10-file/10-readDirectory.ts +52 -0
  30. package/docs/API/20-server/10-file/10-readFile.ts +38 -0
  31. package/docs/API/20-server/10-file/10-readJsonFile.ts +38 -0
  32. package/docs/API/20-server/10-file/10-readLink.ts +37 -0
  33. package/docs/API/20-server/10-file/10-readTextFile.ts +38 -0
  34. package/docs/API/20-server/10-file/10-realPath.ts +36 -0
  35. package/docs/API/20-server/10-file/10-relocate.ts +51 -0
  36. package/docs/API/20-server/10-file/10-remove.ts +40 -0
  37. package/docs/API/20-server/10-file/10-rename.ts +43 -0
  38. package/docs/API/20-server/10-file/10-setMode.ts +37 -0
  39. package/docs/API/20-server/10-file/10-setOwner.ts +38 -0
  40. package/docs/API/20-server/10-file/10-setTime.ts +42 -0
  41. package/docs/API/20-server/10-file/10-stat.ts +37 -0
  42. package/docs/API/20-server/10-file/10-symlink.ts +49 -0
  43. package/docs/API/20-server/10-file/10-truncate.ts +41 -0
  44. package/docs/API/20-server/10-file/10-walkDirectory.ts +75 -0
  45. package/docs/API/20-server/10-file/10-writeFile.ts +50 -0
  46. package/docs/API/20-server/10-file/10-writeJsonFile.ts +41 -0
  47. package/docs/API/20-server/10-file/10-writeTextFile.ts +49 -0
  48. package/docs/API/20-server/10-file/index.llms.md +144 -0
  49. package/docs/API/20-server/10-file/index.md +3 -0
  50. package/docs/API/20-server/20-common/10-environmentVariable.ts +57 -0
  51. package/docs/API/20-server/20-common/10-environmentVariableOrThrow.ts +21 -0
  52. package/docs/API/20-server/20-common/10-exitProcess.ts +9 -0
  53. package/docs/API/20-server/20-common/10-getCurrentDirectoryName.ts +10 -0
  54. package/docs/API/20-server/20-common/10-getCurrentWorkDirectory.ts +10 -0
  55. package/docs/API/20-server/20-common/10-getCurrentWorkDirectoryOrThrow.ts +10 -0
  56. package/docs/API/20-server/20-common/10-getProcessArguments.ts +10 -0
  57. package/docs/API/20-server/20-common/10-setCurrentWorkingDirectory.ts +14 -0
  58. package/docs/API/20-server/20-common/10-setCurrentWorkingDirectoryOrThrow.ts +12 -0
  59. package/docs/API/20-server/20-common/index.llms.md +40 -0
  60. package/docs/API/20-server/20-common/index.md +3 -0
  61. package/docs/API/20-server/30-dataStructure/10-file.ts +14 -0
  62. package/docs/API/20-server/30-dataStructure/10-fileExist.ts +27 -0
  63. package/docs/API/20-server/30-dataStructure/10-folder.ts +14 -0
  64. package/docs/API/20-server/30-dataStructure/10-folderExist.ts +14 -0
  65. package/docs/API/20-server/30-dataStructure/10-mimeType.ts +14 -0
  66. package/docs/API/20-server/30-dataStructure/10-size.ts +32 -0
  67. package/docs/API/20-server/30-dataStructure/index.llms.md +28 -0
  68. package/docs/API/20-server/30-dataStructure/index.md +3 -0
  69. package/docs/API/20-server/40-command/10-create.ts +39 -0
  70. package/docs/API/20-server/40-command/10-createArgument.ts +39 -0
  71. package/docs/API/20-server/40-command/10-createArrayOption.ts +36 -0
  72. package/docs/API/20-server/40-command/10-createBooleanOption.ts +28 -0
  73. package/docs/API/20-server/40-command/10-createOption.ts +46 -0
  74. package/docs/API/20-server/40-command/10-exec.ts +51 -0
  75. package/docs/API/20-server/40-command/10-execOptions.ts +30 -0
  76. package/docs/API/20-server/40-command/index.llms.md +32 -0
  77. package/docs/API/20-server/40-command/index.md +3 -0
  78. package/docs/API/20-server/index.md +3 -0
  79. package/docs/API.llms.md +20 -0
  80. package/package.json +14 -14
  81. package/skills/fundamental/SKILL.md +3 -1
  82. package/skills/fundamental/references/examples/iterations.ts +26 -13
  83. package/skills/fundamental/references/iterations.md +5 -1
@@ -1,25 +1,23 @@
1
1
  /**
2
2
  * @title DCommon.asyncLoop
3
3
  *
4
- * Contrôler une boucle asynchrone avec un compteur et une sortie typée.
4
+ * Répéter une callback asynchrone jusqu’à `exit`, avec un compteur et une valeur de retour typée.
5
5
  */
6
6
  import * as DCommon from "@duplojs/lang/common";
7
7
 
8
- const result = DCommon.asyncLoop<"done", number>(async({
8
+ const result = DCommon.asyncLoop<"done">(async({
9
9
  count,
10
- previousOutput,
11
10
  next,
12
11
  exit,
13
12
  }) => {
14
- const current = previousOutput ?? 0;
15
13
  await DCommon.timeout();
16
14
 
17
15
  if (count === 3) {
18
16
  return exit("done");
19
17
  }
20
18
 
21
- return next(current + 1);
19
+ return next();
22
20
  });
23
21
 
24
- // La callback est attendue asynchrone, mais conserve les mêmes paramètres que `loop`.
22
+ // La callback est attendue à chaque tour. `next` ne transmet pas d’état à l’itération suivante.
25
23
  type _CheckResult = DCommon.ExpectType<typeof result, Promise<"done">, "strict">;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @title DCommon.asyncLoopAccumulator
3
+ *
4
+ * Répéter une callback asynchrone en faisant circuler un accumulateur et retourner la valeur de `exit`.
5
+ */
6
+ import * as DCommon from "@duplojs/lang/common";
7
+
8
+ const total = await DCommon.asyncLoopAccumulator(0, async({ accumulator, count, next, exit }) => {
9
+ await DCommon.timeout();
10
+
11
+ if (count === 3) {
12
+ return exit(accumulator);
13
+ }
14
+
15
+ return next(accumulator + count + 1);
16
+ });
17
+
18
+ // La callback est attendue à chaque tour et le résultat final est celui de `exit`.
19
+ type _CheckTotal = DCommon.ExpectType<typeof total, number, "strict">;
20
+
21
+ interface Accumulator {
22
+ readonly total: number;
23
+ readonly previous?: number;
24
+ }
25
+
26
+ const structuredTotal = await DCommon.asyncLoopAccumulator(
27
+ DCommon.loopAccumulatorFrom<Accumulator>({ total: 0 }),
28
+ async({ accumulator, count, next, exit }) => {
29
+ await DCommon.timeout();
30
+
31
+ return count === 2
32
+ ? exit(accumulator.total)
33
+ : next({
34
+ total: accumulator.total + 1,
35
+ previous: accumulator.total,
36
+ });
37
+ },
38
+ );
39
+
40
+ type _CheckStructuredTotal = DCommon.ExpectType<typeof structuredTotal, number, "strict">;
@@ -1,20 +1,18 @@
1
1
  /**
2
2
  * @title DCommon.loop
3
3
  *
4
- * Contrôler une boucle synchrone avec un compteur et une sortie typée.
4
+ * Répéter une callback synchrone jusqu’à `exit`, avec un compteur et une valeur de retour typée.
5
5
  */
6
6
  import * as DCommon from "@duplojs/lang/common";
7
7
 
8
- const result = DCommon.loop<"done", number>(({ count, previousOutput, next, exit }) => {
9
- const current = previousOutput ?? 0;
10
-
8
+ const result = DCommon.loop<"done">(({ count, next, exit }) => {
11
9
  if (count === 3) {
12
10
  return exit("done");
13
11
  }
14
12
 
15
- return next(current + 1);
13
+ return next();
16
14
  });
17
15
 
18
- // `count` commence à 0 ; `previousOutput` vaut undefined à la première itération.
19
- // `next` poursuit la boucle avec une nouvelle sortie, tandis que `exit` la termine.
16
+ // `count` commence à 0. `next()` poursuit la boucle ; les valeurs d'une itération à l'autre
17
+ // doivent être portées par loopAccumulator, car `loop` ne conserve pas les données de `next`.
20
18
  type _CheckResult = DCommon.ExpectType<typeof result, "done", "strict">;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @title DCommon.loopAccumulator
3
+ *
4
+ * Répéter une callback synchrone en faisant circuler un accumulateur et retourner la valeur de `exit`.
5
+ */
6
+ import * as DCommon from "@duplojs/lang/common";
7
+
8
+ const total = DCommon.loopAccumulator(0, ({ accumulator, count, next, exit }) => {
9
+ if (count === 3) {
10
+ return exit(accumulator);
11
+ }
12
+
13
+ return next(accumulator + count + 1);
14
+ });
15
+
16
+ // Le nombre initial est élargi en number ; chaque `next` fournit l’accumulateur du tour suivant.
17
+ type _CheckTotal = DCommon.ExpectType<typeof total, number, "strict">;
18
+
19
+ interface Accumulator {
20
+ readonly total: number;
21
+ readonly previous?: number;
22
+ }
23
+
24
+ const structuredTotal = DCommon.loopAccumulator(
25
+ DCommon.loopAccumulatorFrom<Accumulator>({ total: 0 }),
26
+ ({ accumulator, count, next, exit }) => count === 2
27
+ ? exit(accumulator.total)
28
+ : next({
29
+ total: accumulator.total + 1,
30
+ previous: accumulator.total,
31
+ }),
32
+ );
33
+
34
+ // `loopAccumulatorFrom` conserve le type choisi pour un accumulateur structuré.
35
+ type _CheckStructuredTotal = DCommon.ExpectType<typeof structuredTotal, number, "strict">;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @title DCommon.loopAccumulatorFrom
3
+ *
4
+ * Marquer une valeur initiale pour fixer précisément le type de l’accumulateur d’une boucle.
5
+ */
6
+ import * as DCommon from "@duplojs/lang/common";
7
+
8
+ interface Accumulator {
9
+ readonly total: number;
10
+ readonly previous?: number;
11
+ }
12
+
13
+ const initialAccumulator = DCommon.loopAccumulatorFrom<Accumulator>({ total: 0 });
14
+
15
+ type _CheckInitialAccumulator = DCommon.ExpectType<
16
+ typeof initialAccumulator,
17
+ DCommon.LoopAccumulatorFromResult<Accumulator>,
18
+ "strict"
19
+ >;
20
+
21
+ const result = DCommon.loopAccumulator(initialAccumulator, ({ accumulator, count, next, exit }) => count === 2
22
+ ? exit(accumulator.total)
23
+ : next({
24
+ total: accumulator.total + 1,
25
+ previous: accumulator.total,
26
+ }));
27
+
28
+ // La boucle reçoit Accumulator comme état et retourne le nombre fourni à `exit`.
29
+ type _CheckResult = DCommon.ExpectType<typeof result, number, "strict">;
@@ -16,7 +16,11 @@ Construire une fonction qui enchaîne des opérations synchrones ou asynchrones.
16
16
 
17
17
  ### [DCommon.asyncLoop](10-asyncLoop.ts)
18
18
 
19
- Contrôler une boucle asynchrone avec un compteur et une sortie typée.
19
+ Répéter une callback asynchrone jusqu’à `exit`, avec un compteur et une valeur de retour typée.
20
+
21
+ ### [DCommon.asyncLoopAccumulator](10-asyncLoopAccumulator.ts)
22
+
23
+ Répéter une callback asynchrone en faisant circuler un accumulateur et retourner la valeur de `exit`.
20
24
 
21
25
  ### [DCommon.asyncPipe](10-asyncPipe.ts)
22
26
 
@@ -120,7 +124,15 @@ Fournir une valeur déjà calculée à une étape de pipe sans écrire de callba
120
124
 
121
125
  ### [DCommon.loop](10-loop.ts)
122
126
 
123
- Contrôler une boucle synchrone avec un compteur et une sortie typée.
127
+ Répéter une callback synchrone jusqu’à `exit`, avec un compteur et une valeur de retour typée.
128
+
129
+ ### [DCommon.loopAccumulator](10-loopAccumulator.ts)
130
+
131
+ Répéter une callback synchrone en faisant circuler un accumulateur et retourner la valeur de `exit`.
132
+
133
+ ### [DCommon.loopAccumulatorFrom](10-loopAccumulatorFrom.ts)
134
+
135
+ Marquer une valeur initiale pour fixer précisément le type de l’accumulateur d’une boucle.
124
136
 
125
137
  ### [DCommon.memo](10-memo.ts)
126
138
 
@@ -1,57 +1,48 @@
1
1
  /**
2
2
  * @title DGenerator.asyncLoop
3
3
  *
4
- * Produire une séquence asynchrone dans un pipe en distinguant l’arrêt avec ou sans dernière valeur émise.
4
+ * Produire une séquence asynchrone en distinguant les valeurs de `next` et celles de la sortie `exit`.
5
5
  */
6
6
  import * as DArray from "@duplojs/lang/array";
7
7
  import * as DCommon from "@duplojs/lang/common";
8
8
  import * as DGenerator from "@duplojs/lang/generator";
9
- import * as DNumber from "@duplojs/lang/number";
10
9
 
11
- // Arrêt sans dernière valeur : `exit()` termine la boucle asynchrone sans émettre d’élément supplémentaire.
10
+ // La callback peut être asynchrone ; `count` est le seul état fourni à chaque tour.
12
11
  const withoutExitValue = DCommon.pipe(
13
- DGenerator.asyncLoop(async({ previousOutput, next, exit }: DGenerator.LoopParams<number>) => {
12
+ DGenerator.asyncLoop(async({ count, next, exit }: DGenerator.LoopParams<number>) => {
14
13
  await DCommon.timeout();
15
14
 
16
- if (previousOutput === 3) {
15
+ if (count === 3) {
17
16
  return exit();
18
17
  }
19
18
 
20
- return next(
21
- previousOutput === undefined
22
- ? 1
23
- : DNumber.sum([previousOutput, 1]),
24
- );
19
+ return next(count + 1);
25
20
  }),
26
21
  DArray.from,
27
22
  );
28
23
 
29
- // La promesse se résout vers [1, 2, 3] : `exit()` n’émet aucune dernière valeur.
24
+ // La promesse se résout vers [1, 2, 3] : `exit()` termine sans ajouter de valeur.
30
25
  type _CheckWithoutExitValue = DCommon.ExpectType<
31
26
  typeof withoutExitValue,
32
27
  Promise<readonly number[]>,
33
28
  "strict"
34
29
  >;
35
30
 
36
- // Arrêt avec dernière valeur : `exit("done")` termine la boucle en l’émettant.
31
+ // La callback est attendue à chaque tour ; les sorties sont émises avant l’appel du tour suivant.
37
32
  const withExitValue = DCommon.pipe(
38
- DGenerator.asyncLoop(async({ previousOutput, next, exit }: DGenerator.LoopParams<number>) => {
33
+ DGenerator.asyncLoop(async({ count, next, exit }: DGenerator.LoopParams<number | "done">) => {
39
34
  await DCommon.timeout();
40
35
 
41
- if (previousOutput === 3) {
36
+ if (count === 3) {
42
37
  return exit("done");
43
38
  }
44
39
 
45
- return next(
46
- previousOutput === undefined
47
- ? 1
48
- : DNumber.sum([previousOutput, 1]),
49
- );
40
+ return next(count + 1);
50
41
  }),
51
42
  DArray.from,
52
43
  );
53
44
 
54
- // La promesse se résout vers [1, 2, 3, "done"] : la valeur de `exit` est émise comme dernier élément.
45
+ // La promesse se résout vers [1, 2, 3, "done"] : `exit` ajoute sa valeur en dernier.
55
46
  type _CheckWithExitValue = DCommon.ExpectType<
56
47
  typeof withExitValue,
57
48
  Promise<readonly (number | "done")[]>,
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @title DGenerator.asyncLoopAccumulator
3
+ *
4
+ * Produire une séquence asynchrone en mettant à jour un accumulateur à chaque itération.
5
+ */
6
+ import * as DArray from "@duplojs/lang/array";
7
+ import * as DCommon from "@duplojs/lang/common";
8
+ import * as DGenerator from "@duplojs/lang/generator";
9
+
10
+ const values = await DArray.from(DGenerator.asyncLoopAccumulator(0, async({ accumulator, count, next, exit }) => {
11
+ await DCommon.timeout();
12
+
13
+ return count === 3
14
+ ? exit(Promise.resolve(accumulator))
15
+ : next(accumulator + 1, Promise.resolve(accumulator));
16
+ }));
17
+
18
+ // La callback et les valeurs émises peuvent être asynchrones ; les sorties sont résolues avant émission.
19
+ type _CheckValues = DCommon.ExpectType<typeof values, readonly number[], "strict">;
20
+
21
+ interface Accumulator {
22
+ readonly total: number;
23
+ readonly previous?: number;
24
+ }
25
+
26
+ const finalTotal = await DArray.from(DGenerator.asyncLoopAccumulator(
27
+ DGenerator.loopAccumulatorFrom<Accumulator>({ total: 0 }),
28
+ async({ accumulator, count, next, exit }) => {
29
+ await DCommon.timeout();
30
+
31
+ return count === 2
32
+ ? exit(Promise.resolve(accumulator.total))
33
+ : next({
34
+ total: accumulator.total + 1,
35
+ previous: accumulator.total,
36
+ }, Promise.resolve(accumulator.total));
37
+ },
38
+ ));
39
+
40
+ type _CheckFinalTotal = DCommon.ExpectType<typeof finalTotal, readonly number[], "strict">;
@@ -1,53 +1,44 @@
1
1
  /**
2
2
  * @title DGenerator.loop
3
3
  *
4
- * Produire une séquence dans un pipe en distinguant l’arrêt avec ou sans dernière valeur émise.
4
+ * Produire une séquence synchrone en distinguant les valeurs de `next` et celles de la sortie `exit`.
5
5
  */
6
6
  import * as DArray from "@duplojs/lang/array";
7
7
  import * as DCommon from "@duplojs/lang/common";
8
8
  import * as DGenerator from "@duplojs/lang/generator";
9
- import * as DNumber from "@duplojs/lang/number";
10
9
 
11
- // Arrêt sans dernière valeur : `exit()` termine la boucle sans émettre d’élément supplémentaire.
10
+ // `count` est le seul état fourni à chaque tour ; `next` émet des valeurs et continue.
12
11
  const withoutExitValue = DCommon.pipe(
13
- DGenerator.loop(({ previousOutput, next, exit }: DGenerator.LoopParams<number>) => {
14
- if (previousOutput === 3) {
12
+ DGenerator.loop(({ count, next, exit }: DGenerator.LoopParams<number>) => {
13
+ if (count === 3) {
15
14
  return exit();
16
15
  }
17
16
 
18
- return next(
19
- previousOutput === undefined
20
- ? 1
21
- : DNumber.sum([previousOutput, 1]),
22
- );
17
+ return next(count + 1);
23
18
  }),
24
19
  DArray.from,
25
20
  );
26
21
 
27
- // La sortie vaut [1, 2, 3] : `next` émet les valeurs intermédiaires, mais `exit()` n’en émet aucune.
22
+ // La sortie vaut [1, 2, 3] : `exit()` termine sans ajouter de valeur.
28
23
  type _CheckWithoutExitValue = DCommon.ExpectType<
29
24
  typeof withoutExitValue,
30
25
  readonly number[],
31
26
  "strict"
32
27
  >;
33
28
 
34
- // Arrêt avec dernière valeur : `exit(value)` termine la boucle en émettant cette valeur.
29
+ // `exit(value)` termine la boucle et émet sa valeur après celles émises par `next`.
35
30
  const withExitValue = DCommon.pipe(
36
- DGenerator.loop(({ previousOutput, next, exit }: DGenerator.LoopParams<number>) => {
37
- if (previousOutput === 3) {
31
+ DGenerator.loop(({ count, next, exit }: DGenerator.LoopParams<number>) => {
32
+ if (count === 3) {
38
33
  return exit(4);
39
34
  }
40
35
 
41
- return next(
42
- previousOutput === undefined
43
- ? 1
44
- : DNumber.sum([previousOutput, 1]),
45
- );
36
+ return next(count + 1);
46
37
  }),
47
38
  DArray.from,
48
39
  );
49
40
 
50
- // La sortie vaut [1, 2, 3, 4] : `exit(4)` ajoute la dernière valeur à la séquence.
41
+ // La sortie vaut [1, 2, 3, 4] : les valeurs multiples de `next` et `exit` forment la séquence.
51
42
  type _CheckWithExitValue = DCommon.ExpectType<
52
43
  typeof withExitValue,
53
44
  readonly number[],
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @title DGenerator.loopAccumulator
3
+ *
4
+ * Produire une séquence synchrone en mettant à jour un accumulateur à chaque itération.
5
+ */
6
+ import * as DArray from "@duplojs/lang/array";
7
+ import type * as DCommon from "@duplojs/lang/common";
8
+ import * as DGenerator from "@duplojs/lang/generator";
9
+
10
+ const values = DArray.from(DGenerator.loopAccumulator(0, ({ accumulator, count, next, exit }) => count === 3
11
+ ? exit(accumulator)
12
+ : next(accumulator + 1, accumulator)));
13
+
14
+ // `next` reçoit d’abord le nouvel accumulateur, puis émet les valeurs suivantes.
15
+ // La valeur de `exit` est également émise avant que le générateur se termine.
16
+ type _CheckValues = DCommon.ExpectType<typeof values, readonly number[], "strict">;
17
+
18
+ interface Accumulator {
19
+ readonly total: number;
20
+ readonly previous?: number;
21
+ }
22
+
23
+ const finalTotal = DArray.from(DGenerator.loopAccumulator(
24
+ DGenerator.loopAccumulatorFrom<Accumulator>({ total: 0 }),
25
+ ({ accumulator, count, next, exit }) => count === 2
26
+ ? exit(accumulator.total)
27
+ : next({
28
+ total: accumulator.total + 1,
29
+ previous: accumulator.total,
30
+ }, accumulator.total),
31
+ ));
32
+
33
+ type _CheckFinalTotal = DCommon.ExpectType<typeof finalTotal, readonly number[], "strict">;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @title DGenerator.loopAccumulatorFrom
3
+ *
4
+ * Marquer une valeur initiale pour fixer précisément le type de l’accumulateur d’une boucle.
5
+ */
6
+ import type * as DCommon from "@duplojs/lang/common";
7
+ import * as DGenerator from "@duplojs/lang/generator";
8
+
9
+ interface Accumulator {
10
+ readonly total: number;
11
+ readonly previous?: number;
12
+ }
13
+
14
+ const initialAccumulator = DGenerator.loopAccumulatorFrom<Accumulator>({ total: 0 });
15
+
16
+ type _CheckInitialAccumulator = DCommon.ExpectType<
17
+ typeof initialAccumulator,
18
+ DGenerator.LoopAccumulatorFromResult<Accumulator>,
19
+ "strict"
20
+ >;
21
+
22
+ const result = DGenerator.loopAccumulator(initialAccumulator, ({ accumulator, count, next, exit }) => count === 2
23
+ ? exit(accumulator.total)
24
+ : next({
25
+ total: accumulator.total + 1,
26
+ previous: accumulator.total,
27
+ }, accumulator.total));
28
+
29
+ // La boucle reçoit Accumulator comme état, tout en produisant sa valeur de sortie dans le générateur.
30
+ type _CheckResult = DCommon.ExpectType<typeof result, Generator<number, unknown, unknown>, "strict">;
@@ -24,7 +24,11 @@ Regrouper les valeurs d’un itérable asynchrone selon les sorties nommées d
24
24
 
25
25
  ### [DGenerator.asyncLoop](10-asyncLoop.ts)
26
26
 
27
- Produire une séquence asynchrone dans un pipe en distinguant l’arrêt avec ou sans dernière valeur émise.
27
+ Produire une séquence asynchrone en distinguant les valeurs de `next` et celles de la sortie `exit`.
28
+
29
+ ### [DGenerator.asyncLoopAccumulator](10-asyncLoopAccumulator.ts)
30
+
31
+ Produire une séquence asynchrone en mettant à jour un accumulateur à chaque itération.
28
32
 
29
33
  ### [DGenerator.asyncMap](10-asyncMap.ts)
30
34
 
@@ -68,7 +72,15 @@ Construire une sortie nommée destinée à la fonction de regroupement.
68
72
 
69
73
  ### [DGenerator.loop](10-loop.ts)
70
74
 
71
- Produire une séquence dans un pipe en distinguant l’arrêt avec ou sans dernière valeur émise.
75
+ Produire une séquence synchrone en distinguant les valeurs de `next` et celles de la sortie `exit`.
76
+
77
+ ### [DGenerator.loopAccumulator](10-loopAccumulator.ts)
78
+
79
+ Produire une séquence synchrone en mettant à jour un accumulateur à chaque itération.
80
+
81
+ ### [DGenerator.loopAccumulatorFrom](10-loopAccumulatorFrom.ts)
82
+
83
+ Marquer une valeur initiale pour fixer précisément le type de l’accumulateur d’une boucle.
72
84
 
73
85
  ### [DGenerator.map](10-map.ts)
74
86
 
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @title DSFile.appendFile
3
+ *
4
+ * Ajouter des octets à un fichier.
5
+ */
6
+ import * as DCommon from "@duplojs/lang/common";
7
+ import type * as DPath from "@duplojs/lang/path";
8
+ import * as DSFile from "@duplojs/server/file";
9
+ import * as DEither from "@duplojs/lang/either";
10
+ import * as DPattern from "@duplojs/lang/pattern";
11
+
12
+ declare const path: string & DPath.Path;
13
+ declare const bytes: Uint8Array;
14
+
15
+ // Appel direct
16
+ const result = await DSFile.appendFile(path, bytes);
17
+
18
+ // Forme curifiée
19
+ const pipedResult = await DCommon.pipe(
20
+ path,
21
+ DSFile.appendFile(bytes),
22
+ );
23
+
24
+ // Chaque résultat indique la réussite ou l'échec de l'écriture.
25
+
26
+ // L’information du Left identifie l’opération ; sa valeur précise la cause.
27
+ if (DEither.isLeft(result)) {
28
+ const error = DEither.unwrapLeft(result);
29
+
30
+ const diagnosis = DPattern.matchWithErrorOtherwise(
31
+ error,
32
+ {
33
+ "file-system-append-file-not-found": () => "missing",
34
+ "file-system-append-file-permission-denied": () => "access-denied",
35
+ },
36
+ (otherError) => otherError,
37
+ );
38
+ }
39
+
40
+ // Identifiants d’erreur déclarés pour cette opération :
41
+ // file-system-append-file-not-found
42
+ // file-system-append-file-permission-denied
43
+ // file-system-append-file-is-directory
44
+ // file-system-append-file-not-directory
45
+ // file-system-append-file-no-space
46
+ // file-system-append-file-read-only
47
+ // file-system-append-file-invalid-argument
48
+ // file-system-append-file-too-many-open-files
49
+ // file-system-append-file-busy
50
+ // file-system-append-file-error
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @title DSFile.appendTextFile
3
+ *
4
+ * Ajouter du texte à un fichier.
5
+ */
6
+ import * as DCommon from "@duplojs/lang/common";
7
+ import type * as DPath from "@duplojs/lang/path";
8
+ import * as DSFile from "@duplojs/server/file";
9
+ import * as DEither from "@duplojs/lang/either";
10
+ import * as DPattern from "@duplojs/lang/pattern";
11
+
12
+ declare const path: string & DPath.Path;
13
+
14
+ // Appel direct
15
+ const result = await DSFile.appendTextFile(path, "nouvelle ligne\n");
16
+
17
+ // Forme curifiée
18
+ const pipedResult = await DCommon.pipe(
19
+ path,
20
+ DSFile.appendTextFile("nouvelle ligne\n"),
21
+ );
22
+
23
+ // Chaque résultat indique la réussite ou l'échec de l'écriture.
24
+
25
+ // L’information du Left identifie l’opération ; sa valeur précise la cause.
26
+ if (DEither.isLeft(result)) {
27
+ const error = DEither.unwrapLeft(result);
28
+
29
+ const diagnosis = DPattern.matchWithErrorOtherwise(
30
+ error,
31
+ {
32
+ "file-system-append-text-file-not-found": () => "missing",
33
+ "file-system-append-text-file-permission-denied": () => "access-denied",
34
+ },
35
+ (otherError) => otherError,
36
+ );
37
+ }
38
+
39
+ // Identifiants d’erreur déclarés pour cette opération :
40
+ // file-system-append-text-file-not-found
41
+ // file-system-append-text-file-permission-denied
42
+ // file-system-append-text-file-is-directory
43
+ // file-system-append-text-file-not-directory
44
+ // file-system-append-text-file-no-space
45
+ // file-system-append-text-file-read-only
46
+ // file-system-append-text-file-invalid-argument
47
+ // file-system-append-text-file-too-many-open-files
48
+ // file-system-append-text-file-busy
49
+ // file-system-append-text-file-error
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @title DSFile.copy
3
+ *
4
+ * Copier une ressource, récursivement pour un dossier.
5
+ */
6
+ import * as DCommon from "@duplojs/lang/common";
7
+ import type * as DPath from "@duplojs/lang/path";
8
+ import * as DSFile from "@duplojs/server/file";
9
+ import * as DEither from "@duplojs/lang/either";
10
+ import * as DPattern from "@duplojs/lang/pattern";
11
+
12
+ declare const source: string & DPath.Path;
13
+ declare const destination: string & DPath.Path;
14
+
15
+ // Appel direct
16
+ const result = await DSFile.copy(source, destination);
17
+
18
+ // Forme curifiée
19
+ const pipedResult = await DCommon.pipe(
20
+ source,
21
+ DSFile.copy(destination),
22
+ );
23
+
24
+ // Les résultats dépendent de l'état du système de fichiers et peuvent échouer.
25
+
26
+ // L’information du Left identifie l’opération ; sa valeur précise la cause.
27
+ if (DEither.isLeft(result)) {
28
+ const error = DEither.unwrapLeft(result);
29
+
30
+ const diagnosis = DPattern.matchWithErrorOtherwise(
31
+ error,
32
+ {
33
+ "file-system-copy-not-found": () => "missing",
34
+ "file-system-copy-permission-denied": () => "access-denied",
35
+ },
36
+ (otherError) => otherError,
37
+ );
38
+ }
39
+
40
+ // Identifiants d’erreur déclarés pour cette opération :
41
+ // file-system-copy-not-found
42
+ // file-system-copy-permission-denied
43
+ // file-system-copy-already-exists
44
+ // file-system-copy-not-directory
45
+ // file-system-copy-no-space
46
+ // file-system-copy-read-only
47
+ // file-system-copy-invalid-argument
48
+ // file-system-copy-too-many-open-files
49
+ // file-system-copy-busy
50
+ // file-system-copy-error
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @title DSFile.createEntryInterface
3
+ *
4
+ * Inspecter une entrée et construire son interface adaptée.
5
+ */
6
+ import type * as DPath from "@duplojs/lang/path";
7
+ import * as DSFile from "@duplojs/server/file";
8
+
9
+ declare const path: string & DPath.Path;
10
+
11
+ const result = await DSFile.createEntryInterface(path);
12
+
13
+ // La réussite distingue fichier, dossier et entrée inconnue ; un échec porte l’erreur d’inspection.
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @title DSFile.createFileInterface
3
+ *
4
+ * Construire une référence de fichier sans accès au disque.
5
+ */
6
+ import type * as DPath from "@duplojs/lang/path";
7
+ import * as DSFile from "@duplojs/server/file";
8
+
9
+ declare const path: string & DPath.Path;
10
+
11
+ const entry = DSFile.createFileInterface(path);
12
+
13
+ // La construction ne vérifie ni l’existence ni la nature de la ressource.
14
+
15
+ // Les méthodes de référence extraient les composants sans accès au disque.
16
+ const name = entry.getName();
17
+ const mimeType = entry.getMimeType();
18
+
19
+ // stat, exists et les opérations de déplacement consultent le système.
20
+ // rename, move et relocate retournent une nouvelle interface en cas de succès ;
21
+ // ils ne modifient pas le chemin de cette référence.
22
+ const metadata = await entry.stat();