vitest 0.0.107 → 0.0.111

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.
@@ -2,15 +2,11 @@ import path$5 from 'path';
2
2
  import fs$5 from 'fs';
3
3
  import require$$0 from 'util';
4
4
  import require$$0$1 from 'child_process';
5
- import { q as commonjsGlobal } from './utils-92ec89d1.js';
6
- import { a as signalExit, b as onetime$1 } from './index-84978a77.js';
5
+ import { c as commonjsGlobal } from './_commonjsHelpers-c9e3b764.js';
6
+ import { a as signalExit, b as onetime$1 } from './index-61c8686f.js';
7
7
  import require$$0$2 from 'os';
8
8
  import require$$0$4 from 'buffer';
9
9
  import require$$0$3 from 'stream';
10
- import 'tty';
11
- import 'local-pkg';
12
- import 'chai';
13
- import 'tinyspy';
14
10
  import 'assert';
15
11
  import 'events';
16
12
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import { Formatter } from 'picocolors/types';
2
+ import { ViteDevServer } from 'vite';
2
3
  import { OptionsReceived } from 'pretty-format';
3
4
  import { MessagePort } from 'worker_threads';
4
- export { assert, default as chai, expect, should } from 'chai';
5
+ export { Spy, SpyFn } from 'tinyspy';
6
+ export { assert, default as chai, should } from 'chai';
5
7
 
6
8
  declare const EXPECTED_COLOR: Formatter;
7
9
  declare const RECEIVED_COLOR: Formatter;
