rura 1.0.8 → 1.1.0

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.
Files changed (42) hide show
  1. package/README.md +38 -118
  2. package/dist/index.cjs +75 -63
  3. package/dist/index.js +70 -64
  4. package/dist/types/export/index.d.ts +9 -0
  5. package/dist/types/export/index.d.ts.map +1 -0
  6. package/dist/types/src/hooks/create-hook.d.ts +18 -0
  7. package/dist/types/src/hooks/create-hook.d.ts.map +1 -0
  8. package/dist/types/src/hooks/index.d.ts +3 -0
  9. package/dist/types/src/hooks/index.d.ts.map +1 -0
  10. package/dist/types/src/hooks/internal.d.ts +2 -0
  11. package/dist/types/src/hooks/internal.d.ts.map +1 -0
  12. package/dist/types/src/hooks/types.d.ts +52 -0
  13. package/dist/types/src/hooks/types.d.ts.map +1 -0
  14. package/dist/types/src/hooks/utils/is-async-hook.d.ts +2 -0
  15. package/dist/types/src/hooks/utils/is-async-hook.d.ts.map +1 -0
  16. package/dist/types/src/pipeline/create/create-pipeline-async.d.ts +20 -0
  17. package/dist/types/src/pipeline/create/create-pipeline-async.d.ts.map +1 -0
  18. package/dist/types/src/pipeline/create/create-pipeline-base.d.ts +2 -0
  19. package/dist/types/src/pipeline/create/create-pipeline-base.d.ts.map +1 -0
  20. package/dist/types/src/pipeline/create/create-pipeline.d.ts +21 -0
  21. package/dist/types/src/pipeline/create/create-pipeline.d.ts.map +1 -0
  22. package/dist/types/src/pipeline/create/index.d.ts +3 -0
  23. package/dist/types/src/pipeline/create/index.d.ts.map +1 -0
  24. package/dist/types/src/pipeline/create/utils/assert-sync-hook.d.ts +2 -0
  25. package/dist/types/src/pipeline/create/utils/assert-sync-hook.d.ts.map +1 -0
  26. package/dist/types/src/pipeline/create/utils/log-pipeline-hooks.d.ts +2 -0
  27. package/dist/types/src/pipeline/create/utils/log-pipeline-hooks.d.ts.map +1 -0
  28. package/dist/types/src/pipeline/index.d.ts +4 -0
  29. package/dist/types/src/pipeline/index.d.ts.map +1 -0
  30. package/dist/types/src/pipeline/run/index.d.ts +3 -0
  31. package/dist/types/src/pipeline/run/index.d.ts.map +1 -0
  32. package/dist/types/src/pipeline/run/run-async.d.ts +21 -0
  33. package/dist/types/src/pipeline/run/run-async.d.ts.map +1 -0
  34. package/dist/types/src/pipeline/run/run.d.ts +22 -0
  35. package/dist/types/src/pipeline/run/run.d.ts.map +1 -0
  36. package/dist/types/src/pipeline/types.d.ts +28 -0
  37. package/dist/types/src/pipeline/types.d.ts.map +1 -0
  38. package/dist/types/src/rura.d.ts +28 -0
  39. package/dist/types/src/rura.d.ts.map +1 -0
  40. package/package.json +16 -20
  41. package/dist/index.d.cts +0 -159
  42. package/dist/index.d.ts +0 -159
package/README.md CHANGED
@@ -2,16 +2,13 @@
2
2
 
3
3
  <div align="center">
4
4
 
5
- A minimal **pipeline engine** for every modern workflow,
6
- built for clarity and stability.
5
+ The hook pipeline
7
6
 
8
7
  </div>
9
8
 
10
9
  <div align="center">
11
10
 
