@shivaedev/platform 0.16.0 → 0.17.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/CHANGELOG.md +17 -0
- package/README.md +33 -45
- package/dist/rpc/requireAdmin.d.ts +3 -3
- package/dist/rpc/requireAdmin.d.ts.map +1 -1
- package/dist/rpc/requireAdmin.js +5 -8
- package/dist/rpc/requireAdmin.js.map +1 -1
- package/dist/server/AppHostFactory.d.ts +15 -0
- package/dist/server/AppHostFactory.d.ts.map +1 -0
- package/dist/server/AppHostFactory.js +2 -0
- package/dist/server/AppHostFactory.js.map +1 -0
- package/dist/server/AppHostInput.d.ts +13 -0
- package/dist/server/AppHostInput.d.ts.map +1 -0
- package/dist/server/AppHostInput.js +2 -0
- package/dist/server/AppHostInput.js.map +1 -0
- package/dist/server/appHost.d.ts +8 -10
- package/dist/server/appHost.d.ts.map +1 -1
- package/dist/server/appHost.js +6 -6
- package/dist/server/appHost.js.map +1 -1
- package/dist/server/appHostHttp.d.ts +5 -2
- package/dist/server/appHostHttp.d.ts.map +1 -1
- package/dist/server/appHostHttp.js.map +1 -1
- package/dist/server/rpc-server/adapters/betterAuthSessions.js +11 -3
- package/dist/server/rpc-server/adapters/betterAuthSessions.js.map +1 -1
- package/package.json +6 -8
- package/src/rpc/requireAdmin.ts +6 -9
- package/src/server/AppHostFactory.ts +121 -0
- package/src/server/AppHostInput.ts +74 -0
- package/src/server/appHost.ts +43 -71
- package/src/server/appHostHttp.ts +4 -4
- package/src/server/rpc-server/adapters/betterAuthSessions.ts +11 -3
- package/docs/north-star.md +0 -36
- package/docs/roadmap.md +0 -31
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.17.0 - 2026-10-18
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `appHost` accepts a native `preflight` Layer that builds before migration checks or execution and application startup. Typed failures stop startup; its services remain available to migrations, application construction, application services, RPC handlers and host callers, and its resources close with the host scope. The host option types accept preflight service, error and requirement parameters and require the Layer whenever any of those types are declared.
|
|
8
|
+
- Export `AppHostFactory`, `AppHostInput` and `HostPreflight` types for annotated host factories, inputs and preflight options.
|
|
9
|
+
|
|
10
|
+
### Breaking
|
|
11
|
+
|
|
12
|
+
- `requireAdmin` now requires `SessionUser` and fails with `Forbidden` for non-admin users. Put RPC handlers behind `AuthenticatedUser`, and wrap HTTP handlers with `withSessionUser`, so authentication supplies the profile and rejects signed-out requests with `Unauthorized`.
|
|
13
|
+
|
|
14
|
+
## 0.16.1 - 2026-10-18
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Report an expired session during Better Auth's provider account lookup as Unauthorized instead of AuthUnavailable.
|
|
19
|
+
|
|
3
20
|
## 0.16.0 - 2026-10-18
|
|
4
21
|
|
|
5
22
|
### Added
|
package/README.md
CHANGED
|
@@ -65,7 +65,7 @@ Omit `services` when the app has no service Layer of its own. The host uses `Lay
|
|
|
65
65
|
|
|
66
66
|
The listener uses `HOST` or `127.0.0.1`, uses `PORT` or 3000, and reads `DATABASE_URL`. Set overrides in the one `config` object: `host`, `port` (0 selects an ephemeral port), `trustedProxy`, `maxBodySize`, `databaseUrl` (an Effect `Redacted<string>`), `applicationName`, and optional `changes`. Migration options accept `table` and `lockTimeout` (default `effect_sql_migrations` and five seconds). Native Layer failures remain in the build error channel; missing application dependencies remain in the requirement type.
|
|
67
67
|
|
|
68
|
-
RPC request bodies are limited to 1 MiB by default. Set `MAX_BODY_SIZE` to a byte count or override it with `config.maxBodySize`, a nonnegative safe integer. An oversized NDJSON body returns a 4xx before any RPC handler runs
|
|
68
|
+
RPC request bodies are limited to 1 MiB by default. Set `MAX_BODY_SIZE` to a byte count or override it with `config.maxBodySize`, a nonnegative safe integer. An oversized NDJSON body, fixed-length or chunked, returns a 4xx before any RPC handler runs. This limit applies to the host's RPC route.
|
|
69
69
|
|
|
70
70
|
For a native Node HTTP route, use `readBoundedBody` from `@shivaedev/platform/server/boundedBody.ts` with Effect's `HttpIncomingMessage.MaxBodySize`. It returns an `ArrayBuffer` without decoding the bytes. Oversized `content-length` headers are rejected before reading; chunked overflow drains the remaining body and preserves the connection for another request. `RequestBodyTooLarge` is a typed failure that implements Effect's `HttpServerRespondable` protocol with status 413; other read errors remain native `HttpServerError` failures. Consume the body once through this reader and decode the result in the application.
|
|
71
71
|
|
|
@@ -84,20 +84,23 @@ const routes = HttpRouter.add("POST", "/webhook", (request) =>
|
|
|
84
84
|
|
|
85
85
|
RPC uses the existing `localRpcGuard`: it requires a loopback peer and Host, same-origin or absent Origin, and the NDJSON content type. Session lookup uses transport headers. The host applies `RequestTracing` last to every served RPC, including loopback RPC, so it wraps authentication and handlers without a per-contract tracing declaration. Existing tracing declarations run once at that outermost boundary. With a session policy, contracts declare `Authenticated` and `MaybeAuthenticated` as needed; the host supplies their implementations. For `AuthenticatedUser`, merge `authenticatedUserLayer(sessions)` beside the handlers as shown below. Declared errors retain their Schema types. Applications still own resource authorization and use `rpcBoundary` when they need to map unexpected failures.
|
|
86
86
|
|
|
87
|
-
For local tools, use `policy: "loopback"` with contracts that do not use session middleware to serve RPC without a session provider. The
|
|
87
|
+
For local tools, use `policy: "loopback"` with contracts that do not use session middleware to serve RPC without a session provider. The same guard applies. This policy does not use `TRUSTED_PROXY` or `config.trustedProxy`. Set `rpcPath` to choose another native RPC route; `/rpc` remains the default.
|
|
88
88
|
|
|
89
|
-
Omit `migrations` to host an app without a database. This form creates no SQL pool and reads no `DATABASE_URL`; `AppHttpHostOptions` describes it. `AppHostOptions` requires migrations for database-backed hosts. A service that needs SQL still requires a SQL Layer. Provide `appDatabase` to the application’s service Layer when it owns database composition
|
|
89
|
+
Omit `migrations` to host an app without a database. This form creates no SQL pool and reads no `DATABASE_URL`; `AppHttpHostOptions` describes it. `AppHostOptions` requires migrations for database-backed hosts. A service that needs SQL still requires a SQL Layer. Provide `appDatabase` to the application’s service Layer when it owns database composition.
|
|
90
90
|
|
|
91
91
|
`appHost` serves unauthenticated `GET /health`. It queries its SQL client on each request and returns `200` only when the query succeeds within two seconds; a missing SQL client, query failure or timeout returns `503`. Both responses have an empty body and `Cache-Control: no-store`. This route also works when the SQL client comes from the application’s `services` Layer. Use it for database readiness checks.
|
|
92
92
|
|
|
93
93
|
Set `migrations.mode: "check"` on `appDatabase` or a database-backed `appHost` when a separate pre-deploy command owns migrations. Startup reads the ledger and fails with native `MigrationError` (`kind: "BadState"`) if any required migration ID or name is missing; it does not run migrations or create a ledger. Later ledger entries are allowed for rolling deployments. Use `migrations.mode: "wait"` for services that can start before that pre-deploy command finishes. It re-reads the ledger every second until current, then starts the application. Set `migrations.pollInterval` and `migrations.waitTimeout` with Effect duration inputs to change the interval and five-minute timeout. Timeout fails with the same `MigrationError` as `"check"`; interruption stops polling and closes the pool. SQL failures fail immediately. With `mode` omitted or `"migrate"`, startup applies pending migrations with a five-second lock timeout unless `migrations.lockTimeout` overrides it.
|
|
94
94
|
|
|
95
|
+
Supply `preflight: AppConfigLive` to `appHost` to build a native Layer before checking or applying migrations, or constructing the application. Use it to validate configuration such as app IDs, keys and invite lists. Its errors stay in the returned Layer's typed error channel, its requirements remain external requirements, and its services are available to migrations, application construction, services and RPC handlers as well as callers of the host Layer. Preflight resources close with the host scope. The option also works without migrations.
|
|
96
|
+
|
|
95
97
|
When construction itself touches the schema, use `appHost({ migrations, config, application })`. `application` is a native Effect that returns the HTTP host options (`group`, handler and service Layers, session policy, and optional HTTP config). The host first builds `appDatabase`, then evaluates this Effect in the host scope with SQL, Reactivity and `AppChanges` available. A failed migration or schema-current check prevents construction. Initialization requirements and errors stay in the returned Layer's types, and acquired resources close with the host scope.
|
|
96
98
|
|
|
97
99
|
```ts
|
|
98
100
|
const host = appHost({
|
|
99
101
|
config: { databaseUrl },
|
|
100
102
|
migrations: { loader: migrations, mode: "check" },
|
|
103
|
+
preflight: AppConfigLive,
|
|
101
104
|
application: Effect.gen(function* () {
|
|
102
105
|
const { routes, sessions } = yield* makeAuth();
|
|
103
106
|
return { group: Api, handlers: Handlers, services: Services, routes, sessions };
|
|
@@ -107,7 +110,7 @@ const host = appHost({
|
|
|
107
110
|
|
|
108
111
|
Construct Better Auth inside `application`, since its constructor starts schema validation. Keep validation enabled so a current migration ledger with missing auth columns still reports drift. The starter uses this form after its pre-deploy migrations.
|
|
109
112
|
|
|
110
|
-
Set `OTEL_EXPORTER_OTLP_ENDPOINT`
|
|
113
|
+
Set `OTEL_EXPORTER_OTLP_ENDPOINT` or `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` to export `appHost`'s Effect spans over OTLP/HTTP. Without an endpoint, no exporter or export loop is built, even when service metadata is set. The `http/protobuf` default follows the [OpenTelemetry recommendation](https://opentelemetry.io/docs/specs/otel/protocol/exporter/#specify-protocol); unsupported protocols, including `grpc`, fail startup with a `ConfigError` naming the value. Header and resource-attribute values are `key=value` pairs with URL-encoded values. Configuration is read through Effect Config.
|
|
111
114
|
|
|
112
115
|
The supported tracing variables and defaults are:
|
|
113
116
|
|
|
@@ -129,20 +132,18 @@ The supported tracing variables and defaults are:
|
|
|
129
132
|
|
|
130
133
|
Timeouts fail through the HTTP client's typed transport-error channel and use the same warning path as other transport failures. Effect retains its native retry policy; the request timeout applies to each attempt. The batch defaults follow Effect's `OtlpTracer.layer`. Its options cannot express a separate batch-operation deadline or a queue capacity, so `OTEL_BSP_EXPORT_TIMEOUT` controls shutdown only and `OTEL_BSP_MAX_QUEUE_SIZE` is unsupported. Other `OTEL_BSP_*` variables are unsupported.
|
|
131
134
|
|
|
132
|
-
On Railway, enable the per-service tracing setting separately for the web service and worker, and leave both exporter endpoint variables unset in your app's configuration. Railway injects the `OTEL_*` variables, including `OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf`, only when the app sets no endpoint of its own. The framework exports through Effect's own `effect/observability` OTLP tracer; eBPF auto-instrumentation is outside this path. For a worker, provide `otlpTracing` from `@shivaedev/platform/server/otlpTracing.ts` to its application Layer. It batches ended Effect spans and flushes during scoped shutdown with a three-second bound by default. The first failed export logs a warning with the collector status and redacted response body, or the transport failure kind when no response arrives. Repeated failures stay quiet until a successful export. Collector connection failures and HTTP errors leave requests, jobs and shutdown successful.
|
|
135
|
+
On Railway, enable the per-service tracing setting separately for the web service and worker, and leave both exporter endpoint variables unset in your app's configuration. Railway documents that it injects the `OTEL_*` variables, including `OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf`, only when the app sets no endpoint of its own. The framework exports through Effect's own `effect/observability` OTLP tracer; eBPF auto-instrumentation is outside this path. For a worker, provide `otlpTracing` from `@shivaedev/platform/server/otlpTracing.ts` to its application Layer. It batches ended Effect spans and flushes during scoped shutdown with a three-second bound by default. The first failed export logs a warning with the collector status and redacted response body, or the transport failure kind when no response arrives. Repeated failures stay quiet until a successful export. Collector connection failures and HTTP errors leave requests, jobs and shutdown successful.
|
|
133
136
|
|
|
134
137
|
Exported HTTP server spans use `{method} {route}` with `http.route` for matched RPC and router paths, including parameter templates; unmatched requests use the method alone. The production host continues incoming W3C `traceparent` context, including one sent by an edge proxy.
|
|
135
138
|
|
|
136
139
|
Both JSON and protobuf export serialization apply sensitive-key and credential-text redaction to span attributes, events, links, error details and resource attributes. Credential text includes JWTs, Bearer/Basic credentials, sensitive assignments including bare `sig=...` anywhere in text (with or without `?`), and complete PEM private-key blocks through their matching END marker, including RSA, EC, OPENSSH and encrypted private keys. Matches become `<redacted>`. `sig` uses the shared sensitive-key policy for attributes and text. URL query values, fragments and user information are also redacted. Exporter headers stay in the collector request, outside the spans. Applications must still avoid placing secrets in span names, free text or custom attributes.
|
|
137
140
|
|
|
138
|
-
Set `config.maxConnections` on `appDatabase` or a migrated `appHost` to bound the pool. A daemon with long-lived RPC streams can use `config.disablePreemptiveShutdown: true` to let scope closure interrupt those streams before closing the listener; omitting it keeps Node's native graceful-shutdown default.
|
|
141
|
+
Set `config.maxConnections` on `appDatabase` or a migrated `appHost` to bound the pool. A daemon with long-lived RPC streams can use `config.disablePreemptiveShutdown: true` to let scope closure interrupt those streams before closing the listener; omitting it keeps Node's native graceful-shutdown default. No platform test covers these two options.
|
|
139
142
|
|
|
140
|
-
For a deployment behind a proxy, set `HOST=0.0.0.0` and `TRUSTED_PROXY` to a comma-separated list of proxy peer IPs or CIDR ranges (IPv4 or IPv6), or use `config.host` and `config.trustedProxy`. Only matching peers may supply `X-Forwarded-Host` and `X-Forwarded-Proto` (`http` or `https`) for the guard's same-origin check; the proxy must overwrite both headers and preserve Origin. A single authority is required, and comma-separated forwarding chains are refused. IPv4-mapped IPv6 peers match their IPv4 address. Malformed addresses or ranges fail `appHost` startup with a typed `ConfigError`. NDJSON and the application's session Origin policy still apply.
|
|
143
|
+
For a deployment behind a proxy, set `HOST=0.0.0.0` and `TRUSTED_PROXY` to a comma-separated list of proxy peer IPs or CIDR ranges (IPv4 or IPv6), or use `config.host` and `config.trustedProxy`. Only matching peers may supply `X-Forwarded-Host` and `X-Forwarded-Proto` (`http` or `https`) for the guard's same-origin check; the proxy must overwrite both headers and preserve Origin. A single authority is required, and comma-separated forwarding chains are refused. IPv4-mapped IPv6 peers match their IPv4 address. Malformed addresses or ranges fail `appHost` startup with a typed `ConfigError`. NDJSON and the application's session Origin policy still apply. See the [deployment quickstart](https://github.com/ShivaeDev/platform/blob/main/docs/framework/quickstart.md#deploy).
|
|
141
144
|
|
|
142
145
|
A subscription handler reads `AppChanges` and returns `changes.stream(keys)` after its authorization check. Writes use `transact` and `invalidateOnCommit` from effect-sql: local streams receive committed invalidations and rollback emits none. For delivery between processes, set `config.changes: { channel: "app_changes" }`; the host binds PostgreSQL LISTEN/NOTIFY to the same SQL pool and resyncs streams when its listener recovers. The native heartbeat and retry options may be supplied in `changes`. A worker can provide `appDatabase({ migrations, config })` to its service Layer to share this database and delivery composition without starting HTTP.
|
|
143
146
|
|
|
144
|
-
The [composed PostgreSQL fixture](https://github.com/ShivaeDev/platform/blob/main/docs/framework/composed-example.md) uses this host for its HTTP servers and `appDatabase` for its worker. It proves commit visibility, rollback silence, typed refusals and delivery between server processes. Platform's host tests also cover static files, environment configuration, guard rejection before session lookup, startup ordering, migration failure and scoped shutdown.
|
|
145
|
-
|
|
146
147
|
### 1. Once per application: contracts and session policy
|
|
147
148
|
|
|
148
149
|
Declare the RPC group in a shared module:
|
|
@@ -219,8 +220,6 @@ export const AccountServer = Layer.merge(AccountHandlers, authenticatedUserLayer
|
|
|
219
220
|
|
|
220
221
|
Here `sessions` is the application's policy from the previous example, with a Better Auth lookup that returns all three user fields. Merge `authenticatedUserLayer(sessions)` alongside the handler Layer when using `appHost`; the host continues to supply its id-only and optional middleware. A missing session fails with typed `Unauthorized`; rejected origins fail with `Forbidden`, and provider failures remain `AuthUnavailable`. The profile contains id, name and email, plus an optional role when the provider supplies it, without exposing the rest of the provider's user record. Handlers do not query the provider's user table.
|
|
221
222
|
|
|
222
|
-
The starter's `notes.whoami` query returns id, name and email, and its note handlers use `SessionUser.id` for ownership. Its PostgreSQL/HTTP test checks concurrent users, anonymous requests and sign-out revocation.
|
|
223
|
-
|
|
224
223
|
#### Reading provider account IDs
|
|
225
224
|
|
|
226
225
|
Opt in to provider account IDs by passing Better Auth's account lookup as the second argument to `betterAuthSessions`. It runs after a session is found, using the same transport headers:
|
|
@@ -241,7 +240,7 @@ const githubAccount = Effect.map(SessionUser, (user) =>
|
|
|
241
240
|
|
|
242
241
|
Use `authenticatedUserLayer(sessions)` as above. `SessionUserValue.providerAccounts` is an optional readonly array of `ProviderAccountValue`, each containing only `{ providerId: string, accountId: string }`. GitHub's numeric user ID is represented as a string, for example `{ providerId: "github", accountId: "123" }`; it is not Better Auth's account-row id. A user without a GitHub account has no matching entry. Without the second lookup, the profile omits `providerAccounts`. No application SQL against Better Auth's `account` table is needed.
|
|
243
242
|
|
|
244
|
-
An account lookup failure follows the same `AuthUnavailable` path as a session lookup failure.
|
|
243
|
+
An account lookup failure follows the same `AuthUnavailable` path as a session lookup failure.
|
|
245
244
|
|
|
246
245
|
### Requiring an admin
|
|
247
246
|
|
|
@@ -275,7 +274,7 @@ const routes = HttpRouter.use((router) =>
|
|
|
275
274
|
);
|
|
276
275
|
```
|
|
277
276
|
|
|
278
|
-
`withSessionUser(policy, headers, operation)` resolves the session through the existing transport-header and Origin policy path and provides `Identity` and `SessionUser` only around the supplied Effect. It is also the boundary used by `authenticatedUserLayer`. Both the guard and identity boundary use public provider data, without reading Better Auth's tables or internal services. Keep Better Auth's cookie cache disabled for database-backed role removal to take effect on the next request, as in the starter.
|
|
277
|
+
`withSessionUser(policy, headers, operation)` resolves the session through the existing transport-header and Origin policy path and provides `Identity` and `SessionUser` only around the supplied Effect. It is also the boundary used by `authenticatedUserLayer`. Both the guard and identity boundary use public provider data, without reading Better Auth's tables or internal services. Keep Better Auth's cookie cache disabled for database-backed role removal to take effect on the next request, as in the starter.
|
|
279
278
|
|
|
280
279
|
### Transport headers and request ids
|
|
281
280
|
|
|
@@ -314,7 +313,7 @@ A missing session produces `Option.none()` here. The same policy still rejects f
|
|
|
314
313
|
|
|
315
314
|
For an HTTP RPC server that serves only the local machine, wrap its HTTP effect with `localRpcGuard` from `@shivaedev/platform/server/rpc-server/local.ts`. Provide the native `HttpServerRequest` and `RpcSerialization` services around the returned effect, using the same serialization as the RPC server. No session provider is required.
|
|
316
315
|
|
|
317
|
-
By default, the guard returns HTTP 403 before running the effect unless the transport reports a loopback peer address, the Host is a loopback host, any Origin matches the HTTP Host, and the content type matches the serialization. An absent peer address is rejected
|
|
316
|
+
By default, the guard returns HTTP 403 before running the effect unless the transport reports a loopback peer address, the Host is a loopback host, any Origin matches the HTTP Host, and the content type matches the serialization. An absent peer address is rejected, and a DNS-rebinding Host on a loopback connection is refused. The optional second argument, `localRpcGuard(effect, trustedProxy)`, enables the same address and range forwarding policy as `appHost`.
|
|
318
317
|
|
|
319
318
|
The same module exports `loopbackOnly(handler)` for local page routes and `sameOrigin(request)` for an HTTP Origin check. `loopbackOnly` checks Host and any known peer address; it permits an absent peer address so embedded Fetch page handlers remain usable. It does not check Origin or content type.
|
|
320
319
|
|
|
@@ -370,8 +369,6 @@ export const save = storageSave.pipe(expose);
|
|
|
370
369
|
|
|
371
370
|
`storageSave` is the application's Effect. `unexpected` constructs a member of the declared schema from the public message. The default message is `Internal server error`; `message` supplies application text, with credential-shaped strings redacted. The original Effect cause is kept on the server rejection's non-enumerable `cause`, so an RPC server span can trace it. Keep `cause` out of the wire schema, as the taxonomy classes do. `ServiceUnavailable` describes a declared availability failure without implying a session-provider outage.
|
|
372
371
|
|
|
373
|
-
The native HTTP RPC fixture in `src/server/rpc-server/unauthenticatedRejections.spec.ts` proves decoded taxonomy types, redacted fallback messages and the original server trace cause without session middleware. Work Board's `src/server/rpc/rejectionTypes.spec.ts` proves its adoption through real loopback HTTP.
|
|
374
|
-
|
|
375
372
|
### Request diagnostics
|
|
376
373
|
|
|
377
374
|
Tracing logs declared failures with `RPC failure` and their tag, and defects with `RPC defect`. The diagnostic payload masks nested credential-shaped keys and Effect `Redacted` values. Credential-shaped strings, such as bearer tokens, URL passwords and sensitive `key=value` text, are masked too. Strings retain at most 2,048 characters before a truncation marker; collections retain at most 50 entries with a marker for the remainder, and binary values become size summaries.
|
|
@@ -507,7 +504,7 @@ it.effectApp("stores the user's email", function* ({ db, trpc, userExists }) {
|
|
|
507
504
|
});
|
|
508
505
|
```
|
|
509
506
|
|
|
510
|
-
The direct database, tRPC caller and extension share the test's PostgreSQL transaction. Successful and expected-failing tests roll their writes back. `trpc({ actor: "admin" })` selects another caller context within the test. `promise(() => auth.api.getSession({ headers }))` runs a Promise boundary with the test's services
|
|
507
|
+
The direct database, tRPC caller and extension share the test's PostgreSQL transaction. Successful and expected-failing tests roll their writes back. `trpc({ actor: "admin" })` selects another caller context within the test. `promise(() => auth.api.getSession({ headers }))` runs a Promise boundary with the test's services, so Better Auth adapter calls inside it join the rollback transaction.
|
|
511
508
|
|
|
512
509
|
### API
|
|
513
510
|
|
|
@@ -515,33 +512,26 @@ Import the module that defines the name; there is no package-root entry. Paths b
|
|
|
515
512
|
|
|
516
513
|
| Module | Names and purpose |
|
|
517
514
|
| --- | --- |
|
|
518
|
-
| `server/otlpTracing.ts` | `otlpTracing`: scoped, opt-in Effect OTLP trace export configured through standard exporter variables; provide it to worker Layers. |
|
|
519
|
-
| `server/boundedBody.ts` | `readBoundedBody`, `RequestBodyTooLarge`: bounded body bytes and a typed HTTP 413 failure. |
|
|
520
|
-
| `server/appHost.ts` | `appHost({ group, handlers, services, migrations?, sessions?, policy?, rpcPath?, assets?, routes?, config? })` or `appHost({ application, migrations, config? })`, `appDatabase({ migrations, config? })`, `AppChanges`, `AppHostOptions`, `AppHttpHostOptions`, `AppLocalHostOptions`, `AppDatabaseOptions`: scoped HTTP and PostgreSQL composition with loopback defaults and optional proxy trust. |
|
|
521
515
|
| `errors/taxonomy.ts` | `NotFound`, `Unauthorized`, `Forbidden`, `BadRequest`, `Conflict`, `PreconditionFailed`, `TooManyRequests`, `AuthUnavailable`, `InternalServerError`, `ServiceUnavailable`: Schema tagged error classes with a `message`; `BadRequest` and `Conflict` also accept an optional `field`. |
|
|
522
|
-
| `errors/rejectedField.ts` | `rejectedField(unknown)
|
|
523
|
-
| `rpc/identity.ts` | `RequestId
|
|
516
|
+
| `errors/rejectedField.ts` | `rejectedField(unknown)`: the field and message of a field rejection. |
|
|
517
|
+
| `rpc/identity.ts` | `RequestId`, `Identity`, `OptionalIdentity`, `SessionUser`: request-local services. |
|
|
524
518
|
| `rpc/middleware.ts` | `RequestTracing`, `Authenticated`, `AuthenticatedUser`, `MaybeAuthenticated`: native RPC middleware declarations. |
|
|
525
|
-
| `
|
|
526
|
-
| `server/
|
|
527
|
-
| `server/
|
|
528
|
-
| `server/
|
|
529
|
-
| `server/rpc-server/
|
|
530
|
-
| `server/rpc-server/
|
|
531
|
-
| `server/rpc-server/
|
|
532
|
-
| `server/rpc-server/
|
|
533
|
-
| `server/rpc-server/
|
|
534
|
-
| `server/rpc-server/
|
|
519
|
+
| `rpc/requireAdmin.ts` | `requireAdmin`: the signed-in user with an admin role. |
|
|
520
|
+
| `server/appHost.ts` | `appHost`, `appDatabase`, `AppChanges`: scoped HTTP and PostgreSQL composition with loopback defaults and optional proxy trust. |
|
|
521
|
+
| `server/boundedBody.ts` | `readBoundedBody`, `RequestBodyTooLarge`: bounded body bytes and a typed HTTP 413 failure. |
|
|
522
|
+
| `server/otlpTracing.ts` | `otlpTracing`: opt-in Effect OTLP trace export for worker Layers. |
|
|
523
|
+
| `server/rpc-server/session.ts` | `authenticatedLayer`, `maybeAuthenticatedLayer`, `authenticatedUserLayer`, `withSessionUser`, `resolveSession`: session middleware implementations and the identity boundary. |
|
|
524
|
+
| `server/rpc-server/adapters/betterAuthSessions.ts` | `betterAuthSessions(getSession, getProviderAccounts?)`: a session provider from Better Auth lookups. |
|
|
525
|
+
| `server/rpc-server/origin.ts` | `trustedOrigins({ allow, missing })`: an exact Origin allowlist. |
|
|
526
|
+
| `server/rpc-server/local.ts` | `localRpcGuard`, `loopbackOnly`, `sameOrigin`, `trustedProxyPeer`, `trustedProxyRanges`: loopback and proxy guards. |
|
|
527
|
+
| `server/rpc-server/transportHeaders.ts` | `transportHeaders(rpcHeaders)`: the headers used for a transport-level decision. |
|
|
528
|
+
| `server/rpc-server/boundary.ts` | `rpcBoundary(schema, { unexpected, message? })`: declared failures pass through, unexpected failures become one declared rejection. |
|
|
529
|
+
| `server/rpc-server/tracing.ts` | `requestTracingLayer({ header?, sensitive? })`. |
|
|
530
|
+
| `server/rpc-server/redact.ts`, `server/rpc-server/redactCause.ts`, `server/rpc-server/sensitive.ts` | `redact`, `redactCause`, `redactDefect`, `redactingErrorReporter`, `isSensitiveKey`, `redactText`: diagnostic redaction. |
|
|
535
531
|
| `server/runtime/makePlatform.ts` | `makePlatformRuntime(layer, { developmentCacheKey? })`. |
|
|
536
|
-
| `server/
|
|
537
|
-
| `server/
|
|
538
|
-
| `server/better-auth/adapter.ts` | `effectPrismaAdapter(Database, runtime, { debugLogs?, modelName?, usePlural? })`; `EffectPrismaAdapterOptions`. |
|
|
532
|
+
| `server/node-http/subscriptionSignal.ts` | `nodeSubscriptionSignal({ nodeRequest?, request?, signals? })`, returning `{ signal, dispose }`. |
|
|
533
|
+
| `server/better-auth/adapter.ts` | `effectPrismaAdapter(Database, runtime, options?)`: a Better Auth adapter over Effect Prisma; `modelName` maps model names. |
|
|
539
534
|
| `server/testing/makePlatformIt.ts` | `makePlatformIt(Database)({ adapter, createCaller, layer, extend? })`. |
|
|
540
|
-
| `server/testing/types.ts` | `MakePlatformItOptions`, `PlatformHarness`, `PlatformIt`, `PlatformTest`, `PlatformTester`. |
|
|
541
|
-
|
|
542
|
-
`PlatformRuntime` exposes `runPromise(effect, { signal? })`, `runPromiseExit(effect, { signal? })`, `runWithServices(context, evaluate)`, `contextEffect`, `currentServices()` and `dispose()`. The harness exposes native Vitest methods plus `effectApp(name, body, options?)`; its tester also has `skip`, `skipIf`, `runIf`, `only`, `each` and `fails`.
|
|
543
|
-
|
|
544
|
-
The exports also include the adapter's translation modules: `makeRowAdapter` and `RelationQuery` in `server/better-auth/rowAdapter.ts`, `refineRelation` and `DynamicRelation` in `server/better-auth/relation.ts`, and `whereExpression`, `CleanedWhere`, `DynamicField` and `Expression` in `server/better-auth/where.ts`. Application storage setup uses `effectPrismaAdapter`.
|
|
545
535
|
|
|
546
536
|
### Install, setup and limits
|
|
547
537
|
|
|
@@ -549,7 +539,7 @@ The exports also include the adapter's translation modules: `makeRowAdapter` and
|
|
|
549
539
|
pnpm add @shivaedev/platform effect@4.0.4
|
|
550
540
|
```
|
|
551
541
|
|
|
552
|
-
Effect is the only required peer. The peer-free implementation lives in the shared `errors/` and `rpc/` folders and the `server/node-http/`, `server/rpc-server/` and `server/runtime/` folders; a module's import path is its path under `src/`. The
|
|
542
|
+
Effect is the only required peer. The peer-free implementation lives in the shared `errors/` and `rpc/` folders and the `server/node-http/`, `server/rpc-server/` and `server/runtime/` folders; a module's import path is its path under `src/`. The core errors, RPC declarations, server middleware, runtime and Node HTTP modules can be imported without the optional peers, including the Promise-based `betterAuthSessions` function. The runtime uses Node's `AsyncLocalStorage`; browser consumers import the shared `errors/` and `rpc/` modules.
|
|
553
543
|
|
|
554
544
|
Install the optional peers for the selected integration:
|
|
555
545
|
|
|
@@ -560,14 +550,12 @@ Install the optional peers for the selected integration:
|
|
|
560
550
|
| `server/better-auth/adapter.ts` | `better-auth`, `@shivaedev/effect-prisma`, `@prisma-next/sql-orm-client` |
|
|
561
551
|
| `server/testing/makePlatformIt.ts` | `@effect/vitest`, `@shivaedev/effect-prisma`, `@shivaedev/effect-trpc`, `@trpc/server` |
|
|
562
552
|
|
|
563
|
-
- The package
|
|
553
|
+
- The package needs Node 24 or newer.
|
|
564
554
|
- Keep the auth provider's configuration, cookie settings and resource authorization in the application. The session adapter takes a session lookup and an optional provider-account lookup and returns a session result; it does not write provider refresh cookies into RPC responses.
|
|
565
555
|
- Without an `HttpServerRequest`, `transportHeaders` falls back to the supplied RPC headers. An application using another transport must decide what headers it can trust.
|
|
566
556
|
- `appHost` adds tracing last on its server-side copy of the group. When composing a native RPC server directly, add `RequestTracing` last on the group, as in the example, so it wraps authentication too. Middleware outside that tracing boundary is responsible for its own diagnostics.
|
|
567
557
|
- Redaction recognizes common shapes. Keep secrets out of messages and extend the key predicate for application-specific sensitive fields.
|
|
568
558
|
- A development cache key is ignored when `NODE_ENV` is `production`. The application owns runtime disposal.
|
|
569
559
|
- The Better Auth storage adapter's default model mapping capitalizes the model name. Supply `modelName` for a generated schema with another naming convention. Native Better Auth joins (`advanced.database.joins`) are rejected; leave that option off so Better Auth reads related rows with separate queries.
|
|
570
|
-
- Package session tests use real Better Auth with ephemeral SQLite and injected HTTP; the WebSocket test uses an in-memory socket. Node signal tests simulate close events. These checks do not establish deployed browser, mobile or Bun behavior.
|
|
571
|
-
- The storage and harness tests require real PostgreSQL and skip without `PLATFORM_EFFECT_PRISMA_TEST_DATABASE_URL`. A skipped test supplies no transaction evidence.
|
|
572
560
|
|
|
573
|
-
|
|
561
|
+
The [framework request-context guide](https://github.com/ShivaeDev/platform/blob/main/docs/framework/request-context.md) explains the browser and native-client Origin choices.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import { Forbidden
|
|
3
|
-
import { type SessionUserValue } from "./identity.ts";
|
|
4
|
-
export declare const requireAdmin: Effect.Effect<SessionUserValue,
|
|
2
|
+
import { Forbidden } from "#errors/taxonomy.ts";
|
|
3
|
+
import { SessionUser, type SessionUserValue } from "./identity.ts";
|
|
4
|
+
export declare const requireAdmin: Effect.Effect<SessionUserValue, Forbidden, SessionUser>;
|
|
5
5
|
//# sourceMappingURL=requireAdmin.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requireAdmin.d.ts","sourceRoot":"","sources":["../../src/rpc/requireAdmin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"requireAdmin.d.ts","sourceRoot":"","sources":["../../src/rpc/requireAdmin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEnE,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,SAAS,EAAE,WAAW,CAM/E,CAAC"}
|
package/dist/rpc/requireAdmin.js
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import { Effect
|
|
2
|
-
import { Forbidden
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { Forbidden } from "#errors/taxonomy.ts";
|
|
3
3
|
import { SessionUser } from "./identity.js";
|
|
4
4
|
export const requireAdmin = Effect.gen(function* () {
|
|
5
|
-
const user = yield*
|
|
6
|
-
if (
|
|
7
|
-
return yield* new Unauthorized({ message: "Authentication required" });
|
|
8
|
-
}
|
|
9
|
-
if (!user.value.role?.split(",").includes("admin")) {
|
|
5
|
+
const user = yield* SessionUser;
|
|
6
|
+
if (!user.role?.split(",").includes("admin")) {
|
|
10
7
|
return yield* new Forbidden({ message: "Administrator role required" });
|
|
11
8
|
}
|
|
12
|
-
return user
|
|
9
|
+
return user;
|
|
13
10
|
});
|
|
14
11
|
//# sourceMappingURL=requireAdmin.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requireAdmin.js","sourceRoot":"","sources":["../../src/rpc/requireAdmin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"requireAdmin.js","sourceRoot":"","sources":["../../src/rpc/requireAdmin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAyB,MAAM,eAAe,CAAC;AAEnE,MAAM,CAAC,MAAM,YAAY,GAA4D,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IACxG,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC;IAChC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC,CAAC,IAAI,SAAS,CAAC,EAAE,OAAO,EAAE,6BAA6B,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Effect, Layer } from "effect";
|
|
2
|
+
import type { Rpc } from "effect/rpc";
|
|
3
|
+
import type { HostPreflight } from "#server/AppHostInput.ts";
|
|
4
|
+
import type { AppDatabaseOptions, AppHostOptions, AppHttpHostOptions, AppLocalHostOptions } from "#server/appHost.ts";
|
|
5
|
+
import type { appHostHttp, deferredHost } from "#server/appHostHttp.ts";
|
|
6
|
+
import type { SessionShape } from "#server/rpc-server/session.ts";
|
|
7
|
+
type PreflightHost<THost extends Layer.Any, TServices, TError, TRequirements> = Layer.Layer<Layer.Success<THost> | TServices, Layer.Error<THost> | TError, Exclude<Layer.Services<THost>, TServices> | TRequirements>;
|
|
8
|
+
export interface AppHostFactory {
|
|
9
|
+
<TRpcs extends Rpc.Any, THandlers, THandlerError, THandlerRequirements, TServices = never, TServiceError = never, TServiceRequirements = never, TMigrations = never, TSession extends SessionShape = SessionShape, TApplicationError = never, TApplicationRequirements = never, TPreflight = never, TPreflightError = never, TPreflightRequirements = never>(options: HostPreflight<TPreflight, TPreflightError, TPreflightRequirements> & ((AppDatabaseOptions<TMigrations> & {
|
|
10
|
+
readonly application: Effect.Effect<AppHttpHostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TSession>, TApplicationError, TApplicationRequirements>;
|
|
11
|
+
}) | AppHostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TMigrations, TSession, TPreflight, TPreflightError, TPreflightRequirements> | AppLocalHostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TMigrations, TPreflight, TPreflightError, TPreflightRequirements>)): PreflightHost<ReturnType<typeof deferredHost<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TMigrations, TSession, TApplicationError, TApplicationRequirements>>, NoInfer<TPreflight>, NoInfer<TPreflightError>, NoInfer<TPreflightRequirements>>;
|
|
12
|
+
<TRpcs extends Rpc.Any, THandlers, THandlerError, THandlerRequirements, TServices = never, TServiceError = never, TServiceRequirements = never, TSession extends SessionShape = SessionShape, TPreflight = never, TPreflightError = never, TPreflightRequirements = never>(options: AppHttpHostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TSession, TPreflight, TPreflightError, TPreflightRequirements>): PreflightHost<ReturnType<typeof appHostHttp<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TSession>>, NoInfer<TPreflight>, NoInfer<TPreflightError>, NoInfer<TPreflightRequirements>>;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=AppHostFactory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppHostFactory.d.ts","sourceRoot":"","sources":["../../src/server/AppHostFactory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppHostFactory.js","sourceRoot":"","sources":["../../src/server/AppHostFactory.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Effect, Layer } from "effect";
|
|
2
|
+
import type { Rpc } from "effect/rpc";
|
|
3
|
+
import type { AppDatabaseOptions, AppHostOptions, AppHttpHostOptions, AppLocalHostOptions } from "#server/appHost.ts";
|
|
4
|
+
import type { SessionShape } from "#server/rpc-server/session.ts";
|
|
5
|
+
export type HostPreflight<TServices = never, TError = never, TRequirements = never> = {
|
|
6
|
+
readonly preflight: Layer.Layer<TServices, TError, TRequirements>;
|
|
7
|
+
} | ([TServices | TError | TRequirements] extends [never] ? {
|
|
8
|
+
readonly preflight?: never;
|
|
9
|
+
} : never);
|
|
10
|
+
export type AppHostInput<TRpcs extends Rpc.Any, THandlers, THandlerError, THandlerRequirements, TServices = never, TServiceError = never, TServiceRequirements = never, TMigrations = never, TSession extends SessionShape = SessionShape, TApplicationError = never, TApplicationRequirements = never, TPreflight = never, TPreflightError = never, TPreflightRequirements = never> = HostPreflight<TPreflight, TPreflightError, TPreflightRequirements> & ((AppDatabaseOptions<TMigrations> & {
|
|
11
|
+
readonly application: Effect.Effect<AppHttpHostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TSession>, TApplicationError, TApplicationRequirements>;
|
|
12
|
+
}) | AppHostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TMigrations, TSession, TPreflight, TPreflightError, TPreflightRequirements> | AppLocalHostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TMigrations, TPreflight, TPreflightError, TPreflightRequirements> | AppHttpHostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TSession, TPreflight, TPreflightError, TPreflightRequirements>);
|
|
13
|
+
//# sourceMappingURL=AppHostInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppHostInput.d.ts","sourceRoot":"","sources":["../../src/server/AppHostInput.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACtH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAElE,MAAM,MAAM,aAAa,CAAC,SAAS,GAAG,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE,aAAa,GAAG,KAAK,IAC/E;IAAE,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,CAAA;CAAE,GACrE,CAAC,CAAC,SAAS,GAAG,MAAM,GAAG,aAAa,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG,KAAK,CAAC,CAAC;AAEnG,MAAM,MAAM,YAAY,CACvB,KAAK,SAAS,GAAG,CAAC,GAAG,EACrB,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,SAAS,GAAG,KAAK,EACjB,aAAa,GAAG,KAAK,EACrB,oBAAoB,GAAG,KAAK,EAC5B,WAAW,GAAG,KAAK,EACnB,QAAQ,SAAS,YAAY,GAAG,YAAY,EAC5C,iBAAiB,GAAG,KAAK,EACzB,wBAAwB,GAAG,KAAK,EAChC,UAAU,GAAG,KAAK,EAClB,eAAe,GAAG,KAAK,EACvB,sBAAsB,GAAG,KAAK,IAC3B,aAAa,CAAC,UAAU,EAAE,eAAe,EAAE,sBAAsB,CAAC,GACrE,CACG,CAAC,kBAAkB,CAAC,WAAW,CAAC,GAAG;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAClC,kBAAkB,CAAC,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,oBAAoB,EAAE,SAAS,EAAE,aAAa,EAAE,oBAAoB,EAAE,QAAQ,CAAC,EACnI,iBAAiB,EACjB,wBAAwB,CACxB,CAAC;CACD,CAAC,GACF,cAAc,CACd,KAAK,EACL,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,WAAW,EACX,QAAQ,EACR,UAAU,EACV,eAAe,EACf,sBAAsB,CACrB,GACD,mBAAmB,CACnB,KAAK,EACL,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,WAAW,EACX,UAAU,EACV,eAAe,EACf,sBAAsB,CACrB,GACD,kBAAkB,CAClB,KAAK,EACL,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,QAAQ,EACR,UAAU,EACV,eAAe,EACf,sBAAsB,CACrB,CACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppHostInput.js","sourceRoot":"","sources":["../../src/server/AppHostInput.ts"],"names":[],"mappings":""}
|
package/dist/server/appHost.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { Context, type Effect } from "effect";
|
|
1
|
+
import { Context, type Effect, Layer } from "effect";
|
|
2
2
|
import type { Rpc } from "effect/rpc";
|
|
3
|
-
import {
|
|
3
|
+
import type { AppHostFactory } from "#server/AppHostFactory.ts";
|
|
4
|
+
import type { HostPreflight } from "#server/AppHostInput.ts";
|
|
4
5
|
import { type DatabaseConfig } from "#server/databaseLayer.ts";
|
|
5
6
|
import type { HostOptions, HostPolicy } from "#server/hostOptions.ts";
|
|
6
7
|
import type { MigrationOptions } from "#server/MigrationOptions.ts";
|
|
@@ -27,23 +28,20 @@ export interface AppDatabaseOptions<R = never> {
|
|
|
27
28
|
readonly config?: DatabaseConfig;
|
|
28
29
|
readonly migrations: MigrationOptions<R>;
|
|
29
30
|
}
|
|
30
|
-
export declare function appDatabase<R>(options: AppDatabaseOptions<R>):
|
|
31
|
-
export type AppHostOptions<TRpcs extends Rpc.Any, THandlers, THandlerError, THandlerRequirements, TServices = never, TServiceError = never, TServiceRequirements = never, TMigrations = never, TSession extends SessionShape = SessionShape> = HostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements> & {
|
|
31
|
+
export declare function appDatabase<R>(options: AppDatabaseOptions<R>): Layer.Layer<AppChanges | import("@effect/sql-pg/PgClient").PgClient | import("effect/reactivity/Reactivity").Reactivity | import("effect/sql/SqlClient").SqlClient, import("effect/Config").ConfigError | import("effect/sql/Migrator").MigrationError | import("effect/sql/SqlError").SqlError, Exclude<Exclude<R, import("effect/Scope").Scope>, import("@effect/sql-pg/PgClient").PgClient | import("effect/sql/SqlClient").SqlClient>>;
|
|
32
|
+
export type AppHostOptions<TRpcs extends Rpc.Any, THandlers, THandlerError, THandlerRequirements, TServices = never, TServiceError = never, TServiceRequirements = never, TMigrations = never, TSession extends SessionShape = SessionShape, TPreflight = never, TPreflightError = never, TPreflightRequirements = never> = HostPreflight<TPreflight, TPreflightError, TPreflightRequirements> & HostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements> & {
|
|
32
33
|
readonly migrations: AppDatabaseOptions<TMigrations>["migrations"];
|
|
33
34
|
readonly policy?: undefined;
|
|
34
35
|
readonly sessions: SessionPolicy<TSession>;
|
|
35
36
|
};
|
|
36
|
-
export type AppLocalHostOptions<TRpcs extends Rpc.Any, THandlers, THandlerError, THandlerRequirements, TServices = never, TServiceError = never, TServiceRequirements = never, TMigrations = never> = HostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements> & {
|
|
37
|
+
export type AppLocalHostOptions<TRpcs extends Rpc.Any, THandlers, THandlerError, THandlerRequirements, TServices = never, TServiceError = never, TServiceRequirements = never, TMigrations = never, TPreflight = never, TPreflightError = never, TPreflightRequirements = never> = HostPreflight<TPreflight, TPreflightError, TPreflightRequirements> & HostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements> & {
|
|
37
38
|
readonly migrations: AppDatabaseOptions<TMigrations>["migrations"];
|
|
38
39
|
readonly policy: "loopback";
|
|
39
40
|
readonly sessions?: never;
|
|
40
41
|
};
|
|
41
|
-
export type AppHttpHostOptions<TRpcs extends Rpc.Any, THandlers, THandlerError, THandlerRequirements, TServices = never, TServiceError = never, TServiceRequirements = never, TSession extends SessionShape = SessionShape> = HostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements> & HostPolicy<TSession> & {
|
|
42
|
+
export type AppHttpHostOptions<TRpcs extends Rpc.Any, THandlers, THandlerError, THandlerRequirements, TServices = never, TServiceError = never, TServiceRequirements = never, TSession extends SessionShape = SessionShape, TPreflight = never, TPreflightError = never, TPreflightRequirements = never> = HostPreflight<TPreflight, TPreflightError, TPreflightRequirements> & HostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements> & HostPolicy<TSession> & {
|
|
42
43
|
readonly migrations?: undefined;
|
|
43
44
|
};
|
|
44
|
-
export declare
|
|
45
|
-
readonly application: Effect.Effect<AppHttpHostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TSession>, TApplicationError, TApplicationRequirements>;
|
|
46
|
-
}) | AppHostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TMigrations, TSession> | AppLocalHostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TMigrations>): ReturnType<typeof deferredHost<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TMigrations, TSession, TApplicationError, TApplicationRequirements>>;
|
|
47
|
-
export declare function appHost<TRpcs extends Rpc.Any, THandlers, THandlerError, THandlerRequirements, TServices = never, TServiceError = never, TServiceRequirements = never, TSession extends SessionShape = SessionShape>(options: AppHttpHostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TSession>): ReturnType<typeof appHostHttp<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements, TSession>>;
|
|
45
|
+
export declare const appHost: AppHostFactory;
|
|
48
46
|
export {};
|
|
49
47
|
//# sourceMappingURL=appHost.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appHost.d.ts","sourceRoot":"","sources":["../../src/server/appHost.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"appHost.d.ts","sourceRoot":"","sources":["../../src/server/appHost.ts"],"names":[],"mappings":"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"}
|
package/dist/server/appHost.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Context } from "effect";
|
|
1
|
+
import { Context, Layer } from "effect";
|
|
2
2
|
import { appHostHttp, deferredHost, migratedHost } from "#server/appHostHttp.ts";
|
|
3
3
|
import { databaseLayer } from "#server/databaseLayer.ts";
|
|
4
4
|
export class AppChanges extends Context.Service()("@shivaedev/platform/AppChanges") {
|
|
@@ -6,12 +6,12 @@ export class AppChanges extends Context.Service()("@shivaedev/platform/AppChange
|
|
|
6
6
|
export function appDatabase(options) {
|
|
7
7
|
return databaseLayer(options, AppChanges);
|
|
8
8
|
}
|
|
9
|
-
export
|
|
9
|
+
export const appHost = (options) => {
|
|
10
10
|
if ("application" in options) {
|
|
11
|
-
return deferredHost(options.application, appDatabase(options));
|
|
11
|
+
return deferredHost(options.application, appDatabase(options)).pipe(Layer.provideMerge(options.preflight ?? Layer.empty));
|
|
12
12
|
}
|
|
13
13
|
return options.migrations === undefined
|
|
14
|
-
? appHostHttp(options)
|
|
15
|
-
: migratedHost({ ...options, migrations: options.migrations }, appDatabase({ ...options, migrations: options.migrations }));
|
|
16
|
-
}
|
|
14
|
+
? appHostHttp(options).pipe(Layer.provideMerge(options.preflight ?? Layer.empty))
|
|
15
|
+
: migratedHost({ ...options, migrations: options.migrations }, appDatabase({ ...options, migrations: options.migrations })).pipe(Layer.provideMerge(options.preflight ?? Layer.empty));
|
|
16
|
+
};
|
|
17
17
|
//# sourceMappingURL=appHost.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appHost.js","sourceRoot":"","sources":["../../src/server/appHost.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"appHost.js","sourceRoot":"","sources":["../../src/server/appHost.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,KAAK,EAAE,MAAM,QAAQ,CAAC;AAKrD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACjF,OAAO,EAAuB,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAK9E,MAAM,OAAO,UAAW,SAAQ,OAAO,CAAC,OAAO,EAAqD,CAAC,gCAAgC,CAAC;CAAG;AAMzI,MAAM,UAAU,WAAW,CAAI,OAA8B;IAC5D,OAAO,aAAa,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC3C,CAAC;AAwDD,MAAM,CAAC,MAAM,OAAO,GAAmB,CAgBtC,OAeC,EACA,EAAE;IACH,IAAI,aAAa,IAAI,OAAO,EAAE,CAAC;QAC9B,OAAO,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3H,CAAC;IACD,OAAO,OAAO,CAAC,UAAU,KAAK,SAAS;QACtC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;QACjF,CAAC,CAAC,YAAY,CAAC,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,EAAE,WAAW,CAAC,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAC9H,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC,CACpD,CAAC;AACL,CAAC,CAAC"}
|