@@ -116,6 +118,7 @@ interface AsymmetricMatcherInterface {
116
118
  declare abstract class AsymmetricMatcher<T, State extends MatcherState = MatcherState> implements AsymmetricMatcherInterface {
117
119
  protected sample: T;
118
120
  protected inverse: boolean;
121
+ $$typeof: symbol;
119
122
  constructor(sample: T, inverse?: boolean);
120
123
  protected getMatcherContext(): State;
121
124
  abstract asymmetricMatch(other: unknown): boolean;
@@ -157,6 +160,123 @@ declare class StringMatching extends AsymmetricMatcher<RegExp> {
157
160
  getExpectedType(): string;
158
161
  }
159
162
 
163
+ declare class SnapshotManager {
164
+ config: ResolvedConfig;
165
+ summary: SnapshotSummary;
166
+ constructor(config: ResolvedConfig);
167
+ clear(): void;
168
+ add(result: SnapshotResult): void;
169
+ }
170
+
171
+ declare type RunWithFiles = (files: string[], invalidates?: string[]) => Promise<void>;
172
+ interface WorkerPool {
173
+ runTests: RunWithFiles;
174
+ collectTests: RunWithFiles;
175
+ close: () => Promise<void>;
176
+ }
177
+
178
+ declare class StateManager {
179
+ filesMap: Record<string, File>;
180
+ idMap: Record<string, Task>;
181
+ taskFileMap: WeakMap<Task, File>;
182
+ getFiles(keys?: string[]): File[];
183
+ collectFiles(files: File[]): void;
184
+ updateId(task: Task): void;
185
+ updateTasks(packs: TaskResultPack[]): void;
186
+ }
187
+
188
+ declare class Vitest {
189
+ config: ResolvedConfig;
190
+ server: ViteDevServer;
191
+ state: StateManager;
192
+ snapshot: SnapshotManager;
193
+ reporters: Reporter[];
194
+ console: Console;
195
+ pool: WorkerPool | undefined;
196
+ invalidates: Set<string>;
197
+ changedTests: Set<string>;
198
+ runningPromise?: Promise<void>;
199
+ isFirstRun: boolean;
200
+ restartsCount: number;
201
+ private _onRestartListeners;
202
+ constructor();
203
+ setServer(options: UserConfig, server: ViteDevServer): void;
204
+ start(filters?: string[]): Promise<void>;
205
+ runFiles(files: string[]): Promise<void>;
206
+ log(...args: any[]): void;
207
+ error(...args: any[]): void;
208
+ private _rerunTimer;
209
+ private scheduleRerun;
210
+ private unregisterWatcher;
211
+ private registerWatcher;
212
+ private handleFileChanged;
213
+ close(): Promise<void>;
214
+ report<T extends keyof Reporter>(name: T, ...args: ArgumentsType<Reporter[T]>): Promise<void>;
215
+ globTestFiles(filters?: string[]): Promise<string[]>;
216
+ isTargetFile(id: string): boolean;
217
+ onServerRestarted(fn: () => void): void;
218
+ }
219
+
220
+ declare abstract class BaseReporter implements Reporter {
221
+ ctx: Vitest;
222
+ start: number;
223
+ end: number;
224
+ watchFilters?: string[];
225
+ isTTY: boolean;
226
+ constructor(ctx: Vitest);
227
+ relative(path: string): string;
228
+ onFinished(files?: File[]): Promise<void>;
229
+ onTaskUpdate(pack: TaskResultPack): void;
230
+ isFirstWatchRun: boolean;
231
+ onWatcherStart(): Promise<void>;
232
+ onWatcherRerun(files: string[], trigger: string): Promise<void>;
233
+ onUserConsoleLog(log: UserConsoleLog): void;
234
+ onServerRestart(): void;
235
+ reportSummary(files: File[]): Promise<void>;
236
+ }
237
+
238
+ interface ListRendererOptions {
239
+ renderSucceed?: boolean;
240
+ }
241
+ declare const createListRenderer: (_tasks: Task[], options?: ListRendererOptions) => {
242
+ start(): any;
243
+ update(_tasks: Task[]): any;
244
+ stop(): Promise<any>;
245
+ clear(): void;
246
+ };
247
+
248
+ declare class DefaultReporter extends BaseReporter {
249
+ renderer?: ReturnType<typeof createListRenderer>;
250
+ rendererOptions: ListRendererOptions;
251
+ onStart(): void;
252
+ onFinished(files?: File[]): Promise<void>;
253
+ onWatcherStart(): Promise<void>;
254
+ stopListRender(): Promise<void>;
255
+ onWatcherRerun(files: string[], trigger: string): Promise<void>;
256
+ onUserConsoleLog(log: UserConsoleLog): void;
257
+ }
258
+
259
+ declare class DotReporter extends BaseReporter {
260
+ renderer?: ReturnType<typeof createListRenderer>;
261
+ onStart(): void;
262
+ onFinished(files?: File[]): Promise<void>;
263
+ onWatcherStart(): Promise<void>;
264
+ stopListRender(): Promise<void>;
265
+ onWatcherRerun(files: string[], trigger: string): Promise<void>;
266
+ onUserConsoleLog(log: UserConsoleLog): void;
267
+ }
268
+
269
+ declare class VerboseReporter extends DefaultReporter {
270
+ constructor(ctx: Vitest);
271
+ }
272
+
273
+ declare const ReportersMap: {
274
+ default: typeof DefaultReporter;
275
+ verbose: typeof VerboseReporter;
276
+ dot: typeof DotReporter;
277
+ };
278
+ declare type BuiltinReporters = keyof typeof ReportersMap;
279
+
160
280
  declare type Awaitable<T> = T | PromiseLike<T>;
161
281
  declare type Nullable<T> = T | null | undefined;
162
282
  declare type Arrayable<T> = T | Array<T>;
@@ -370,7 +490,7 @@ interface InlineConfig {
370
490
  /**
371
491
  * Custom reporter for output
372
492
  */
373
- reporters?: Reporter | Reporter[];
493
+ reporters?: Arrayable<BuiltinReporters | Reporter>;
374
494
  /**
375
495
  * Enable multi-threading
376
496
  *
@@ -507,26 +627,14 @@ declare const suite: ChainableFunction<"skip" | "only" | "todo" | "concurrent",
507
627
  declare const test: TestCollector;
508
628
  declare const describe: ChainableFunction<"skip" | "only" | "todo" | "concurrent", [name: string, factory?: TestFactory | undefined], SuiteCollector>;
509
629
  declare const it: TestCollector;
510
- declare global {
511
- namespace NodeJS {
512
- interface Process {
513
- __vitest_worker__: {
514
- config: ResolvedConfig;
515
- rpc: RpcCall;
516
- send: RpcSend;
517
- current?: Test;
518
- filepath?: string;
519
- moduleCache: Map<string, ModuleCache>;
520
- };
521
- }
522
- }
523
- }
524
630
 
525
631
  declare const beforeAll: (fn: SuiteHooks['beforeAll'][0], timeout?: number | undefined) => void;
526
632
  declare const afterAll: (fn: SuiteHooks['afterAll'][0], timeout?: number | undefined) => void;
527
633
  declare const beforeEach: (fn: SuiteHooks['beforeEach'][0], timeout?: number | undefined) => void;
528
634
  declare const afterEach: (fn: SuiteHooks['afterEach'][0], timeout?: number | undefined) => void;
529
635
 
636
+ declare const expect: (value: any, message?: string | undefined) => Chai.Assertion;
637
+
530
638
  interface MockResultReturn<T> {
531
639
  type: 'return';
532
640
  value: T;
@@ -619,10 +727,60 @@ declare class VitestUtils {
619
727
  getMockedDate(): string | number | Date | null;
620
728
  spyOn: typeof spyOn;
621
729
  fn: typeof fn;
622
- mock(path: string): void;
730
+ /**
731
+ * Makes all `imports` to passed module to be mocked.
732
+ * - If there is a factory, will return it's result. The call to `vi.mock` is hoisted to the top of the file,
733
+ * so you don't have access to variables declared in the global file scope, if you didn't put them before imports!
734
+ * - If `__mocks__` folder with file of the same name exist, all imports will
735
+ * return it.
736
+ * - If there is no `__mocks__` folder or a file with the same name inside, will call original
737
+ * module and mock it.
738
+ * @param path Path to the module. Can be aliased, if your config suppors it
739
+ * @param factory Factory for the mocked module. Has the highest priority.
740
+ */
741
+ mock(path: string, factory?: () => any): void;
742
+ /**
743
+ * Removes module from mocked registry. All subsequent calls to import will
744
+ * return original module even if it was mocked.
745
+ * @param path Path to the module. Can be aliased, if your config suppors it
746
+ */
623
747
  unmock(path: string): void;
748
+ /**
749
+ * Imports module, bypassing all checks if it should be mocked.
750
+ * Can be useful if you want to mock module partially.
751
+ * @example
752
+ * vi.mock('./example', async () => {
753
+ * const axios = await vi.importActual('./example')
754
+ *
755
+ * return { ...axios, get: vi.fn() }
756
+ * })
757
+ * @param path Path to the module. Can be aliased, if your config suppors it
758
+ * @returns Actual module without spies
759
+ */
624
760
  importActual<T>(path: string): Promise<T>;
625
- importMock<T>(path: string): Promise<T>;
761
+ /**
762
+ * Imports a module with all of its properties and nested properties mocked.
763
+ * For the rules applied, see docs.
764
+ * @param path Path to the module. Can be aliased, if your config suppors it
765
+ * @returns Fully mocked module
766
+ */
767
+ importMock<T>(path: string): Promise<MaybeMockedDeep<T>>;
768
+ /**
769
+ * Type helpers for TypeScript. In reality just returns the object that was passed.
770
+ * @example
771
+ * import example from './example'
772
+ * vi.mock('./example')
773
+ *
774
+ * test('1+1 equals 2' async () => {
775
+ * vi.mocked(example.calc).mockRestore()
776
+ *
777
+ * const res = example.calc(1, '+', 1)
778
+ *
779
+ * expect(res).toBe(2)
780
+ * })
781
+ * @param item Anything that can be mocked
782
+ * @param deep If the object is deeply mocked
783
+ */
626
784
  mocked<T>(item: T, deep?: false): MaybeMocked<T>;
627
785
  mocked<T>(item: T, deep: true): MaybeMockedDeep<T>;
628
786
  isMockFunction(fn: any): any;
@@ -653,6 +811,7 @@ declare global {
653
811
  any(constructor: unknown): Any;
654
812
  arrayContaining(expected: any): ArrayContaining;
655
813
  stringMatching(expected: RegExp): StringMatching;
814
+ assertions(expected: number): void;
656
815
  }
657
816
  interface Assertion {
658
817
  chaiEqual(expected: any): void;
@@ -707,4 +866,4 @@ declare global {
707
866
  }
708
867
  }
709
868
 
710
- export { ArgumentsOf, ArgumentsType, Arrayable, Awaitable, BuiltinEnvironment, ComputeMode, ConstructorArgumentsOf, DoneCallback, Environment, EnvironmentReturn, File, HookListener, InlineConfig, JestMockCompat, JestMockCompatContext, JestMockCompatFn, MaybeMocked, MaybeMockedConstructor, MaybeMockedDeep, MethodKeysOf, MockWithArgs, MockableFunction, MockedFunction, MockedFunctionDeep, MockedObject, MockedObjectDeep, ModuleCache, Nullable, PropertyKeysOf, Reporter, ResolvedConfig, RpcCall, RpcMap, RpcPayload, RpcSend, RunMode, RuntimeContext, SnapshotData, SnapshotMatchOptions, SnapshotResult, SnapshotStateOptions, SnapshotSummary, SnapshotUpdateState, Suite, SuiteCollector, SuiteHooks, Task, TaskBase, TaskResult, TaskResultPack, TaskState, Test, TestCollector, TestFactory, TestFunction, UncheckedSnapshot, UserConfig, UserConsoleLog, WorkerContext, afterAll, afterEach, beforeAll, beforeEach, describe, fn, it, spies, spyOn, suite, test, vi, vitest };
869
+ export { ArgumentsOf, ArgumentsType, Arrayable, Awaitable, BuiltinEnvironment, ComputeMode, ConstructorArgumentsOf, DoneCallback, Environment, EnvironmentReturn, File, HookListener, InlineConfig, JestMockCompat, JestMockCompatContext, JestMockCompatFn, MaybeMocked, MaybeMockedConstructor, MaybeMockedDeep, MethodKeysOf, MockWithArgs, MockableFunction, MockedFunction, MockedFunctionDeep, MockedObject, MockedObjectDeep, ModuleCache, Nullable, PropertyKeysOf, Reporter, ResolvedConfig, RpcCall, RpcMap, RpcPayload, RpcSend, RunMode, RuntimeContext, SnapshotData, SnapshotMatchOptions, SnapshotResult, SnapshotStateOptions, SnapshotSummary, SnapshotUpdateState, Suite, SuiteCollector, SuiteHooks, Task, TaskBase, TaskResult, TaskResultPack, TaskState, Test, TestCollector, TestFactory, TestFunction, UncheckedSnapshot, UserConfig, UserConsoleLog, WorkerContext, afterAll, afterEach, beforeAll, beforeEach, describe, expect, fn, it, spies, spyOn, suite, test, vi, vitest };
package/dist/index.js CHANGED
@@ -1,9 +1,10 @@
1
- export { d as describe, i as it, s as suite, t as test } from './suite-ff89a82e.js';
2
- export { a as afterAll, d as afterEach, b as beforeAll, c as beforeEach } from './index-77f19d39.js';
3
- export { assert, default as chai, expect, should } from 'chai';
4
- export { f as fn, s as spies, a as spyOn, b as vi, v as vitest } from './utils-92ec89d1.js';
5
- import './index-9e71c815.js';
1
+ export { d as describe, i as it, c as suite, t as test, e as vi, v as vitest } from './vi-cb9e4e4e.js';
2
+ export { a as afterAll, d as afterEach, b as beforeAll, c as beforeEach, e as expect } from './index-2bb9fd4d.js';
3
+ export { f as fn, s as spies, a as spyOn } from './jest-mock-a57b745c.js';
4
+ export { assert, default as chai, should } from 'chai';
5
+ import './utils-cb6b1266.js';
6
6
  import 'tty';
7
7
  import 'local-pkg';
8
8
  import 'path';
9
+ import './_commonjsHelpers-c9e3b764.js';
9
10
  import 'tinyspy';
@@ -0,0 +1,101 @@
1
+ import { util } from 'chai';
2
+ import * as tinyspy from 'tinyspy';
3
+
4
+ let urlAlphabet =
5
+ 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict';
6
+ let nanoid = (size = 21) => {
7
+ let id = '';
8
+ let i = size;
9
+ while (i--) {
10
+ id += urlAlphabet[(Math.random() * 64) | 0];
11
+ }
12
+ return id
13
+ };
14
+
15
+ const spies = /* @__PURE__ */ new Set();
16
+ function spyOn(obj, method, accessType) {
17
+ const dictionary = {
18
+ get: "getter",
19
+ set: "setter"
20
+ };
21
+ const objMethod = accessType ? { [dictionary[accessType]]: method } : method;
22
+ const stub = tinyspy.spyOn(obj, objMethod);
23
+ return enhanceSpy(stub);
24
+ }
25
+ function enhanceSpy(spy) {
26
+ const stub = spy;
27
+ let implementation;
28
+ const instances = [];
29
+ const mockContext = {
30
+ get calls() {
31
+ return stub.calls;
32
+ },
33
+ get instances() {
34
+ return instances;
35
+ },
36
+ get invocationCallOrder() {
37
+ return [];
38
+ },
39
+ get results() {
40
+ return stub.results.map(([callType, value]) => {
41
+ const type = callType === "error" ? "throw" : "return";
42
+ return { type, value };
43
+ });
44
+ }
45
+ };
46
+ let onceImplementations = [];
47
+ let name = stub.name;
48
+ stub.getMockName = () => name || "vi.fn()";
49
+ stub.mockName = (n) => {
50
+ name = n;
51
+ return stub;
52
+ };
53
+ stub.mockClear = () => {
54
+ stub.reset();
55
+ return stub;
56
+ };
57
+ stub.mockReset = () => {
58
+ stub.reset();
59
+ implementation = () => void 0;
60
+ onceImplementations = [];
61
+ return stub;
62
+ };
63
+ stub.mockRestore = () => {
64
+ stub.mockReset();
65
+ implementation = void 0;
66
+ return stub;
67
+ };
68
+ stub.getMockImplementation = () => implementation;
69
+ stub.mockImplementation = (fn2) => {
70
+ implementation = fn2;
71
+ return stub;
72
+ };
73
+ stub.mockImplementationOnce = (fn2) => {
74
+ onceImplementations.push(fn2);
75
+ return stub;
76
+ };
77
+ stub.mockReturnThis = () => stub.mockImplementation(function() {
78
+ return this;
79
+ });
80
+ stub.mockReturnValue = (val) => stub.mockImplementation(() => val);
81
+ stub.mockReturnValueOnce = (val) => stub.mockImplementationOnce(() => val);
82
+ stub.mockResolvedValue = (val) => stub.mockImplementation(() => Promise.resolve(val));
83
+ stub.mockResolvedValueOnce = (val) => stub.mockImplementationOnce(() => Promise.resolve(val));
84
+ stub.mockRejectedValue = (val) => stub.mockImplementation(() => Promise.reject(val));
85
+ stub.mockRejectedValueOnce = (val) => stub.mockImplementationOnce(() => Promise.reject(val));
86
+ util.addProperty(stub, "mock", () => mockContext);
87
+ stub.willCall(function(...args) {
88
+ instances.push(this);
89
+ const impl = onceImplementations.shift() || implementation || stub.getOriginal() || (() => {
90
+ });
91
+ return impl.apply(this, args);
92
+ });
93
+ spies.add(stub);
94
+ return stub;
95
+ }
96
+ function fn(implementation) {
97
+ return enhanceSpy(tinyspy.spyOn({ fn: implementation || (() => {
98
+ }) }, "fn"));
99
+ }
100
+
101
+ export { spyOn as a, fn as f, nanoid as n, spies as s };
@@ -1,11 +1,9 @@
1
- import { A as API_PATH } from './constants-82dad049.js';
1
+ import { A as API_PATH } from './constants-2b0310b7.js';
2
2
  import 'url';
3
- import './utils-92ec89d1.js';
3
+ import './utils-cb6b1266.js';
4
4
  import 'tty';
5
5
  import 'local-pkg';
6
6
  import 'path';
7
- import 'chai';
8
- import 'tinyspy';
9
7
 
10
8
  /*! (c) 2020 Andrea Giammarchi */
11
9
 
package/dist/node.d.ts CHANGED
@@ -1,7 +1,68 @@
1
1
  import { ViteDevServer, UserConfig as UserConfig$1 } from 'vite';
2
2
  import { OptionsReceived } from 'pretty-format';
3
3
 
4
+ declare abstract class BaseReporter implements Reporter {
5
+ ctx: Vitest;
6
+ start: number;
7
+ end: number;
8
+ watchFilters?: string[];
9
+ isTTY: boolean;
10
+ constructor(ctx: Vitest);
11
+ relative(path: string): string;
12
+ onFinished(files?: File[]): Promise<void>;
13
+ onTaskUpdate(pack: TaskResultPack): void;
14
+ isFirstWatchRun: boolean;
15
+ onWatcherStart(): Promise<void>;
16
+ onWatcherRerun(files: string[], trigger: string): Promise<void>;
17
+ onUserConsoleLog(log: UserConsoleLog): void;
18
+ onServerRestart(): void;
19
+ reportSummary(files: File[]): Promise<void>;
20
+ }
21
+
22
+ interface ListRendererOptions {
23
+ renderSucceed?: boolean;
24
+ }
25
+ declare const createListRenderer: (_tasks: Task[], options?: ListRendererOptions) => {
26
+ start(): any;
27
+ update(_tasks: Task[]): any;
28
+ stop(): Promise<any>;
29
+ clear(): void;
30
+ };
31
+
32
+ declare class DefaultReporter extends BaseReporter {
33
+ renderer?: ReturnType<typeof createListRenderer>;
34
+ rendererOptions: ListRendererOptions;
35
+ onStart(): void;
36
+ onFinished(files?: File[]): Promise<void>;
37
+ onWatcherStart(): Promise<void>;
38
+ stopListRender(): Promise<void>;
39
+ onWatcherRerun(files: string[], trigger: string): Promise<void>;
40
+ onUserConsoleLog(log: UserConsoleLog): void;
41
+ }
42
+
43
+ declare class DotReporter extends BaseReporter {
44
+ renderer?: ReturnType<typeof createListRenderer>;
45
+ onStart(): void;
46
+ onFinished(files?: File[]): Promise<void>;
47
+ onWatcherStart(): Promise<void>;
48
+ stopListRender(): Promise<void>;
49
+ onWatcherRerun(files: string[], trigger: string): Promise<void>;
50
+ onUserConsoleLog(log: UserConsoleLog): void;
51
+ }
52
+
53
+ declare class VerboseReporter extends DefaultReporter {
54
+ constructor(ctx: Vitest);
55
+ }
56
+
57
+ declare const ReportersMap: {
58
+ default: typeof DefaultReporter;
59
+ verbose: typeof VerboseReporter;
60
+ dot: typeof DotReporter;
61
+ };
62
+ declare type BuiltinReporters = keyof typeof ReportersMap;
63
+
4
64
  declare type Awaitable<T> = T | PromiseLike<T>;
65
+ declare type Arrayable<T> = T | Array<T>;
5
66
  declare type ArgumentsType<T> = T extends (...args: infer U) => any ? U : never;
6
67
  interface UserConsoleLog {
7
68
  content: string;
@@ -156,7 +217,7 @@ interface InlineConfig {
156
217
  /**
157
218
  * Custom reporter for output
158
219
  */
159
- reporters?: Reporter | Reporter[];
220
+ reporters?: Arrayable<BuiltinReporters | Reporter>;
160
221
  /**
161
222
  * Enable multi-threading
162
223
  *
package/dist/node.js CHANGED
@@ -1,10 +1,8 @@
1
- export { c as createVitest } from './index-8cc284f9.js';
2
- import './utils-92ec89d1.js';
1
+ export { c as createVitest } from './index-8ab26d25.js';
2
+ import './utils-cb6b1266.js';
3
3
  import 'tty';
4
4
  import 'local-pkg';
5
5
  import 'path';
6
- import 'chai';
7
- import 'tinyspy';
8
6
  import 'vite';
9
7
  import 'process';
10
8
  import 'fs';
@@ -12,11 +10,12 @@ import 'os';
12
10
  import 'util';
13
11
  import 'stream';
14
12
  import 'events';
15
- import './constants-82dad049.js';
13
+ import './constants-2b0310b7.js';
16
14
  import 'url';
17
15
  import 'perf_hooks';
18
- import './error-e81aa23d.js';
19
- import './index-84978a77.js';
16
+ import './diff-66d6bb83.js';
17
+ import './index-61c8686f.js';
18
+ import './_commonjsHelpers-c9e3b764.js';
20
19
  import 'assert';
21
20
  import 'worker_threads';
22
21
  import 'tinypool';