@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.
- package/docs/API/10-lang/10-common/10-asyncLoop.ts +4 -6
- package/docs/API/10-lang/10-common/10-asyncLoopAccumulator.ts +40 -0
- package/docs/API/10-lang/10-common/10-loop.ts +5 -7
- package/docs/API/10-lang/10-common/10-loopAccumulator.ts +35 -0
- package/docs/API/10-lang/10-common/10-loopAccumulatorFrom.ts +29 -0
- package/docs/API/10-lang/10-common/index.llms.md +14 -2
- package/docs/API/10-lang/10-generator/10-asyncLoop.ts +11 -20
- package/docs/API/10-lang/10-generator/10-asyncLoopAccumulator.ts +40 -0
- package/docs/API/10-lang/10-generator/10-loop.ts +11 -20
- package/docs/API/10-lang/10-generator/10-loopAccumulator.ts +33 -0
- package/docs/API/10-lang/10-generator/10-loopAccumulatorFrom.ts +30 -0
- package/docs/API/10-lang/10-generator/index.llms.md +14 -2
- package/docs/API/20-server/10-file/10-appendFile.ts +50 -0
- package/docs/API/20-server/10-file/10-appendTextFile.ts +49 -0
- package/docs/API/20-server/10-file/10-copy.ts +50 -0
- package/docs/API/20-server/10-file/10-createEntryInterface.ts +13 -0
- package/docs/API/20-server/10-file/10-createFileInterface.ts +22 -0
- package/docs/API/20-server/10-file/10-createFolderInterface.ts +20 -0
- package/docs/API/20-server/10-file/10-createUnknownEntryInterface.ts +13 -0
- package/docs/API/20-server/10-file/10-ensureDirectory.ts +39 -0
- package/docs/API/20-server/10-file/10-ensureFile.ts +40 -0
- package/docs/API/20-server/10-file/10-exists.ts +36 -0
- package/docs/API/20-server/10-file/10-link.ts +51 -0
- package/docs/API/20-server/10-file/10-linkStat.ts +37 -0
- package/docs/API/20-server/10-file/10-makeDirectory.ts +41 -0
- package/docs/API/20-server/10-file/10-makeTemporaryDirectory.ts +35 -0
- package/docs/API/20-server/10-file/10-makeTemporaryFile.ts +40 -0
- package/docs/API/20-server/10-file/10-move.ts +51 -0
- package/docs/API/20-server/10-file/10-readDirectory.ts +52 -0
- package/docs/API/20-server/10-file/10-readFile.ts +38 -0
- package/docs/API/20-server/10-file/10-readJsonFile.ts +38 -0
- package/docs/API/20-server/10-file/10-readLink.ts +37 -0
- package/docs/API/20-server/10-file/10-readTextFile.ts +38 -0
- package/docs/API/20-server/10-file/10-realPath.ts +36 -0
- package/docs/API/20-server/10-file/10-relocate.ts +51 -0
- package/docs/API/20-server/10-file/10-remove.ts +40 -0
- package/docs/API/20-server/10-file/10-rename.ts +43 -0
- package/docs/API/20-server/10-file/10-setMode.ts +37 -0
- package/docs/API/20-server/10-file/10-setOwner.ts +38 -0
- package/docs/API/20-server/10-file/10-setTime.ts +42 -0
- package/docs/API/20-server/10-file/10-stat.ts +37 -0
- package/docs/API/20-server/10-file/10-symlink.ts +49 -0
- package/docs/API/20-server/10-file/10-truncate.ts +41 -0
- package/docs/API/20-server/10-file/10-walkDirectory.ts +75 -0
- package/docs/API/20-server/10-file/10-writeFile.ts +50 -0
- package/docs/API/20-server/10-file/10-writeJsonFile.ts +41 -0
- package/docs/API/20-server/10-file/10-writeTextFile.ts +49 -0
- package/docs/API/20-server/10-file/index.llms.md +144 -0
- package/docs/API/20-server/10-file/index.md +3 -0
- package/docs/API/20-server/20-common/10-environmentVariable.ts +57 -0
- package/docs/API/20-server/20-common/10-environmentVariableOrThrow.ts +21 -0
- package/docs/API/20-server/20-common/10-exitProcess.ts +9 -0
- package/docs/API/20-server/20-common/10-getCurrentDirectoryName.ts +10 -0
- package/docs/API/20-server/20-common/10-getCurrentWorkDirectory.ts +10 -0
- package/docs/API/20-server/20-common/10-getCurrentWorkDirectoryOrThrow.ts +10 -0
- package/docs/API/20-server/20-common/10-getProcessArguments.ts +10 -0
- package/docs/API/20-server/20-common/10-setCurrentWorkingDirectory.ts +14 -0
- package/docs/API/20-server/20-common/10-setCurrentWorkingDirectoryOrThrow.ts +12 -0
- package/docs/API/20-server/20-common/index.llms.md +40 -0
- package/docs/API/20-server/20-common/index.md +3 -0
- package/docs/API/20-server/30-dataStructure/10-file.ts +14 -0
- package/docs/API/20-server/30-dataStructure/10-fileExist.ts +27 -0
- package/docs/API/20-server/30-dataStructure/10-folder.ts +14 -0
- package/docs/API/20-server/30-dataStructure/10-folderExist.ts +14 -0
- package/docs/API/20-server/30-dataStructure/10-mimeType.ts +14 -0
- package/docs/API/20-server/30-dataStructure/10-size.ts +32 -0
- package/docs/API/20-server/30-dataStructure/index.llms.md +28 -0
- package/docs/API/20-server/30-dataStructure/index.md +3 -0
- package/docs/API/20-server/40-command/10-create.ts +39 -0
- package/docs/API/20-server/40-command/10-createArgument.ts +39 -0
- package/docs/API/20-server/40-command/10-createArrayOption.ts +36 -0
- package/docs/API/20-server/40-command/10-createBooleanOption.ts +28 -0
- package/docs/API/20-server/40-command/10-createOption.ts +46 -0
- package/docs/API/20-server/40-command/10-exec.ts +51 -0
- package/docs/API/20-server/40-command/10-execOptions.ts +30 -0
- package/docs/API/20-server/40-command/index.llms.md +32 -0
- package/docs/API/20-server/40-command/index.md +3 -0
- package/docs/API/20-server/index.md +3 -0
- package/docs/API.llms.md +20 -0
- package/package.json +14 -14
- package/skills/fundamental/SKILL.md +3 -1
- package/skills/fundamental/references/examples/iterations.ts +26 -13
- package/skills/fundamental/references/iterations.md +5 -1
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @title DCommon.asyncLoop
|
|
3
3
|
*
|
|
4
|
-
*
|
|
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"
|
|
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(
|
|
19
|
+
return next();
|
|
22
20
|
});
|
|
23
21
|
|
|
24
|
-
// La callback est attendue
|
|
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
|
-
*
|
|
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"
|
|
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(
|
|
13
|
+
return next();
|
|
16
14
|
});
|
|
17
15
|
|
|
18
|
-
// `count` commence à 0
|
|
19
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
//
|
|
10
|
+
// La callback peut être asynchrone ; `count` est le seul état fourni à chaque tour.
|
|
12
11
|
const withoutExitValue = DCommon.pipe(
|
|
13
|
-
DGenerator.asyncLoop(async({
|
|
12
|
+
DGenerator.asyncLoop(async({ count, next, exit }: DGenerator.LoopParams<number>) => {
|
|
14
13
|
await DCommon.timeout();
|
|
15
14
|
|
|
16
|
-
if (
|
|
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()`
|
|
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
|
-
//
|
|
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({
|
|
33
|
+
DGenerator.asyncLoop(async({ count, next, exit }: DGenerator.LoopParams<number | "done">) => {
|
|
39
34
|
await DCommon.timeout();
|
|
40
35
|
|
|
41
|
-
if (
|
|
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"] :
|
|
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
|
|
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
|
-
//
|
|
10
|
+
// `count` est le seul état fourni à chaque tour ; `next` émet des valeurs et continue.
|
|
12
11
|
const withoutExitValue = DCommon.pipe(
|
|
13
|
-
DGenerator.loop(({
|
|
14
|
-
if (
|
|
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] : `
|
|
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
|
-
//
|
|
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(({
|
|
37
|
-
if (
|
|
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] : `
|
|
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
|
|
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
|
|
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();
|