• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

syarul / requrse / 17678315076

12 Sep 2025 03:03PM UTC coverage: 98.685% (-1.3%) from 100.0%
17678315076

push

github

web-flow
Merge pull request #14 from syarul/getDie

fix update

235 of 244 branches covered (96.31%)

Branch coverage included in aggregate %.

207 of 215 new or added lines in 5 files covered. (96.28%)

1041 of 1049 relevant lines covered (99.24%)

99.73 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.55
/libs/executeQuery.cjs
1
// @ts-check
15✔
2
const equal = require("deep-equal");
15✔
3
const resolvePromises = require("./resolvePromises.cjs");
15✔
4
const iterate = require("./iterate.cjs");
15✔
5
const computeMethod = require("./computeMethod.cjs");
15✔
6
const getAlias = require("./getAlias.cjs");
15✔
7
const getCurrentQueryArgs = require("./getCurrentQueryArgs.cjs");
15✔
8
const { buildArgs, isObj } = require("./buildArgs.cjs");
15✔
9
const merge = require("./mergeQuery.cjs");
15✔
10
const mapResult = require("./mapResult.cjs");
15✔
11

15✔
12
/**
15✔
13
 * @typedef ComputeParams
15✔
14
 * @property {CurrentQuery} currentQuery
15✔
15
 * @property {ResultQuery} resultQuery
15✔
16
 * @property {MergeQuery} mergeQuery
15✔
17
 * @property {Boolean | undefined} failedComputed
15✔
18
 */
15✔
19

15✔
20
/**
15✔
21
 *
15✔
22
 * @param {ComputeParams & GeneratedParams} _
15✔
23
 * @returns
15✔
24
 */
15✔
25
function handleComputeParams({
20✔
26
  compute,
20✔
27
  currentQuery,
20✔
28
  resultQuery,
20✔
29
  mergeQuery,
20✔
30
  $vParams,
20✔
31
  params,
20✔
32
  key,
20✔
33
}) {
20✔
34
  if (currentQuery instanceof Array && !equal(resultQuery, currentQuery)) {
20✔
35
    for (const obj of currentQuery) {
7✔
36
      if ($vParams && !params && !obj[key]) {
11✔
37
        try {
2✔
38
          resultQuery.push(compute.apply(mergeQuery, [obj, $vParams]));
2✔
39
        } catch (err) {
2!
NEW
40
          throw err;
×
NEW
41
        }
×
42
      } else {
11✔
43
        try {
9✔
44
          resultQuery.push(
9✔
45
            compute.apply(
9✔
46
              mergeQuery,
9✔
47
              buildArgs.apply(mergeQuery, [
9✔
48
                $vParams,
9✔
49
                params,
9✔
50
                { [key]: obj[key] },
9✔
51
              ]),
9✔
52
            ),
9✔
53
          );
9✔
54
        } catch (err) {
9!
NEW
55
          throw err;
×
NEW
56
        }
×
57
      }
9✔
58
    }
11✔
59
  } else {
20✔
60
    try {
13✔
61
      resultQuery = [
13✔
62
        compute.apply(
13✔
63
          mergeQuery,
13✔
64
          buildArgs.apply(mergeQuery, [$vParams, params, currentQuery]),
13✔
65
        ),
13✔
66
      ];
13✔
67
    } catch (err) {
13✔
68
      throw err;
1✔
69
    }
1✔
70
  }
13✔
71
  return {
19✔
72
    computed: true,
19✔
73
    ...(resultQuery instanceof Object
19✔
74
      ? { currentQuery: resultQuery }
19✔
75
      : { currentQuery }),
20!
76
    resultQuery,
20✔
77
    mergeQuery,
20✔
78
  };
20✔
79
}
20✔
80

15✔
81
/**
15✔
82
 *
15✔
83
 * @param {ComputeParams & GeneratedParams & import("./executor.cjs").QueryOptions} _
15✔
84
 * @returns
15✔
85
 */
