@rhythmjs/rhythm 0.0.1 → 0.0.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/README.md +5 -5
- package/dist/rhythm.js +10 -10
- package/package.json +2 -6
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ The core composition kernel `@rhythmjs/router` and `@rhythmjs/cli` are built on.
|
|
|
5
5
|
## Concepts
|
|
6
6
|
|
|
7
7
|
- **Onion middleware** — `use()` wraps downstream steps, running code before _and_ after `next()`.
|
|
8
|
-
- **Providers** — `provide()` registers a value or async factory that resolves once and
|
|
8
|
+
- **Providers** — `provide()` registers a value or async factory that resolves once and joins the context at its position in the chain: only middleware (and mounted controllers) added after it see the value. A returned key prefixed with `#` (e.g. `"#close"`) stays out of context but is still passed in full to `dispose()`.
|
|
9
9
|
- **Encapsulated modules** — `register()` mounts a child `Rhythm`; its context stays sealed unless you explicitly export fields from it.
|
|
10
10
|
- **Readonly context** — the context passed to middleware is deeply readonly at the type level; state only changes via `next(extra)`, or through a value branded with the `RhythmMutable` symbol (how `RhythmRouter`/`RhythmCli`'s response objects stay mutable).
|
|
11
11
|
|
|
@@ -32,7 +32,7 @@ await app.run({ userId: "u1" });
|
|
|
32
32
|
await app.teardown();
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
`provide()` factories run once, in declaration order, each receiving everything resolved so far via `deps`. `
|
|
35
|
+
`provide()` factories run once, in declaration order, each receiving everything resolved so far via `deps`. On each `run()`, the whole chain — middleware and provider injections alike — executes in registration order, onion-style: everything only applies to what was chained after it.
|
|
36
36
|
|
|
37
37
|
### Module registration
|
|
38
38
|
|
|
@@ -57,11 +57,11 @@ const app = new Rhythm<{ userId: string }>()
|
|
|
57
57
|
|
|
58
58
|
- `new Rhythm<TInput>(options?)` — creates a pipeline; `options.name`/`options.type` label errors from `register()`.
|
|
59
59
|
- `.use(fn: (ctx, next) => Promise<void> | void)` — add an onion middleware step.
|
|
60
|
-
- `.provide(factory: (deps) => TValue | Promise<TValue>, dispose?)` — register a provider; resolved once, disposed in reverse order on `teardown()`.
|
|
61
|
-
- `.register(other: Rhythm, exportValue?)` — mount a child module; sealed by default, opt in via `exportValue`.
|
|
60
|
+
- `.provide(factory: (deps) => TValue | Promise<TValue>, dispose?)` — register a provider; resolved once, injected at its chain position, disposed in reverse order on `teardown()`.
|
|
61
|
+
- `.register(other: Rhythm, exportValue?)` — mount a child `Rhythm` module; sealed by default, opt in via `exportValue`. Controllers (`RhythmRouter`, `RhythmCli`) are not modules — they mount via `.use()` instead.
|
|
62
62
|
- `.run(input)` — runs `setup()` if needed, dispatches `input` through the middleware chain.
|
|
63
63
|
- `.callback()` — returns the cached, reusable `(input) => Promise<TContext>` handler `run()` uses internally.
|
|
64
|
-
- `.middleware()` — returns this instance as a plain middleware, for flat mounting into a parent via `.use()` instead of `.register()
|
|
64
|
+
- `.middleware()` — returns this instance as a plain middleware, for flat mounting into a parent via `.use()` instead of `.register()`.
|
|
65
65
|
- `.setup()` — resolves all providers, cascading into registered modules. Idempotent; retryable on failure.
|
|
66
66
|
- `.teardown()` — disposes all providers in reverse order, cascading into registered modules.
|
|
67
67
|
- `compose(middleware[])` — the standalone Koa-style onion dispatcher `Rhythm` is built on.
|
package/dist/rhythm.js
CHANGED
|
@@ -29,7 +29,6 @@ var Rhythm = class {
|
|
|
29
29
|
#options;
|
|
30
30
|
#providers = [];
|
|
31
31
|
#setupPromise = null;
|
|
32
|
-
#providedCache = null;
|
|
33
32
|
#composed = null;
|
|
34
33
|
#callbackFn = null;
|
|
35
34
|
constructor(options = {}) {
|
|
@@ -42,10 +41,17 @@ var Rhythm = class {
|
|
|
42
41
|
return this;
|
|
43
42
|
}
|
|
44
43
|
provide(factory, dispose) {
|
|
45
|
-
|
|
44
|
+
const entry = {
|
|
46
45
|
factory,
|
|
47
46
|
dispose
|
|
47
|
+
};
|
|
48
|
+
this.#providers.push(entry);
|
|
49
|
+
this.#middleware.push(async (ctx, next) => {
|
|
50
|
+
const exported = {};
|
|
51
|
+
for (const [key, value] of Object.entries(entry.resolved)) if (!key.startsWith("#")) exported[key] = value;
|
|
52
|
+
await next(exported);
|
|
48
53
|
});
|
|
54
|
+
this.#invalidateCallback();
|
|
49
55
|
return this;
|
|
50
56
|
}
|
|
51
57
|
register(other, exportValue) {
|
|
@@ -87,7 +93,6 @@ var Rhythm = class {
|
|
|
87
93
|
entry.resolved = await entry.factory(resolved);
|
|
88
94
|
for (const [key, value] of Object.entries(entry.resolved)) if (!key.startsWith("#")) resolved[key] = value;
|
|
89
95
|
}
|
|
90
|
-
this.#providedCache = resolved;
|
|
91
96
|
}
|
|
92
97
|
async teardown() {
|
|
93
98
|
for (const entry of [...this.#providers].reverse()) await entry.dispose?.(entry.resolved);
|
|
@@ -98,10 +103,7 @@ var Rhythm = class {
|
|
|
98
103
|
const fn = this.#composed;
|
|
99
104
|
this.#callbackFn = async (input) => {
|
|
100
105
|
await this.setup();
|
|
101
|
-
return fn({
|
|
102
|
-
...this.#providedCache,
|
|
103
|
-
...input
|
|
104
|
-
});
|
|
106
|
+
return fn({ ...input });
|
|
105
107
|
};
|
|
106
108
|
}
|
|
107
109
|
return this.#callbackFn;
|
|
@@ -113,9 +115,7 @@ var Rhythm = class {
|
|
|
113
115
|
return async (ctx, next) => {
|
|
114
116
|
await this.setup();
|
|
115
117
|
if (!this.#composed) this.#composed = compose(this.#middleware);
|
|
116
|
-
|
|
117
|
-
Object.assign(context, this.#providedCache);
|
|
118
|
-
await this.#composed(context, next);
|
|
118
|
+
await this.#composed(ctx, next);
|
|
119
119
|
};
|
|
120
120
|
}
|
|
121
121
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rhythmjs/rhythm",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "A minimal, type-safe onion-middleware and provider composition kernel.",
|
|
5
|
+
"homepage": "https://rhythm.js.org/rhythm",
|
|
5
6
|
"license": "ISC",
|
|
6
7
|
"repository": {
|
|
7
8
|
"type": "git",
|
|
@@ -30,10 +31,5 @@
|
|
|
30
31
|
},
|
|
31
32
|
"engines": {
|
|
32
33
|
"node": ">=20.19.0"
|
|
33
|
-
},
|
|
34
|
-
"scripts": {
|
|
35
|
-
"build": "vp pack",
|
|
36
|
-
"typecheck": "tsc --noEmit",
|
|
37
|
-
"test": "vp test"
|
|
38
34
|
}
|
|
39
35
|
}
|