@duplojs/utils 1.5.9 → 1.5.10

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 (46) hide show
  1. package/dist/array/includes.d.ts +2 -2
  2. package/dist/array/index.cjs +2 -0
  3. package/dist/array/index.d.ts +1 -0
  4. package/dist/array/index.mjs +1 -0
  5. package/dist/array/mapTuple.cjs +15 -0
  6. package/dist/array/mapTuple.d.ts +45 -0
  7. package/dist/array/mapTuple.mjs +13 -0
  8. package/dist/array/notIncludes.d.ts +8 -3
  9. package/dist/array/types/index.d.ts +1 -0
  10. package/dist/array/types/mapTuple.d.ts +1 -0
  11. package/dist/common/types/bivariantFunction.d.ts +9 -0
  12. package/dist/common/types/index.d.ts +1 -0
  13. package/dist/dataParser/parsers/record/findRecordRequiredKey.cjs +2 -1
  14. package/dist/dataParser/parsers/record/findRecordRequiredKey.mjs +2 -1
  15. package/dist/date/index.cjs +2 -0
  16. package/dist/date/index.mjs +1 -0
  17. package/dist/date/operators/equal.cjs +14 -0
  18. package/dist/date/operators/equal.d.ts +35 -0
  19. package/dist/date/operators/equal.mjs +12 -0
  20. package/dist/date/operators/index.d.ts +1 -0
  21. package/dist/generator/createExternalAsyncGenerator.cjs +26 -0
  22. package/dist/generator/createExternalAsyncGenerator.d.ts +46 -0
  23. package/dist/generator/createExternalAsyncGenerator.mjs +24 -0
  24. package/dist/generator/index.cjs +2 -0
  25. package/dist/generator/index.d.ts +1 -0
  26. package/dist/generator/index.mjs +1 -0
  27. package/dist/metadata.json +66 -0
  28. package/dist/number/types/absolute.d.ts +1 -3
  29. package/dist/string/index.cjs +6 -0
  30. package/dist/string/index.d.ts +3 -0
  31. package/dist/string/index.mjs +3 -0
  32. package/dist/string/pop.cjs +10 -0
  33. package/dist/string/pop.d.ts +26 -0
  34. package/dist/string/pop.mjs +8 -0
  35. package/dist/string/prepend.cjs +12 -0
  36. package/dist/string/prepend.d.ts +40 -0
  37. package/dist/string/prepend.mjs +10 -0
  38. package/dist/string/shift.cjs +10 -0
  39. package/dist/string/shift.d.ts +26 -0
  40. package/dist/string/shift.mjs +8 -0
  41. package/dist/string/types/index.d.ts +2 -0
  42. package/dist/string/types/pop.d.ts +3 -0
  43. package/dist/string/types/shift.d.ts +3 -0
  44. package/dist/string/types/split.d.ts +5 -4
  45. package/dist/string/types/templateLiteralContainLargeType.d.ts +2 -1
  46. package/package.json +1 -1
@@ -38,5 +38,5 @@
38
38
  * @namespace A
39
39
  *
40
40
  */
41
- export declare function includes<GenericArrayValue extends unknown>(value: NoInfer<GenericArrayValue>): (array: readonly GenericArrayValue[]) => boolean;
42
- export declare function includes<GenericArrayValue extends unknown>(array: readonly GenericArrayValue[], value: NoInfer<GenericArrayValue>): boolean;
41
+ export declare function includes<GenericArray extends readonly unknown[], GenericArrayValue extends GenericArray[number]>(value: GenericArrayValue): (array: GenericArray) => boolean;
42
+ export declare function includes<GenericArray extends readonly unknown[], GenericArrayValue extends GenericArray[number]>(array: GenericArray, value: GenericArrayValue): boolean;
@@ -44,6 +44,7 @@ var insert$2 = require('./insert.cjs');
44
44
  var isLastIndex = require('./isLastIndex.cjs');
45
45
  var select = require('./select.cjs');
46
46
  var lengthEqual = require('./lengthEqual.cjs');
47
+ var mapTuple = require('./mapTuple.cjs');
47
48
  var _delete = require('./splice/delete.cjs');
48
49
  var insert = require('./splice/insert.cjs');
49
50
  var replace = require('./splice/replace.cjs');
@@ -108,6 +109,7 @@ exports.isLastIndex = isLastIndex.isLastIndex;
108
109
  exports.select = select.select;
109
110
  exports.selectTools = select.selectTools;
110
111
  exports.lengthEqual = lengthEqual.lengthEqual;
112
+ exports.mapTuple = mapTuple.mapTuple;
111
113
  exports.spliceDelete = _delete.spliceDelete;
112
114
  exports.spliceInsert = insert.spliceInsert;
113
115
  exports.spliceReplace = replace.spliceReplace;
@@ -74,3 +74,4 @@ export * from "./insert";
74
74
  export * from "./isLastIndex";
75
75
  export * from "./select";
76
76
  export * from "./lengthEqual";
77
+ export * from "./mapTuple";
@@ -42,6 +42,7 @@ export { insert } from './insert.mjs';
42
42
  export { isLastIndex } from './isLastIndex.mjs';
43
43
  export { select, selectTools } from './select.mjs';
44
44
  export { lengthEqual } from './lengthEqual.mjs';
45
+ export { mapTuple } from './mapTuple.mjs';
45
46
  export { spliceDelete } from './splice/delete.mjs';
46
47
  export { spliceInsert } from './splice/insert.mjs';