15✔
86
function handleCompute({
75✔
87
  key,
75✔
88
  compute,
75✔
89
  currentQuery,
75✔
90
  resultQuery,
75✔
91
  mergeQuery,
75✔
92
  $vParams,
75✔
93
  params,
75✔
94
  failedComputed,
75✔
95
  args,
75✔
96
  config,
75✔
97
  methods,
75✔
98
}) {
75✔
99
  try {
75✔
100
    currentQuery = compute.apply(
75✔
101
      mergeQuery,
75✔
102
      buildArgs.apply(mergeQuery, [$vParams, params, ...args]),
75✔
103
    );
75✔
104
  } catch (err) {
75!
NEW
105
    throw err;
×
NEW
106
  }
×
107
  if (currentQuery === undefined) {
75✔
108
    failedComputed = true;
7✔
109
  }
7✔
110
  // look for computed field
75✔
111
  if (isObj(currentQuery)) {
75✔
112
    for (const key in currentQuery) {
57✔
113
      compute =
1,503✔
114
        (typeof config === "function" && config(key)) ||
1,503✔
115
        methods?.[key] ||
1,503✔
116
        compute;
1,503✔
117
      if (methods?.[key] && compute && typeof compute === "function") {
1,503✔
118
        try {
32✔
119
          currentQuery[key] = compute.apply(
32✔
120
            mergeQuery,
32✔
121
            buildArgs.apply(mergeQuery, [$vParams, params, ...args]),
32✔
122
          );
32✔
123
        } catch (err) {
32!
NEW
124
          throw err;
×
NEW
125
        }
×
126
      }
32✔
127
    }
1,503✔
128
  }
57✔
129
  return {
75✔
130
    computed: true,
75✔
131
    failedComputed,
75✔
132
    currentQuery,
75✔
133
    resultQuery,
75✔
134
    mergeQuery,
75✔
135
  };
75✔
136
}
75✔
137

15✔
138
/**
15✔
139
 *
15✔
140
 * @param {ComputeParams & GeneratedParams & import("./executor.cjs").QueryOptions} _
15✔
141
 * @returns
15✔
142
 */
15✔
143
function handleOther({
194✔
144
  key,
194✔
145
  compute,
194✔
146
  currentQuery,
194✔
147
  resultQuery,
194✔
148
  mergeQuery,
194✔
149
  config,
194✔
150
  $vParams,
194✔
151
  params,
194✔
152
}) {
194✔
153
  currentQuery = compute;
194✔
154
  // resolve recurrence
194✔
155
  if (typeof currentQuery === "string" && config(currentQuery)) {
194✔
156
    currentQuery = config(currentQuery);
1✔
157
  }
1✔
158
  if (!currentQuery && ($vParams || params)) {
194✔
159
    currentQuery = $vParams || params;
1!
160
  }
1✔
161
  return {
194✔
162
    computed: false,
194✔
163
    currentQuery,
194✔
164
    resultQuery,
194✔
165
    mergeQuery,
194✔
166
  };
194✔
167
}
194✔
168

15✔
169
/**
15✔
170
 * @typedef ValueIsObject
15✔
171
 * @property {*} value
15✔
172
 * @property {CurrentQuery} resolvedCurrentQuery
15✔
173
 * @property {Boolean | undefined} [computed]
15✔
174
 * @property {Boolean | undefined} [failedComputed]
15✔
175
 */
15✔
176

15✔
177
/**
15✔
178
 *
15✔
179
 * @param {ReducerOptions & import("./executor.cjs").QueryOptions & ValueIsObject} _
15✔
180
 * @returns
15✔
181
 */
