rura 1.0.2 → 1.0.4
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 +30 -12
- package/dist/index.cjs +35 -14
- package/dist/index.d.cts +75 -15
- package/dist/index.d.ts +75 -15
- package/dist/index.js +35 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,38 +49,51 @@ type Ctx = typeof ctx;
|
|
|
49
49
|
- Hooks may specify an `order`; omitted values default to `0`.
|
|
50
50
|
|
|
51
51
|
```ts
|
|
52
|
+
import { createHook, type RuraHook } from "rura";
|
|
53
|
+
|
|
52
54
|
// With createHook (recommended for convenience)
|
|
53
55
|
const addOne = createHook<Ctx>("add-one", (ctx) => {
|
|
54
56
|
ctx.count += 1;
|
|
55
57
|
}); // order: 0
|
|
56
58
|
|
|
57
59
|
// Manual hook definition (full control)
|
|
58
|
-
const stopIfEven:
|
|
60
|
+
const stopIfEven: RuraHook<Ctx, number> = {
|
|
59
61
|
name: "stop-if-even",
|
|
60
62
|
run: (ctx) => {
|
|
61
63
|
if (ctx.count % 2 === 0) {
|
|
62
|
-
return {
|
|
64
|
+
return { early: true, output: ctx.count };
|
|
63
65
|
}
|
|
64
66
|
},
|
|
65
67
|
order: 2, // order: 2
|
|
66
68
|
};
|
|
67
69
|
```
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
- Rura executes hooks in order and exits early when a hook returns `{ early: true, output }`.
|
|
72
|
+
|
|
73
|
+
- When the pipeline does not exit early, `output` is omitted and `early` becomes `false`.
|
|
70
74
|
|
|
71
75
|
#### 3. Run the pipeline
|
|
72
76
|
|
|
73
77
|
```ts
|
|
74
78
|
const result = await runRura(ctx, [addOne, stopIfEven]);
|
|
75
79
|
|
|
76
|
-
console.log(result);
|
|
80
|
+
console.log(result);
|
|
81
|
+
// -> {
|
|
82
|
+
// early: true,
|
|
83
|
+
// ctx: { count: 2 },
|
|
84
|
+
// output: 2
|
|
85
|
+
// }
|
|
77
86
|
```
|
|
78
87
|
|
|
88
|
+
_If you prefer working with a reusable pipeline instance,
|
|
89
|
+
you can use the **Pipeline Builder**, introduced below:_
|
|
90
|
+
|
|
79
91
|
---
|
|
80
92
|
|
|
81
93
|
## Pipeline Builder
|
|
82
94
|
|
|
83
|
-
**createRura()** - Creates a lightweight, composable pipeline instance
|
|
95
|
+
**createRura()** - Creates a lightweight, composable pipeline instance
|
|
96
|
+
that can register hooks, merge with other pipelines, and be inspected.
|
|
84
97
|
|
|
85
98
|
```ts
|
|
86
99
|
const rura = createRura<Context, Output>();
|
|
@@ -125,14 +138,19 @@ const pipeline = pipelineA.merge(pipelineB);
|
|
|
125
138
|
// Run it
|
|
126
139
|
const result = await pipeline.run({ value: 1 });
|
|
127
140
|
|
|
128
|
-
console.log(result);
|
|
141
|
+
console.log(result);
|
|
142
|
+
// -> {
|
|
143
|
+
// early: false,
|
|
144
|
+
// ctx: { value: 9 }
|
|
145
|
+
// }
|
|
129
146
|
```
|
|
130
147
|
|
|
131
148
|
#### Pipeline Instance Methods
|
|
132
149
|
|
|
133
|
-
| Method | Description
|
|
134
|
-
| ---------------- |
|
|
135
|
-
| **use(hook)** | Adds a hook
|
|
136
|
-
| **merge(other)** | Merges hooks from another pipeline
|
|
137
|
-
| **getHooks()** | Returns all registered hooks.
|
|
138
|
-
| **
|
|
150
|
+
| Method | Description | Parameters | Returns |
|
|
151
|
+
| ---------------- | ------------------------------------------------------ | ---------- | --------------------- |
|
|
152
|
+
| **use(hook)** | Adds a hook, normalizes its order, and re-sorts hooks. | `hook` | `this` (chainable) |
|
|
153
|
+
| **merge(other)** | Merges hooks from another pipeline and re-sorts them. | `other` | `this` (chainable) |
|
|
154
|
+
| **getHooks()** | Returns a sorted shallow copy of all registered hooks. | – | `RuraHook[]` |
|
|
155
|
+
| **debugHooks()** | Prints a formatted, human-readable hook list. | – | `void` |
|
|
156
|
+
| **run(ctx)** | Executes the pipeline (delegates to `runRura`). | `ctx` | `Promise<RuraResult>` |
|
package/dist/index.cjs
CHANGED
|
@@ -1,40 +1,61 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
// src/is-done.ts
|
|
4
|
-
function isDone(r) {
|
|
5
|
-
return typeof r === "object" && r !== null && "done" in r;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
3
|
// src/run-rura.ts
|
|
9
4
|
async function runRura(ctx, hooks) {
|
|
10
|
-
hooks.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
11
5
|
for (const hook of hooks) {
|
|
12
6
|
const result = await hook.run(ctx);
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
const isEarlyReturn = result && result.early === true;
|
|
8
|
+
if (isEarlyReturn) {
|
|
9
|
+
return {
|
|
10
|
+
early: true,
|
|
11
|
+
ctx,
|
|
12
|
+
output: result.output
|
|
13
|
+
};
|
|
15
14
|
}
|
|
16
15
|
}
|
|
17
|
-
return
|
|
16
|
+
return {
|
|
17
|
+
early: false,
|
|
18
|
+
ctx
|
|
19
|
+
};
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
// src/create-rura.ts
|
|
21
23
|
function createRura(initialHooks = []) {
|
|
22
|
-
const hooks = [...initialHooks];
|
|
24
|
+
const hooks = [...initialHooks].map((h) => applyDefaultOrder(h));
|
|
25
|
+
function applyDefaultOrder(h) {
|
|
26
|
+
return { ...h, order: h.order ?? 0 };
|
|
27
|
+
}
|
|
28
|
+
function sortHooks() {
|
|
29
|
+
hooks.sort((a, b) => a.order - b.order);
|
|
30
|
+
}
|
|
23
31
|
function use(hook) {
|
|
24
|
-
hooks.push(hook);
|
|
32
|
+
hooks.push(applyDefaultOrder(hook));
|
|
33
|
+
sortHooks();
|
|
25
34
|
return api;
|
|
26
35
|
}
|
|
27
36
|
function merge(other) {
|
|
28
|
-
other.getHooks().forEach((h) => hooks.push(h));
|
|
37
|
+
other.getHooks().forEach((h) => hooks.push(applyDefaultOrder(h)));
|
|
38
|
+
sortHooks();
|
|
29
39
|
return api;
|
|
30
40
|
}
|
|
31
41
|
function getHooks() {
|
|
32
|
-
return hooks;
|
|
42
|
+
return [...hooks];
|
|
43
|
+
}
|
|
44
|
+
function debugHooks() {
|
|
45
|
+
console.log(`
|
|
46
|
+
\u{1F4A7} Rura Pipeline (${hooks.length} hooks)`);
|
|
47
|
+
console.log("\u2500\u2500\u2500");
|
|
48
|
+
hooks.forEach(({ name, order }, i) => {
|
|
49
|
+
const paddedOrder = String(order).padStart(4, " ");
|
|
50
|
+
console.log(`${i + 1}. order: ${paddedOrder} | name: ${name}`);
|
|
51
|
+
});
|
|
52
|
+
console.log("\u2500\u2500\u2500\n");
|
|
33
53
|
}
|
|
34
54
|
async function run(ctx) {
|
|
35
55
|
return runRura(ctx, hooks);
|
|
36
56
|
}
|
|
37
|
-
const api = { use, merge, getHooks, run };
|
|
57
|
+
const api = { use, merge, getHooks, debugHooks, run };
|
|
58
|
+
sortHooks();
|
|
38
59
|
return api;
|
|
39
60
|
}
|
|
40
61
|
|
package/dist/index.d.cts
CHANGED
|
@@ -1,23 +1,83 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The return type of a Rura hook.
|
|
3
|
+
*
|
|
4
|
+
* - Return `void` to continue the pipeline.
|
|
5
|
+
* - Return `{ early: true, output }` to stop the pipeline immediately.
|
|
6
|
+
*
|
|
7
|
+
* Supports both sync and async forms.
|
|
8
|
+
*/
|
|
9
|
+
type RuraHookResult<Out> = void | {
|
|
10
|
+
early: true;
|
|
11
|
+
output: Out;
|
|
12
|
+
} | Promise<void | {
|
|
13
|
+
early: true;
|
|
14
|
+
output: Out;
|
|
15
|
+
}>;
|
|
16
|
+
/**
|
|
17
|
+
* A single pipeline hook.
|
|
18
|
+
*
|
|
19
|
+
* Hooks receive the current context and may:
|
|
20
|
+
* - mutate it and continue, or
|
|
21
|
+
* - return `{ early: true, output }` to exit the pipeline early.
|
|
22
|
+
*/
|
|
23
|
+
interface RuraHook<Ctx = unknown, Out = unknown> {
|
|
24
|
+
/** Unique name for debugging and inspection. */
|
|
7
25
|
name: string;
|
|
26
|
+
/** Executes the hook. */
|
|
27
|
+
run(ctx: Ctx): RuraHookResult<Out>;
|
|
28
|
+
/** Optional execution order. Lower values run first. */
|
|
8
29
|
order?: number;
|
|
9
|
-
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Final result of a pipeline execution.
|
|
33
|
+
*
|
|
34
|
+
* - If `early` is true, the pipeline stopped before completing all hooks.
|
|
35
|
+
* - The `ctx` field always contains the final context.
|
|
36
|
+
* - The `output` field appears only when early termination occurs.
|
|
37
|
+
*/
|
|
38
|
+
interface RuraResult<Ctx, Out> {
|
|
39
|
+
/** Indicates whether the pipeline exited early. */
|
|
40
|
+
early: boolean;
|
|
41
|
+
/** The final context after all executed hooks. */
|
|
42
|
+
ctx: Ctx;
|
|
43
|
+
/** The output value when the pipeline ends early. */
|
|
44
|
+
output?: Out;
|
|
10
45
|
}
|
|
11
46
|
|
|
12
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Executes a list of hooks in order.
|
|
49
|
+
* - Stops early when a hook returns `{ early: true, output }`.
|
|
50
|
+
*
|
|
51
|
+
* @returns A `RuraResult` describing whether the pipeline ended early
|
|
52
|
+
* and the final context/output.
|
|
53
|
+
*/
|
|
54
|
+
declare function runRura<Ctx = unknown, Out = unknown>(ctx: Ctx, hooks: RuraHook<Ctx, Out>[]): Promise<RuraResult<Ctx, Out>>;
|
|
13
55
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Creates a reusable pipeline instance.
|
|
58
|
+
* Hooks can be registered, merged, inspected, and executed in order.
|
|
59
|
+
*
|
|
60
|
+
* @param initialHooks - Optional list of hooks to initialize the pipeline with.
|
|
61
|
+
*
|
|
62
|
+
* @returns An API for managing and running the pipeline.
|
|
63
|
+
*/
|
|
64
|
+
declare function createRura<Ctx = unknown, Out = unknown>(initialHooks?: RuraHook<Ctx, Out>[]): {
|
|
65
|
+
use: (hook: RuraHook<Ctx, Out>) => /*elided*/ any;
|
|
66
|
+
merge: (other: ReturnType<typeof createRura<Ctx, Out>>) => /*elided*/ any;
|
|
67
|
+
getHooks: () => RuraHook<Ctx, Out>[];
|
|
68
|
+
debugHooks: () => void;
|
|
69
|
+
run: (ctx: Ctx) => Promise<RuraResult<Ctx, Out>>;
|
|
19
70
|
};
|
|
20
71
|
|
|
21
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Creates a pipeline hook.
|
|
74
|
+
*
|
|
75
|
+
* @param name - Unique name for debugging and inspection.
|
|
76
|
+
* @param run - Hook implementation.
|
|
77
|
+
* @param order - Optional execution order. Lower values run first.
|
|
78
|
+
*
|
|
79
|
+
* @returns A normalized `RuraHook` object.
|
|
80
|
+
*/
|
|
81
|
+
declare function createHook<Ctx = unknown, Out = unknown>(name: string, run: RuraHook<Ctx, Out>["run"], order?: number): RuraHook<Ctx, Out>;
|
|
22
82
|
|
|
23
|
-
export { type
|
|
83
|
+
export { type RuraHook, type RuraHookResult, type RuraResult, createHook, createRura, runRura };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,23 +1,83 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The return type of a Rura hook.
|
|
3
|
+
*
|
|
4
|
+
* - Return `void` to continue the pipeline.
|
|
5
|
+
* - Return `{ early: true, output }` to stop the pipeline immediately.
|
|
6
|
+
*
|
|
7
|
+
* Supports both sync and async forms.
|
|
8
|
+
*/
|
|
9
|
+
type RuraHookResult<Out> = void | {
|
|
10
|
+
early: true;
|
|
11
|
+
output: Out;
|
|
12
|
+
} | Promise<void | {
|
|
13
|
+
early: true;
|
|
14
|
+
output: Out;
|
|
15
|
+
}>;
|
|
16
|
+
/**
|
|
17
|
+
* A single pipeline hook.
|
|
18
|
+
*
|
|
19
|
+
* Hooks receive the current context and may:
|
|
20
|
+
* - mutate it and continue, or
|
|
21
|
+
* - return `{ early: true, output }` to exit the pipeline early.
|
|
22
|
+
*/
|
|
23
|
+
interface RuraHook<Ctx = unknown, Out = unknown> {
|
|
24
|
+
/** Unique name for debugging and inspection. */
|
|
7
25
|
name: string;
|
|
26
|
+
/** Executes the hook. */
|
|
27
|
+
run(ctx: Ctx): RuraHookResult<Out>;
|
|
28
|
+
/** Optional execution order. Lower values run first. */
|
|
8
29
|
order?: number;
|
|
9
|
-
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Final result of a pipeline execution.
|
|
33
|
+
*
|
|
34
|
+
* - If `early` is true, the pipeline stopped before completing all hooks.
|
|
35
|
+
* - The `ctx` field always contains the final context.
|
|
36
|
+
* - The `output` field appears only when early termination occurs.
|
|
37
|
+
*/
|
|
38
|
+
interface RuraResult<Ctx, Out> {
|
|
39
|
+
/** Indicates whether the pipeline exited early. */
|
|
40
|
+
early: boolean;
|
|
41
|
+
/** The final context after all executed hooks. */
|
|
42
|
+
ctx: Ctx;
|
|
43
|
+
/** The output value when the pipeline ends early. */
|
|
44
|
+
output?: Out;
|
|
10
45
|
}
|
|
11
46
|
|
|
12
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Executes a list of hooks in order.
|
|
49
|
+
* - Stops early when a hook returns `{ early: true, output }`.
|
|
50
|
+
*
|
|
51
|
+
* @returns A `RuraResult` describing whether the pipeline ended early
|
|
52
|
+
* and the final context/output.
|
|
53
|
+
*/
|
|
54
|
+
declare function runRura<Ctx = unknown, Out = unknown>(ctx: Ctx, hooks: RuraHook<Ctx, Out>[]): Promise<RuraResult<Ctx, Out>>;
|
|
13
55
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Creates a reusable pipeline instance.
|
|
58
|
+
* Hooks can be registered, merged, inspected, and executed in order.
|
|
59
|
+
*
|
|
60
|
+
* @param initialHooks - Optional list of hooks to initialize the pipeline with.
|
|
61
|
+
*
|
|
62
|
+
* @returns An API for managing and running the pipeline.
|
|
63
|
+
*/
|
|
64
|
+
declare function createRura<Ctx = unknown, Out = unknown>(initialHooks?: RuraHook<Ctx, Out>[]): {
|
|
65
|
+
use: (hook: RuraHook<Ctx, Out>) => /*elided*/ any;
|
|
66
|
+
merge: (other: ReturnType<typeof createRura<Ctx, Out>>) => /*elided*/ any;
|
|
67
|
+
getHooks: () => RuraHook<Ctx, Out>[];
|
|
68
|
+
debugHooks: () => void;
|
|
69
|
+
run: (ctx: Ctx) => Promise<RuraResult<Ctx, Out>>;
|
|
19
70
|
};
|
|
20
71
|
|
|
21
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Creates a pipeline hook.
|
|
74
|
+
*
|
|
75
|
+
* @param name - Unique name for debugging and inspection.
|
|
76
|
+
* @param run - Hook implementation.
|
|
77
|
+
* @param order - Optional execution order. Lower values run first.
|
|
78
|
+
*
|
|
79
|
+
* @returns A normalized `RuraHook` object.
|
|
80
|
+
*/
|
|
81
|
+
declare function createHook<Ctx = unknown, Out = unknown>(name: string, run: RuraHook<Ctx, Out>["run"], order?: number): RuraHook<Ctx, Out>;
|
|
22
82
|
|
|
23
|
-
export { type
|
|
83
|
+
export { type RuraHook, type RuraHookResult, type RuraResult, createHook, createRura, runRura };
|
package/dist/index.js
CHANGED
|
@@ -1,38 +1,59 @@
|
|
|
1
|
-
// src/is-done.ts
|
|
2
|
-
function isDone(r) {
|
|
3
|
-
return typeof r === "object" && r !== null && "done" in r;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
1
|
// src/run-rura.ts
|
|
7
2
|
async function runRura(ctx, hooks) {
|
|
8
|
-
hooks.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
9
3
|
for (const hook of hooks) {
|
|
10
4
|
const result = await hook.run(ctx);
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
const isEarlyReturn = result && result.early === true;
|
|
6
|
+
if (isEarlyReturn) {
|
|
7
|
+
return {
|
|
8
|
+
early: true,
|
|
9
|
+
ctx,
|
|
10
|
+
output: result.output
|
|
11
|
+
};
|
|
13
12
|
}
|
|
14
13
|
}
|
|
15
|
-
return
|
|
14
|
+
return {
|
|
15
|
+
early: false,
|
|
16
|
+
ctx
|
|
17
|
+
};
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
// src/create-rura.ts
|
|
19
21
|
function createRura(initialHooks = []) {
|
|
20
|
-
const hooks = [...initialHooks];
|
|
22
|
+
const hooks = [...initialHooks].map((h) => applyDefaultOrder(h));
|
|
23
|
+
function applyDefaultOrder(h) {
|
|
24
|
+
return { ...h, order: h.order ?? 0 };
|
|
25
|
+
}
|
|
26
|
+
function sortHooks() {
|
|
27
|
+
hooks.sort((a, b) => a.order - b.order);
|
|
28
|
+
}
|
|
21
29
|
function use(hook) {
|
|
22
|
-
hooks.push(hook);
|
|
30
|
+
hooks.push(applyDefaultOrder(hook));
|
|
31
|
+
sortHooks();
|
|
23
32
|
return api;
|
|
24
33
|
}
|
|
25
34
|
function merge(other) {
|
|
26
|
-
other.getHooks().forEach((h) => hooks.push(h));
|
|
35
|
+
other.getHooks().forEach((h) => hooks.push(applyDefaultOrder(h)));
|
|
36
|
+
sortHooks();
|
|
27
37
|
return api;
|
|
28
38
|
}
|
|
29
39
|
function getHooks() {
|
|
30
|
-
return hooks;
|
|
40
|
+
return [...hooks];
|
|
41
|
+
}
|
|
42
|
+
function debugHooks() {
|
|
43
|
+
console.log(`
|
|
44
|
+
\u{1F4A7} Rura Pipeline (${hooks.length} hooks)`);
|
|
45
|
+
console.log("\u2500\u2500\u2500");
|
|
46
|
+
hooks.forEach(({ name, order }, i) => {
|
|
47
|
+
const paddedOrder = String(order).padStart(4, " ");
|
|
48
|
+
console.log(`${i + 1}. order: ${paddedOrder} | name: ${name}`);
|
|
49
|
+
});
|
|
50
|
+
console.log("\u2500\u2500\u2500\n");
|
|
31
51
|
}
|
|
32
52
|
async function run(ctx) {
|
|
33
53
|
return runRura(ctx, hooks);
|
|
34
54
|
}
|
|
35
|
-
const api = { use, merge, getHooks, run };
|
|
55
|
+
const api = { use, merge, getHooks, debugHooks, run };
|
|
56
|
+
sortHooks();
|
|
36
57
|
return api;
|
|
37
58
|
}
|
|
38
59
|
|