47
48
  export { spliceReplace } from './splice/replace.mjs';
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ function mapTuple(...args) {
4
+ if (args.length === 1) {
5
+ const [theFunction] = args;
6
+ return (input) => mapTuple(input, theFunction);
7
+ }
8
+ const [input, theFunction] = args;
9
+ return input.map((element, index) => theFunction(element, {
10
+ index,
11
+ self: input,
12
+ }));
13
+ }
14
+
15
+ exports.mapTuple = mapTuple;
@@ -0,0 +1,45 @@
1
+ import type { MapTuple } from "./types";
2
+ interface ArrayMapTupleParams<GenericInputTuple extends readonly unknown[]> {
3
+ index: number;
4
+ self: GenericInputTuple;
5
+ }
6
+ /**
7
+ * Transforms each element of an array while preserving tuple length in types.
8
+ *
9
+ * **Supported call styles:**
10
+ * - Classic: `mapTuple(input, theFunction)` -> returns a new array
11
+ * - Curried: `mapTuple(theFunction)` -> returns a function waiting for the input
12
+ *
13
+ * The mapping function receives `(element, { index, self })`, where `index` is the element position and `self` is the original array.
14
+ * The input array is not mutated.
15
+ *
16
+ * ```ts
17
+ * A.mapTuple(
18
+ * <const>[1, 2, 3],
19
+ * (value) => value * 2,
20
+ * ); // [2, 4, 6]
21
+ *
22
+ * pipe(
23
+ * <const>["alpha", "beta"],
24
+ * A.mapTuple((value, { index }) => `${index}:${value}`),
25
+ * ); // ["0:alpha", "1:beta"]
26
+ *
27
+ * A.mapTuple(
28
+ * [10, 20, 30],
29
+ * (value, { self }) => value / self.length,
30
+ * ); // [3.333..., 6.666..., 10]
31
+ * ```
32
+ *
33
+ * @remarks
34
+ * - For tuple inputs (`as const`), the output keeps the same tuple length.
35
+ * - For non-tuple arrays, the output type is `GenericOutput[]`.
36
+ *
37
+ * @see [`A.map`](https://utils.duplojs.dev/en/v1/api/array/map) For generic array mapping
38
+ * @see https://utils.duplojs.dev/en/v1/api/array/mapTuple
39
+ *
40
+ * @namespace A
41
+ *
42
+ */
43
+ export declare function mapTuple<GenericInput extends readonly unknown[], GenericOutput extends unknown>(theFunction: (element: GenericInput[number], params: ArrayMapTupleParams<GenericInput>) => GenericOutput): (input: GenericInput) => MapTuple<GenericInput, GenericOutput>;
44
+ export declare function mapTuple<GenericInput extends readonly unknown[], GenericOutput extends unknown>(input: GenericInput, theFunction: (element: GenericInput[number], params: ArrayMapTupleParams<GenericInput>) => GenericOutput): MapTuple<GenericInput, GenericOutput>;
45
+ export {};
@@ -0,0 +1,13 @@
1
+ function mapTuple(...args) {
2
+ if (args.length === 1) {
3
+ const [theFunction] = args;
4
+ return (input) => mapTuple(input, theFunction);
5
+ }
6
+ const [input, theFunction] = args;
7
+ return input.map((element, index) => theFunction(element, {
8
+ index,
9
+ self: input,
10
+ }));
11
+ }
12
+
13
+ export { mapTuple };
@@ -1,5 +1,7 @@
1
1
  import { type RemoveFromUnion } from "../common";
2
- export type NotIncludeValue = string | null | undefined | boolean | number | bigint | symbol;
2
+ import { type MapTuple } from "./types";
3
+ type EligibleValue = string | null | undefined | boolean | number | bigint | symbol;
4
+ type TooLargeType = string | number | boolean | bigint | symbol;
3
5
  /**
4
6
  * Checks that an array does not include a value.
5
7
  *
@@ -41,5 +43,8 @@ export type NotIncludeValue = string | null | undefined | boolean | number | big
41
43
  * @namespace A
42
44
  *
43
45
  */
44
- export declare function notIncludes<GenericArrayValue extends unknown, const GenericNotIncludeValue extends RemoveFromUnion<Extract<GenericArrayValue, NotIncludeValue>, Exclude<NotIncludeValue, null | undefined>>>(value: GenericNotIncludeValue): (input: readonly GenericArrayValue[]) => input is Exclude<GenericArrayValue, GenericNotIncludeValue>[];
45
- export declare function notIncludes<GenericArrayValue extends unknown, const GenericNotIncludeValue extends RemoveFromUnion<Extract<GenericArrayValue, NotIncludeValue>, Exclude<NotIncludeValue, null | undefined>>>(input: readonly GenericArrayValue[], value: GenericNotIncludeValue): input is Exclude<GenericArrayValue, GenericNotIncludeValue>[];
46
+ export declare function notIncludes<GenericArray extends readonly unknown[], const GenericNotIncludeValue extends RemoveFromUnion<Extract<GenericArray[number], EligibleValue>, TooLargeType>>(value: GenericNotIncludeValue): (input: GenericArray) => input is MapTuple<GenericArray, Exclude<GenericArray[number], GenericNotIncludeValue>>;
47
+ export declare function notIncludes<GenericArray extends readonly unknown[]>(value: NoInfer<GenericArray[number]>): (input: GenericArray) => boolean;
48
+ export declare function notIncludes<GenericArray extends readonly unknown[], const GenericNotIncludeValue extends RemoveFromUnion<Extract<GenericArray[number], EligibleValue>, TooLargeType>>(input: GenericArray, value: GenericNotIncludeValue): input is MapTuple<GenericArray, Exclude<GenericArray[number], GenericNotIncludeValue>>;
49
+ export declare function notIncludes<GenericArray extends readonly unknown[]>(input: GenericArray, value: NoInfer<GenericArray[number]>): boolean;
50
+ export {};
@@ -9,3 +9,4 @@ export * from "./excludeTuple";
9
9
  export * from "./createTuple";
