@modern-js/plugin 1.0.0 → 1.1.2
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/CHANGELOG.md +18 -0
- package/README.md +1 -4
- package/dist/js/modern/index.js +2 -3
- package/dist/js/modern/manager/async.js +1 -1
- package/dist/js/modern/manager/runner.js +1 -1
- package/dist/js/modern/manager/sync.js +1 -6
- package/dist/js/modern/waterfall/async.js +28 -34
- package/dist/js/modern/waterfall/sync.js +29 -36
- package/dist/js/modern/workflow/async.js +31 -30
- package/dist/js/modern/workflow/parallel.js +20 -29
- package/dist/js/modern/workflow/sync.js +20 -27
- package/dist/js/node/index.js +12 -25
- package/dist/js/node/manager/async.js +4 -4
- package/dist/js/node/manager/runner.js +2 -2
- package/dist/js/node/manager/sync.js +6 -12
- package/dist/js/node/waterfall/async.js +27 -34
- package/dist/js/node/waterfall/sync.js +29 -36
- package/dist/js/node/workflow/async.js +30 -30
- package/dist/js/node/workflow/parallel.js +19 -29
- package/dist/js/node/workflow/sync.js +19 -27
- package/dist/js/treeshaking/index.js +2 -3
- package/dist/js/treeshaking/manager/async.js +1 -1
- package/dist/js/treeshaking/manager/runner.js +1 -1
- package/dist/js/treeshaking/manager/sync.js +1 -6
- package/dist/js/treeshaking/waterfall/async.js +63 -108
- package/dist/js/treeshaking/waterfall/sync.js +36 -39
- package/dist/js/treeshaking/workflow/async.js +89 -88
- package/dist/js/treeshaking/workflow/parallel.js +42 -66
- package/dist/js/treeshaking/workflow/sync.js +50 -30
- package/dist/types/index.d.ts +2 -3
- package/dist/types/manager/runner.d.ts +1 -1
- package/dist/types/manager/sync.d.ts +2 -3
- package/dist/types/waterfall/async.d.ts +9 -5
- package/dist/types/waterfall/sync.d.ts +4 -4
- package/dist/types/workflow/async.d.ts +3 -2
- package/dist/types/workflow/parallel.d.ts +1 -1
- package/dist/types/workflow/sync.d.ts +1 -1
- package/node.d.ts +1 -1
- package/node.js +1 -1
- package/package.json +5 -4
- package/src/index.ts +2 -2
- package/src/manager/async.ts +1 -1
- package/src/manager/runner.ts +1 -1
- package/src/manager/sync.ts +12 -16
- package/src/waterfall/async.ts +34 -49
- package/src/waterfall/sync.ts +26 -45
- package/src/workflow/async.ts +29 -33
- package/src/workflow/parallel.ts +17 -35
- package/src/workflow/sync.ts +13 -35
- package/tests/.eslintrc.js +6 -0
- package/tests/async.test.ts +7 -3
- package/tests/fixtures/async/base/foo.ts +0 -1
- package/tests/fixtures/async/base/fooManager.ts +1 -1
- package/tests/fixtures/async/core/index.ts +1 -1
- package/tests/fixtures/async/dynamic/bar.ts +0 -1
- package/tests/fixtures/async/dynamic/foo.ts +1 -1
- package/tests/fixtures/sync/base/foo.ts +0 -2
- package/tests/fixtures/sync/base/fooManager.ts +1 -1
- package/tests/fixtures/sync/core/index.ts +1 -1
- package/tests/fixtures/sync/dynamic/bar.ts +0 -1
- package/tests/fixtures/sync/dynamic/foo.ts +1 -1
- package/tests/pipeline.test.ts +4 -15
- package/tests/sync.test.ts +6 -2
- package/tests/waterfall.test.ts +1 -2
- package/dist/js/modern/asyncHooksImpl.js +0 -63
- package/dist/js/modern/asyncHooksInterface.js +0 -16
- package/dist/js/modern/context.js +0 -130
- package/dist/js/modern/counter.js +0 -40
- package/dist/js/modern/hook.js +0 -47
- package/dist/js/modern/pipeline/async.js +0 -97
- package/dist/js/modern/pipeline/index.js +0 -2
- package/dist/js/modern/pipeline/sync.js +0 -97
- package/dist/js/node/asyncHooksImpl.js +0 -82
- package/dist/js/node/asyncHooksInterface.js +0 -30
- package/dist/js/node/context.js +0 -164
- package/dist/js/node/counter.js +0 -52
- package/dist/js/node/hook.js +0 -57
- package/dist/js/node/pipeline/async.js +0 -110
- package/dist/js/node/pipeline/index.js +0 -31
- package/dist/js/node/pipeline/sync.js +0 -110
- package/dist/js/treeshaking/asyncHooksImpl.js +0 -65
- package/dist/js/treeshaking/asyncHooksInterface.js +0 -16
- package/dist/js/treeshaking/context.js +0 -137
- package/dist/js/treeshaking/counter.js +0 -74
- package/dist/js/treeshaking/hook.js +0 -51
- package/dist/js/treeshaking/pipeline/async.js +0 -165
- package/dist/js/treeshaking/pipeline/index.js +0 -2
- package/dist/js/treeshaking/pipeline/sync.js +0 -118
- package/dist/types/asyncHooksImpl.d.ts +0 -10
- package/dist/types/asyncHooksInterface.d.ts +0 -21
- package/dist/types/context.d.ts +0 -47
- package/dist/types/counter.d.ts +0 -22
- package/dist/types/hook.d.ts +0 -13
- package/dist/types/pipeline/async.d.ts +0 -35
- package/dist/types/pipeline/index.d.ts +0 -2
- package/dist/types/pipeline/sync.d.ts +0 -37
- package/src/asyncHooksImpl.ts +0 -64
- package/src/asyncHooksInterface.ts +0 -34
- package/src/context.ts +0 -184
- package/src/counter.ts +0 -78
- package/src/hook.ts +0 -46
- package/src/pipeline/async.ts +0 -155
- package/src/pipeline/index.ts +0 -2
- package/src/pipeline/sync.ts +0 -152
- package/tests/context.test.ts +0 -114
- package/tests/counter.test.ts +0 -32
- package/tests/hook.test.ts +0 -113
package/src/context.ts
DELETED
@@ -1,184 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Copyright Lucifier129 and other contributors.
|
3
|
-
*
|
4
|
-
* This source code is licensed under the MIT license found in the
|
5
|
-
* LICENSE file at
|
6
|
-
* https://github.com/farrow-js/farrow/blob/master/LICENSE
|
7
|
-
*
|
8
|
-
*/
|
9
|
-
|
10
|
-
import { createHooks } from './hook';
|
11
|
-
|
12
|
-
const ContextSymbol = Symbol('Context');
|
13
|
-
|
14
|
-
export type Context<T = any> = {
|
15
|
-
id: symbol;
|
16
|
-
[ContextSymbol]: T;
|
17
|
-
// create a new context equipped a new value
|
18
|
-
create: (value: T) => Context<T>;
|
19
|
-
// get context ref { value } for accessing context in current container of waterfall
|
20
|
-
use: () => {
|
21
|
-
value: T;
|
22
|
-
};
|
23
|
-
// get context value
|
24
|
-
get: () => T;
|
25
|
-
// set context value
|
26
|
-
set: (value: T) => void;
|
27
|
-
// assert context value is not null or undefined and return context value
|
28
|
-
assert: () => Exclude<T, undefined | null>;
|
29
|
-
};
|
30
|
-
|
31
|
-
export const isContext = (input: any): input is Context =>
|
32
|
-
Object.prototype.hasOwnProperty.call(input, ContextSymbol);
|
33
|
-
|
34
|
-
type AssertContext = (input: any) => asserts input is Context;
|
35
|
-
|
36
|
-
export const assertContext: AssertContext = input => {
|
37
|
-
if (!isContext(input)) {
|
38
|
-
throw new Error(`Expected Context, but received ${input}`);
|
39
|
-
}
|
40
|
-
};
|
41
|
-
|
42
|
-
export const createContext = <T>(value: T) => {
|
43
|
-
const id = Symbol('ContextID');
|
44
|
-
|
45
|
-
// eslint-disable-next-line @typescript-eslint/no-shadow
|
46
|
-
const create = (value: T): Context<T> => {
|
47
|
-
const use = () => {
|
48
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
49
|
-
const container = useContainer();
|
50
|
-
return Object.seal({
|
51
|
-
get value() {
|
52
|
-
return container.read(Context);
|
53
|
-
},
|
54
|
-
set value(v) {
|
55
|
-
container.write(Context, v);
|
56
|
-
},
|
57
|
-
});
|
58
|
-
};
|
59
|
-
const get = () => {
|
60
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
61
|
-
const container = useContainer();
|
62
|
-
return container.read(Context);
|
63
|
-
};
|
64
|
-
const set = (v: T) => {
|
65
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
66
|
-
const container = useContainer();
|
67
|
-
container.write(Context, v);
|
68
|
-
};
|
69
|
-
const assert = () => {
|
70
|
-
// eslint-disable-next-line @typescript-eslint/no-shadow
|
71
|
-
const value = get();
|
72
|
-
if (value === null || value === undefined) {
|
73
|
-
throw new Error(
|
74
|
-
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
75
|
-
`Expected value is not null or undefined, but got: ${value}`,
|
76
|
-
);
|
77
|
-
}
|
78
|
-
return value as Exclude<T, null | undefined>;
|
79
|
-
};
|
80
|
-
const Context: Context<T> = {
|
81
|
-
id,
|
82
|
-
[ContextSymbol]: value,
|
83
|
-
create,
|
84
|
-
use,
|
85
|
-
get,
|
86
|
-
set,
|
87
|
-
assert,
|
88
|
-
};
|
89
|
-
return Context;
|
90
|
-
};
|
91
|
-
|
92
|
-
return create(value);
|
93
|
-
};
|
94
|
-
|
95
|
-
export type ContextStorage = {
|
96
|
-
[key: string]: Context;
|
97
|
-
};
|
98
|
-
|
99
|
-
export const ContainerSymbol = Symbol('Container');
|
100
|
-
|
101
|
-
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
102
|
-
export type ContextSymbol = typeof ContainerSymbol;
|
103
|
-
|
104
|
-
export const isContainer = (input: any): input is Container =>
|
105
|
-
Boolean(input?.[ContainerSymbol]);
|
106
|
-
|
107
|
-
type AssertContainer = (input: any) => asserts input is Container;
|
108
|
-
|
109
|
-
export const assertContainer: AssertContainer = input => {
|
110
|
-
if (!isContainer(input)) {
|
111
|
-
throw new Error(`Expected Context, but received ${input}`);
|
112
|
-
}
|
113
|
-
};
|
114
|
-
|
115
|
-
export type Container = {
|
116
|
-
[ContainerSymbol]: true;
|
117
|
-
read: <V>(Context: Context<V>) => V;
|
118
|
-
write: <V>(Context: Context<V>, value: V) => void;
|
119
|
-
};
|
120
|
-
|
121
|
-
const createContextMap = (storage: ContextStorage) => {
|
122
|
-
const contextMap = new Map<symbol, Context>();
|
123
|
-
|
124
|
-
Object.values(storage).forEach(context => {
|
125
|
-
contextMap.set(context.id, context);
|
126
|
-
});
|
127
|
-
|
128
|
-
return contextMap;
|
129
|
-
};
|
130
|
-
|
131
|
-
export const createContainer = (
|
132
|
-
ContextStorage: ContextStorage = {},
|
133
|
-
): Container => {
|
134
|
-
const contextMap = createContextMap(ContextStorage);
|
135
|
-
|
136
|
-
const read: Container['read'] = context => {
|
137
|
-
const target = contextMap.get(context.id);
|
138
|
-
if (target) {
|
139
|
-
return target[ContextSymbol];
|
140
|
-
}
|
141
|
-
return context[ContextSymbol];
|
142
|
-
};
|
143
|
-
|
144
|
-
const write: Container['write'] = (context, value) => {
|
145
|
-
contextMap.set(context.id, context.create(value));
|
146
|
-
};
|
147
|
-
|
148
|
-
const container: Container = Object.freeze({
|
149
|
-
[ContainerSymbol]: true,
|
150
|
-
read,
|
151
|
-
write,
|
152
|
-
});
|
153
|
-
|
154
|
-
return container;
|
155
|
-
};
|
156
|
-
|
157
|
-
export type ValueFromContext<C extends Context> = C extends Context<infer V>
|
158
|
-
? V
|
159
|
-
: never;
|
160
|
-
|
161
|
-
export type Hooks = {
|
162
|
-
useContainer: () => Container;
|
163
|
-
};
|
164
|
-
|
165
|
-
const { run, hooks } = createHooks<Hooks>({
|
166
|
-
useContainer: () => {
|
167
|
-
throw new Error(
|
168
|
-
`Can't call useContainer out of scope, it should be placed on top of the function`,
|
169
|
-
);
|
170
|
-
},
|
171
|
-
});
|
172
|
-
|
173
|
-
export const runHooks = run;
|
174
|
-
|
175
|
-
export const { useContainer } = hooks;
|
176
|
-
|
177
|
-
export const fromContainer = (container: Container): Hooks => ({
|
178
|
-
useContainer: () => container,
|
179
|
-
});
|
180
|
-
|
181
|
-
export const runWithContainer = <F extends (...args: any) => any>(
|
182
|
-
f: F,
|
183
|
-
container: Container,
|
184
|
-
) => runHooks(f, fromContainer(container));
|
package/src/counter.ts
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Copyright Lucifier129 and other contributors.
|
3
|
-
*
|
4
|
-
* This source code is licensed under the MIT license found in the
|
5
|
-
* LICENSE file at
|
6
|
-
* https://github.com/farrow-js/farrow/blob/master/LICENSE
|
7
|
-
*
|
8
|
-
*/
|
9
|
-
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
11
|
-
export type Next<I = unknown, O = void> = (input?: I) => O;
|
12
|
-
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
14
|
-
export type CounterCallback<I = unknown, O = void> = (
|
15
|
-
index: number,
|
16
|
-
input: I,
|
17
|
-
next: Next<I, O>,
|
18
|
-
) => O;
|
19
|
-
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
21
|
-
export type Counter<I = unknown, O = void> = {
|
22
|
-
start: (input: I) => O;
|
23
|
-
dispatch: (index: number, input: I) => O;
|
24
|
-
};
|
25
|
-
|
26
|
-
export const createCounter = <I, O>(
|
27
|
-
callback: CounterCallback<I, O>,
|
28
|
-
): Counter<I, O> => {
|
29
|
-
type Dispatch = Counter<I, O>['dispatch'];
|
30
|
-
type Start = Counter<I, O>['start'];
|
31
|
-
|
32
|
-
const dispatch: Dispatch = (index, input) => {
|
33
|
-
const next = (nextInput = input) => dispatch(index + 1, nextInput);
|
34
|
-
return callback(index, input, next);
|
35
|
-
};
|
36
|
-
|
37
|
-
const start: Start = input => dispatch(0, input);
|
38
|
-
|
39
|
-
return {
|
40
|
-
start,
|
41
|
-
dispatch,
|
42
|
-
};
|
43
|
-
};
|
44
|
-
|
45
|
-
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
46
|
-
export type AsyncNext<I = unknown, O = void> = (input: I) => Promise<O>;
|
47
|
-
|
48
|
-
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
49
|
-
export type AsyncCounterCallback<I = unknown, O = void> = (
|
50
|
-
index: number,
|
51
|
-
input: I,
|
52
|
-
next: AsyncNext<I, O>,
|
53
|
-
) => Promise<O>;
|
54
|
-
|
55
|
-
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
56
|
-
export type AsyncCounter<I = unknown, O = void> = {
|
57
|
-
start: (input: I) => Promise<O>;
|
58
|
-
dispatch: (index: number, input: I) => Promise<O>;
|
59
|
-
};
|
60
|
-
|
61
|
-
export const createAsyncCounter = <I, O>(
|
62
|
-
callback: AsyncCounterCallback<I, O>,
|
63
|
-
): AsyncCounter<I, O> => {
|
64
|
-
type Dispatch = AsyncCounter<I, O>['dispatch'];
|
65
|
-
type Start = AsyncCounter<I, O>['start'];
|
66
|
-
|
67
|
-
const dispatch: Dispatch = async (index, input) => {
|
68
|
-
const next = (nextInput = input) => dispatch(index + 1, nextInput);
|
69
|
-
return callback(index, input, next);
|
70
|
-
};
|
71
|
-
|
72
|
-
const start: Start = input => dispatch(0, input);
|
73
|
-
|
74
|
-
return {
|
75
|
-
start,
|
76
|
-
dispatch,
|
77
|
-
};
|
78
|
-
};
|
package/src/hook.ts
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Copyright Lucifier129 and other contributors.
|
3
|
-
*
|
4
|
-
* This source code is licensed under the MIT license found in the
|
5
|
-
* LICENSE file at
|
6
|
-
* https://github.com/farrow-js/farrow/blob/master/LICENSE
|
7
|
-
*
|
8
|
-
*/
|
9
|
-
|
10
|
-
import { Hooks, AnyFn, asyncHooks } from './asyncHooksInterface';
|
11
|
-
|
12
|
-
export const createHooks = <HS extends Hooks>(defaultHooks: HS) => {
|
13
|
-
let currentHooks = {} as HS;
|
14
|
-
|
15
|
-
const hooks = {} as HS;
|
16
|
-
|
17
|
-
for (const key in defaultHooks) {
|
18
|
-
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
19
|
-
const f = ((...args) => {
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-shadow
|
21
|
-
const hooks =
|
22
|
-
currentHooks === defaultHooks
|
23
|
-
? asyncHooks?.get() ?? defaultHooks
|
24
|
-
: currentHooks;
|
25
|
-
let handler = hooks[key];
|
26
|
-
if (typeof handler !== 'function') {
|
27
|
-
handler = defaultHooks[key];
|
28
|
-
}
|
29
|
-
return handler(...args);
|
30
|
-
}) as HS[typeof key];
|
31
|
-
|
32
|
-
hooks[key] = f;
|
33
|
-
}
|
34
|
-
|
35
|
-
const run = <F extends AnyFn>(f: F, implementations?: HS): ReturnType<F> => {
|
36
|
-
try {
|
37
|
-
currentHooks = implementations || defaultHooks;
|
38
|
-
asyncHooks?.set(currentHooks);
|
39
|
-
return f();
|
40
|
-
} finally {
|
41
|
-
currentHooks = defaultHooks;
|
42
|
-
}
|
43
|
-
};
|
44
|
-
|
45
|
-
return { run, hooks };
|
46
|
-
};
|
package/src/pipeline/async.ts
DELETED
@@ -1,155 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Copyright Lucifier129 and other contributors.
|
3
|
-
*
|
4
|
-
* This source code is licensed under the MIT license found in the
|
5
|
-
* LICENSE file at
|
6
|
-
* https://github.com/farrow-js/farrow/blob/master/LICENSE
|
7
|
-
*
|
8
|
-
*/
|
9
|
-
|
10
|
-
import {
|
11
|
-
createContainer,
|
12
|
-
Container,
|
13
|
-
fromContainer,
|
14
|
-
runHooks,
|
15
|
-
useContainer,
|
16
|
-
Hooks,
|
17
|
-
} from '../context';
|
18
|
-
|
19
|
-
import { AsyncNext, createAsyncCounter } from '../counter';
|
20
|
-
|
21
|
-
import type { PipelineOptions } from './sync';
|
22
|
-
|
23
|
-
export type AsyncMiddleware<I = unknown, O = unknown> = (
|
24
|
-
input: I,
|
25
|
-
next: AsyncNext<I, O>,
|
26
|
-
) => O | Promise<O>;
|
27
|
-
|
28
|
-
export type AsyncMiddlewares<I = unknown, O = unknown> = AsyncMiddleware<
|
29
|
-
I,
|
30
|
-
O
|
31
|
-
>[];
|
32
|
-
|
33
|
-
const ASYNC_PIPELINE_SYMBOL = Symbol('ASYNC_PIPELINE_SYMBOL');
|
34
|
-
export const isAsyncPipeline = (input: any): input is AsyncPipeline =>
|
35
|
-
Boolean(input?.[ASYNC_PIPELINE_SYMBOL]);
|
36
|
-
|
37
|
-
export type RunAsyncPipelineOptions<I = unknown, O = unknown> = {
|
38
|
-
container?: Container;
|
39
|
-
onLast?: (input: I) => O | Promise<O>;
|
40
|
-
};
|
41
|
-
|
42
|
-
export type AsyncMiddlewareInput<I = unknown, O = unknown> =
|
43
|
-
| AsyncMiddleware<I, O>
|
44
|
-
| { middleware: AsyncMiddleware<I, O> };
|
45
|
-
|
46
|
-
export type AsyncMiddlewareType<T extends AsyncMiddlewareInput> =
|
47
|
-
T extends AsyncMiddlewareInput<infer I, infer O>
|
48
|
-
? AsyncMiddleware<I, O>
|
49
|
-
: never;
|
50
|
-
|
51
|
-
export const getAsyncMiddleware = <I, O>(input: AsyncMiddlewareInput<I, O>) => {
|
52
|
-
if (typeof input === 'function') {
|
53
|
-
return input;
|
54
|
-
} else if (input && typeof input.middleware === 'function') {
|
55
|
-
return input.middleware;
|
56
|
-
}
|
57
|
-
// eslint-disable-next-line @typescript-eslint/no-base-to-string,@typescript-eslint/restrict-template-expressions
|
58
|
-
throw new Error(`${input} is not a Middleware or { middleware: Middleware }`);
|
59
|
-
};
|
60
|
-
|
61
|
-
export type AsyncPipeline<I = unknown, O = unknown> = {
|
62
|
-
[ASYNC_PIPELINE_SYMBOL]: true;
|
63
|
-
use: (...inputs: AsyncMiddlewareInput<I, O>[]) => AsyncPipeline<I, O>;
|
64
|
-
run: (input: I, options?: RunAsyncPipelineOptions<I, O>) => Promise<O>;
|
65
|
-
middleware: AsyncMiddleware<I, O>;
|
66
|
-
};
|
67
|
-
|
68
|
-
export const createAsyncPipeline = <I, O>(options?: PipelineOptions) => {
|
69
|
-
const config = { ...options };
|
70
|
-
|
71
|
-
const middlewares: AsyncMiddlewares<I, O> = [];
|
72
|
-
|
73
|
-
const use: AsyncPipeline<I, O>['use'] = (...inputs) => {
|
74
|
-
middlewares.push(...inputs.map(getAsyncMiddleware));
|
75
|
-
return pipeline;
|
76
|
-
};
|
77
|
-
|
78
|
-
const createCurrentCounter = (
|
79
|
-
hooks: Hooks,
|
80
|
-
onLast?: (input: I) => O | Promise<O>,
|
81
|
-
) =>
|
82
|
-
createAsyncCounter<I, O>(async (index, input, next) => {
|
83
|
-
if (index >= middlewares.length) {
|
84
|
-
if (onLast) {
|
85
|
-
return onLast(input);
|
86
|
-
}
|
87
|
-
throw new Error(
|
88
|
-
`Expect returning a value, but all middlewares just calling next()`,
|
89
|
-
);
|
90
|
-
}
|
91
|
-
|
92
|
-
const middleware = middlewares[index];
|
93
|
-
const result = await runHooks(async () => middleware(input, next), hooks);
|
94
|
-
|
95
|
-
return result;
|
96
|
-
});
|
97
|
-
|
98
|
-
const currentContainer = createContainer(config.contexts);
|
99
|
-
const currentHooks = fromContainer(currentContainer);
|
100
|
-
const currentCounter = createCurrentCounter(currentHooks);
|
101
|
-
|
102
|
-
// eslint-disable-next-line @typescript-eslint/no-shadow
|
103
|
-
const run: AsyncPipeline<I, O>['run'] = (input, options) => {
|
104
|
-
const container = options?.container ?? currentContainer;
|
105
|
-
const hooks =
|
106
|
-
container === currentContainer ? currentHooks : fromContainer(container);
|
107
|
-
let counter =
|
108
|
-
container === currentContainer
|
109
|
-
? currentCounter
|
110
|
-
: createCurrentCounter(hooks);
|
111
|
-
|
112
|
-
if (options?.onLast) {
|
113
|
-
counter = createCurrentCounter(hooks, options.onLast);
|
114
|
-
}
|
115
|
-
|
116
|
-
const result = counter.start(input);
|
117
|
-
|
118
|
-
return result;
|
119
|
-
};
|
120
|
-
|
121
|
-
const middleware: AsyncPipeline<I, O>['middleware'] = (input, next) => {
|
122
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
123
|
-
const container = useContainer();
|
124
|
-
return run(input, {
|
125
|
-
container,
|
126
|
-
onLast: next,
|
127
|
-
});
|
128
|
-
};
|
129
|
-
|
130
|
-
const pipeline: AsyncPipeline<I, O> = {
|
131
|
-
[ASYNC_PIPELINE_SYMBOL]: true,
|
132
|
-
use,
|
133
|
-
run,
|
134
|
-
middleware,
|
135
|
-
};
|
136
|
-
|
137
|
-
return pipeline;
|
138
|
-
};
|
139
|
-
|
140
|
-
export type AsyncPipelineInput<T extends AsyncPipeline> =
|
141
|
-
T extends AsyncPipeline<infer I> ? I : never;
|
142
|
-
|
143
|
-
export type AsyncPipelineOutput<T extends AsyncPipeline> =
|
144
|
-
T extends AsyncPipeline<any, infer O> ? O : never;
|
145
|
-
|
146
|
-
export const useAsyncPipeline = <I, O>(pipeline: AsyncPipeline<I, O>) => {
|
147
|
-
const container = useContainer();
|
148
|
-
|
149
|
-
const runPipeline = (
|
150
|
-
input: I,
|
151
|
-
options?: RunAsyncPipelineOptions<I, O>,
|
152
|
-
): Promise<O> => pipeline.run(input, { ...options, container });
|
153
|
-
|
154
|
-
return runPipeline;
|
155
|
-
};
|
package/src/pipeline/index.ts
DELETED
package/src/pipeline/sync.ts
DELETED
@@ -1,152 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Copyright Lucifier129 and other contributors.
|
3
|
-
*
|
4
|
-
* This source code is licensed under the MIT license found in the
|
5
|
-
* LICENSE file at
|
6
|
-
* https://github.com/farrow-js/farrow/blob/master/LICENSE
|
7
|
-
*
|
8
|
-
*/
|
9
|
-
|
10
|
-
import {
|
11
|
-
createContainer,
|
12
|
-
ContextStorage,
|
13
|
-
Container,
|
14
|
-
fromContainer,
|
15
|
-
runHooks,
|
16
|
-
useContainer,
|
17
|
-
Hooks,
|
18
|
-
} from '../context';
|
19
|
-
|
20
|
-
import { Next, createCounter } from '../counter';
|
21
|
-
|
22
|
-
export type Middleware<I = unknown, O = unknown> = (
|
23
|
-
input: I,
|
24
|
-
next: Next<I, O>,
|
25
|
-
) => O;
|
26
|
-
|
27
|
-
export type Middlewares<I = unknown, O = unknown> = Middleware<I, O>[];
|
28
|
-
|
29
|
-
const PIPELINE_SYMBOL = Symbol('PIPELINE_SYMBOL');
|
30
|
-
export const isPipeline = (input: any): input is Pipeline =>
|
31
|
-
Boolean(input?.[PIPELINE_SYMBOL]);
|
32
|
-
|
33
|
-
export type PipelineOptions = {
|
34
|
-
contexts?: ContextStorage;
|
35
|
-
};
|
36
|
-
|
37
|
-
export type RunPipelineOptions<I = unknown, O = unknown> = {
|
38
|
-
container?: Container;
|
39
|
-
onLast?: (input: I) => O;
|
40
|
-
};
|
41
|
-
|
42
|
-
export type MiddlewareInput<I = unknown, O = unknown> =
|
43
|
-
| Middleware<I, O>
|
44
|
-
| { middleware: Middleware<I, O> };
|
45
|
-
|
46
|
-
export type MiddlewareType<T extends MiddlewareInput> =
|
47
|
-
T extends MiddlewareInput<infer I, infer O> ? Middleware<I, O> : never;
|
48
|
-
|
49
|
-
export const getMiddleware = <I, O>(input: MiddlewareInput<I, O>) => {
|
50
|
-
if (typeof input === 'function') {
|
51
|
-
return input;
|
52
|
-
} else if (input && typeof input.middleware === 'function') {
|
53
|
-
return input.middleware;
|
54
|
-
}
|
55
|
-
// eslint-disable-next-line @typescript-eslint/no-base-to-string,@typescript-eslint/restrict-template-expressions
|
56
|
-
throw new Error(`${input} is not a Middleware or { middleware: Middleware }`);
|
57
|
-
};
|
58
|
-
|
59
|
-
export type Pipeline<I = unknown, O = unknown> = {
|
60
|
-
[PIPELINE_SYMBOL]: true;
|
61
|
-
use: (...inputs: MiddlewareInput<I, O>[]) => Pipeline<I, O>;
|
62
|
-
run: (input: I, options?: RunPipelineOptions<I, O>) => O;
|
63
|
-
middleware: Middleware<I, O>;
|
64
|
-
};
|
65
|
-
|
66
|
-
export const createPipeline = <I, O>(options?: PipelineOptions) => {
|
67
|
-
const config = { ...options };
|
68
|
-
|
69
|
-
const middlewares: Middlewares<I, O> = [];
|
70
|
-
|
71
|
-
const use: Pipeline<I, O>['use'] = (...inputs) => {
|
72
|
-
middlewares.push(...inputs.map(getMiddleware));
|
73
|
-
return pipeline;
|
74
|
-
};
|
75
|
-
|
76
|
-
const createCurrentCounter = (hooks: Hooks, onLast?: (input: I) => O) =>
|
77
|
-
createCounter<I, O>((index, input, next) => {
|
78
|
-
if (index >= middlewares.length) {
|
79
|
-
if (onLast) {
|
80
|
-
return onLast(input);
|
81
|
-
}
|
82
|
-
throw new Error(
|
83
|
-
`Expect returning a value, but all middlewares just calling next()`,
|
84
|
-
);
|
85
|
-
}
|
86
|
-
|
87
|
-
const middleware = middlewares[index];
|
88
|
-
const result = runHooks(() => middleware(input, next), hooks);
|
89
|
-
|
90
|
-
return result;
|
91
|
-
});
|
92
|
-
|
93
|
-
const currentContainer = createContainer(config.contexts);
|
94
|
-
const currentHooks = fromContainer(currentContainer);
|
95
|
-
const currentCounter = createCurrentCounter(currentHooks);
|
96
|
-
|
97
|
-
// eslint-disable-next-line @typescript-eslint/no-shadow
|
98
|
-
const run: Pipeline<I, O>['run'] = (input, options) => {
|
99
|
-
const container = options?.container ?? currentContainer;
|
100
|
-
const hooks =
|
101
|
-
container === currentContainer ? currentHooks : fromContainer(container);
|
102
|
-
let counter =
|
103
|
-
container === currentContainer
|
104
|
-
? currentCounter
|
105
|
-
: createCurrentCounter(hooks);
|
106
|
-
|
107
|
-
if (options?.onLast) {
|
108
|
-
counter = createCurrentCounter(hooks, options.onLast);
|
109
|
-
}
|
110
|
-
|
111
|
-
const result = counter.start(input);
|
112
|
-
|
113
|
-
return result;
|
114
|
-
};
|
115
|
-
|
116
|
-
const middleware: Pipeline<I, O>['middleware'] = (input, next) => {
|
117
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
118
|
-
const container = useContainer();
|
119
|
-
return run(input, {
|
120
|
-
container,
|
121
|
-
onLast: next,
|
122
|
-
});
|
123
|
-
};
|
124
|
-
|
125
|
-
const pipeline: Pipeline<I, O> = {
|
126
|
-
[PIPELINE_SYMBOL]: true,
|
127
|
-
use,
|
128
|
-
run,
|
129
|
-
middleware,
|
130
|
-
};
|
131
|
-
|
132
|
-
return pipeline;
|
133
|
-
};
|
134
|
-
|
135
|
-
export type PipelineInput<T extends Pipeline> = T extends Pipeline<infer I>
|
136
|
-
? I
|
137
|
-
: never;
|
138
|
-
export type PipelineOutput<T extends Pipeline> = T extends Pipeline<
|
139
|
-
any,
|
140
|
-
infer O
|
141
|
-
>
|
142
|
-
? O
|
143
|
-
: never;
|
144
|
-
|
145
|
-
export const usePipeline = <I, O>(pipeline: Pipeline<I, O>) => {
|
146
|
-
const container = useContainer();
|
147
|
-
|
148
|
-
const runPipeline = (input: I, options?: RunPipelineOptions<I, O>): O =>
|
149
|
-
pipeline.run(input, { ...options, container });
|
150
|
-
|
151
|
-
return runPipeline;
|
152
|
-
};
|