poku 4.3.2 → 4.3.3-canary.2648bb03

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 CHANGED
@@ -168,7 +168,7 @@ deno run npm:poku
168
168
  <td>🌐 Run package.json scripts and files in background</td>
169
169
  </tr>
170
170
  <tr>
171
- <td><a href="https://poku.io/docs/documentation/helpers/containers">docker</a></td>
171
+ <td><a href="https://poku.io/docs/documentation/plugins/official/containers">docker</a></td>
172
172
  <td>🐳 Build, start, compose, stop, remove, and test containers</td>
173
173
  </tr>
174
174
  <tr>
@@ -197,7 +197,7 @@ deno run npm:poku
197
197
 
198
198
  <table>
199
199
  <tr>
200
- <td><a href="https://poku.io/docs/documentation/helpers/coverage">coverage</a></td>
200
+ <td><a href="https://poku.io/docs/documentation/plugins/official/coverage">coverage</a></td>
201
201
  <td>☔️ Enable coverage collection using a coverage plugin</td>
202
202
  </tr>
203
203
  <tr>
@@ -243,6 +243,20 @@ ${preIdentation} ${format(`${options?.expected ?? "Expected"}:`).dim()}`
243
243
  const indent = getIndent();
244
244
  log$1(`${indent}${format(`\u25CF ${message}`).cyan().bold()}`);
245
245
  },
246
+ onRetryStart({ attempt, total }) {
247
+ const indent = indentation.test.repeat(
248
+ indentation.describeDepth + indentation.itDepth
249
+ );
250
+ log$1(`${indent}${format(`\u21BB Retry ${attempt}/${total}`).dim()}`);
251
+ },
252
+ onRetryEnd({ attempt, success }) {
253
+ if (success && attempt > 1) {
254
+ const indent = indentation.test.repeat(
255
+ indentation.describeDepth + indentation.itDepth
256
+ );
257
+ log$1(`${indent}${format("\u2714 Retry succeeded").success().dim()}`);
258
+ }
259
+ },
246
260
  onFileResult({ status, path, duration, output }) {
247
261
  process$1.stdout.write(`
248
262
  `), status ? (log$1(
@@ -264,15 +278,14 @@ ${preIdentation} ${format(`${options?.expected ?? "Expected"}:`).dim()}`
264
278
  `${format(String(errors.length)).fail().bold()} ${format("test file(s) failed:").bold()}
265
279
  `
266
280
  );
267
- for (const i in errors)
268
- if (Object.prototype.hasOwnProperty.call(errors, i)) {
269
- const { file, output } = errors[i], index = +i;
270
- index > 0 && process$1.stdout.write(`
281
+ for (const i in errors) {
282
+ const { file, output } = errors[i], index = +i;
283
+ index > 0 && process$1.stdout.write(`
271
284
  `), log$1(
272
- `${format(`${index + 1})`).dim().bold()} ${format(file).underline()}`
273
- ), output && log$1(`
285
+ `${format(`${index + 1})`).dim().bold()} ${format(file).underline()}`
286
+ ), output && log$1(`
274
287
  ${output}`);
275
- }
288
+ }
276
289
  }
277
290
  },
278
291
  onExit({ results: results2, timespan: timespan2 }) {
@@ -356,6 +369,10 @@ ${message}
356
369
  },
357
370
  onTodoModifier() {
358
371
  },