10
10
  export * from "./arrayCoalescing";
11
11
  export * from "./joinTuple";
12
+ export * from "./mapTuple";
@@ -0,0 +1 @@
1
+ export type MapTuple<GenericArray extends readonly unknown[], GenericOutput extends unknown> = GenericArray extends readonly [] ? [] : GenericArray extends readonly [infer _InferredFirst, ...infer InferredRest] ? MapTuple<InferredRest, GenericOutput> extends infer InferredResult extends readonly any[] ? [GenericOutput, ...InferredResult] : never : GenericOutput[];
@@ -0,0 +1,9 @@
1
+ import type { AnyFunction } from "./anyFunction";
2
+ /**
3
+ * @remarks allows you to bypass the `strictFunctionTypes` rule.
4
+ * @link https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-function-parameters-bivariant
5
+ * @link https://www.typescriptlang.org/tsconfig/#strictFunctionTypes
6
+ */
7
+ export type BivariantFunction<GenericFunction extends AnyFunction> = {
8
+ bivariantFunction(...args: Parameters<GenericFunction>): ReturnType<GenericFunction>;
9
+ }["bivariantFunction"];
@@ -46,3 +46,4 @@ export * from "./falsyValue";
46
46
  export * from "./DeepReadonly";
47
47
  export * from "./json";
48
48
  export * from "./predicate";
49
+ export * from "./bivariantFunction";
@@ -17,6 +17,7 @@ var isType = require('../../../common/isType.cjs');
17
17
  var map = require('../../../array/map.cjs');
18
18
  var concat = require('../../../string/concat.cjs');
19
19
  var flatMap = require('../../../array/flatMap.cjs');
20
+ var prepend = require('../../../string/prepend.cjs');
20
21
  var exhaustive = require('../../../pattern/exhaustive.cjs');
21
22
  var innerPipe = require('../../../common/innerPipe.cjs');
22
23
  var notIncludes = require('../../../array/notIncludes.cjs');
@@ -37,7 +38,7 @@ function findRecordRequiredKeyOnTemplateLiteralPart(templatePart) {
37
38
  isType.isType("number"),
38
39
  isType.isType("string"),
39
40
  isType.isType("undefined"),
40
- ]), innerPipe.innerPipe(when$1.when(isType.isType("bigint"), (value) => `${value}n`), String)), when.when(literal.literalKind.has, (value) => findRecordRequiredKey(value)), when.when(index.templateLiteralKind.has, (value) => findRecordRequiredKeyOnTemplateLiteralPart(value.definition.template)), when.when(boolean.booleanKind.has, justReturn.justReturn(["true", "false"])), when.when(empty.emptyKind.has, justReturn.justReturn("undefined")), when.when(nil.nilKind.has, justReturn.justReturn("null")), when.when(union.unionKind.has, (dataParser) => pipe.pipe(dataParser.definition.options, map.map((element) => findRecordRequiredKeyOnTemplateLiteralPart([element])), when.when(notIncludes.notIncludes(null), flat.flat), otherwise.otherwise(justReturn.justReturn(null)))), exhaustive.exhaustive)), reduce.reduce(reduce.reduceFrom([""]), ({ lastValue, element, exit, next }) => pipe.pipe(element, when.when(isType.isType("null"), justReturn.justReturn(exit(null))), when.when(isType.isType("string"), (element) => next(map.map(lastValue, (value) => concat.concat(value, element)))), when.when(isType.isType("array"), (elements) => next(flatMap.flatMap(lastValue, (value) => map.map(elements, (subValue) => concat.concat(value, subValue))))), exhaustive.exhaustive)));
41
+ ]), innerPipe.innerPipe(when$1.when(isType.isType("bigint"), (value) => `${value}n`), String)), when.when(literal.literalKind.has, (value) => findRecordRequiredKey(value)), when.when(index.templateLiteralKind.has, (value) => findRecordRequiredKeyOnTemplateLiteralPart(value.definition.template)), when.when(boolean.booleanKind.has, justReturn.justReturn(["true", "false"])), when.when(empty.emptyKind.has, justReturn.justReturn("undefined")), when.when(nil.nilKind.has, justReturn.justReturn("null")), when.when(union.unionKind.has, (dataParser) => pipe.pipe(dataParser.definition.options, map.map((element) => findRecordRequiredKeyOnTemplateLiteralPart([element])), when.when(notIncludes.notIncludes(null), flat.flat), otherwise.otherwise(justReturn.justReturn(null)))), exhaustive.exhaustive)), reduce.reduce(reduce.reduceFrom([""]), ({ lastValue, element, exit, next }) => pipe.pipe(element, when.when(isType.isType("null"), justReturn.justReturn(exit(null))), when.when(isType.isType("string"), (element) => next(map.map(lastValue, concat.concat(element)))), when.when(isType.isType("array"), (elements) => next(flatMap.flatMap(lastValue, (value) => map.map(elements, prepend.prepend(value))))), exhaustive.exhaustive)));
41
42
  }
