@empyria/restate 0.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.
- package/.oxfmtrc.json +9 -0
- package/AGENTS.md +64 -0
- package/README.md +78 -0
- package/index.js +7 -0
- package/lib/Admin.js +737 -0
- package/lib/Caller.js +50 -0
- package/lib/Cron.js +109 -0
- package/lib/Validation.js +39 -0
- package/package.json +44 -0
- package/test/Admin.test.js +470 -0
- package/test/Caller.test.js +42 -0
- package/test/Cron.test.js +151 -0
- package/test/Validation.test.js +34 -0
package/.oxfmtrc.json
ADDED
package/AGENTS.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Restate.dev helpers for **Principia**, a nanoservice framework built primarily on Bun:
|
|
4
|
+
an Admin API client, a dynamic-dispatch service, cron-driven workflow scheduling, and
|
|
5
|
+
schema validation for workflow handlers.
|
|
6
|
+
|
|
7
|
+
Targets Restate server `1.7.x` and `@restatedev/restate-sdk` `1.6.x` — check both when
|
|
8
|
+
touching version pins; the SDK's own version numbering runs well ahead of the server's
|
|
9
|
+
(e.g. `1.16.x` was latest on npm when `1.6.x` was what this repo targets), so "latest"
|
|
10
|
+
is not the right default here.
|
|
11
|
+
|
|
12
|
+
## Runtime
|
|
13
|
+
|
|
14
|
+
- Requires Bun `>=1.4.0` or Node.js `>=26`, inherited from `@empyria/classification`'s use
|
|
15
|
+
of native `Temporal`. Both `@empyria/classification` and `@empyria/common` are **git
|
|
16
|
+
dependencies** — this package only sees their pushed commits, not local working-tree changes
|
|
17
|
+
in sibling repos.
|
|
18
|
+
- Plain ESM, no TypeScript, no build step. The original `admin.ts`/`admin.types.ts`/`Caller.ts`
|
|
19
|
+
(and the `generateTypes.sh` script that regenerated `admin.types.ts` from a live server's
|
|
20
|
+
`/openapi` spec) have been removed — `lib/Admin.js`/`lib/Caller.js` are the canonical,
|
|
21
|
+
hand-converted, tested equivalents. There is no generated-types workflow left in this repo;
|
|
22
|
+
if the Admin API needs re-syncing, diff `lib/Admin.js`'s assumptions against a live server's
|
|
23
|
+
`<admin-url>/openapi` by hand.
|
|
24
|
+
- Relative imports must include explicit `.js` extensions — Bun tolerates missing ones, Node's
|
|
25
|
+
ESM resolver doesn't.
|
|
26
|
+
|
|
27
|
+
## No official Admin API client
|
|
28
|
+
|
|
29
|
+
Verified directly against the published `@restatedev/restate-sdk`/`-clients` package
|
|
30
|
+
internals (both the `1.6.x` line this repo targets and the latest available at the time):
|
|
31
|
+
zero Admin API exports. Only the ingress/invocation client and the service-authoring API
|
|
32
|
+
(`restate.service`/`object`/`workflow`) are official. `lib/Admin.js` fetches the Admin API's
|
|
33
|
+
REST endpoints directly — that's not a stopgap, it's the only way to do this today.
|
|
34
|
+
|
|
35
|
+
## Testing Restate service/object definitions
|
|
36
|
+
|
|
37
|
+
`restate.service({...})`/`restate.object({...})` do **not** return your handler functions
|
|
38
|
+
under `.handlers` — that property doesn't exist on the returned definition. The raw handler
|
|
39
|
+
functions are reachable at `.service` (for `restate.service`) or `.object` (for
|
|
40
|
+
`restate.object`), e.g. `cronJob.object.initiate(mockCtx, request)`. See `test/Cron.test.js`.
|
|
41
|
+
|
|
42
|
+
`@restatedev/restate-sdk-clients`'s `clients` export (re-exported from `lib/Admin.js`) is a
|
|
43
|
+
live ESM namespace binding — you cannot reassign `clients.connect` directly (`TypeError:
|
|
44
|
+
Attempted to assign to readonly property`). Use `mock.module('@restatedev/restate-sdk-clients',
|
|
45
|
+
() => ({...}))` instead, and capture the _real_ `connect` function once at module load (before
|
|
46
|
+
any mocking) if you need to restore it — reading it back off the live `clients` binding later
|
|
47
|
+
may observe an already-mocked value. See `test/Admin.test.js`.
|
|
48
|
+
|
|
49
|
+
`setupRestate` (in `lib/Admin.js`) is not unit tested: it binds real HTTP/2 + health-check
|
|
50
|
+
ports, installs process-wide `SIGTERM`/`SIGINT` handlers, and its returned `forceClose` calls
|
|
51
|
+
`process.exit()` — none of which are safe to exercise in-process in a test run.
|
|
52
|
+
|
|
53
|
+
## Zero-dependency preference
|
|
54
|
+
|
|
55
|
+
Cron parsing uses `croner` (zero dependencies), not `cron-parser` (pulls in `luxon`). If you
|
|
56
|
+
touch `lib/Cron.js`'s scheduling logic: `new Cron(pattern)` without a callback just parses —
|
|
57
|
+
it does not start a timer — and `.nextRun(referenceDate)` is what gives a deterministic next
|
|
58
|
+
run time from Restate's replay-safe `ctx.date.now()`, matching the library's actual API rather
|
|
59
|
+
than `cron-parser`'s `CronExpressionParser.parse(...).next()` shape.
|
|
60
|
+
|
|
61
|
+
## Style
|
|
62
|
+
|
|
63
|
+
- Formatting is enforced by oxfmt ([.oxfmtrc.json](./.oxfmtrc.json)): tabs, single quotes, no
|
|
64
|
+
semicolons, trailing commas. Run `bun run format:fix` before committing.
|
package/README.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# @empyria/restate
|
|
2
|
+
|
|
3
|
+
[Restate.dev](https://restate.dev) helpers for **Principia**, a nanoservice framework built
|
|
4
|
+
primarily on Bun: an Admin API client, a generic dynamic-dispatch service, cron-driven
|
|
5
|
+
workflow scheduling, and Restate-aware input/output schema validation.
|
|
6
|
+
|
|
7
|
+
Targets Restate server `1.7.x` and `@restatedev/restate-sdk` `1.6.x`.
|
|
8
|
+
|
|
9
|
+
## Requirements
|
|
10
|
+
|
|
11
|
+
- Bun `>=1.4.0` or Node.js `>=26`
|
|
12
|
+
- Plain ESM, no build step, no TypeScript
|
|
13
|
+
|
|
14
|
+
Both requirements come from [@empyria/classification](https://github.com/imrefazekas/empyria-classification)
|
|
15
|
+
and [@empyria/common](https://github.com/imrefazekas/empyria-common), which this package
|
|
16
|
+
depends on and which use the native `Temporal` global for all date/time handling.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
bun add @empyria/restate
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import { createRestateAdmin, withValidation, cronJob, cronJobInitiator } from '@empyria/restate'
|
|
28
|
+
|
|
29
|
+
const admin = createRestateAdmin({
|
|
30
|
+
restateAdminURL: 'http://localhost:9070',
|
|
31
|
+
restateURL: 'http://localhost:9071',
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const services = await admin.listServices()
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Everything is re-exported from the package root via [index.js](./index.js). Individual
|
|
38
|
+
modules under `lib/` can also be imported directly if you only need one:
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
import { checkServiceHandler } from '@empyria/restate/lib/Admin.js'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Modules
|
|
45
|
+
|
|
46
|
+
| Module | Purpose |
|
|
47
|
+
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
48
|
+
| [lib/Admin.js](./lib/Admin.js) | Restate Admin API client — service/handler discovery, deployment registration and teardown, workflow/message dispatch, and `setupRestate` for wiring up an endpoint with health checks and graceful shutdown. |
|
|
49
|
+
| [lib/Caller.js](./lib/Caller.js) | `CallerServiceDef` — a generic Restate service that dispatches a call to any handler on any other service by name, for when the target isn't known at compile time. |
|
|
50
|
+
| [lib/Cron.js](./lib/Cron.js) | `cronJobInitiator`/`cronJob` — Restate services implementing cron-driven, replay-safe recurring job scheduling on top of `croner`. |
|
|
51
|
+
| [lib/Validation.js](./lib/Validation.js) | `withValidation` — wraps a workflow handler with input/output JSON schema validation via `@empyria/common`. |
|
|
52
|
+
|
|
53
|
+
There is no official Restate Admin API client (verified directly against the published
|
|
54
|
+
`@restatedev/restate-sdk`/`-clients` packages) — `lib/Admin.js` is a hand-written wrapper kept
|
|
55
|
+
in sync with the live Admin API's OpenAPI spec (`<admin-url>/openapi`) by hand.
|
|
56
|
+
|
|
57
|
+
Every exported function is documented with JSDoc directly in its source file — hovering
|
|
58
|
+
a function in VSCode or Zed shows its parameters and return type without any extra
|
|
59
|
+
tooling, since both editors read JSDoc from plain `.js` files automatically.
|
|
60
|
+
|
|
61
|
+
Tests live under [test/](./test/), one file per module, separate from the sources. They
|
|
62
|
+
mock `fetch` and the Restate SDK client rather than requiring a live server — the one
|
|
63
|
+
exception is `setupRestate`, which binds real ports and installs process signal handlers
|
|
64
|
+
and is deliberately left untested (see [AGENTS.md](./AGENTS.md)).
|
|
65
|
+
|
|
66
|
+
## Scripts
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
bun run format # check formatting (oxfmt)
|
|
70
|
+
bun run format:fix # apply formatting
|
|
71
|
+
bun run lint # lint (oxlint)
|
|
72
|
+
bun run lint:fix # lint and fix
|
|
73
|
+
bun run test # run tests with coverage
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
|
|
78
|
+
MIT © Imre Fazekas
|