functional-examples 0.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -0
- package/dist/cli/commands/generate.d.ts +10 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +64 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +14 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +95 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/scan.d.ts +20 -0
- package/dist/cli/commands/scan.d.ts.map +1 -0
- package/dist/cli/commands/scan.js +182 -0
- package/dist/cli/commands/scan.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +10 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +65 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/index.d.ts +88 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +43 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/plugin-commands.d.ts +17 -0
- package/dist/cli/plugin-commands.d.ts.map +1 -0
- package/dist/cli/plugin-commands.js +45 -0
- package/dist/cli/plugin-commands.js.map +1 -0
- package/dist/config/index.d.ts +11 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +9 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/index.spec.d.ts +5 -0
- package/dist/config/index.spec.d.ts.map +1 -0
- package/dist/config/index.spec.js +142 -0
- package/dist/config/index.spec.js.map +1 -0
- package/dist/config/loader.d.ts +7 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +85 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/merger.d.ts +27 -0
- package/dist/config/merger.d.ts.map +1 -0
- package/dist/config/merger.js +41 -0
- package/dist/config/merger.js.map +1 -0
- package/dist/config/resolver.d.ts +28 -0
- package/dist/config/resolver.d.ts.map +1 -0
- package/dist/config/resolver.js +165 -0
- package/dist/config/resolver.js.map +1 -0
- package/dist/config/schema.d.ts +53 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +42 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/types.d.ts +17 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +5 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/validator.d.ts +6 -0
- package/dist/config/validator.d.ts.map +1 -0
- package/dist/config/validator.js +17 -0
- package/dist/config/validator.js.map +1 -0
- package/dist/extractors/index.d.ts +9 -0
- package/dist/extractors/index.d.ts.map +1 -0
- package/dist/extractors/index.js +9 -0
- package/dist/extractors/index.js.map +1 -0
- package/dist/extractors/loader.d.ts +19 -0
- package/dist/extractors/loader.d.ts.map +1 -0
- package/dist/extractors/loader.js +120 -0
- package/dist/extractors/loader.js.map +1 -0
- package/dist/extractors/meta-yml-fn.d.ts +19 -0
- package/dist/extractors/meta-yml-fn.d.ts.map +1 -0
- package/dist/extractors/meta-yml-fn.js +66 -0
- package/dist/extractors/meta-yml-fn.js.map +1 -0
- package/dist/extractors/meta-yml.d.ts +24 -0
- package/dist/extractors/meta-yml.d.ts.map +1 -0
- package/dist/extractors/meta-yml.js +65 -0
- package/dist/extractors/meta-yml.js.map +1 -0
- package/dist/extractors/registry.d.ts +58 -0
- package/dist/extractors/registry.d.ts.map +1 -0
- package/dist/extractors/registry.js +114 -0
- package/dist/extractors/registry.js.map +1 -0
- package/dist/extractors/registry.spec.d.ts +2 -0
- package/dist/extractors/registry.spec.d.ts.map +1 -0
- package/dist/extractors/registry.spec.js +102 -0
- package/dist/extractors/registry.spec.js.map +1 -0
- package/dist/extractors/types.d.ts +34 -0
- package/dist/extractors/types.d.ts.map +1 -0
- package/dist/extractors/types.js +8 -0
- package/dist/extractors/types.js.map +1 -0
- package/dist/extractors/yaml-frontmatter-fn.d.ts +18 -0
- package/dist/extractors/yaml-frontmatter-fn.d.ts.map +1 -0
- package/dist/extractors/yaml-frontmatter-fn.js +73 -0
- package/dist/extractors/yaml-frontmatter-fn.js.map +1 -0
- package/dist/extractors/yaml-frontmatter.d.ts +22 -0
- package/dist/extractors/yaml-frontmatter.d.ts.map +1 -0
- package/dist/extractors/yaml-frontmatter.js +83 -0
- package/dist/extractors/yaml-frontmatter.js.map +1 -0
- package/dist/extractors/yaml-frontmatter.spec.d.ts +2 -0
- package/dist/extractors/yaml-frontmatter.spec.d.ts.map +1 -0
- package/dist/extractors/yaml-frontmatter.spec.js +134 -0
- package/dist/extractors/yaml-frontmatter.spec.js.map +1 -0
- package/dist/files/index.d.ts +5 -0
- package/dist/files/index.d.ts.map +1 -0
- package/dist/files/index.js +5 -0
- package/dist/files/index.js.map +1 -0
- package/dist/files/reader.d.ts +50 -0
- package/dist/files/reader.d.ts.map +1 -0
- package/dist/files/reader.js +62 -0
- package/dist/files/reader.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/index.d.ts +4 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +4 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/pipeline.d.ts +11 -0
- package/dist/plugins/pipeline.d.ts.map +1 -0
- package/dist/plugins/pipeline.js +24 -0
- package/dist/plugins/pipeline.js.map +1 -0
- package/dist/plugins/registry.d.ts +57 -0
- package/dist/plugins/registry.d.ts.map +1 -0
- package/dist/plugins/registry.js +93 -0
- package/dist/plugins/registry.js.map +1 -0
- package/dist/plugins/validation.d.ts +64 -0
- package/dist/plugins/validation.d.ts.map +1 -0
- package/dist/plugins/validation.js +55 -0
- package/dist/plugins/validation.js.map +1 -0
- package/dist/regions/index.d.ts +7 -0
- package/dist/regions/index.d.ts.map +1 -0
- package/dist/regions/index.js +6 -0
- package/dist/regions/index.js.map +1 -0
- package/dist/regions/languages.d.ts +15 -0
- package/dist/regions/languages.d.ts.map +1 -0
- package/dist/regions/languages.js +182 -0
- package/dist/regions/languages.js.map +1 -0
- package/dist/regions/parser.d.ts +63 -0
- package/dist/regions/parser.d.ts.map +1 -0
- package/dist/regions/parser.js +175 -0
- package/dist/regions/parser.js.map +1 -0
- package/dist/regions/parser.spec.d.ts +2 -0
- package/dist/regions/parser.spec.d.ts.map +1 -0
- package/dist/regions/parser.spec.js +190 -0
- package/dist/regions/parser.spec.js.map +1 -0
- package/dist/regions/types.d.ts +37 -0
- package/dist/regions/types.d.ts.map +1 -0
- package/dist/regions/types.js +5 -0
- package/dist/regions/types.js.map +1 -0
- package/dist/scanner/candidates.d.ts +24 -0
- package/dist/scanner/candidates.d.ts.map +1 -0
- package/dist/scanner/candidates.js +83 -0
- package/dist/scanner/candidates.js.map +1 -0
- package/dist/scanner/index.d.ts +8 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +6 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/scan.d.ts +40 -0
- package/dist/scanner/scan.d.ts.map +1 -0
- package/dist/scanner/scan.js +44 -0
- package/dist/scanner/scan.js.map +1 -0
- package/dist/scanner/scanner.d.ts +29 -0
- package/dist/scanner/scanner.d.ts.map +1 -0
- package/dist/scanner/scanner.js +296 -0
- package/dist/scanner/scanner.js.map +1 -0
- package/dist/scanner/scanner.spec.d.ts +2 -0
- package/dist/scanner/scanner.spec.d.ts.map +1 -0
- package/dist/scanner/scanner.spec.js +262 -0
- package/dist/scanner/scanner.spec.js.map +1 -0
- package/dist/scanner/types.d.ts +43 -0
- package/dist/scanner/types.d.ts.map +1 -0
- package/dist/scanner/types.js +5 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/schema/index.d.ts +4 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +4 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/merger.d.ts +35 -0
- package/dist/schema/merger.d.ts.map +1 -0
- package/dist/schema/merger.js +161 -0
- package/dist/schema/merger.js.map +1 -0
- package/dist/schema/typegen.d.ts +13 -0
- package/dist/schema/typegen.d.ts.map +1 -0
- package/dist/schema/typegen.js +125 -0
- package/dist/schema/typegen.js.map +1 -0
- package/dist/schema/validator.d.ts +7 -0
- package/dist/schema/validator.d.ts.map +1 -0
- package/dist/schema/validator.js +32 -0
- package/dist/schema/validator.js.map +1 -0
- package/dist/types/default-map.d.ts +21 -0
- package/dist/types/default-map.d.ts.map +1 -0
- package/dist/types/default-map.js +32 -0
- package/dist/types/default-map.js.map +1 -0
- package/dist/types/extended-iterable.d.ts +197 -0
- package/dist/types/extended-iterable.d.ts.map +1 -0
- package/dist/types/extended-iterable.js +769 -0
- package/dist/types/extended-iterable.js.map +1 -0
- package/dist/types/guards.d.ts +2 -0
- package/dist/types/guards.d.ts.map +1 -0
- package/dist/types/guards.js +2 -0
- package/dist/types/guards.js.map +1 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,769 @@
|
|
|
1
|
+
// Shared done sentinel to reduce allocations
|
|
2
|
+
const DONE = { done: true, value: undefined };
|
|
3
|
+
// --- Sync iterator classes ---
|
|
4
|
+
// Classes give V8 stable hidden classes and monomorphic inline caches on next(),
|
|
5
|
+
// which outperforms plain object factories on chained operations.
|
|
6
|
+
class MapIterator {
|
|
7
|
+
source;
|
|
8
|
+
fn;
|
|
9
|
+
r = { done: false, value: undefined };
|
|
10
|
+
constructor(source, fn) {
|
|
11
|
+
this.source = source;
|
|
12
|
+
this.fn = fn;
|
|
13
|
+
}
|
|
14
|
+
next() {
|
|
15
|
+
const result = this.source.next();
|
|
16
|
+
if (result.done)
|
|
17
|
+
return DONE;
|
|
18
|
+
this.r.value = this.fn(result.value);
|
|
19
|
+
return this.r;
|
|
20
|
+
}
|
|
21
|
+
[Symbol.iterator]() {
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
class FilterIterator {
|
|
26
|
+
source;
|
|
27
|
+
fn;
|
|
28
|
+
r = { done: false, value: undefined };
|
|
29
|
+
constructor(source, fn) {
|
|
30
|
+
this.source = source;
|
|
31
|
+
this.fn = fn;
|
|
32
|
+
}
|
|
33
|
+
next() {
|
|
34
|
+
while (true) {
|
|
35
|
+
const result = this.source.next();
|
|
36
|
+
if (result.done)
|
|
37
|
+
return DONE;
|
|
38
|
+
if (this.fn(result.value)) {
|
|
39
|
+
this.r.value = result.value;
|
|
40
|
+
return this.r;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
[Symbol.iterator]() {
|
|
45
|
+
return this;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
class TakeIterator {
|
|
49
|
+
source;
|
|
50
|
+
n;
|
|
51
|
+
r = { done: false, value: undefined };
|
|
52
|
+
count = 0;
|
|
53
|
+
constructor(source, n) {
|
|
54
|
+
this.source = source;
|
|
55
|
+
this.n = n;
|
|
56
|
+
}
|
|
57
|
+
next() {
|
|
58
|
+
if (this.count >= this.n)
|
|
59
|
+
return DONE;
|
|
60
|
+
const result = this.source.next();
|
|
61
|
+
if (result.done)
|
|
62
|
+
return DONE;
|
|
63
|
+
this.count++;
|
|
64
|
+
this.r.value = result.value;
|
|
65
|
+
return this.r;
|
|
66
|
+
}
|
|
67
|
+
[Symbol.iterator]() {
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
class FlatIterator {
|
|
72
|
+
source;
|
|
73
|
+
r = { done: false, value: undefined };
|
|
74
|
+
inner = null;
|
|
75
|
+
constructor(source) {
|
|
76
|
+
this.source = source;
|
|
77
|
+
}
|
|
78
|
+
next() {
|
|
79
|
+
while (true) {
|
|
80
|
+
if (this.inner) {
|
|
81
|
+
const result = this.inner.next();
|
|
82
|
+
if (!result.done) {
|
|
83
|
+
this.r.value = result.value;
|
|
84
|
+
return this.r;
|
|
85
|
+
}
|
|
86
|
+
this.inner = null;
|
|
87
|
+
}
|
|
88
|
+
const result = this.source.next();
|
|
89
|
+
if (result.done)
|
|
90
|
+
return DONE;
|
|
91
|
+
const value = result.value;
|
|
92
|
+
if (value != null &&
|
|
93
|
+
typeof value !== 'string' &&
|
|
94
|
+
typeof value[Symbol.iterator] === 'function') {
|
|
95
|
+
this.inner = value[Symbol.iterator]();
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
this.r.value = value;
|
|
99
|
+
return this.r;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
[Symbol.iterator]() {
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
class PrefixIterator {
|
|
108
|
+
source;
|
|
109
|
+
prefixIt;
|
|
110
|
+
constructor(prefix, source) {
|
|
111
|
+
this.source = source;
|
|
112
|
+
this.prefixIt = prefix[Symbol.iterator]();
|
|
113
|
+
}
|
|
114
|
+
next() {
|
|
115
|
+
if (this.prefixIt) {
|
|
116
|
+
const result = this.prefixIt.next();
|
|
117
|
+
if (!result.done)
|
|
118
|
+
return result;
|
|
119
|
+
this.prefixIt = null;
|
|
120
|
+
}
|
|
121
|
+
return this.source.next();
|
|
122
|
+
}
|
|
123
|
+
[Symbol.iterator]() {
|
|
124
|
+
return this;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// --- Async iterator classes ---
|
|
128
|
+
class AsyncMapIterator {
|
|
129
|
+
source;
|
|
130
|
+
fn;
|
|
131
|
+
constructor(source, fn) {
|
|
132
|
+
this.source = source;
|
|
133
|
+
this.fn = fn;
|
|
134
|
+
}
|
|
135
|
+
async next() {
|
|
136
|
+
const result = await this.source.next();
|
|
137
|
+
if (result.done)
|
|
138
|
+
return DONE;
|
|
139
|
+
return { done: false, value: await this.fn(result.value) };
|
|
140
|
+
}
|
|
141
|
+
[Symbol.asyncIterator]() {
|
|
142
|
+
return this;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
class AsyncFilterIterator {
|
|
146
|
+
source;
|
|
147
|
+
fn;
|
|
148
|
+
constructor(source, fn) {
|
|
149
|
+
this.source = source;
|
|
150
|
+
this.fn = fn;
|
|
151
|
+
}
|
|
152
|
+
async next() {
|
|
153
|
+
while (true) {
|
|
154
|
+
const result = await this.source.next();
|
|
155
|
+
if (result.done)
|
|
156
|
+
return DONE;
|
|
157
|
+
if (await this.fn(result.value))
|
|
158
|
+
return { done: false, value: result.value };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
[Symbol.asyncIterator]() {
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
class AsyncTakeIterator {
|
|
166
|
+
source;
|
|
167
|
+
n;
|
|
168
|
+
count = 0;
|
|
169
|
+
constructor(source, n) {
|
|
170
|
+
this.source = source;
|
|
171
|
+
this.n = n;
|
|
172
|
+
}
|
|
173
|
+
async next() {
|
|
174
|
+
if (this.count >= this.n)
|
|
175
|
+
return DONE;
|
|
176
|
+
const result = await this.source.next();
|
|
177
|
+
if (result.done)
|
|
178
|
+
return DONE;
|
|
179
|
+
this.count++;
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
[Symbol.asyncIterator]() {
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function createSpliceGenerators(source, matcher, deleteCount, insertIterable) {
|
|
187
|
+
const state = {
|
|
188
|
+
phase: 'seeking',
|
|
189
|
+
deletedCache: [],
|
|
190
|
+
slicedCache: [],
|
|
191
|
+
deletedPtr: 0,
|
|
192
|
+
slicedPtr: 0,
|
|
193
|
+
deleteRemaining: deleteCount,
|
|
194
|
+
insertIterator: null,
|
|
195
|
+
sourceIterator: source[Symbol.iterator](),
|
|
196
|
+
};
|
|
197
|
+
function* slicedGenerator() {
|
|
198
|
+
while (true) {
|
|
199
|
+
while (state.slicedPtr < state.slicedCache.length) {
|
|
200
|
+
yield state.slicedCache[state.slicedPtr++];
|
|
201
|
+
}
|
|
202
|
+
if (state.phase === 'seeking') {
|
|
203
|
+
const next = state.sourceIterator.next();
|
|
204
|
+
if (next.done) {
|
|
205
|
+
state.phase = 'done';
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const val = next.value;
|
|
209
|
+
if (matcher(val)) {
|
|
210
|
+
state.phase = 'deleting';
|
|
211
|
+
state.deletedCache.push(val);
|
|
212
|
+
state.deleteRemaining--;
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
state.slicedCache.push(val);
|
|
216
|
+
state.slicedPtr++;
|
|
217
|
+
yield val;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
else if (state.phase === 'deleting') {
|
|
221
|
+
if (state.deleteRemaining > 0) {
|
|
222
|
+
const next = state.sourceIterator.next();
|
|
223
|
+
if (next.done) {
|
|
224
|
+
state.phase = 'done';
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
state.deletedCache.push(next.value);
|
|
228
|
+
state.deleteRemaining--;
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
state.phase = 'inserting';
|
|
232
|
+
state.insertIterator = insertIterable[Symbol.iterator]();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
else if (state.phase === 'inserting') {
|
|
236
|
+
if (state.insertIterator === null) {
|
|
237
|
+
state.insertIterator = insertIterable[Symbol.iterator]();
|
|
238
|
+
}
|
|
239
|
+
const next = state.insertIterator.next();
|
|
240
|
+
if (next.done) {
|
|
241
|
+
state.phase = 'done';
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
state.slicedCache.push(next.value);
|
|
245
|
+
state.slicedPtr++;
|
|
246
|
+
yield next.value;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
else if (state.phase === 'done') {
|
|
250
|
+
const next = state.sourceIterator.next();
|
|
251
|
+
if (next.done)
|
|
252
|
+
return;
|
|
253
|
+
state.slicedCache.push(next.value);
|
|
254
|
+
state.slicedPtr++;
|
|
255
|
+
yield next.value;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function* deletedGenerator() {
|
|
260
|
+
while (true) {
|
|
261
|
+
while (state.deletedPtr < state.deletedCache.length) {
|
|
262
|
+
yield state.deletedCache[state.deletedPtr++];
|
|
263
|
+
}
|
|
264
|
+
if (state.phase === 'seeking' || state.phase === 'deleting') {
|
|
265
|
+
const slicedIter = slicedGenerator();
|
|
266
|
+
let result = slicedIter.next();
|
|
267
|
+
// slicedGenerator mutates state.phase as it iterates, so re-read
|
|
268
|
+
// through the full type to avoid TS narrowing from the outer `if`.
|
|
269
|
+
while (!result.done && state.phase !== 'done') {
|
|
270
|
+
result = slicedIter.next();
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (state.deletedPtr >= state.deletedCache.length) {
|
|
274
|
+
if (state.phase === 'done' || state.phase === 'inserting')
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
sliced: slicedGenerator(),
|
|
281
|
+
deleted: deletedGenerator(),
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
async function createAsyncSpliceGenerators(source, matcher, deleteCount, insertIterable) {
|
|
285
|
+
const state = {
|
|
286
|
+
phase: 'seeking',
|
|
287
|
+
deletedCache: [],
|
|
288
|
+
slicedCache: [],
|
|
289
|
+
deletedPtr: 0,
|
|
290
|
+
slicedPtr: 0,
|
|
291
|
+
deleteRemaining: deleteCount,
|
|
292
|
+
insertIterator: null,
|
|
293
|
+
sourceIterator: source[Symbol.asyncIterator](),
|
|
294
|
+
};
|
|
295
|
+
async function* slicedGenerator() {
|
|
296
|
+
while (true) {
|
|
297
|
+
while (state.slicedPtr < state.slicedCache.length) {
|
|
298
|
+
yield state.slicedCache[state.slicedPtr++];
|
|
299
|
+
}
|
|
300
|
+
if (state.phase === 'seeking') {
|
|
301
|
+
const next = await state.sourceIterator.next();
|
|
302
|
+
if (next.done) {
|
|
303
|
+
state.phase = 'done';
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const val = next.value;
|
|
307
|
+
if (await matcher(val)) {
|
|
308
|
+
state.phase = 'deleting';
|
|
309
|
+
state.deletedCache.push(val);
|
|
310
|
+
state.deleteRemaining--;
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
state.slicedCache.push(val);
|
|
314
|
+
state.slicedPtr++;
|
|
315
|
+
yield val;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
else if (state.phase === 'deleting') {
|
|
319
|
+
if (state.deleteRemaining > 0) {
|
|
320
|
+
const next = await state.sourceIterator.next();
|
|
321
|
+
if (next.done) {
|
|
322
|
+
state.phase = 'done';
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
state.deletedCache.push(next.value);
|
|
326
|
+
state.deleteRemaining--;
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
state.phase = 'inserting';
|
|
330
|
+
state.insertIterator = insertIterable[Symbol.asyncIterator]();
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
else if (state.phase === 'inserting') {
|
|
334
|
+
if (state.insertIterator === null) {
|
|
335
|
+
state.insertIterator = insertIterable[Symbol.asyncIterator]();
|
|
336
|
+
}
|
|
337
|
+
const next = await state.insertIterator.next();
|
|
338
|
+
if (next.done) {
|
|
339
|
+
state.phase = 'done';
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
state.slicedCache.push(next.value);
|
|
343
|
+
state.slicedPtr++;
|
|
344
|
+
yield next.value;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
else if (state.phase === 'done') {
|
|
348
|
+
const next = await state.sourceIterator.next();
|
|
349
|
+
if (next.done)
|
|
350
|
+
return;
|
|
351
|
+
state.slicedCache.push(next.value);
|
|
352
|
+
state.slicedPtr++;
|
|
353
|
+
yield next.value;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
async function* deletedGenerator() {
|
|
358
|
+
while (true) {
|
|
359
|
+
while (state.deletedPtr < state.deletedCache.length) {
|
|
360
|
+
yield state.deletedCache[state.deletedPtr++];
|
|
361
|
+
}
|
|
362
|
+
if (state.phase === 'seeking' || state.phase === 'deleting') {
|
|
363
|
+
const slicedIter = slicedGenerator();
|
|
364
|
+
let result = await slicedIter.next();
|
|
365
|
+
// slicedGenerator mutates state.phase as it iterates, so re-read
|
|
366
|
+
// through the full type to avoid TS narrowing from the outer `if`.
|
|
367
|
+
while (!result.done &&
|
|
368
|
+
state.phase !== 'done') {
|
|
369
|
+
result = await slicedIter.next();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
if (state.deletedPtr >= state.deletedCache.length) {
|
|
373
|
+
if (state.phase === 'done' || state.phase === 'inserting')
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return {
|
|
379
|
+
sliced: slicedGenerator(),
|
|
380
|
+
deleted: deletedGenerator(),
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
function asyncIterableFrom(factory) {
|
|
384
|
+
return { [Symbol.asyncIterator]: factory };
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* A wrapper around Iterable that provides chainable transformation methods.
|
|
388
|
+
* Each method returns a new ExtendedIterable wrapping the source,
|
|
389
|
+
* mirroring how Array methods work but with lazy evaluation.
|
|
390
|
+
*
|
|
391
|
+
* @example
|
|
392
|
+
* ```typescript
|
|
393
|
+
* const numbers = new ExtendedIterable([1, 2, 3]);
|
|
394
|
+
* const doubled = numbers.map(x => x * 2).collect(); // [2, 4, 6]
|
|
395
|
+
*
|
|
396
|
+
* // Works with any iterable, including generators
|
|
397
|
+
* const result = new ExtendedIterable(myGenerator())
|
|
398
|
+
* .map(transform)
|
|
399
|
+
* .join(', ');
|
|
400
|
+
* ```
|
|
401
|
+
*/
|
|
402
|
+
export class ExtendedIterable {
|
|
403
|
+
_iterFn;
|
|
404
|
+
constructor(iterable) {
|
|
405
|
+
// Store a factory so we can create fresh iterators on each iteration.
|
|
406
|
+
// For iterables that are already single-use (generators), this preserves
|
|
407
|
+
// the existing behavior — iterating twice just yields nothing the second time.
|
|
408
|
+
this._iterFn = () => iterable[Symbol.iterator]();
|
|
409
|
+
}
|
|
410
|
+
// Internal: create from a factory directly, skipping the iterable wrapper
|
|
411
|
+
static _from(factory) {
|
|
412
|
+
const inst = Object.create(ExtendedIterable.prototype);
|
|
413
|
+
inst._iterFn = factory;
|
|
414
|
+
return inst;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Flattens one level of nesting by yielding elements from nested iterables.
|
|
418
|
+
* Non-iterable values are yielded as-is. Strings are not split into characters.
|
|
419
|
+
*/
|
|
420
|
+
flat() {
|
|
421
|
+
const parentIter = this._iterFn;
|
|
422
|
+
return ExtendedIterable._from(() => new FlatIterator(parentIter()));
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Maps each element through a transformation function.
|
|
426
|
+
* Evaluation is lazy - the function is called only when iterating.
|
|
427
|
+
*/
|
|
428
|
+
map(fn) {
|
|
429
|
+
const parentIter = this._iterFn;
|
|
430
|
+
return ExtendedIterable._from(() => new MapIterator(parentIter(), fn));
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Filters elements using a predicate function.
|
|
434
|
+
* Supports type guards for narrowing.
|
|
435
|
+
*/
|
|
436
|
+
filter(predicate) {
|
|
437
|
+
const parentIter = this._iterFn;
|
|
438
|
+
return ExtendedIterable._from(() => new FilterIterator(parentIter(), predicate));
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Takes the first n elements.
|
|
442
|
+
*/
|
|
443
|
+
take(n) {
|
|
444
|
+
const parentIter = this._iterFn;
|
|
445
|
+
return ExtendedIterable._from(() => new TakeIterator(parentIter(), n));
|
|
446
|
+
}
|
|
447
|
+
some(predicate) {
|
|
448
|
+
const iterator = this[Symbol.iterator]();
|
|
449
|
+
const processAsync = async (pending) => {
|
|
450
|
+
if (await pending)
|
|
451
|
+
return true;
|
|
452
|
+
for (let next = iterator.next(); !next.done; next = iterator.next()) {
|
|
453
|
+
if (await predicate(next.value))
|
|
454
|
+
return true;
|
|
455
|
+
}
|
|
456
|
+
return false;
|
|
457
|
+
};
|
|
458
|
+
for (let next = iterator.next(); !next.done; next = iterator.next()) {
|
|
459
|
+
const result = predicate(next.value);
|
|
460
|
+
if (result instanceof Promise) {
|
|
461
|
+
return processAsync(result);
|
|
462
|
+
}
|
|
463
|
+
if (result)
|
|
464
|
+
return true;
|
|
465
|
+
}
|
|
466
|
+
return false;
|
|
467
|
+
}
|
|
468
|
+
find(predicate) {
|
|
469
|
+
const iterator = this[Symbol.iterator]();
|
|
470
|
+
const processAsync = async (currentVal, pending) => {
|
|
471
|
+
if (await pending)
|
|
472
|
+
return currentVal;
|
|
473
|
+
for (let next = iterator.next(); !next.done; next = iterator.next()) {
|
|
474
|
+
if (await predicate(next.value))
|
|
475
|
+
return next.value;
|
|
476
|
+
}
|
|
477
|
+
return undefined;
|
|
478
|
+
};
|
|
479
|
+
for (let next = iterator.next(); !next.done; next = iterator.next()) {
|
|
480
|
+
const result = predicate(next.value);
|
|
481
|
+
if (result instanceof Promise) {
|
|
482
|
+
return processAsync(next.value, result);
|
|
483
|
+
}
|
|
484
|
+
if (result)
|
|
485
|
+
return next.value;
|
|
486
|
+
}
|
|
487
|
+
return undefined;
|
|
488
|
+
}
|
|
489
|
+
reduce(fn, ...rest) {
|
|
490
|
+
const it = this[Symbol.iterator]();
|
|
491
|
+
let acc;
|
|
492
|
+
if (rest.length > 0) {
|
|
493
|
+
acc = rest[0];
|
|
494
|
+
}
|
|
495
|
+
else {
|
|
496
|
+
const first = it.next();
|
|
497
|
+
if (first.done) {
|
|
498
|
+
throw new TypeError('Reduce of empty iterable with no initial value');
|
|
499
|
+
}
|
|
500
|
+
acc = first.value;
|
|
501
|
+
}
|
|
502
|
+
for (let r = it.next(); !r.done; r = it.next()) {
|
|
503
|
+
acc = fn(acc, r.value);
|
|
504
|
+
}
|
|
505
|
+
return acc;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Collects all elements into an array.
|
|
509
|
+
*/
|
|
510
|
+
collect() {
|
|
511
|
+
const arr = [];
|
|
512
|
+
const it = this[Symbol.iterator]();
|
|
513
|
+
for (let r = it.next(); !r.done; r = it.next()) {
|
|
514
|
+
arr.push(r.value);
|
|
515
|
+
}
|
|
516
|
+
return arr;
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Joins all elements into a string with a separator.
|
|
520
|
+
* Elements are converted to strings using toString().
|
|
521
|
+
*/
|
|
522
|
+
join(separator) {
|
|
523
|
+
const it = this[Symbol.iterator]();
|
|
524
|
+
let r = it.next();
|
|
525
|
+
if (r.done)
|
|
526
|
+
return '';
|
|
527
|
+
let str = String(r.value);
|
|
528
|
+
for (r = it.next(); !r.done; r = it.next()) {
|
|
529
|
+
str += separator + String(r.value);
|
|
530
|
+
}
|
|
531
|
+
return str;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Prepends an iterable to the start of this iterable.
|
|
535
|
+
*/
|
|
536
|
+
prefix(prefix) {
|
|
537
|
+
const parentIter = this._iterFn;
|
|
538
|
+
return ExtendedIterable._from(() => new PrefixIterator(prefix, parentIter()));
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Removes elements from the iterable and optionally inserts new elements.
|
|
542
|
+
* Returns both the modified iterable and the deleted elements.
|
|
543
|
+
* Both iterables share state - iterating either will cache results for the other.
|
|
544
|
+
*
|
|
545
|
+
* @param matcher - Predicate to find the splice position
|
|
546
|
+
* @param deleteCount - Number of elements to remove after the match
|
|
547
|
+
* @param insertIterable - Elements to insert after removing
|
|
548
|
+
* @returns Object with `sliced` (modified iterable) and `deleted` (removed elements)
|
|
549
|
+
*
|
|
550
|
+
* @example
|
|
551
|
+
* ```typescript
|
|
552
|
+
* const { deleted, sliced } = iter([1, 2, 3, 4, 5])
|
|
553
|
+
* .splice((el) => el === 3, 2, iter([10, 20]));
|
|
554
|
+
* sliced.collect(); // [1, 2, 10, 20, 5]
|
|
555
|
+
* deleted.collect(); // [3, 4]
|
|
556
|
+
* ```
|
|
557
|
+
*/
|
|
558
|
+
splice(matcher, deleteCount, insertIterable) {
|
|
559
|
+
const { sliced, deleted } = createSpliceGenerators(this, matcher, deleteCount, insertIterable);
|
|
560
|
+
return {
|
|
561
|
+
sliced: new ExtendedIterable(sliced),
|
|
562
|
+
deleted: new ExtendedIterable(deleted),
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
[Symbol.iterator]() {
|
|
566
|
+
return this._iterFn();
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
export class AsyncExtendedIterable {
|
|
570
|
+
asyncIterable;
|
|
571
|
+
constructor(iterable) {
|
|
572
|
+
if (Symbol.asyncIterator in iterable) {
|
|
573
|
+
this.asyncIterable = iterable;
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
const syncIterable = iterable;
|
|
577
|
+
this.asyncIterable = {
|
|
578
|
+
async *[Symbol.asyncIterator]() {
|
|
579
|
+
for (const val of syncIterable) {
|
|
580
|
+
yield val;
|
|
581
|
+
}
|
|
582
|
+
},
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Maps each element through a transformation function.
|
|
588
|
+
* The function can be sync or async.
|
|
589
|
+
* Evaluation is lazy - the function is called only when iterating.
|
|
590
|
+
*/
|
|
591
|
+
map(fn) {
|
|
592
|
+
const source = this.asyncIterable;
|
|
593
|
+
return new AsyncExtendedIterable(asyncIterableFrom(() => new AsyncMapIterator(source[Symbol.asyncIterator](), fn)));
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Filters elements using a predicate function.
|
|
597
|
+
* The predicate can be sync or async.
|
|
598
|
+
*/
|
|
599
|
+
filter(predicate) {
|
|
600
|
+
const source = this.asyncIterable;
|
|
601
|
+
return new AsyncExtendedIterable(asyncIterableFrom(() => new AsyncFilterIterator(source[Symbol.asyncIterator](), predicate)));
|
|
602
|
+
}
|
|
603
|
+
async reduce(fn, ...rest) {
|
|
604
|
+
const it = this[Symbol.asyncIterator]();
|
|
605
|
+
let acc;
|
|
606
|
+
if (rest.length > 0) {
|
|
607
|
+
acc = rest[0];
|
|
608
|
+
}
|
|
609
|
+
else {
|
|
610
|
+
const first = await it.next();
|
|
611
|
+
if (first.done) {
|
|
612
|
+
throw new TypeError('Reduce of empty iterable with no initial value');
|
|
613
|
+
}
|
|
614
|
+
acc = first.value;
|
|
615
|
+
}
|
|
616
|
+
for (let r = await it.next(); !r.done; r = await it.next()) {
|
|
617
|
+
acc = await fn(acc, r.value);
|
|
618
|
+
}
|
|
619
|
+
return acc;
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Collects all elements into an array.
|
|
623
|
+
*/
|
|
624
|
+
async collect() {
|
|
625
|
+
const arr = [];
|
|
626
|
+
for await (const val of this) {
|
|
627
|
+
arr.push(val);
|
|
628
|
+
}
|
|
629
|
+
return arr;
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Joins all elements into a string with a separator.
|
|
633
|
+
* Elements are converted to strings using String().
|
|
634
|
+
*/
|
|
635
|
+
async join(separator) {
|
|
636
|
+
const arr = await this.collect();
|
|
637
|
+
return arr.map(String).join(separator);
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Takes the first n elements.
|
|
641
|
+
*/
|
|
642
|
+
take(n) {
|
|
643
|
+
const source = this.asyncIterable;
|
|
644
|
+
return new AsyncExtendedIterable(asyncIterableFrom(() => new AsyncTakeIterator(source[Symbol.asyncIterator](), n)));
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Tests whether at least one element passes the predicate.
|
|
648
|
+
* Short-circuits on first match. Predicate can be sync or async.
|
|
649
|
+
*/
|
|
650
|
+
async some(predicate) {
|
|
651
|
+
for await (const val of this) {
|
|
652
|
+
if (await predicate(val)) {
|
|
653
|
+
return true;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
return false;
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Returns the first element that passes the predicate, or undefined.
|
|
660
|
+
* Short-circuits on first match. Predicate can be sync or async.
|
|
661
|
+
*/
|
|
662
|
+
async find(predicate) {
|
|
663
|
+
for await (const val of this) {
|
|
664
|
+
if (await predicate(val)) {
|
|
665
|
+
return val;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
return undefined;
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Removes elements from the async iterable and optionally inserts new elements.
|
|
672
|
+
* Returns both the modified iterable and the deleted elements.
|
|
673
|
+
* Both iterables share state - iterating either will cache results for the other.
|
|
674
|
+
*/
|
|
675
|
+
async splice(matcher, deleteCount, insertIterable) {
|
|
676
|
+
const asyncInsert = Symbol.asyncIterator in insertIterable
|
|
677
|
+
? insertIterable
|
|
678
|
+
: {
|
|
679
|
+
async *[Symbol.asyncIterator]() {
|
|
680
|
+
for (const val of insertIterable) {
|
|
681
|
+
yield val;
|
|
682
|
+
}
|
|
683
|
+
},
|
|
684
|
+
};
|
|
685
|
+
const { sliced, deleted } = await createAsyncSpliceGenerators(this, matcher, deleteCount, asyncInsert);
|
|
686
|
+
return {
|
|
687
|
+
sliced: new AsyncExtendedIterable(sliced),
|
|
688
|
+
deleted: new AsyncExtendedIterable(deleted),
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
[Symbol.asyncIterator]() {
|
|
692
|
+
return this.asyncIterable[Symbol.asyncIterator]();
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Helper to create an AsyncExtendedIterable from any iterable.
|
|
697
|
+
*/
|
|
698
|
+
export function asyncIter(iterable) {
|
|
699
|
+
return new AsyncExtendedIterable(iterable);
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Returns an AsyncExtendedIterable that yields promise results as they settle,
|
|
703
|
+
* in completion order (not input order).
|
|
704
|
+
*
|
|
705
|
+
* Like Promise.allSettled, but streaming - you get results as soon as they're ready,
|
|
706
|
+
* with full chaining support.
|
|
707
|
+
*
|
|
708
|
+
* @example
|
|
709
|
+
* ```typescript
|
|
710
|
+
* const promises = [
|
|
711
|
+
* fetch('/slow'), // takes 3s
|
|
712
|
+
* fetch('/fast'), // takes 1s
|
|
713
|
+
* fetch('/medium'), // takes 2s
|
|
714
|
+
* ];
|
|
715
|
+
*
|
|
716
|
+
* // Results arrive in order: fast, medium, slow
|
|
717
|
+
* for await (const result of asSettled(promises)) {
|
|
718
|
+
* if (result.status === 'fulfilled') {
|
|
719
|
+
* console.log('Got:', result.value);
|
|
720
|
+
* } else {
|
|
721
|
+
* console.log('Failed:', result.reason);
|
|
722
|
+
* }
|
|
723
|
+
* }
|
|
724
|
+
*
|
|
725
|
+
* // Chain operations
|
|
726
|
+
* const firstThreeSuccesses = await asSettled(promises)
|
|
727
|
+
* .filter(r => r.status === 'fulfilled')
|
|
728
|
+
* .map(r => (r as PromiseFulfilledResult<Response>).value)
|
|
729
|
+
* .take(3)
|
|
730
|
+
* .collect();
|
|
731
|
+
* ```
|
|
732
|
+
*/
|
|
733
|
+
export function asSettled(promises) {
|
|
734
|
+
return new AsyncExtendedIterable(asSettledGen(promises));
|
|
735
|
+
}
|
|
736
|
+
async function* asSettledGen(promises) {
|
|
737
|
+
const queue = [];
|
|
738
|
+
let notifyReady = null;
|
|
739
|
+
let remaining = 0;
|
|
740
|
+
for (const p of promises) {
|
|
741
|
+
remaining++;
|
|
742
|
+
Promise.resolve(p).then((value) => {
|
|
743
|
+
queue.push({ status: 'fulfilled', value });
|
|
744
|
+
notifyReady?.();
|
|
745
|
+
}, (reason) => {
|
|
746
|
+
queue.push({ status: 'rejected', reason });
|
|
747
|
+
notifyReady?.();
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
while (remaining > 0) {
|
|
751
|
+
if (queue.length === 0) {
|
|
752
|
+
await new Promise((resolve) => {
|
|
753
|
+
notifyReady = resolve;
|
|
754
|
+
});
|
|
755
|
+
notifyReady = null;
|
|
756
|
+
}
|
|
757
|
+
while (queue.length > 0 && remaining > 0) {
|
|
758
|
+
yield queue.shift();
|
|
759
|
+
remaining--;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* Helper to create an ExtendedIterable from any iterable.
|
|
765
|
+
*/
|
|
766
|
+
export function iter(iterable) {
|
|
767
|
+
return new ExtendedIterable(iterable);
|
|
768
|
+
}
|
|
769
|
+
//# sourceMappingURL=extended-iterable.js.map
|