42
43
  function findRecordRequiredKey(keyParser) {
43
44
  return pipe.pipe(keyParser, when.when((value) => index$1.stringKind.has(value) || index$2.numberKind.has(value), justReturn.justReturn(null)), when.when(literal.literalKind.has, (dataParser) => pipe.pipe(dataParser.definition.value, map.map(innerPipe.innerPipe(when$1.when(isType.isType("bigint"), (value) => `${value}n`), String)))), when.when(union.unionKind.has, (dataParser) => pipe.pipe(dataParser.definition.options, map.map(findRecordRequiredKey), when.when(includes.includes(null), justReturn.justReturn(null)), otherwise.otherwise(innerPipe.innerPipe(filter.filter(isType.isType("array")), flat.flat)))), when.when(index.templateLiteralKind.has, (dataParser) => findRecordRequiredKeyOnTemplateLiteralPart(dataParser.definition.template)), exhaustive.exhaustive);
@@ -15,6 +15,7 @@ import { isType } from '../../../common/isType.mjs';
15
15
  import { map } from '../../../array/map.mjs';
16
16
  import { concat } from '../../../string/concat.mjs';
17
17
  import { flatMap } from '../../../array/flatMap.mjs';
18
+ import { prepend } from '../../../string/prepend.mjs';
18
19
  import { exhaustive } from '../../../pattern/exhaustive.mjs';
19
20
  import { innerPipe } from '../../../common/innerPipe.mjs';
20
21
  import { notIncludes } from '../../../array/notIncludes.mjs';
@@ -35,7 +36,7 @@ function findRecordRequiredKeyOnTemplateLiteralPart(templatePart) {
35
36
  isType("number"),
36
37
  isType("string"),
37
38
  isType("undefined"),
38
- ]), innerPipe(when$1(isType("bigint"), (value) => `${value}n`), String)), when(literalKind.has, (value) => findRecordRequiredKey(value)), when(templateLiteralKind.has, (value) => findRecordRequiredKeyOnTemplateLiteralPart(value.definition.template)), when(booleanKind.has, justReturn(["true", "false"])), when(emptyKind.has, justReturn("undefined")), when(nilKind.has, justReturn("null")), when(unionKind.has, (dataParser) => pipe(dataParser.definition.options, map((element) => findRecordRequiredKeyOnTemplateLiteralPart([element])), when(notIncludes(null), flat), otherwise(justReturn(null)))), exhaustive)), reduce(reduceFrom([""]), ({ lastValue, element, exit, next }) => pipe(element, when(isType("null"), justReturn(exit(null))), when(isType("string"), (element) => next(map(lastValue, (value) => concat(value, element)))), when(isType("array"), (elements) => next(flatMap(lastValue, (value) => map(elements, (subValue) => concat(value, subValue))))), exhaustive)));
39
+ ]), innerPipe(when$1(isType("bigint"), (value) => `${value}n`), String)), when(literalKind.has, (value) => findRecordRequiredKey(value)), when(templateLiteralKind.has, (value) => findRecordRequiredKeyOnTemplateLiteralPart(value.definition.template)), when(booleanKind.has, justReturn(["true", "false"])), when(emptyKind.has, justReturn("undefined")), when(nilKind.has, justReturn("null")), when(unionKind.has, (dataParser) => pipe(dataParser.definition.options, map((element) => findRecordRequiredKeyOnTemplateLiteralPart([element])), when(notIncludes(null), flat), otherwise(justReturn(null)))), exhaustive)), reduce(reduceFrom([""]), ({ lastValue, element, exit, next }) => pipe(element, when(isType("null"), justReturn(exit(null))), when(isType("string"), (element) => next(map(lastValue, concat(element)))), when(isType("array"), (elements) => next(flatMap(lastValue, (value) => map(elements, prepend(value))))), exhaustive)));
39
40
  }