15✔
182
async function valueIsObject({
167✔
183
  value,
167✔
184
  resolvedCurrentQuery,
167✔
185
  methods,
167✔
186
  config,
167✔
187
  mergeQuery,
167✔
188
  query,
167✔
189
  computed,
167✔
190
  failedComputed,
167✔
191
}) {
167✔
192
  /** @type {*} */
167✔
193
  let result = await executeQuery(
167✔
194
    value,
167✔
195
    resolvedCurrentQuery,
167✔
196
    { methods, config },
167✔
197
    mergeQuery,
167✔
198
  );
167✔
199
  if (resolvedCurrentQuery) {
167✔
200
    if (
79✔
201
      !(resolvedCurrentQuery instanceof Array) &&
79✔
202
      resolvedCurrentQuery &&
79✔
203
      Object.entries(value) !== result
51✔
204
    ) {
79✔
205
      result = mapResult(query, result, resolvedCurrentQuery);
51✔
206
    } else {
71✔
207
      result = iterate(result, resolvedCurrentQuery);
28✔
208
    }
28✔
209
  }
79✔
210
  const e = Object.entries(value);
165✔
211
  // unresolved value is return as null
165✔
212
  if (
165✔
213
    computed &&
167✔
214
    failedComputed &&
167✔
215
    result &&
167✔
216
    result[0] &&
167✔
217
    e &&
167✔
218
    e[0] &&
167✔
219
    result[0][0] === e[0][0] &&
167✔
220
    result[0][1] === e[0][1]
7✔
221
  ) {
167✔
222
    result = null;
1✔
223
  }
1✔
224
  return { res: result, mergeQuery };
165✔
225
}
167✔
226

15✔
227
/**
15✔
228
 * @typedef Result
15✔
229
 * @property {Promise<CurrentQuery>} currentQuery
15✔
230
 * @property {ResultQuery} resultQuery
15✔
231
 * @property {Boolean | undefined} [computed]
15✔
232
 * @property {Boolean | undefined} [failedComputed]
15✔
233
 */
15✔
234

15✔
235
/**
15✔
236
 * @typedef QueryResult
15✔
237
 * @property {*} res
15✔
238
 * @property {MergeQuery} mergeQuery
15✔
239
 */
15✔
240

15✔
241
/**
15✔
242
 *
15✔
243
 * @param {CombineOptions & Result} _
15✔
244
 * @returns {Promise<QueryResult>}
15✔
245
 */
15✔
246
async function getResult({
288✔
247
  // _key,
288✔
248
  value,
288✔
249
  currentQuery,
288✔
250
  resultQuery,
288✔
251
  methods,
288✔
252
  config,
288✔
253
  mergeQuery,
288✔
254
  query,
288✔
255
  computed,
288✔
256
  failedComputed,
288✔
257
}) {
288✔
258
  const resolvedCurrentQuery = await resolvePromises(currentQuery);
288✔
259
  let res;
288✔
260
  if (value instanceof Object) {
288✔
261
    return valueIsObject({
167✔
262
      value,
167✔
263
      resolvedCurrentQuery,
167✔
264
      methods,
167✔
265
      config,
167✔
266
      mergeQuery,
167✔
267
      query,
167✔
268
      computed,
167✔
269
      failedComputed,
167✔
270
    });
167✔
271
  } else if (typeof resolvedCurrentQuery === typeof value || value === "*") {
285✔
272
    res = currentQuery;
10✔
273
  } else if (
115✔
274
    resultQuery instanceof Array &&
111✔
275
    resultQuery.length === 1 &&
111✔
276
    typeof resultQuery[0] !== "object"
2✔
277
  ) {
111✔
278
    res = resultQuery[0];
1✔
279
  } else {
110✔
280
    res = value;
110✔
281
  }
110✔
282
  return { res, mergeQuery };
121✔
283
}
288✔
284

15✔
285
/**
15✔
286
 * @typedef CombineQuery
15✔
287
 * @property {CurrentQuery} currentQuery
15✔
288
 * @property {ResultQuery} resultQuery
15✔
289
 * @property {MergeQuery} mergeQuery
15✔
290
 */
15✔
291

15✔
292
/**
15✔
293
 *
15✔
294
 * @param {GeneratedParams & import("./executor.cjs").QueryOptions & CombineQuery} _
15✔
295
 * @returns
15✔
296
 */