12
11
  [![NPM version](https://img.shields.io/npm/v/rura?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/rura)
13
- [![Bundle size](https://img.shields.io/bundlephobia/minzip/rura?style=flat&colorA=000000&colorB=000000)](https://bundlephobia.com/package/rura)
14
- [![Coverage Status](https://img.shields.io/coveralls/github/yiming-liao/rura.svg?branch=main&style=flat&colorA=000000&colorB=000000)](https://coveralls.io/github/yiming-liao/rura?branch=main)
15
12
  [![TypeScript](https://img.shields.io/badge/TypeScript-%E2%9C%94-blue?style=flat&colorA=000000&colorB=000000)](https://www.typescriptlang.org/)
16
13
  [![License](https://img.shields.io/npm/l/rura?style=flat&colorA=000000&colorB=000000)](LICENSE)
17
14
 
@@ -19,158 +16,81 @@ built for clarity and stability.
19
16
 
20
17
  ## Features
21
18
 
22
- - **Deterministic** Ordered hooks with effortless early exit.
23
- - **Typed** Inferred context and output with zero boilerplate.
24
- - **Universal** Tiny, framework-agnostic, and ready for any flow.
19
+ - **Deterministic** Strict hook ordering with early termination.
20
+ - **Type-safe** Fully inferred context and output.
21
+ - **Composable** Minimal and framework-agnostic.
25
22
 
26
23
  ## Installation
27
24
 
28
25
  ```bash
29
- # npm
30
26
  npm install rura
31
- # yarn
27
+ # or
32
28
  yarn add rura
33
- # pnpm
29
+ # or
34
30
  pnpm add rura
35
31
  ```
36
32
 
37
- ## Quick Start
38
-
39
- #### 1. Define the initial context
33
+ ## Example
40
34
 
41
35
  ```ts
42
- const ctx = { count: 1 };
43
- type Ctx = typeof ctx;
44
- ```
45
-
46
- #### 2. Create your hooks
47
-
48
- - Hooks can be created with `rura.createHook`, or defined manually using the `RuraHook` type.
49
- - Hooks may specify an `order`; omitted values default to `0`.
36
+ import { rura } from "rura";
50
37
 
51
- ```ts
52
- import { rura, type RuraHook } from "rura";
38
+ // Shared pipeline context.
39
+ type Ctx = { count: number };
53
40
 
54
- // With createHook (recommended for convenience)
41
+ // Synchronous hook.
55
42
  const addOne = rura.createHook<Ctx>("add-one", (ctx) => {
56
43
  ctx.count += 1;
57
- }); // order: 0
44
+ });
58
45
 
59
- // Manual hook definition (full control)
60
- const stopIfEven: RuraHook<Ctx, number> = {
61
- name: "stop-if-even",
62
- run: (ctx) => {
46
+ // Synchronous hook (Early-terminating).
47
+ const stopIfEven = rura.createHook<Ctx, number>(
48
+ "stop-if-even",
49
+ (ctx) => {
63
50
  if (ctx.count % 2 === 0) {
64
51
  return { early: true, output: ctx.count };
65
52
  }
66
53
  },
67
- order: 2, // order: 2
68
- };
69
- ```
70
-
71
- - Rura executes hooks in order and exits early when a hook returns `{ early: true, output }`.
54
+ 2, // optional execution order
55
+ );
72
56
 
73
- - When the pipeline does not exit early, `output` is omitted and `early` becomes `false`.
57
+ // Deterministic execution.
58
+ const result = rura.run({ count: 1 }, [addOne, stopIfEven, addOne]);
59
+ ```
74
60
 
75
- #### 3. Run the pipeline
61
+ Asynchronous variant:
76
62
 
77
63
  ```ts
78
- const result = rura.run(ctx, [addOne, stopIfEven]);
79
-
80
- console.log(result);
81
- // -> {
82
- // early: true,
83
- // ctx: { count: 2 },
84
- // output: 2
85
- // }
64
+ rura.createHookAsync(...)
65
+ rura.runAsync(...)
86
66
  ```
87
67
 
88
- > Note: If your hooks are asynchronous,
89
- > use `rura.createHookAsync()` and run them through `rura.runAsync()` accordingly.
90
-
91
68
  ---
92
69
 
93
70
  ## Pipeline Builder
94
71
 
95
- > If you prefer working with a reusable pipeline instance
96
-
97
- **rura.createPipeline()** - Creates a lightweight, composable pipeline instance
98
- that can register hooks, merge with other pipelines, and be inspected.
72
+ Reusable pipeline instance:
99
73
 
100
74
  ```ts
101
- import { rura } from "rura";
75
+ const pipeline = rura.createPipeline<Ctx>();
102
76
 
103
- const pipeline = rura.createPipeline<Context, Output>();
77
+ pipeline.use(hookA).use(hookB);
104
78
 
105
- // Add hooks
106
- pipeline
107
- .use(hookA) // chainable
108
- .use(hookB)
109
- .use(hookC);
79
+ const result = pipeline.run({ count: 1 });
110
80
  ```
111
81
 
112
- example:
82
+ Asynchronous variant:
113
83
 
114
84
  ```ts
115
- type Ctx = { value: number };
116
-
117
- // Create a reusable pipeline instance
118
- const pipelineA = rura.createPipeline<Ctx>();
119
-
120
- // Register a hook using `use()`
121
- pipelineA.use({
122
- name: "add-two",
123
- run: (ctx) => {
124
- ctx.value += 2;
125
- },
126
- });
127
-
128
- // Create another pipeline (preloaded with hooks)
129
- const pipelineB = rura.createPipeline<Ctx>([
130
- {
131
- name: "multiply-three",
132
- run: (ctx) => {
133
- ctx.value *= 3;
134
- },
135
- },
136
- ]);
137
-
138
- // Merge pipelines into a single combined pipeline
139
- const pipeline = pipelineA.merge(pipelineB);
140
-
141
- // Execute the pipeline
142
- const result = await pipeline.run({ value: 1 });
143
-
144
- console.log(result);
145
- // -> {
146
- // early: false,
147
- // ctx: { value: 9 }
148
- // }
85
+ const pipeline = rura.createPipelineAsync<Ctx>();
86
+ await pipeline.run(ctx);
149
87
  ```
150
88
 
151
- > Note: If your pipeline includes async hooks,
152
- > be sure to use `rura.createPipelineAsync()`, which awaits each hook in order.
153
-
154
- #### Pipeline Instance Methods
155
-
156
- `rura.createPipeline()` — Synchronous Pipeline
157
-
158
- | Method | Description | Parameters | Returns |
159
- | ---------------- | ----------------------------------------------------------------- | ---------- | ------------------ |
160
- | **use(hook)** | Adds a hook, normalizes its order, and re-sorts hooks. | `hook` | `this` (chainable) |
161
- | **merge(other)** | Merges hooks from another pipeline and re-sorts them. | `other` | `this` (chainable) |
162
- | **getHooks()** | Returns a sorted shallow copy of all registered hooks. | – | `RuraHook[]` |
163
- | **debugHooks()** | Prints a formatted, human-readable hook list. | – | `void` |
164
- | **run(ctx)** | Executes the pipeline synchronously. (delegates to `rura.run()`). | `ctx` | `RuraResult` |
165
-
166
- <br/>
167
-
168
- `rura.createPipelineAsync()` — Asynchronous Pipeline
89
+ #### Pipeline Instance API
169
90
 
170
- | Method | Description | Parameters | Returns |
171
- | ---------------- | ----------------------------------------------------------------------- | ---------- | --------------------- |
172
- | **use(hook)** | Adds a hook, normalizes its order, and re-sorts hooks. | `hook` | `this` (chainable) |
173
- | **merge(other)** | Merges hooks from another pipeline and re-sorts them. | `other` | `this` (chainable) |
174
- | **getHooks()** | Returns a sorted shallow copy of all registered hooks. | – | `RuraHook[]` |
175
- | **debugHooks()** | Prints a formatted, human-readable hook list. | – | `void` |
176
- | **run(ctx)** | Executes the pipeline asynchronously. (delegates to `rura.runAsync()`). | `ctx` | `Promise<RuraResult>` |
91
+ | Method | Description | Returns |
92
+ | ------------ | ------------------------------------------- | ------------------------ |
93
+ | **use** | Registers a hook and re-sorts the pipeline. | `this` (chainable) |
94
+ | **getHooks** | Returns a shallow copy of sorted hooks. | `Hook[]` |
95
+ | **logHooks** | Logs hook order and execution type. | `void` |
96
+ | **run** | Executes the pipeline. | `RuraResult` / `Promise` |
package/dist/index.cjs CHANGED
@@ -1,87 +1,95 @@
1
1
  'use strict';
2
2
 
3
+ // src/hooks/internal.ts
4
+ var ASYNC_HOOK = /* @__PURE__ */ Symbol("rura.async");
5
+
3
6
  // src/hooks/create-hook.ts
4
7
  function createHook(name, run2, order) {
5
- return { name, run: run2, order };
8
+ const hook = {
9
+ name,
10
+ run: run2,
11
+ ...order !== void 0 ? { order } : {}
12
+ };
13
+ return hook;
6
14
  }
7
15
  function createHookAsync(name, run2, order) {
8
- return { name, run: run2, order };
16
+ const hook = {
17
+ name,
18
+ run: run2,
19
+ ...order !== void 0 ? { order } : {},
20
+ [ASYNC_HOOK]: true
21
+ };
22
+ return hook;
9
23
  }
10
24
 
11
25
  // src/hooks/utils/is-async-hook.ts
12
26
  function isAsyncHook(hook) {
13
- return hook.run.constructor.name === "AsyncFunction";
27
+ return hook[ASYNC_HOOK] === true;
14
28
  }
15
29
 
16
- // src/pipeline/create/utils/format-debug-message.ts
17
- var formatDebugMessage = (hooks, name, title) => {
18
- if (title) {
19
- console.log(`
20
- ${title(hooks)}`);
21
- } else {
22
- const label = name ? ` <${name}>` : "";
23
- console.log(`
24
- \u{1F30A} Rura Pipeline${label} (${hooks.length} hooks)`);
30
+ // src/pipeline/create/utils/assert-sync-hook.ts
31
+ function assertSyncHook(hook) {
32
+ if (isAsyncHook(hook)) {
33
+ throw new Error(
34
+ `Async hook "${hook.name}" is not allowed in sync pipeline.`
35
+ );
25
36
  }
26
- console.log(`\u2500\u2500\u2500`);
37
+ }
38
+
39
+ // src/pipeline/create/utils/log-pipeline-hooks.ts
40
+ function logPipelineHooks(hooks, name = "Rura") {
41
+ const count = hooks.length;
42
+ const suffix = count === 1 ? "hook" : "hooks";
43
+ console.log(`${name} (${count} ${suffix})`);
44
+ console.log("\u2500\u2500\u2500");
27
45
  hooks.forEach((hook, i) => {
28
46
  const kind = isAsyncHook(hook) ? "async" : "sync";
47
+ const order = hook.order ?? "-";
29
48
  console.log(
30
- `${i + 1}. order:${String(hook.order).padStart(4)} | ${hook.name} (${kind})`
49
+ `${i + 1}. order: ${String(order).padEnd(4)} | ${hook.name} (${kind})`
31
50
  );
32
51
  });
33
- console.log(`\u2500\u2500\u2500
34
- `);
35
- };
52
+ console.log("\u2500\u2500\u2500");
53
+ }
36
54
 
37
55
  // src/pipeline/create/create-pipeline-base.ts
38
56
  function createPipelineBase(initialHooks, runFn, options) {
57
+ const isSync = options.mode === "sync";
58
+ if (isSync) for (const hook of initialHooks) assertSyncHook(hook);
39
59
  const name = options.name;
40
- const hooks = initialHooks.map((h) => applyDefaultOrder(h));
41
- function applyDefaultOrder(h) {
42
- return { ...h, order: h.order ?? 0 };
43
- }
60
+ const hooks = [...initialHooks];
44
61
  function sortHooks() {
45
- hooks.sort((a, b) => a.order - b.order);
62
+ hooks.sort((a, b) => {
63
+ const ao = a.order ?? Number.POSITIVE_INFINITY;
64
+ const bo = b.order ?? Number.POSITIVE_INFINITY;
65
+ return ao - bo;
66
+ });
46
67
  }
47
- function use(h) {
48
- if (options.mode === "sync" && isAsyncHook(h)) {
49
- throw new Error(`Async hook "${h.name}" is not allowed in createRura().`);
50
- }
51
- hooks.push(applyDefaultOrder(h));
52
- sortHooks();
53
- return api;
54
- }
55
- function merge(other) {
56
- other.getHooks().forEach((h) => hooks.push(applyDefaultOrder(h)));
68
+ function use(hook) {
69
+ if (isSync) assertSyncHook(hook);
70
+ hooks.push(hook);
57
71
  sortHooks();
58
- return api;
72
+ return pipeline;
59
73
  }
60
74
  function getHooks() {
61
75
  return [...hooks];
62
76
  }
63
- function debugHooks(title) {
64
- formatDebugMessage(hooks, name, title);
77
+ function logHooks() {
78
+ logPipelineHooks(hooks, name);
65
79
  }
66
80
  function run2(ctx) {
67
- return runFn(ctx, hooks);
81
+ return runFn(ctx, [...hooks]);
68
82
  }
69
- const api = { use, merge, getHooks, debugHooks, run: run2 };
83
+ const pipeline = { use, getHooks, logHooks, run: run2 };
70
84
  sortHooks();
71
- return api;
85
+ return pipeline;
72
86
  }
73
87
 
74
88
  // src/pipeline/run/run.ts
75
89
  function run(ctx, hooks) {
76
90
  for (const hook of hooks) {
77
- if (isAsyncHook(hook)) {
78
- throw new Error(
79
- `Async hook "${hook.name}" detected in run(). Use runAsync() instead.`
80
- );
81
- }
82
91
  const result = hook.run(ctx);
83
- const isEarlyReturn = result && result.early === true;
84
- if (isEarlyReturn) {
92
+ if (result?.early === true) {
85
93
  return {
86
94
  early: true,
87
95
  ctx,
@@ -95,20 +103,11 @@ function run(ctx, hooks) {
95
103
  };
96
104
  }
97
105
 
98
- // src/pipeline/create/create-pipeline.ts
99
- function createPipeline(hooks = []) {
100
- return createPipelineBase(
101
- hooks,
102
- run,
103
- { mode: "sync" }
104
- );
105
- }
106
-
107
106
  // src/pipeline/run/run-async.ts
108
107
  async function runAsync(ctx, hooks) {
109
108
  for (const hook of hooks) {
110
109
  const result = await hook.run(ctx);
111
- if (result && result.early === true) {
110
+ if (result?.early === true) {
112
111
  return {
113
112
  early: true,
114
113
  ctx,
@@ -122,6 +121,15 @@ async function runAsync(ctx, hooks) {
122
121
  };
123
122
  }
124
123
 
124
+ // src/pipeline/create/create-pipeline.ts
125
+ function createPipeline(hooks = []) {
126
+ return createPipelineBase(
127
+ hooks,
128
+ run,
129
+ { mode: "sync" }
130
+ );
131
+ }
132
+
125
133
  // src/pipeline/create/create-pipeline-async.ts
126
134
  function createPipelineAsync(hooks = []) {
127
135
  return createPipelineBase(
@@ -132,18 +140,22 @@ function createPipelineAsync(hooks = []) {
132
140
  }
133
141
 
134
142
  // src/rura.ts
135
- var rura = {
136
- // hook factories
143
+ var rura = Object.freeze({
144
+ // Hook creation
137
145
  createHook,
138
146
  createHookAsync,
139
- // executors
147
+ // Direct execution
140
148
  run,
141
149
  runAsync,
142
- // pipeline constructors
150
+ // Pipeline construction
143
151
  createPipeline,
144
- createPipelineAsync,
145
- // utils
146
- isAsyncHook
147
- };
152
+ createPipelineAsync
153
+ });
148
154
 
155
+ exports.createHook = createHook;
156
+ exports.createHookAsync = createHookAsync;
157
+ exports.createPipeline = createPipeline;
158
+ exports.createPipelineAsync = createPipelineAsync;
159
+ exports.run = run;
160
+ exports.runAsync = runAsync;
149
161
  exports.rura = rura;
package/dist/index.js CHANGED
@@ -1,85 +1,93 @@
1
+ // src/hooks/internal.ts
2
+ var ASYNC_HOOK = /* @__PURE__ */ Symbol("rura.async");
3
+
1
4
  // src/hooks/create-hook.ts
2
5
  function createHook(name, run2, order) {
3
- return { name, run: run2, order };
6
+ const hook = {
7
+ name,
8
+ run: run2,
9
+ ...order !== void 0 ? { order } : {}
10
+ };
11
+ return hook;
4
12
  }
5
13
  function createHookAsync(name, run2, order) {
6
- return { name, run: run2, order };
14
+ const hook = {
15
+ name,
16
+ run: run2,
17
+ ...order !== void 0 ? { order } : {},
18
+ [ASYNC_HOOK]: true
19
+ };
20
+ return hook;
7
21
  }
8
22
 
9
23
  // src/hooks/utils/is-async-hook.ts
10
24
  function isAsyncHook(hook) {
11
- return hook.run.constructor.name === "AsyncFunction";
25
+ return hook[ASYNC_HOOK] === true;
12
26
  }
13
27
 
14
- // src/pipeline/create/utils/format-debug-message.ts
15
- var formatDebugMessage = (hooks, name, title) => {
16
- if (title) {
17
- console.log(`
18
- ${title(hooks)}`);
19
- } else {
20
- const label = name ? ` <${name}>` : "";
21
- console.log(`
22
- \u{1F30A} Rura Pipeline${label} (${hooks.length} hooks)`);
28
+ // src/pipeline/create/utils/assert-sync-hook.ts
29
+ function assertSyncHook(hook) {
30
+ if (isAsyncHook(hook)) {
31
+ throw new Error(
32
+ `Async hook "${hook.name}" is not allowed in sync pipeline.`
33
+ );
23
34
  }
24
- console.log(`\u2500\u2500\u2500`);
35
+ }
36
+
37
+ // src/pipeline/create/utils/log-pipeline-hooks.ts
38
+ function logPipelineHooks(hooks, name = "Rura") {
39
+ const count = hooks.length;
40
+ const suffix = count === 1 ? "hook" : "hooks";
41
+ console.log(`${name} (${count} ${suffix})`);
42
+ console.log("\u2500\u2500\u2500");
25
43
  hooks.forEach((hook, i) => {
26
44
  const kind = isAsyncHook(hook) ? "async" : "sync";
45
+ const order = hook.order ?? "-";
27
46
  console.log(
28
- `${i + 1}. order:${String(hook.order).padStart(4)} | ${hook.name} (${kind})`
47
+ `${i + 1}. order: ${String(order).padEnd(4)} | ${hook.name} (${kind})`
29
48
  );
30
49
  });
31
- console.log(`\u2500\u2500\u2500
32
- `);
33
- };
50
+ console.log("\u2500\u2500\u2500");
51
+ }
34
52
 
35
53
  // src/pipeline/create/create-pipeline-base.ts
36
54
  function createPipelineBase(initialHooks, runFn, options) {
55
+ const isSync = options.mode === "sync";
56
+ if (isSync) for (const hook of initialHooks) assertSyncHook(hook);
37
57
  const name = options.name;
38
- const hooks = initialHooks.map((h) => applyDefaultOrder(h));
39
- function applyDefaultOrder(h) {
40
- return { ...h, order: h.order ?? 0 };
41
- }
58
+ const hooks = [...initialHooks];
42
59
  function sortHooks() {
43
- hooks.sort((a, b) => a.order - b.order);
60
+ hooks.sort((a, b) => {
61
+ const ao = a.order ?? Number.POSITIVE_INFINITY;
62
+ const bo = b.order ?? Number.POSITIVE_INFINITY;
63
+ return ao - bo;
64
+ });
44
65
  }
45
- function use(h) {
46
- if (options.mode === "sync" && isAsyncHook(h)) {
47
- throw new Error(`Async hook "${h.name}" is not allowed in createRura().`);
48
- }
49
- hooks.push(applyDefaultOrder(h));
50
- sortHooks();
51
- return api;
52
- }
53
- function merge(other) {
54
- other.getHooks().forEach((h) => hooks.push(applyDefaultOrder(h)));
66
+ function use(hook) {
67
+ if (isSync) assertSyncHook(hook);
68
+ hooks.push(hook);
55
69
  sortHooks();
56
- return api;
70
+ return pipeline;
57
71
  }
58
72
  function getHooks() {
59
73
  return [...hooks];
60
74
  }
61
- function debugHooks(title) {
62
- formatDebugMessage(hooks, name, title);
75
+ function logHooks() {
76
+ logPipelineHooks(hooks, name);
63
77
  }
64
78
  function run2(ctx) {
65
- return runFn(ctx, hooks);
79
+ return runFn(ctx, [...hooks]);
66
80
  }
67
- const api = { use, merge, getHooks, debugHooks, run: run2 };
81
+ const pipeline = { use, getHooks, logHooks, run: run2 };
68
82
  sortHooks();
69
- return api;
83
+ return pipeline;
70
84
  }
71
85
 
72
86
  // src/pipeline/run/run.ts
73
87
  function run(ctx, hooks) {
74
88
  for (const hook of hooks) {
75
- if (isAsyncHook(hook)) {
76
- throw new Error(
77
- `Async hook "${hook.name}" detected in run(). Use runAsync() instead.`
78
- );
79
- }
80
89
  const result = hook.run(ctx);
81
- const isEarlyReturn = result && result.early === true;
82
- if (isEarlyReturn) {
90
+ if (result?.early === true) {
83
91
  return {
84
92
  early: true,
85
93
  ctx,
@@ -93,20 +101,11 @@ function run(ctx, hooks) {
93
101
  };
94
102
  }
95
103
 
96
- // src/pipeline/create/create-pipeline.ts
97
- function createPipeline(hooks = []) {
98
- return createPipelineBase(
99
- hooks,
100
- run,
101
- { mode: "sync" }
102
- );
103
- }
104
-
105
104
  // src/pipeline/run/run-async.ts
106
105
  async function runAsync(ctx, hooks) {
107
106
  for (const hook of hooks) {
108
107
  const result = await hook.run(ctx);
109
- if (result && result.early === true) {
108
+ if (result?.early === true) {
110
109
  return {
111
110
  early: true,
112
111
  ctx,
@@ -120,6 +119,15 @@ async function runAsync(ctx, hooks) {
120
119
  };
121
120
  }
122
121
 
122
+ // src/pipeline/create/create-pipeline.ts
123
+ function createPipeline(hooks = []) {
124
+ return createPipelineBase(
125
+ hooks,
126
+ run,
127
+ { mode: "sync" }
128
+ );
129
+ }
130
+
123
131
  // src/pipeline/create/create-pipeline-async.ts
124
132
  function createPipelineAsync(hooks = []) {
125
133
  return createPipelineBase(
@@ -130,18 +138,16 @@ function createPipelineAsync(hooks = []) {
130
138
  }
131
139
 
132
140
  // src/rura.ts
133
- var rura = {
134
- // hook factories
141
+ var rura = Object.freeze({
142
+ // Hook creation
135
143
  createHook,
136
144
  createHookAsync,
137
- // executors
145
+ // Direct execution
138
146
  run,
139
147
  runAsync,
140
- // pipeline constructors
148
+ // Pipeline construction
141
149
  createPipeline,
142
- createPipelineAsync,
143
- // utils
144
- isAsyncHook
145
- };
150
+ createPipelineAsync
151
+ });
146
152
 
147
- export { rura };
153
+ export { createHook, createHookAsync, createPipeline, createPipelineAsync, run, runAsync, rura };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Rura — The hook pipeline.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ export { rura } from "../src/rura";
7
+ export { createHook, createHookAsync, type RuraHookBase, type RuraHookSync, type RuraHookAsync, type RuraHook, } from "../src/hooks";
8
+ export { createPipeline, createPipelineAsync, run, runAsync, type RuraResult, } from "../src/pipeline";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../export/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGnC,OAAO,EACL,UAAU,EACV,eAAe,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,QAAQ,GACd,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,GAAG,EACH,QAAQ,EACR,KAAK,UAAU,GAChB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { RuraHookAsync, RuraHookSync } from "./types";
2
+ /**
3
+ * Creates a synchronous hook.
4
+ *
5
+ * The hook executes without awaiting.
6
+ *
7
+ * @public
8
+ */
9
+ export declare function createHook<Ctx = unknown, Out = unknown>(name: string, run: RuraHookSync<Ctx, Out>["run"], order?: number): RuraHookSync<Ctx, Out>;
10
+ /**
11
+ * Creates an asynchronous hook.
12
+ *
13
+ * The hook executes via `await`.
14
+ *
15
+ * @public
16
+ */
17
+ export declare function createHookAsync<Ctx = unknown, Out = unknown>(name: string, run: RuraHookAsync<Ctx, Out>["run"], order?: number): RuraHookAsync<Ctx, Out>;
18
+ //# sourceMappingURL=create-hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-hook.d.ts","sourceRoot":"","sources":["../../../../src/hooks/create-hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG3D;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,GAAG,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO,EACrD,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,EAClC,KAAK,CAAC,EAAE,MAAM,GACb,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAQxB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO,EAC1D,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,EACnC,KAAK,CAAC,EAAE,MAAM,GACb,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CASzB"}
@@ -0,0 +1,3 @@
1
+ export { createHook, createHookAsync } from "./create-hook";
2
+ export type { RuraHookBase, RuraHookSync, RuraHookAsync, RuraHook, } from "./types";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC5D,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,QAAQ,GACT,MAAM,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../../../src/hooks/internal.ts"],"names":[],"mappings":""}