40
41
  function findRecordRequiredKey(keyParser) {
41
42
  return pipe(keyParser, when((value) => stringKind.has(value) || numberKind.has(value), justReturn(null)), when(literalKind.has, (dataParser) => pipe(dataParser.definition.value, map(innerPipe(when$1(isType("bigint"), (value) => `${value}n`), String)))), when(unionKind.has, (dataParser) => pipe(dataParser.definition.options, map(findRecordRequiredKey), when(includes(null), justReturn(null)), otherwise(innerPipe(filter(isType("array")), flat)))), when(templateLiteralKind.has, (dataParser) => findRecordRequiredKeyOnTemplateLiteralPart(dataParser.definition.template)), exhaustive);
@@ -84,6 +84,7 @@ var less = require('./operators/less.cjs');
84
84
  var lessThan = require('./operators/lessThan.cjs');
85
85
  var lessThanTime = require('./operators/lessThanTime.cjs');
86
86
  var lessTime = require('./operators/lessTime.cjs');
87
+ var equal = require('./operators/equal.cjs');
87
88
 
88
89
  /**
89
90
  * {@include date/index.md}
@@ -192,3 +193,4 @@ exports.less = less.less;
192
193
  exports.lessThan = lessThan.lessThan;
193
194
  exports.lessThanTime = lessThanTime.lessThanTime;
194
195
  exports.lessTime = lessTime.lessTime;
196
+ exports.equal = equal.equal;
@@ -82,6 +82,7 @@ export { less } from './operators/less.mjs';
82
82
  export { lessThan } from './operators/lessThan.mjs';
83
83
  export { lessThanTime } from './operators/lessThanTime.mjs';
84
84
  export { lessTime } from './operators/lessTime.mjs';
85
+ export { equal } from './operators/equal.mjs';
85
86
 
86
87
  /**
87
88
  * {@include date/index.md}
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ var toTimestamp = require('../toTimestamp.cjs');
4
+
5
+ function equal(...args) {
6
+ if (args.length === 1) {
7
+ const [second] = args;
8
+ return (first) => equal(first, second);
9
+ }
10
+ const [first, second] = args;
11
+ return toTimestamp.toTimestamp(first) === toTimestamp.toTimestamp(second);
12
+ }
13
+
14
+ exports.equal = equal;
@@ -0,0 +1,35 @@
1
+ import type { TheDate } from "../theDate";
2
+ import type { SerializedTheDate } from "../types";
3
+ /**
4
+ * Checks whether two dates point to the same timestamp.
5
+ *
6
+ * **Supported call styles:**
7
+ * - Classic: `equal(first, second)` -> `boolean`
8
+ * - Curried: `equal(second)` -> `(first) => boolean`
9
+ *
10
+ * All parameters accept `TheDate` or `SerializedTheDate`.
11
+ *
12
+ * ```ts
13
+ * const first = D.create("2024-06-20");
14
+ * const second = D.create("2024-06-20");
15
+ *
16
+ * if (D.equal(first, second)) {
17
+ * // is equal
18
+ * }
19
+ *
20
+ * const serialized = D.serialize(second);
21
+ * D.equal(first, serialized); // true
22
+ * ```
23
+ *
24
+ * @remarks
25
+ * - Equality is based on normalized timestamps.
26
+ *
27
+ * @see [`D.greater`](https://utils.duplojs.dev/en/v1/api/date/greater) For inclusive greater-than comparison
28
+ * @see [`D.less`](https://utils.duplojs.dev/en/v1/api/date/less) For inclusive less-than comparison
29
+ * @see https://utils.duplojs.dev/en/v1/api/date/equal
30
+ *
31
+ * @namespace D
32
+ *
33
+ */
34
+ export declare function equal(second: TheDate | SerializedTheDate): (first: TheDate | SerializedTheDate) => boolean;
35
+ export declare function equal(first: TheDate | SerializedTheDate, second: TheDate | SerializedTheDate): boolean;
@@ -0,0 +1,12 @@
1
+ import { toTimestamp } from '../toTimestamp.mjs';
2
+
3
+ function equal(...args) {
4
+ if (args.length === 1) {
5
+ const [second] = args;
6
+ return (first) => equal(first, second);
7
+ }
8
+ const [first, second] = args;
9
+ return toTimestamp(first) === toTimestamp(second);
10
+ }
11
+
12
+ export { equal };
@@ -28,3 +28,4 @@ export * from "./less";
28
28
  export * from "./lessThan";
29
29
  export * from "./lessThanTime";
30
30
  export * from "./lessTime";
31
+ export * from "./equal";
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ const exitExternalAsync = Symbol("exitExternalAsync");
4
+ /**
5
+ * {@include generator/createExternalAsyncGenerator/index.md}
6
+ */
7
+ function createExternalAsyncGenerator() {
8
+ let externalResolve = undefined;
9
+ return {
10
+ asyncGenerator: (async function* () {
11
+ const result = await new Promise((resolve) => {
12
+ externalResolve = resolve;
13
+ });
14
+ if (result === exitExternalAsync) {
15
+ return;
16
+ }
17
+ else {
18
+ yield result;
19
+ }
20
+ })(),
21
+ next: (value) => void externalResolve?.(value),
22
+ exit: () => void externalResolve?.(exitExternalAsync),
23
+ };
24
+ }
25
+
26
+ exports.createExternalAsyncGenerator = createExternalAsyncGenerator;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Creates an externally controlled async generator that emits at most one value.
3
+ *
4
+ * Signature: `createExternalAsyncGenerator()` -> returns `{ asyncGenerator, next, exit }`
5
+ *
6
+ * Use `next(value)` to resolve the pending iteration with a value, or `exit()` to stop it without yielding.
7
+ *
8
+ * ```ts
9
+ * const first = G.createExternalAsyncGenerator<number>();
10
+ * const firstPending = first.asyncGenerator.next();
11
+ * first.next(42);
12
+ * const firstResult = await firstPending;
13
+ * // firstResult: { done: false, value: 42 }
14
+ *
15
+ * const second = G.createExternalAsyncGenerator<string>();
16
+ * const secondPending = second.asyncGenerator.next();
17
+ * second.exit();
18
+ * const secondResult = await secondPending;
19
+ * // secondResult: { done: true, value: undefined }
20
+ *
21
+ * const third = G.createExternalAsyncGenerator<string>();
22
+ * const collected: string[] = [];
23
+ * const consume = (async() => {
24
+ * for await (const value of third.asyncGenerator) {
25
+ * collected.push(value);
26
+ * }
27
+ * })();
28
+ * third.next("hello");
29
+ * await consume;
30
+ * // collected: ["hello"]
31
+ * ```
32
+ *
33
+ * @remarks
34
+ * - The returned async generator waits for one external resolution.
35
+ * - The first call to `next` or `exit` settles that pending resolution.
36
+ *
37
+ * @see https://utils.duplojs.dev/en/v1/api/generator/createExternalAsyncGenerator
38
+ *
39
+ * @namespace G
40
+ *
41
+ */
42
+ export declare function createExternalAsyncGenerator<GenericValue extends unknown>(): {
43
+ asyncGenerator: AsyncGenerator<Awaited<GenericValue>, void, unknown>;
44
+ next: (value: GenericValue) => undefined;
45
+ exit: () => undefined;
46
+ };
@@ -0,0 +1,24 @@
1
+ const exitExternalAsync = Symbol("exitExternalAsync");
2
+ /**
3
+ * {@include generator/createExternalAsyncGenerator/index.md}
4
+ */
5
+ function createExternalAsyncGenerator() {
6
+ let externalResolve = undefined;
7
+ return {
8
+ asyncGenerator: (async function* () {
9
+ const result = await new Promise((resolve) => {
10
+ externalResolve = resolve;
11
+ });
12
+ if (result === exitExternalAsync) {
13
+ return;
14
+ }
15
+ else {
16
+ yield result;
17
+ }
18
+ })(),
19
+ next: (value) => void externalResolve?.(value),
20
+ exit: () => void externalResolve?.(exitExternalAsync),
21
+ };
22
+ }
23
+
24
+ export { createExternalAsyncGenerator };
@@ -13,6 +13,7 @@ var chunk = require('./chunk.cjs');
13
13
  var asyncChunk = require('./asyncChunk.cjs');
14
14
  var group = require('./group.cjs');
15
15
  var asyncGroup = require('./asyncGroup.cjs');
16
+ var createExternalAsyncGenerator = require('./createExternalAsyncGenerator.cjs');
16
17
 
17
18
  /**
18
19
  * {@include generator/index.md}
@@ -33,3 +34,4 @@ exports.asyncChunk = asyncChunk.asyncChunk;
33
34
  exports.group = group.group;
34
35
  exports.groupOutput = group.groupOutput;
35
36
  exports.asyncGroup = asyncGroup.asyncGroup;
37
+ exports.createExternalAsyncGenerator = createExternalAsyncGenerator.createExternalAsyncGenerator;
@@ -38,3 +38,4 @@ export * from "./chunk";
38
38
  export * from "./asyncChunk";
39
39
  export * from "./group";
40
40
  export * from "./asyncGroup";
41
+ export * from "./createExternalAsyncGenerator";
@@ -11,6 +11,7 @@ export { chunk } from './chunk.mjs';
11
11
  export { asyncChunk } from './asyncChunk.mjs';
12
12
  export { group, groupOutput } from './group.mjs';
13
13
  export { asyncGroup } from './asyncGroup.mjs';
14
+ export { createExternalAsyncGenerator } from './createExternalAsyncGenerator.mjs';
14
15
 
15
16
  /**
16
17
  * {@include generator/index.md}
@@ -159,6 +159,9 @@
159
159
  {
160
160
  "name": "joinTuple.d.ts"
161
161
  },
162
+ {
163
+ "name": "mapTuple.d.ts"
164
+ },
162
165
  {
163
166
  "name": "mergeUnionTuple.d.ts"
164
167
  },
@@ -410,6 +413,15 @@
410
413
  {
411
414
  "name": "map.mjs"
412
415
  },
416
+ {
417
+ "name": "mapTuple.cjs"
418
+ },
419
+ {
420
+ "name": "mapTuple.d.ts"
421
+ },
422
+ {
423
+ "name": "mapTuple.mjs"
424
+ },
413
425
  {
414
426
  "name": "maxElements.cjs"
415
427
  },
@@ -1070,6 +1082,9 @@
1070
1082
  {
1071
1083
  "name": "anyValue.d.ts"
1072
1084
  },
1085
+ {
1086
+ "name": "bivariantFunction.d.ts"
1087
+ },
1073
1088
  {
1074
1089
  "name": "breakGenericLink.d.ts"
1075
1090
  },
@@ -2890,6 +2905,15 @@
2890
2905
  {
2891
2906
  "name": "betweenTime.mjs"
2892
2907
  },
2908
+ {
2909
+ "name": "equal.cjs"
2910
+ },
2911
+ {
2912
+ "name": "equal.d.ts"
2913
+ },
2914
+ {
2915
+ "name": "equal.mjs"
2916
+ },
2893
2917
  {
2894
2918
  "name": "greater.cjs"
2895
2919
  },
@@ -3944,6 +3968,15 @@
3944
3968
  {
3945
3969
  "name": "chunk.mjs"
3946
3970
  },
3971
+ {
3972
+ "name": "createExternalAsyncGenerator.cjs"
3973
+ },
3974
+ {
3975
+ "name": "createExternalAsyncGenerator.d.ts"
3976
+ },
3977
+ {
3978
+ "name": "createExternalAsyncGenerator.mjs"
3979
+ },
3947
3980
  {
3948
3981
  "name": "execute.cjs"
3949
3982
  },
@@ -4808,9 +4841,15 @@
4808
4841
  {
4809
4842
  "name": "number.d.ts"
4810
4843
  },
4844
+ {
4845
+ "name": "pop.d.ts"
4846
+ },
4811
4847
  {
4812
4848
  "name": "replace.d.ts"
4813
4849
  },
4850
+ {
4851
+ "name": "shift.d.ts"
4852
+ },
4814
4853
  {
4815
4854
  "name": "split.d.ts"
4816
4855
  },
@@ -4987,6 +5026,24 @@
4987
5026
  {
4988
5027
  "name": "padStart.mjs"
4989
5028
  },
5029
+ {
5030
+ "name": "pop.cjs"
5031
+ },
5032
+ {
5033
+ "name": "pop.d.ts"
5034
+ },
5035
+ {
5036
+ "name": "pop.mjs"
5037
+ },
5038
+ {
5039
+ "name": "prepend.cjs"
5040
+ },
5041
+ {
5042
+ "name": "prepend.d.ts"
5043
+ },
5044
+ {
5045
+ "name": "prepend.mjs"
5046
+ },
4990
5047
  {
4991
5048
  "name": "repeat.cjs"
4992
5049
  },
@@ -5023,6 +5080,15 @@
5023
5080
  {
5024
5081
  "name": "search.mjs"
5025
5082
  },
5083
+ {
5084
+ "name": "shift.cjs"
5085
+ },
5086
+ {
5087
+ "name": "shift.d.ts"
5088
+ },
5089
+ {
5090
+ "name": "shift.mjs"
5091
+ },
5026
5092
  {
5027
5093
  "name": "slice.cjs"
5028
5094
  },
@@ -1,5 +1,3 @@
1
1
  import type * as DString from "../../string";
2
- import type * as DArray from "../../array";
3
- import { type AnyTuple, type Adaptor } from "../../common";
4
2
  import { type IsPositive } from "./isPositive";
5
- export type Absolute<GenericValue extends number> = IsPositive<GenericValue> extends true ? GenericValue : DArray.JoinTuple<DArray.ShiftTuple<Adaptor<DString.Split<`${GenericValue}`, "">, AnyTuple<string>>>, ""> extends `${infer InferredResult extends number}` ? InferredResult : never;
3
+ export type Absolute<GenericValue extends number> = IsPositive<GenericValue> extends true ? GenericValue : DString.Shift<`${GenericValue}`> extends `${infer InferredResult extends number}` ? InferredResult : never;
@@ -32,6 +32,9 @@ var sortCompare = require('./sortCompare.cjs');
32
32
  var to = require('./to.cjs');
33
33
  var extract = require('./extract.cjs');
34
34
  var extractAll = require('./extractAll.cjs');
35
+ var shift = require('./shift.cjs');
36
+ var pop = require('./pop.cjs');
37
+ var prepend = require('./prepend.cjs');
35
38
  var _default = require('./at/default.cjs');
36
39
  var first = require('./at/first.cjs');
37
40
  var last = require('./at/last.cjs');
@@ -75,6 +78,9 @@ exports.sortCompare = sortCompare.sortCompare;
75
78
  exports.to = to.to;
76
79
  exports.extract = extract.extract;
77
80
  exports.extractAll = extractAll.extractAll;
81
+ exports.shift = shift.shift;
82
+ exports.pop = pop.pop;
83
+ exports.prepend = prepend.prepend;
78
84
  exports.at = _default.at;
79
85
  exports.first = first.first;
80
86
  exports.last = last.last;
@@ -60,3 +60,6 @@ export * from "./sortCompare";
60
60
  export * from "./to";
61
61
  export * from "./extract";
62
62
  export * from "./extractAll";
63
+ export * from "./shift";
64
+ export * from "./pop";
65
+ export * from "./prepend";
@@ -30,6 +30,9 @@ export { sortCompare } from './sortCompare.mjs';
30
30
  export { to } from './to.mjs';
31
31
  export { extract } from './extract.mjs';
32
32
  export { extractAll } from './extractAll.mjs';
33
+ export { shift } from './shift.mjs';
34
+ export { pop } from './pop.mjs';
35
+ export { prepend } from './prepend.mjs';
33
36
  export { at } from './at/default.mjs';
34
37
  export { first } from './at/first.mjs';
35
38
  export { last } from './at/last.mjs';
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * {@include string/pop/index.md}
5
+ */
6
+ function pop(input) {
7
+ return input.slice(0, -1);
8
+ }
9
+
10
+ exports.pop = pop;
@@ -0,0 +1,26 @@
1
+ import type { Pop } from "./types";
2
+ /**
3
+ * Removes the last character from a string.
4
+ *
5
+ * Signature: `pop(input)` -> returns a new string
6
+ *
7
+ * The input string is not mutated.
8
+ *
9
+ * ```ts
10
+ * S.pop("Duplo"); // "Dupl"
11
+ *
12
+ * S.pop("A"); // ""
13
+ *
14
+ * S.pop(""); // ""
15
+ * ```
16
+ *
17
+ * @remarks
18
+ * - Type-safe with literal strings: return type removes the last character when possible.
19
+ *
20
+ * @see [`S.shift`](https://utils.duplojs.dev/en/v1/api/string/shift) For removing the first character
21
+ * @see https://utils.duplojs.dev/en/v1/api/string/pop
22
+ *
23
+ * @namespace S
24
+ *
25
+ */
26
+ export declare function pop<GenericInput extends string>(input: GenericInput): Pop<GenericInput>;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * {@include string/pop/index.md}
3
+ */
4
+ function pop(input) {
5
+ return input.slice(0, -1);
6
+ }
7
+
8
+ export { pop };
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ function prepend(...args) {
4
+ if (args.length === 1) {
5
+ const [text] = args;
6
+ return (input) => prepend(input, text);
7
+ }
8
+ const [input, ...textsRest] = args;
9
+ return "".concat(...textsRest, input);
10
+ }
11
+
12
+ exports.prepend = prepend;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Prepends one or more strings to an input string.
3
+ *
4
+ * **Supported call styles:**
5
+ * - Classic: `prepend(input, text, ...textsRest)` -> returns a new string
6
+ * - Curried: `prepend(text)` -> returns a function waiting for the input
7
+ *
8
+ * The input string is not mutated.
9
+ *
10
+ * ```ts
11
+ * S.prepend(
12
+ * "Utils",
13
+ * "Duplo",
14
+ * "JS ",
15
+ * ); // "DuploJS Utils"
16
+ *
17
+ * pipe(
18
+ * "world",
19
+ * S.prepend("hello "),
20
+ * ); // "hello world"
21
+ *
22
+ * S.prepend(
23
+ * "value",
24
+ * "[",
25
+ * "] ",
26
+ * ); // "[] value"
27
+ * ```
28
+ *
29
+ * @remarks
30
+ * - Classic style supports multiple prefix strings with rest parameters.
31
+ * - Curried style prepends a single `text` value.
32
+ *
33
+ * @see https://utils.duplojs.dev/en/v1/api/string/prepend
34
+ * @see [`S.concat`](https://utils.duplojs.dev/en/v1/api/string/concat) For appending strings
35
+ *
36
+ * @namespace S
37
+ *
38
+ */
39
+ export declare function prepend(text: string): (input: string) => string;
40
+ export declare function prepend(input: string, ...textsRest: string[]): string;
@@ -0,0 +1,10 @@
1
+ function prepend(...args) {
2
+ if (args.length === 1) {
3
+ const [text] = args;
4
+ return (input) => prepend(input, text);
5
+ }
6
+ const [input, ...textsRest] = args;
7
+ return "".concat(...textsRest, input);
8
+ }
9
+
10
+ export { prepend };
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * {@include string/shift/index.md}
5
+ */
6
+ function shift(input) {
7
+ return input.slice(1);
8
+ }
9
+
10
+ exports.shift = shift;
@@ -0,0 +1,26 @@
1
+ import type { Shift } from "./types";
2
+ /**
3
+ * Removes the first character from a string.
4
+ *
5
+ * Signature: `shift(input)` -> returns a new string
6
+ *
7
+ * The input string is not mutated.
8
+ *
9
+ * ```ts
10
+ * S.shift("Duplo"); // "uplo"
11
+ *
12
+ * S.shift("A"); // ""
13
+ *
14
+ * S.shift(""); // ""
15
+ * ```
16
+ *
17
+ * @remarks
18
+ * - Type-safe with literal strings: return type removes the first character when possible.
19
+ *
20
+ * @see [`S.pop`](https://utils.duplojs.dev/en/v1/api/string/pop) For removing the last character
21
+ * @see https://utils.duplojs.dev/en/v1/api/string/shift
22
+ *
23
+ * @namespace S
24
+ *
25
+ */
26
+ export declare function shift<GenericInput extends string>(input: GenericInput): Shift<GenericInput>;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * {@include string/shift/index.md}
3
+ */
4
+ function shift(input) {
5
+ return input.slice(1);
6
+ }
7
+
8
+ export { shift };
@@ -11,3 +11,5 @@ export * from "./number";
11
11
  export * from "./digit";
12
12
  export * from "./templateLiteralContainLargeType";
13
13
  export * from "./replace";
14
+ export * from "./shift";
15
+ export * from "./pop";
@@ -0,0 +1,3 @@
1
+ import type { IsEqual } from "../../common";
2
+ import type { TemplateLiteralContainLargeType } from "./templateLiteralContainLargeType";
3
+ export type Pop<GenericValue extends string> = TemplateLiteralContainLargeType<GenericValue> extends true ? string : IsEqual<GenericValue, ""> extends true ? "" : GenericValue extends `${infer InferredFirst}${infer InferredRest}` ? IsEqual<InferredRest, ""> extends true ? "" : Pop<InferredRest> extends infer InferredResult extends string ? `${InferredFirst}${InferredResult}` : never : string;
@@ -0,0 +1,3 @@
1
+ import type { IsEqual } from "../../common";
2
+ import type { TemplateLiteralContainLargeType } from "./templateLiteralContainLargeType";
3
+ export type Shift<GenericValue extends string> = TemplateLiteralContainLargeType<GenericValue> extends true ? string : IsEqual<GenericValue, ""> extends true ? "" : GenericValue extends `${infer _InferredFirst}${infer InferredRest}` ? InferredRest : string;
@@ -1,6 +1,7 @@
1
1
  import { type Or, type IsEqual } from "../../common";
2
2
  import { type Includes } from "./includes";
3
- export type Split<GenericString extends string, GenericSeparator extends string, GenericLimit extends number = number, GenericLastResult extends string[] = []> = Or<[
4
- IsEqual<GenericString, string>,
5
- IsEqual<GenericSeparator, string>
6
- ]> extends true ? string[] : GenericString extends `${infer InferredBefore}${GenericSeparator}${infer InferredAfter}` ? [...GenericLastResult, InferredBefore] extends infer InferredResult extends any[] ? IsEqual<InferredAfter, ""> extends true ? InferredResult : IsEqual<InferredResult["length"], 250> extends true ? Includes<InferredAfter, GenericSeparator> extends true ? [...InferredResult, ...string[]] : InferredResult : IsEqual<InferredResult["length"], GenericLimit> extends true ? InferredResult : Split<InferredAfter, GenericSeparator, GenericLimit, InferredResult> : never : [...GenericLastResult, GenericString];
3
+ import { type TemplateLiteralContainLargeType } from "./templateLiteralContainLargeType";
4
+ export type Split<GenericString extends string, GenericSeparator extends string, GenericLimit extends number = number, GenericLastResult extends string[] = []> = IsEqual<GenericLimit, 0> extends true ? [] : Or<[
5
+ TemplateLiteralContainLargeType<GenericString>,
6
+ TemplateLiteralContainLargeType<GenericSeparator>
7
+ ]> extends true ? [string, ...string[]] : GenericString extends `${infer InferredBefore}${GenericSeparator}${infer InferredAfter}` ? [...GenericLastResult, InferredBefore] extends infer InferredResult extends any[] ? IsEqual<InferredAfter, ""> extends true ? InferredResult : IsEqual<InferredResult["length"], 250> extends true ? Includes<InferredAfter, GenericSeparator> extends true ? [...InferredResult, ...string[]] : InferredResult : IsEqual<InferredResult["length"], GenericLimit> extends true ? InferredResult : Split<InferredAfter, GenericSeparator, GenericLimit, InferredResult> : never : [...GenericLastResult, GenericString];
@@ -1,5 +1,6 @@
1
1
  import { type IsEqual, type Or } from "../../common";
2
2
  export type TemplateLiteralContainLargeType<GenericValue extends string> = (GenericValue extends `${infer InferredFirst}${infer InferredLast}` ? Or<[
3
3
  IsEqual<InferredFirst, `${number}`>,
4
- IsEqual<InferredFirst, `${bigint}`>
4
+ IsEqual<InferredFirst, `${bigint}`>,
5
+ IsEqual<InferredFirst, string>
5
6
  ]> extends false ? TemplateLiteralContainLargeType<InferredLast> : true : GenericValue extends "" ? false : true) extends false ? false : true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duplojs/utils",
3
- "version": "1.5.9",
3
+ "version": "1.5.10",
4
4
  "author": {
5
5
  "name": "mathcovax",
6
6
  "url": "https://github.com/mathcovax"