15✔
297
const processHandler = ({
15✔
298
  key,
289✔
299
  compute,
289✔
300
  $params,
289✔
301
  currentQuery,
289✔
302
  resultQuery,
289✔
303
  mergeQuery,
289✔
304
  $vParams,
289✔
305
  params,
289✔
306
  args,
289✔
307
  config,
289✔
308
  methods,
289✔
309
}) => {
289✔
310
  mergeQuery.key = mergeQuery?.key || key; // model cache support
289✔
311
  mergeQuery = merge(mergeQuery, currentQuery);
289✔
312
  const checks = {
289✔
313
    0:
289✔
314
      typeof compute === "function" &&
289✔
315
      $params.currentQuery &&
289✔
316
      !$params.currentQuery[key],
289✔
317
    1: typeof compute === "function",
289✔
318
  };
289✔
319
  const handlers = {
289✔
320
    0: handleComputeParams,
289✔
321
    1: handleCompute,
289✔
322
  };
289✔
323

289✔
324
  const match = Object.keys(checks).find((key) => checks[parseInt(key)]);
289✔
325

289✔
326
  return (handlers?.[match] || handleOther)({
289✔
327
    compute,
289✔
328
    currentQuery,
289✔
329
    resultQuery,
289✔
330
    mergeQuery,
289✔
331
    $vParams,
289✔
332
    params,
289✔
333
    key,
289✔
334
    args,
289✔
335
    config,
289✔
336
    methods,
289✔
337
  });
289✔
338
};
15✔
339

15✔
340
/**
15✔
341
 * @typedef GeneratedParams
15✔
342
 * @property {*} key
15✔
343
 * @property {*} alias
15✔
344
 * @property {*} compute
15✔
345
 * @property {*} params
15✔
346
 * @property {*} args
15✔
347
 * @property {*} $params
15✔
348
 * @property {*} $vParams
15✔
349
 */
15✔
350

15✔
351
/**
15✔
352
 *
15✔
353
 * @param {CurrentQuery} currentQuery
15✔
354
 * @param {CombineOptions} options
15✔
355
 * @returns {GeneratedParams}
15✔
356
 */
15✔
357
function genParams(currentQuery, options) {
289✔
358
  const { _key, value } = options;
289✔
359
  const { key, alias } = getAlias("/", _key);
289✔
360
  const { compute, params } = computeMethod(options, key);
289✔
361
  const { args, $params, $vParams } = getCurrentQueryArgs(
289✔
362
    value,
289✔
363
    currentQuery,
289✔
364
    alias,
289✔
365
    params,
289✔
366
  );
289✔
367
  return {
289✔
368
    key,
289✔
369
    alias,
289✔
370
    compute,
289✔
371
    params,
289✔
372
    args,
289✔
373
    $params,
289✔
374
    $vParams,
289✔
375
  };
289✔
376
}
289✔
377

15✔
378
/** @typedef {Record<string, any>} ResultQuery */
15✔
379

15✔
380
/**
15✔
381
 * @typedef ResultParams
15✔
382
 * @property {String} key
15✔
383
 * @property {String} alias
15✔
384
 * @property {BuildEntries} buildEntries
15✔
385
 * @property {ResultQuery} resultQuery
15✔
386
 * @property {CurrentQuery} currentQuery
15✔
387
 * @property {MergeQuery} mergeQuery
15✔
388
 */
15✔
389

15✔
390
/**
15✔
391
 *
15✔
392
 * @param {ResultParams} _
15✔
393
 * @returns
15✔
394
 */
15✔
395
function handleResult({
288✔
396
  key,
288✔
397
  alias,
288✔
398
  buildEntries,
288✔
399
  resultQuery,
288✔
400
  currentQuery,
288✔
401
  mergeQuery,
288✔
402
}) {
288✔
403
  /** @param {QueryResult} result */
288✔
404
  return (result) => {
288✔
405
    buildEntries.push([alias ? `${key}/${alias}` : key, result.res]);
286✔
406
    return {
286✔
407
      buildEntries,
286✔
408
      resultQuery,
286✔
409
      currentQuery,
286✔
410
      mergeQuery: { ...mergeQuery, ...(result?.mergeQuery || {}) },
286!
411
    };
286✔
412
  };
288✔
413
}
288✔
414

15✔
415
/**
15✔
416
 * @typedef ChainReducerOptions
15✔
417
 * @property {String} _key
15✔
418
 * @property {*} value
15✔
419
 */
15✔
420

15✔
421
/** @typedef {ChainReducerOptions & ReducerOptions & import("./executor.cjs").QueryOptions} CombineOptions */
15✔
422

15✔
423
/**
15✔
424
 *
15✔
425
 * @param {CombineOptions} options
15✔
426
 * @returns {function}
15✔
427
 */