372
+ onRetryStart() {
373
+ },
374
+ onRetryEnd() {
375
+ },
359
376
  onFileResult({ status, path, output }) {
360
377
  log$1(`${status ? BADGE_PASS : BADGE_FAIL} ${path.relative}`), status || (countFails++, errors.push({
361
378
  file: path.relative,
@@ -378,6 +395,10 @@ ${message}
378
395
  },
379
396
  onSkipFile() {
380
397
  },
398
+ onRetryStart() {
399
+ },
400
+ onRetryEnd() {
401
+ },
381
402
  onFileResult({ path, status, output }) {
382
403
  process$1.stdout.write(status ? DOT_PASS : DOT_FAIL), status || errors.push({
383
404
  file: path.relative,
@@ -401,6 +422,10 @@ ${message}
401
422
  },
402
423
  onSkipFile() {
403
424
  },
425
+ onRetryStart() {
426
+ },
427
+ onRetryEnd() {
428
+ },
404
429
  onFileResult({ status, output }) {
405
430
  status || (countFails++, output && log$1(output));
406
431
  },
@@ -425,7 +450,7 @@ const states = getSharedState("states", {
425
450
  }), errorHoist = getSharedState("errorHoist", {
426
451
  depth: 0,
427
452
  failed: !1
428
- }), VERSION = "4.3.2", deepOptions = getSharedState("deepOptions", []), GLOBAL = getSharedState("GLOBAL", {
453
+ }), VERSION = "4.3.3-canary.2648bb03", deepOptions = getSharedState("deepOptions", []), GLOBAL = getSharedState("GLOBAL", {
429
454
  cwd: cwd$1,
430
455
  configs: {
431
456
  filter: void 0,
@@ -679,11 +704,14 @@ const poku = (async (targetPaths, configs) => {
679
704
  for (const plugin2 of plugins)
680
705
  plugin2.teardown && await plugin2.teardown(pluginContext);
681
706
  if (GLOBAL.configs.noExit) return code;
707
+ }), retryContext = getSharedState("retryContext", {
708
+ stack: null
682
709
  }), assertProcessor = () => {
683
710
  const { reporter: reporter2 } = GLOBAL, handleSuccess = ({ message }) => {
684
711
  typeof message == "string" && reporter2.onAssertionSuccess({ message });
685
712
  }, handleError = (error, options) => {
686
- throw process$1.exitCode = 1, error instanceof nodeAssert.AssertionError && reporter2.onAssertionFailure({ assertOptions: options, error }), error;
713
+ const ctx = retryContext.stack?.[retryContext.stack.length - 1];
714
+ throw ctx ? ctx.failed = !0 : process$1.exitCode = 1, error instanceof nodeAssert.AssertionError && reporter2.onAssertionFailure({ assertOptions: options, error }), error;
687
715
  };
688
716
  return { processAssert: (cb, options) => {
689
717
  try {
@@ -854,7 +882,8 @@ const poku = (async (targetPaths, configs) => {
854
882
  const insideDescribe = errorHoist.depth > 0;
855
883
  let onError;
856
884
  insideDescribe ? errorHoist.failed = !1 : (onError = (error) => {
857
- process$1.exitCode = 1, success = !1, error instanceof nodeAssert.AssertionError || console.error(error);
885
+ const ctx = retryContext.stack?.[retryContext.stack.length - 1];
886
+ ctx ? ctx.failed = !0 : (process$1.exitCode = 1, success = !1, error instanceof nodeAssert.AssertionError || console.error(error));
858
887
  }, process$1.once("uncaughtException", onError), process$1.once("unhandledRejection", onError)), start = process$1.hrtime();
859
888
  try {
860
889
  const hooks = getScopeHook();
@@ -866,9 +895,15 @@ const poku = (async (targetPaths, configs) => {
866
895
  resultCb instanceof Promise && await resultCb;
867
896
  }
868
897
  } catch (error) {
869
- process$1.exitCode = 1, success = !1, error instanceof nodeAssert.AssertionError || console.error(error);
898
+ const ctx = retryContext.stack?.[retryContext.stack.length - 1];
899
+ ctx ? ctx.failed = !0 : (process$1.exitCode = 1, success = !1, error instanceof nodeAssert.AssertionError || console.error(error));
870
900
  } finally {
871
- end = process$1.hrtime(start), onError ? (process$1.removeListener("uncaughtException", onError), process$1.removeListener("unhandledRejection", onError)) : errorHoist.failed && (success = !1, errorHoist.failed = !1);
901
+ if (end = process$1.hrtime(start), onError)
902
+ process$1.removeListener("uncaughtException", onError), process$1.removeListener("unhandledRejection", onError);
903
+ else if (errorHoist.failed) {
904
+ const ctx = retryContext.stack?.[retryContext.stack.length - 1];
905
+ ctx ? ctx.failed = !0 : success = !1, errorHoist.failed = !1;
906
+ }
872
907
  }
873
908
  if (typeof each.after.cb == "function") {
874
909
  const afterResult = each.after.cb();
@@ -907,7 +942,10 @@ const poku = (async (targetPaths, configs) => {
907
942
  } catch (error) {
908
943
  onError(error);
909
944
  } finally {
910
- end = process$1.hrtime(start), process$1.removeListener("uncaughtException", onError), process$1.removeListener("unhandledRejection", onError), errorHoist.depth--, process$1.exitCode !== initialExitCode && (success = !1);
945
+ if (end = process$1.hrtime(start), process$1.removeListener("uncaughtException", onError), process$1.removeListener("unhandledRejection", onError), errorHoist.depth--, process$1.exitCode !== initialExitCode && (success = !1), !success) {
946
+ const ctx = retryContext.stack?.[retryContext.stack.length - 1];
947
+ ctx && (ctx.failed = !0);
948
+ }
911
949
  }
912
950
  if (!title) return;
913
951
  const duration = end[0] * 1e3 + end[1] / 1e6;
@@ -985,7 +1023,36 @@ const poku = (async (targetPaths, configs) => {
985
1023
  each.after.status = !0;
986
1024
  }, reset: () => {
987
1025
  each.after.cb = void 0;
988
- } }), regex = {
1026
+ } });
1027
+ async function retry(config, callback) {
1028
+ const attempts = typeof config == "number" ? config : config.attempts, delay = typeof config == "number" ? 0 : config.delay ?? 0;
1029
+ retryContext.stack || (retryContext.stack = []);
1030
+ const stack = retryContext.stack;
1031
+ for (let attempt = 1; attempt <= attempts; attempt++) {
1032
+ const context = {
1033
+ attempts,
1034
+ currentAttempt: attempt,
1035
+ delay,
1036
+ failed: !1
1037
+ };
1038
+ stack.push(context), GLOBAL.reporter.onRetryStart?.({ attempt, total: attempts });
1039
+ try {
1040
+ const result = callback();
1041
+ if (result instanceof Promise && await result, !context.failed) {
1042
+ stack.pop(), GLOBAL.reporter.onRetryEnd?.({
1043
+ attempt,
1044
+ total: attempts,
1045
+ success: !0
1046
+ }), stack.length === 0 && (retryContext.stack = null);
1047
+ return;
1048
+ }
1049
+ } catch {
1050
+ }
1051
+ stack.pop(), GLOBAL.reporter.onRetryEnd?.({ attempt, total: attempts, success: !1 }), attempt < attempts && delay > 0 && await new Promise((resolve) => setTimeout(resolve, delay));
1052
+ }
1053
+ stack.length === 0 && (retryContext.stack = null), process.exitCode = 1;
1054
+ }
1055
+ const regex = {
989
1056
  sequentialSpaces: /\s+/
990
1057
  }, setPortsAndPIDs = (portOrPID) => Array.isArray(portOrPID) ? portOrPID : [portOrPID].map((p) => Number(p)).filter((p) => !Number.isNaN(p)), populateRange = (startsAt, endsAt) => {
991
1058
  const first = Number(startsAt), last = Number(endsAt);
@@ -1206,6 +1273,7 @@ exports.onSigint = onSigint;
1206
1273
  exports.parserOutput = parserOutput;
1207
1274
  exports.poku = poku;
1208
1275
  exports.reporter = reporter;
1276
+ exports.retry = retry;
1209
1277
  exports.runner = runner;
1210
1278
  exports.skip = skip;
1211
1279
  exports.sleep = sleep;
@@ -151,6 +151,15 @@ type ReporterPlugin = (configs?: Configs) => {
151
151
  onTodoModifier: (options: {
152
152
  message: string;
153
153
  }) => void;
154
+ onRetryStart: (options: {
155
+ attempt: number;
156
+ total: number;
157
+ }) => void;
158
+ onRetryEnd: (options: {
159
+ attempt: number;
160
+ total: number;
161
+ success: boolean;
162
+ }) => void;
154
163
  onFileStart: (options: {
155
164
  path: Path;
156
165
  }) => void;
@@ -151,6 +151,15 @@ type ReporterPlugin = (configs?: Configs) => {
151
151
  onTodoModifier: (options: {
152
152
  message: string;
153
153
  }) => void;
154
+ onRetryStart: (options: {
155
+ attempt: number;
156
+ total: number;
157
+ }) => void;
158
+ onRetryEnd: (options: {
159
+ attempt: number;
160
+ total: number;
161
+ success: boolean;
162
+ }) => void;
154
163
  onFileStart: (options: {
155
164
  path: Path;
156
165
  }) => void;
@@ -237,6 +237,20 @@ ${preIdentation} ${format(`${options?.expected ?? "Expected"}:`).dim()}`
237
237
  const indent = getIndent();
238
238
  log$1(`${indent}${format(`\u25CF ${message}`).cyan().bold()}`);
239
239
  },
240
+ onRetryStart({ attempt, total }) {
241
+ const indent = indentation.test.repeat(
242
+ indentation.describeDepth + indentation.itDepth
243
+ );
244
+ log$1(`${indent}${format(`\u21BB Retry ${attempt}/${total}`).dim()}`);
245
+ },
246
+ onRetryEnd({ attempt, success }) {
247
+ if (success && attempt > 1) {
248
+ const indent = indentation.test.repeat(
249
+ indentation.describeDepth + indentation.itDepth
250
+ );
251
+ log$1(`${indent}${format("\u2714 Retry succeeded").success().dim()}`);
252
+ }
253
+ },
240
254
  onFileResult({ status, path, duration, output }) {
241
255
  stdout.write(`
242
256
  `), status ? (log$1(
@@ -258,15 +272,14 @@ ${preIdentation} ${format(`${options?.expected ?? "Expected"}:`).dim()}`
258
272
  `${format(String(errors.length)).fail().bold()} ${format("test file(s) failed:").bold()}
259
273
  `
260
274
  );
261
- for (const i in errors)
262
- if (Object.prototype.hasOwnProperty.call(errors, i)) {
263
- const { file, output } = errors[i], index = +i;
264
- index > 0 && stdout.write(`
275
+ for (const i in errors) {
276
+ const { file, output } = errors[i], index = +i;
277
+ index > 0 && stdout.write(`
265
278
  `), log$1(
266
- `${format(`${index + 1})`).dim().bold()} ${format(file).underline()}`
267
- ), output && log$1(`
279
+ `${format(`${index + 1})`).dim().bold()} ${format(file).underline()}`
280
+ ), output && log$1(`
268
281
  ${output}`);
269
- }
282
+ }
270
283
  }
271
284
  },
272
285
  onExit({ results: results2, timespan: timespan2 }) {
@@ -350,6 +363,10 @@ ${message}
350
363
  },
351
364
  onTodoModifier() {
352
365
  },
366
+ onRetryStart() {
367
+ },
368
+ onRetryEnd() {
369
+ },
353
370
  onFileResult({ status, path, output }) {
354
371
  log$1(`${status ? BADGE_PASS : BADGE_FAIL} ${path.relative}`), status || (countFails++, errors.push({
355
372
  file: path.relative,
@@ -372,6 +389,10 @@ ${message}
372
389
  },
373
390
  onSkipFile() {
374
391
  },
392
+ onRetryStart() {
393
+ },
394
+ onRetryEnd() {
395
+ },
375
396
  onFileResult({ path, status, output }) {
376
397
  stdout.write(status ? DOT_PASS : DOT_FAIL), status || errors.push({
377
398
  file: path.relative,
@@ -395,6 +416,10 @@ ${message}
395
416
  },
396
417
  onSkipFile() {
397
418
  },
419
+ onRetryStart() {
420
+ },
421
+ onRetryEnd() {
422
+ },
398
423
  onFileResult({ status, output }) {
399
424
  status || (countFails++, output && log$1(output));
400
425
  },
@@ -419,7 +444,7 @@ const states = getSharedState("states", {
419
444
  }), errorHoist = getSharedState("errorHoist", {
420
445
  depth: 0,
421
446
  failed: !1
422
- }), VERSION = "4.3.2", deepOptions = getSharedState("deepOptions", []), GLOBAL = getSharedState("GLOBAL", {
447
+ }), VERSION = "4.3.3-canary.2648bb03", deepOptions = getSharedState("deepOptions", []), GLOBAL = getSharedState("GLOBAL", {
423
448
  cwd: cwd$1,
424
449
  configs: {
425
450
  filter: void 0,
@@ -687,11 +712,14 @@ const poku = (async (targetPaths, configs) => {
687
712
  for (const plugin2 of plugins)
688
713
  plugin2.teardown && await plugin2.teardown(pluginContext);
689
714
  if (GLOBAL.configs.noExit) return code;
715
+ }), retryContext = getSharedState("retryContext", {
716
+ stack: null
690
717
  }), assertProcessor = () => {
691
718
  const { reporter: reporter2 } = GLOBAL, handleSuccess = ({ message }) => {
692
719
  typeof message == "string" && reporter2.onAssertionSuccess({ message });
693
720
  }, handleError = (error, options) => {
694
- throw process$1.exitCode = 1, error instanceof AssertionError && reporter2.onAssertionFailure({ assertOptions: options, error }), error;
721
+ const ctx = retryContext.stack?.[retryContext.stack.length - 1];
722
+ throw ctx ? ctx.failed = !0 : process$1.exitCode = 1, error instanceof AssertionError && reporter2.onAssertionFailure({ assertOptions: options, error }), error;
695
723
  };
696
724
  return { processAssert: (cb, options) => {
697
725
  try {
@@ -862,7 +890,8 @@ const poku = (async (targetPaths, configs) => {
862
890
  const insideDescribe = errorHoist.depth > 0;
863
891
  let onError;
864
892
  insideDescribe ? errorHoist.failed = !1 : (onError = (error) => {
865
- process$1.exitCode = 1, success = !1, error instanceof AssertionError || console.error(error);
893
+ const ctx = retryContext.stack?.[retryContext.stack.length - 1];
894
+ ctx ? ctx.failed = !0 : (process$1.exitCode = 1, success = !1, error instanceof AssertionError || console.error(error));
866
895
  }, process$1.once("uncaughtException", onError), process$1.once("unhandledRejection", onError)), start = process$1.hrtime();
867
896
  try {
868
897
  const hooks = getScopeHook();
@@ -874,9 +903,15 @@ const poku = (async (targetPaths, configs) => {
874
903
  resultCb instanceof Promise && await resultCb;
875
904
  }
876
905
  } catch (error) {
877
- process$1.exitCode = 1, success = !1, error instanceof AssertionError || console.error(error);
906
+ const ctx = retryContext.stack?.[retryContext.stack.length - 1];
907
+ ctx ? ctx.failed = !0 : (process$1.exitCode = 1, success = !1, error instanceof AssertionError || console.error(error));
878
908
  } finally {
879
- end = process$1.hrtime(start), onError ? (process$1.removeListener("uncaughtException", onError), process$1.removeListener("unhandledRejection", onError)) : errorHoist.failed && (success = !1, errorHoist.failed = !1);
909
+ if (end = process$1.hrtime(start), onError)
910
+ process$1.removeListener("uncaughtException", onError), process$1.removeListener("unhandledRejection", onError);
911
+ else if (errorHoist.failed) {
912
+ const ctx = retryContext.stack?.[retryContext.stack.length - 1];
913
+ ctx ? ctx.failed = !0 : success = !1, errorHoist.failed = !1;
914
+ }
880
915
  }
881
916
  if (typeof each.after.cb == "function") {
882
917
  const afterResult = each.after.cb();
@@ -915,7 +950,10 @@ const poku = (async (targetPaths, configs) => {
915
950
  } catch (error) {
916
951
  onError(error);
917
952
  } finally {
918
- end = process$1.hrtime(start), process$1.removeListener("uncaughtException", onError), process$1.removeListener("unhandledRejection", onError), errorHoist.depth--, process$1.exitCode !== initialExitCode && (success = !1);
953
+ if (end = process$1.hrtime(start), process$1.removeListener("uncaughtException", onError), process$1.removeListener("unhandledRejection", onError), errorHoist.depth--, process$1.exitCode !== initialExitCode && (success = !1), !success) {
954
+ const ctx = retryContext.stack?.[retryContext.stack.length - 1];
955
+ ctx && (ctx.failed = !0);
956
+ }
919
957
  }
920
958
  if (!title) return;
921
959
  const duration = end[0] * 1e3 + end[1] / 1e6;
@@ -993,7 +1031,36 @@ const poku = (async (targetPaths, configs) => {
993
1031
  each.after.status = !0;
994
1032
  }, reset: () => {
995
1033
  each.after.cb = void 0;
996
- } }), regex = {
1034
+ } });
1035
+ async function retry(config, callback) {
1036
+ const attempts = typeof config == "number" ? config : config.attempts, delay = typeof config == "number" ? 0 : config.delay ?? 0;
1037
+ retryContext.stack || (retryContext.stack = []);
1038
+ const stack = retryContext.stack;
1039
+ for (let attempt = 1; attempt <= attempts; attempt++) {
1040
+ const context = {
1041
+ attempts,
1042
+ currentAttempt: attempt,
1043
+ delay,
1044
+ failed: !1
1045
+ };
1046
+ stack.push(context), GLOBAL.reporter.onRetryStart?.({ attempt, total: attempts });
1047
+ try {
1048
+ const result = callback();
1049
+ if (result instanceof Promise && await result, !context.failed) {
1050
+ stack.pop(), GLOBAL.reporter.onRetryEnd?.({
1051
+ attempt,
1052
+ total: attempts,
1053
+ success: !0
1054
+ }), stack.length === 0 && (retryContext.stack = null);
1055
+ return;
1056
+ }
1057
+ } catch {
1058
+ }
1059
+ stack.pop(), GLOBAL.reporter.onRetryEnd?.({ attempt, total: attempts, success: !1 }), attempt < attempts && delay > 0 && await new Promise((resolve2) => setTimeout(resolve2, delay));
1060
+ }
1061
+ stack.length === 0 && (retryContext.stack = null), process.exitCode = 1;
1062
+ }
1063
+ const regex = {
997
1064
  sequentialSpaces: /\s+/
998
1065
  }, setPortsAndPIDs = (portOrPID) => Array.isArray(portOrPID) ? portOrPID : [portOrPID].map((p) => Number(p)).filter((p) => !Number.isNaN(p)), populateRange = (startsAt, endsAt) => {
999
1066
  const first = Number(startsAt), last = Number(endsAt);
@@ -1228,6 +1295,7 @@ export {
1228
1295
  poku,
1229
1296
  reporter,
1230
1297
  results,
1298
+ retry,
1231
1299
  runner,
1232
1300
  skip,
1233
1301
  sleep,
@@ -14,6 +14,7 @@ exports.kill = _shared.kill;
14
14
  exports.listFiles = _shared.listFiles;
15
15
  exports.log = _shared.log;
16
16
  exports.poku = _shared.poku;
17
+ exports.retry = _shared.retry;
17
18
  exports.skip = _shared.skip;
18
19
  exports.sleep = _shared.sleep;
19
20
  exports.startScript = _shared.startScript;
@@ -131,6 +131,13 @@ declare const beforeEach: (callback: () => unknown, options?: EachOptions) => Co
131
131
  */
132
132
  declare const afterEach: (callback: () => unknown) => Control;
133
133
 
134
+ type RetryConfig = {
135
+ attempts: number;
136
+ delay?: number;
137
+ };
138
+
139
+ declare function retry(config: number | RetryConfig, callback: () => unknown | Promise<unknown>): Promise<void>;
140
+
134
141
  type Runner = 'npm' | 'bun' | 'deno' | 'yarn' | 'pnpm';
135
142
 
136
143
  type BackgroundProcessOptions = {
@@ -250,5 +257,5 @@ declare const listFiles: (targetDir: string, configs?: Configs) => Promise<strin
250
257
  /** 🐷 Auxiliary function to define the `poku` configurations */
251
258
  declare const defineConfig: (options: ConfigFile) => ConfigFile;
252
259
 
253
- export { Code, ConfigFile, Configs as ListFilesConfigs, afterEach, assert, beforeEach, defineConfig, describe, envFile, exit, getPIDs, it, kill, listFiles, log, skip, sleep, startScript, startService, strict, test, waitForExpectedResult, waitForPort };
254
- export type { StartScriptOptions, StartServiceOptions, WaitForExpectedResultOptions, WaitForPortOptions };
260
+ export { Code, ConfigFile, Configs as ListFilesConfigs, afterEach, assert, beforeEach, defineConfig, describe, envFile, exit, getPIDs, it, kill, listFiles, log, retry, skip, sleep, startScript, startService, strict, test, waitForExpectedResult, waitForPort };
261
+ export type { RetryConfig, StartScriptOptions, StartServiceOptions, WaitForExpectedResultOptions, WaitForPortOptions };
@@ -131,6 +131,13 @@ declare const beforeEach: (callback: () => unknown, options?: EachOptions) => Co
131
131
  */
132
132
  declare const afterEach: (callback: () => unknown) => Control;
133
133
 
134
+ type RetryConfig = {
135
+ attempts: number;
136
+ delay?: number;
137
+ };
138
+
139
+ declare function retry(config: number | RetryConfig, callback: () => unknown | Promise<unknown>): Promise<void>;
140
+
134
141
  type Runner = 'npm' | 'bun' | 'deno' | 'yarn' | 'pnpm';
135
142
 
136
143
  type BackgroundProcessOptions = {
@@ -250,5 +257,5 @@ declare const listFiles: (targetDir: string, configs?: Configs) => Promise<strin
250
257
  /** 🐷 Auxiliary function to define the `poku` configurations */
251
258
  declare const defineConfig: (options: ConfigFile) => ConfigFile;
252
259
 
253
- export { Code, ConfigFile, Configs as ListFilesConfigs, afterEach, assert, beforeEach, defineConfig, describe, envFile, exit, getPIDs, it, kill, listFiles, log, skip, sleep, startScript, startService, strict, test, waitForExpectedResult, waitForPort };
254
- export type { StartScriptOptions, StartServiceOptions, WaitForExpectedResultOptions, WaitForPortOptions };
260
+ export { Code, ConfigFile, Configs as ListFilesConfigs, afterEach, assert, beforeEach, defineConfig, describe, envFile, exit, getPIDs, it, kill, listFiles, log, retry, skip, sleep, startScript, startService, strict, test, waitForExpectedResult, waitForPort };
261
+ export type { RetryConfig, StartScriptOptions, StartServiceOptions, WaitForExpectedResultOptions, WaitForPortOptions };
@@ -1,4 +1,4 @@
1
- import { afterEach$1, assert, beforeEach$1, describe, envFile, exit, getPIDs, it, kill, listFiles, log, poku, skip, sleep, startScript, startService, strict, test, VERSION, waitForExpectedResult, waitForPort } from "./_shared.js";
1
+ import { afterEach$1, assert, beforeEach$1, describe, envFile, exit, getPIDs, it, kill, listFiles, log, poku, retry, skip, sleep, startScript, startService, strict, test, VERSION, waitForExpectedResult, waitForPort } from "./_shared.js";
2
2
  import "node:path";
3
3
  import "node:process";
4
4
  import "node:os";
@@ -22,6 +22,7 @@ export {
22
22
  listFiles,
23
23
  log,
24
24
  poku,
25
+ retry,
25
26
  skip,
26
27
  sleep,
27
28
  startScript,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poku",
3
- "version": "4.3.2",
3
+ "version": "4.3.3-canary.2648bb03",
4
4
  "description": "🐷 Poku makes testing easy for Node.js, Bun, Deno, and you at the same time.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -52,7 +52,7 @@
52
52
  "build": "bash scripts/build.sh",
53
53
  "lint": "bash scripts/lint.sh",
54
54
  "lint:fix": "bash scripts/lint-fix.sh",
55
- "lint:types": "bash scripts/lint-types.sh",
55
+ "typecheck": "bash scripts/typecheck.sh",
56
56
  "update": "bash scripts/update.sh",
57
57
  "benchmark": "npm --prefix benchmark start"
58
58
  },