15✔
428
function chainReducer(options) {
289✔
429
  return ({ buildEntries, resultQuery, currentQuery, mergeQuery }) => {
289✔
430
    const params = genParams(currentQuery, options);
289✔
431
    const res = processHandler({
289✔
432
      ...options,
289✔
433
      ...params,
289✔
434
      resultQuery,
289✔
435
      currentQuery,
289✔
436
      mergeQuery,
289✔
437
    });
289✔
438
    currentQuery = res?.currentQuery || currentQuery;
289✔
439
    return getResult({
289✔
440
      ...options,
289✔
441
      ...res,
289✔
442
      currentQuery,
289✔
443
    }).then(
289✔
444
      handleResult({
289✔
445
        buildEntries,
289✔
446
        resultQuery: res.resultQuery,
289✔
447
        currentQuery,
289✔
448
        mergeQuery,
289✔
449
        ...params,
289✔
450
      }),
289✔
451
    );
289✔
452
  };
289✔
453
}
289✔
454

15✔
455
/**
15✔
456
 * @typedef ReducerOptions
15✔
457
 * @property {Query} query
15✔
458
 * @property {MergeQuery} mergeQuery
15✔
459
 */
15✔
460

15✔
461
/**
15✔
462
 *
15✔
463
 * @param {ReducerOptions & import("./executor.cjs").QueryOptions} options
15✔
464
 * @returns
15✔
465
 */
15✔
466
function entryReducer(options) {
234✔
467
  return (promiseChain, [_key, value]) =>
234✔
468
    promiseChain.then(
289✔
469
      chainReducer({
289✔
470
        _key,
289✔
471
        value,
289✔
472
        ...options,
289✔
473
      }),
289✔
474
    );
234✔
475
}
234✔
476

15✔
477
/**
15✔
478
 * @typedef EntriesParams
15✔
479
 * @property {Query} query
15✔
480
 * @property {CurrentQuery} currentQuery
15✔
481
 * @property {MergeQuery} mergeQuery
15✔
482
 * @property {import("./executor.cjs").QueryOptions} options
15✔
483
 */
15✔
484

15✔
485
/**
15✔
486
 *
15✔
487
 * @param {EntriesParams} _
15✔
488
 * @returns
15✔
489
 */
15✔
490
const handleEntries = ({ query, currentQuery, mergeQuery, options }) =>
15✔
491
  Object.entries(query).reduce(
234✔
492
    entryReducer({
234✔
493
      query,
234✔
494
      mergeQuery,
234✔
495
      ...options,
234✔
496
    }),
234✔
497
    Promise.resolve({
234✔
498
      buildEntries: [],
234✔
499
      resultQuery: [],
234✔
500
      currentQuery,
234✔
501
      mergeQuery,
234✔
502
    }),
234✔
503
  );
15✔
504

15✔
505
/** @typedef {Record<string, any>} Query */
15✔
506
/** @typedef {Record<string, any> | null} CurrentQuery */
15✔
507
/** @typedef {Record<string, any>} MergeQuery */
15✔
508
/** @typedef {any[]} BuildEntries */
15✔
509

15✔
510
/**
15✔
511
 * Executes a query with the provided configuration.
15✔
512
 *
15✔
513
 * @param {Query} query - The query object to execute.
15✔
514
 * @param {CurrentQuery} currentQuery - The current query object.
15✔
515
 * @param {import("./executor.cjs").QueryOptions} options - The configuration object with methods and config function.
15✔
516
 * @param {MergeQuery} mergeQuery - The mergeQuery object (optional, defaults to an empty object).
15✔
517
 * @returns {Promise<BuildEntries>} A promise that resolves to an array of key-value pairs.
15✔
518
 */
15✔
519
const executeQuery = async (query, currentQuery, options, mergeQuery = {}) =>
15✔
520
  handleEntries({
234✔
521
    query,
234✔
522
    currentQuery,
234✔
523
    mergeQuery,
234✔
524
    options,
234✔
525
  }).then(({ buildEntries }) => buildEntries);
15✔
526

15✔
527
module.exports = executeQuery;
15✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc