@shivaedev/server 0.0.0 → 0.2.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 (148) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +322 -1
  3. package/dist/AppHostFactory.d.ts +15 -0
  4. package/dist/AppHostFactory.d.ts.map +1 -0
  5. package/dist/AppHostFactory.js +2 -0
  6. package/dist/AppHostFactory.js.map +1 -0
  7. package/dist/AppHostInput.d.ts +13 -0
  8. package/dist/AppHostInput.d.ts.map +1 -0
  9. package/dist/AppHostInput.js +2 -0
  10. package/dist/AppHostInput.js.map +1 -0
  11. package/dist/MigrationOptions.d.ts +15 -0
  12. package/dist/MigrationOptions.d.ts.map +1 -0
  13. package/dist/MigrationOptions.js +2 -0
  14. package/dist/MigrationOptions.js.map +1 -0
  15. package/dist/RedactionPolicy.d.ts +4 -0
  16. package/dist/RedactionPolicy.d.ts.map +1 -0
  17. package/dist/RedactionPolicy.js +4 -0
  18. package/dist/RedactionPolicy.js.map +1 -0
  19. package/dist/appHost.d.ts +47 -0
  20. package/dist/appHost.d.ts.map +1 -0
  21. package/dist/appHost.js +17 -0
  22. package/dist/appHost.js.map +1 -0
  23. package/dist/appHostHttp.d.ts +88 -0
  24. package/dist/appHostHttp.d.ts.map +1 -0
  25. package/dist/appHostHttp.js +66 -0
  26. package/dist/appHostHttp.js.map +1 -0
  27. package/dist/boundedRpcRequest.d.ts +3 -0
  28. package/dist/boundedRpcRequest.d.ts.map +1 -0
  29. package/dist/boundedRpcRequest.js +22 -0
  30. package/dist/boundedRpcRequest.js.map +1 -0
  31. package/dist/databaseAddress.d.ts +4 -0
  32. package/dist/databaseAddress.d.ts.map +1 -0
  33. package/dist/databaseAddress.js +25 -0
  34. package/dist/databaseAddress.js.map +1 -0
  35. package/dist/databaseLayer.d.ts +14 -0
  36. package/dist/databaseLayer.d.ts.map +1 -0
  37. package/dist/databaseLayer.js +100 -0
  38. package/dist/databaseLayer.js.map +1 -0
  39. package/dist/development.d.ts +10 -0
  40. package/dist/development.d.ts.map +1 -0
  41. package/dist/development.js +20 -0
  42. package/dist/development.js.map +1 -0
  43. package/dist/healthRoute.d.ts +3 -0
  44. package/dist/healthRoute.d.ts.map +1 -0
  45. package/dist/healthRoute.js +18 -0
  46. package/dist/healthRoute.js.map +1 -0
  47. package/dist/hostChanges.d.ts +7 -0
  48. package/dist/hostChanges.d.ts.map +1 -0
  49. package/dist/hostChanges.js +25 -0
  50. package/dist/hostChanges.js.map +1 -0
  51. package/dist/hostOptions.d.ts +34 -0
  52. package/dist/hostOptions.d.ts.map +1 -0
  53. package/dist/hostOptions.js +2 -0
  54. package/dist/hostOptions.js.map +1 -0
  55. package/dist/hostTransport.d.ts +18 -0
  56. package/dist/hostTransport.d.ts.map +1 -0
  57. package/dist/hostTransport.js +26 -0
  58. package/dist/hostTransport.js.map +1 -0
  59. package/dist/nativeClientOrigins.d.ts +4 -0
  60. package/dist/nativeClientOrigins.d.ts.map +1 -0
  61. package/dist/nativeClientOrigins.js +38 -0
  62. package/dist/nativeClientOrigins.js.map +1 -0
  63. package/dist/node-http/subscriptionSignal.d.ts +12 -0
  64. package/dist/node-http/subscriptionSignal.d.ts.map +1 -0
  65. package/dist/node-http/subscriptionSignal.js +55 -0
  66. package/dist/node-http/subscriptionSignal.js.map +1 -0
  67. package/dist/otlpHttpClient.d.ts +4 -0
  68. package/dist/otlpHttpClient.d.ts.map +1 -0
  69. package/dist/otlpHttpClient.js +36 -0
  70. package/dist/otlpHttpClient.js.map +1 -0
  71. package/dist/otlpTracing.d.ts +3 -0
  72. package/dist/otlpTracing.d.ts.map +1 -0
  73. package/dist/otlpTracing.js +35 -0
  74. package/dist/otlpTracing.js.map +1 -0
  75. package/dist/redactOtlpUrl.d.ts +2 -0
  76. package/dist/redactOtlpUrl.d.ts.map +1 -0
  77. package/dist/redactOtlpUrl.js +41 -0
  78. package/dist/redactOtlpUrl.js.map +1 -0
  79. package/dist/redactingDiagnostics.d.ts +5 -0
  80. package/dist/redactingDiagnostics.d.ts.map +1 -0
  81. package/dist/redactingDiagnostics.js +25 -0
  82. package/dist/redactingDiagnostics.js.map +1 -0
  83. package/dist/redactingRpcSerialization.d.ts +4 -0
  84. package/dist/redactingRpcSerialization.d.ts.map +1 -0
  85. package/dist/redactingRpcSerialization.js +74 -0
  86. package/dist/redactingRpcSerialization.js.map +1 -0
  87. package/dist/redactingTracer.d.ts +4 -0
  88. package/dist/redactingTracer.d.ts.map +1 -0
  89. package/dist/redactingTracer.js +32 -0
  90. package/dist/redactingTracer.js.map +1 -0
  91. package/dist/rpc-server/publicConfigLayer.d.ts +4 -0
  92. package/dist/rpc-server/publicConfigLayer.d.ts.map +1 -0
  93. package/dist/rpc-server/publicConfigLayer.js +9 -0
  94. package/dist/rpc-server/publicConfigLayer.js.map +1 -0
  95. package/dist/runtime/makePlatform.d.ts +4 -0
  96. package/dist/runtime/makePlatform.d.ts.map +1 -0
  97. package/dist/runtime/makePlatform.js +65 -0
  98. package/dist/runtime/makePlatform.js.map +1 -0
  99. package/dist/runtime/types.d.ts +19 -0
  100. package/dist/runtime/types.d.ts.map +1 -0
  101. package/dist/runtime/types.js +2 -0
  102. package/dist/runtime/types.js.map +1 -0
  103. package/dist/safeOtlpSerialization.d.ts +6 -0
  104. package/dist/safeOtlpSerialization.d.ts.map +1 -0
  105. package/dist/safeOtlpSerialization.js +67 -0
  106. package/dist/safeOtlpSerialization.js.map +1 -0
  107. package/dist/schemaSensitiveKeys.d.ts +5 -0
  108. package/dist/schemaSensitiveKeys.d.ts.map +1 -0
  109. package/dist/schemaSensitiveKeys.js +143 -0
  110. package/dist/schemaSensitiveKeys.js.map +1 -0
  111. package/dist/setupDatabases.d.ts +3 -0
  112. package/dist/setupDatabases.d.ts.map +1 -0
  113. package/dist/setupDatabases.js +12 -0
  114. package/dist/setupDatabases.js.map +1 -0
  115. package/dist/tracedGroup.d.ts +4 -0
  116. package/dist/tracedGroup.d.ts.map +1 -0
  117. package/dist/tracedGroup.js +13 -0
  118. package/dist/tracedGroup.js.map +1 -0
  119. package/package.json +107 -4
  120. package/src/AppHostFactory.ts +121 -0
  121. package/src/AppHostInput.ts +74 -0
  122. package/src/MigrationOptions.ts +15 -0
  123. package/src/RedactionPolicy.ts +4 -0
  124. package/src/appHost.ts +117 -0
  125. package/src/appHostHttp.ts +149 -0
  126. package/src/boundedRpcRequest.ts +28 -0
  127. package/src/databaseAddress.ts +25 -0
  128. package/src/databaseLayer.ts +127 -0
  129. package/src/development.ts +34 -0
  130. package/src/healthRoute.ts +27 -0
  131. package/src/hostChanges.ts +34 -0
  132. package/src/hostOptions.ts +30 -0
  133. package/src/hostTransport.ts +39 -0
  134. package/src/nativeClientOrigins.ts +44 -0
  135. package/src/node-http/subscriptionSignal.ts +64 -0
  136. package/src/otlpHttpClient.ts +54 -0
  137. package/src/otlpTracing.ts +61 -0
  138. package/src/redactOtlpUrl.ts +48 -0
  139. package/src/redactingDiagnostics.ts +33 -0
  140. package/src/redactingRpcSerialization.ts +85 -0
  141. package/src/redactingTracer.ts +37 -0
  142. package/src/rpc-server/publicConfigLayer.ts +12 -0
  143. package/src/runtime/makePlatform.ts +75 -0
  144. package/src/runtime/types.ts +24 -0
  145. package/src/safeOtlpSerialization.ts +73 -0
  146. package/src/schemaSensitiveKeys.ts +148 -0
  147. package/src/setupDatabases.ts +12 -0
  148. package/src/tracedGroup.ts +14 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ShivaeDev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,324 @@
1
1
  # @shivaedev/server
2
2
 
3
- Placeholder. Real releases start above 0.0.0.
3
+ The application host for Effect apps: one Layer that runs migrations, serves native RPC and static assets over Node HTTP, checks sessions, redacts diagnostics and exports traces. Applications describe their contracts, handlers and session policy; the host owns the process around them.
4
+
5
+ ## Why you want this
6
+
7
+ Every Effect application needs the same server shell: wait for migrations, open a pool, serve RPC with bounded bodies and trusted proxies, keep secrets out of logs and traces, shut down cleanly. Assembling that by hand per app is a week of careful work and a long list of ways to get it subtly wrong. Here it is one call:
8
+
9
+ ```ts
10
+ import { NodeRuntime } from "@effect/platform-node";
11
+ import { Layer } from "effect";
12
+ import { appHost } from "@shivaedev/server/appHost.ts";
13
+ import { Api, Handlers, Services, migrations, sessions } from "./app.ts";
14
+
15
+ NodeRuntime.runMain(
16
+ Layer.launch(appHost({ group: Api, handlers: Handlers, services: Services, migrations: { loader: migrations }, sessions, assets: "./public" })),
17
+ );
18
+ ```
19
+
20
+ The process migrates the database, serves `Api` at `/rpc` and the built client from `./public`, and stops in order on a signal.
21
+
22
+ ## Using it
23
+
24
+ ### How to think about it
25
+
26
+ The host composes pieces that live in their own packages. Request identity, sessions, Origin policy, permissions and Better Auth come from [`@shivaedev/identity`](https://github.com/ShivaeDev/platform/tree/main/packages/identity#readme); shared failures and redaction from [`@shivaedev/errors`](https://github.com/ShivaeDev/platform/tree/main/packages/errors#readme); outside HTTP calls from [`@shivaedev/http`](https://github.com/ShivaeDev/platform/tree/main/packages/http#readme). This package hosts them: `appHost` serves the RPC group with the application's session policy, database and migrations.
27
+
28
+ The optional modules solve different boundaries. `runtime/` carries Effect services into Promise callers, and `node-http/` combines subscription cancellation sources. Choose the modules that match the application rather than adopting every integration.
29
+
30
+ ### Prepare local development
31
+
32
+ `setupDatabases()` from `@shivaedev/server/setupDatabases.ts` reads `DATABASE_URL` and `TEST_DATABASE_URL` through Effect Config and prepares both local databases with `@shivaedev/local-postgres`. Database names come from those URLs. `DOCKER_HOST` and `DOCKER_CONTEXT` are optional. Missing database URLs fail with a typed Config error; migrations remain the application's responsibility.
33
+
34
+ `development({ server, worker, conditions? })` from `@shivaedev/server/development.ts` starts the two application entry points with Node's watch mode and runs `pnpm exec vite`. Supply paths relative to the application directory and any export conditions its code needs. Provide `NodeServices.layer` to run it. When a process exits, the other processes stop and the Effect returns the first exit code, which the entry point can assign to `process.exitCode`. Use `runDevelopment(options)` from the same module for the Node entry point with that runtime wiring included.
35
+
36
+ ### Host the application
37
+
38
+ `appHost` is the server entry point for an Effect app. For a PostgreSQL app, supply the native RPC group, handler and service Layers, migration loader, session policy and static asset directory. The host completes migrations before acquiring application services, starts Node HTTP with NDJSON RPC at `/rpc`, and provides SQL, Reactivity and `AppChanges` to those Layers.
39
+
40
+ ```ts
41
+ import { NodeRuntime } from "@effect/platform-node";
42
+ import { Layer } from "effect";
43
+ import { appHost } from "@shivaedev/server/appHost.ts";
44
+ import { Api, Handlers, Services, migrations, sessions } from "./app.ts";
45
+
46
+ const Server = appHost({
47
+ group: Api,
48
+ handlers: Handlers,
49
+ services: Services,
50
+ migrations: { loader: migrations },
51
+ sessions,
52
+ assets: "./public",
53
+ });
54
+
55
+ NodeRuntime.runMain(Layer.launch(Server));
56
+ ```
57
+
58
+ `app.ts` exports the application's contracts, native Layers, numbered `Migrator.Loader` and `SessionPolicy`. The host needs the optional peers `@effect/platform-node` and `@effect/sql-pg` at the workspace's Effect version; install both for this entry point. The `node-http/`, `rpc-server/` and `runtime/` entries still work without them.
59
+
60
+ Omit `services` when the app has no service Layer of its own. The host uses `Layer.empty`; handler requirements remain explicit, and a migrated host still provides its database services to handlers. Annotated options that declare service outputs, errors or requirements must supply a `services` Layer.
61
+
62
+ `assets` accepts a directory string or native `HttpStaticServer.layer` options. For a browser app whose routes must also work on direct navigation or reload, use `{ root: "dist", spa: true }` or merge `HttpStaticServer.layer({ root: "dist", spa: true })` from `effect/http` alongside the handler Layer. Native route Layers can register additional endpoints in that same composition; `routes` also accepts a native `Layer<never, never, HttpRouter>` for endpoints on the same listener. The [starter](https://github.com/ShivaeDev/platform/tree/main/examples/starter) uses it for static assets and Better Auth at `/api/auth/*`, with provider-owned cookies and the host's RPC session middleware.
63
+
64
+ 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.
65
+
66
+ 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.
67
+
68
+ For a native Node HTTP route outside RPC, read the request body with `readBoundedBody` from [`@shivaedev/http`](https://github.com/ShivaeDev/platform/tree/main/packages/http#readme), which rejects oversized bodies with a typed 413 failure.
69
+
70
+ 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.
71
+
72
+ Every response from the host's native RPC endpoint carries `Cache-Control: private, no-store`, including mixed public and authenticated batches, typed failures, transport rejections, body-read failures and streams. The host sets this at the outer response boundary without inspecting batch contents.
73
+
74
+ 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.
75
+
76
+ 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.
77
+
78
+ `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.
79
+
80
+ 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 or a schema component is pending; 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 and every registered component every second until all are current, then starts the application. Set `migrations.pollInterval` and `migrations.waitTimeout` with Effect duration inputs to change the interval and five-minute timeout. If the first check finds pending work, Effect’s logger emits `Waiting for database migrations` at info, then `Still waiting for database migrations` every 30 seconds independently of polling. Set `migrations.progressInterval` with an Effect duration input to change that progress interval. These lines carry `pendingMigrations` (ID and name) and `pendingComponents` (name and detail) annotations. A later successful check logs `Database migrations current` once; timeout logs `Timed out waiting for database migrations` with the pending annotations before failing. An initially current schema emits none of these lines. The host adds no connection details or secrets to these diagnostics. 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 ledger migrations with a five-second lock timeout unless `migrations.lockTimeout` overrides it, then applies schema components outside the ledger transaction.
81
+
82
+ Pass `migrations.components` beside `loader` for storage managed by another engine. For pg-boss, register `pgBossSchema({ schema: "app_jobs" })` from `@shivaedev/jobs/server/schema.ts`, then start every jobs Layer with `migrate: false`. `check` and `wait` use the same `MigrationError` readout for pending ledger IDs and component names and details, including pg-boss’s installed and required versions.
83
+
84
+ 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.
85
+
86
+ 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.
87
+
88
+ ```ts
89
+ const host = appHost({
90
+ config: { databaseUrl },
91
+ migrations: { loader: migrations, mode: "check" },
92
+ preflight: AppConfigLive,
93
+ application: Effect.gen(function* () {
94
+ const { routes, sessions } = yield* makeAuth();
95
+ return { group: Api, handlers: Handlers, services: Services, routes, sessions };
96
+ }),
97
+ });
98
+ ```
99
+
100
+ 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.
101
+
102
+ 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.
103
+
104
+ The supported tracing variables and defaults are:
105
+
106
+ | Variable | Default | Meaning |
107
+ | --- | --- | --- |
108
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | Unset | Collector base URL. |
109
+ | `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | Base URL plus `/v1/traces` | Complete traces URL; takes precedence. |
110
+ | `OTEL_EXPORTER_OTLP_PROTOCOL` | `http/protobuf` | `http/protobuf` or `http/json`. |
111
+ | `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL` | General protocol | Overrides the protocol for traces. |
112
+ | `OTEL_EXPORTER_OTLP_HEADERS` | Empty | Comma-separated exporter headers. |
113
+ | `OTEL_SERVICE_NAME` | Resource `service.name`, then `unknown_service` | Service name. |
114
+ | `OTEL_SERVICE_VERSION` | Resource `service.version`, otherwise unset | Service version. |
115
+ | `OTEL_RESOURCE_ATTRIBUTES` | Empty | Comma-separated resource attributes. |
116
+ | `OTEL_EXPORTER_OTLP_TIMEOUT` | `10000` ms | Timeout for each HTTP export attempt, including its response body. |
117
+ | `OTEL_EXPORTER_OTLP_TRACES_TIMEOUT` | General timeout | Overrides the request timeout for traces. |
118
+ | `OTEL_BSP_SCHEDULE_DELAY` | `5000` ms | Effect tracer's batch export interval. |
119
+ | `OTEL_BSP_MAX_EXPORT_BATCH_SIZE` | `1000` spans | Effect tracer's batch-size trigger. |
120
+ | `OTEL_BSP_EXPORT_TIMEOUT` | `3000` ms | Effect tracer's shutdown flush bound, capped at the request timeout. |
121
+
122
+ 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.
123
+
124
+ 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/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.
125
+
126
+ 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.
127
+
128
+ 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.
129
+
130
+ Set `config.maxConnections` on `appDatabase` or a migrated `appHost` to bound the PostgreSQL pool. The change listener reserves one connection; when transactions hold the remaining connections, another query waits until a transaction releases its connection. A daemon with long-lived RPC streams can use `config.disablePreemptiveShutdown: true` so scope closure interrupts an active HTTP RPC stream and runs its finalizer before host disposal completes, without waiting for Node's preemptive graceful-shutdown timeout. Omitting it keeps Node's native graceful-shutdown default.
131
+
132
+ 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).
133
+
134
+ Build application handlers with `Api.application.toLayer(...)` (and `Api.application.of(...)` for an Effect-built handler map), then pass the full `Api` to the host and client. `Api.application` is the native RPC group without the reserved `$changes` stream; the host supplies that handler. The explicit `Api.omit("<namespace>.$changes")` form also works.
135
+
136
+ Database-backed hosts enable PostgreSQL change delivery by default and serve each contract's reserved change stream under its middleware. After a command handler succeeds, its declared invalidation keys publish without repeating keys already announced by repository commits. The handler keeps ownership of its transactions and error mapping. `config.changes.channel` overrides the app-derived default, and heartbeat and retry settings remain optional. Use the same application name or channel across web and worker processes. A worker can provide `appDatabase({ migrations, config })` without starting HTTP. See [commit-bound changes](https://github.com/ShivaeDev/platform/blob/main/docs/framework/changes.md) for defaults and limits.
137
+
138
+ ### Public client configuration
139
+
140
+ Use one `publicConfig` declaration per application as the one path for server configuration that a client needs. Declare only public fields in a shared Schema; the declaration creates a standard contract query, so applications write no config RPC. Keep private configuration in server modules.
141
+
142
+ ```ts
143
+ import { Schema } from "effect";
144
+ import { publicConfig } from "@shivaedev/contract/publicConfig.ts";
145
+
146
+ export const PublicConfig = publicConfig(
147
+ Schema.Struct({ installUrl: Schema.URL }).pipe(
148
+ Schema.encodeKeys({ installUrl: "INSTALL_URL" }),
149
+ ),
150
+ );
151
+ ```
152
+
153
+ On the server, merge the declaration into the application's group and its generated handler Layer into the handlers:
154
+
155
+ ```ts
156
+ import { Layer } from "effect";
157
+ import { appHost } from "@shivaedev/server/appHost.ts";
158
+ import { publicConfigLayer } from "@shivaedev/server/rpc-server/publicConfigLayer.ts";
159
+ import { Api, Handlers, sessions } from "./app.ts";
160
+ import { PublicConfig } from "./public-config.ts";
161
+
162
+ export const Server = appHost({
163
+ group: Api.merge(PublicConfig),
164
+ handlers: Layer.merge(Handlers, publicConfigLayer(PublicConfig)),
165
+ sessions,
166
+ });
167
+ ```
168
+
169
+ `publicConfigLayer` reads `Config.schema` from the host's native ConfigProvider when the handler Layer builds. Missing or invalid required fields fail startup with a typed `ConfigError`. An optional second argument supplies a native Config path: `publicConfigLayer(PublicConfig, "PUBLIC")` reads `PUBLIC_INSTALL_URL` with the default environment provider. Only schema-declared fields are loaded and serialized; other server values never enter this response. The generated query has no session middleware, so it can supply public configuration before sign-in. Merge it alongside authenticated contracts rather than applying authentication to the merged group.
170
+
171
+ On the client, use the same native `AtomRpc.Service`, NDJSON HTTP protocol and contract `bind` as other queries:
172
+
173
+ ```ts
174
+ import { Layer } from "effect";
175
+ import { FetchHttpClient } from "effect/http";
176
+ import * as AtomRpc from "effect/reactivity/AtomRpc";
177
+ import { RpcClient, RpcSerialization } from "effect/rpc";
178
+ import { bind } from "@shivaedev/contract/bind.ts";
179
+ import { useQuery } from "@shivaedev/react/client/resultState.ts";
180
+ import { PublicConfig } from "./public-config.ts";
181
+
182
+ class ConfigClient extends AtomRpc.Service<ConfigClient>()("app/ConfigClient", {
183
+ group: PublicConfig,
184
+ protocol: RpcClient.layerProtocolHttp({ url: "/rpc" }).pipe(
185
+ Layer.provide([FetchHttpClient.layer, RpcSerialization.layerNdjson]),
186
+ ),
187
+ }) {}
188
+ const config = bind(PublicConfig, ConfigClient);
189
+
190
+ export function usePublicConfig() {
191
+ return useQuery(config.get.query());
192
+ }
193
+ ```
194
+
195
+ Render inside the application's native registry provider. The query's `data` is an `Option<{ readonly installUrl: URL }>`: the same codec validates server configuration and decodes the RPC response on the client. Public configuration uses the existing atom registry and query lifecycle.
196
+
197
+ ### Request diagnostics
198
+
199
+ Tracing logs declared failures with `RPC failure` and their tag, and defects with `RPC defect`. Interrupt-only causes emit `RPC interrupted` at debug instead, with `rpc.method`, `requestId`, the `rpc.duration` log span and the same redacted payload. The RPC trace span carries `rpc.interrupted: true`; Effect exports interruption with an unset span status. Completed and failed RPCs receive no interruption marker. 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.
200
+
201
+ `appHost` derives sensitive field names from the served RPC group's payload, success, error, defect and middleware error schemas, including nested schemas. Use `Schema.Redacted(...)`, `Schema.RedactedFromValue(...)`, or annotate a field with `sensitive: true`. The host treats those names as sensitive throughout that app, even when a diagnostic contains an unwrapped value. Add other exact, case-sensitive names once in `config.sensitiveKeys`:
202
+
203
+ ```ts
204
+ import { Schema } from "effect";
205
+
206
+ const Contact = Schema.Struct({
207
+ deliveryAddress: Schema.String.annotate({ sensitive: true }),
208
+ recoveryCode: Schema.RedactedFromValue(Schema.String),
209
+ });
210
+
211
+ const Server = appHost({
212
+ group: Api,
213
+ handlers: Handlers,
214
+ sessions,
215
+ config: { sensitiveKeys: ["customerReference"] },
216
+ });
217
+ ```
218
+
219
+ Use `Contact` in `Api`'s RPC schemas. A `sensitive: true` annotation also applies to a checked schema, such as `Schema.String.check(Schema.isMinLength(1)).annotate({ sensitive: true })`, and to checks or groups nested inside other check groups. Values under the declared names become `<redacted>` in host log messages and annotations, failure and defect payloads sent to RPC clients, causes passed to installed error reporters, and exported trace attributes, events, links and resource attributes. Nested structured values follow the same policy before trace serialization. A field containing sensitive array items or record values is masked as a whole. `Schema.encodeKeys` and other schema encoders carry sensitivity to their declared output names, including chains of renamed fields. The host collects all sensitive declarations before propagating encoded names and enclosing-field protection until the key set stops growing, so schema and RPC order do not change the policy. Sensitivity is checked throughout each transformation's source subtree, including fields named in `config.sensitiveKeys`. Policy derivation does not execute encoder callbacks: their field provenance is unknown, so every declared output field of a sensitive source is treated as sensitive, including every union branch, otherwise public fields and error discriminators. When a sensitive source encodes to a scalar, its enclosing field is masked as a whole. Sensitive error tags are masked before tracing copies them into the `rpc.failure` log annotation. Native RPC protocol tags remain intact. An `Error` retains its message, stack and cause in redacted form. If `message` or `name` is sensitive, its stack is masked too, including stack headers encoded by `Schema.Defect({ includeStack: true })`. Successful RPC responses retain their application data. Error schemas consumed by native clients must accept the redaction marker for sensitive fields; a constrained string, numeric or collection field may otherwise fail client decoding after masking.
220
+
221
+ A sensitive error encoded to a top-level scalar or record has no fixed output field name to mask. The host replaces that entire failure value with `<redacted>`. This decision follows each RPC schema, so other methods' failures and successful results retain their application data. Client wire-error schemas must accept the string marker in place of that error. Wire masking preserves public collection entries, deeply nested values and long text; diagnostic collection, depth and string limits apply to logs and diagnostic copies, not client failure data.
222
+
223
+ Diagnostic failure, defect and interruption reasons are rebuilt with sanitized annotations. When `stack` is sensitive, native `Cause.StackTrace` and `Cause.InterruptorStackTrace` annotations are omitted before reporters or trace exporters receive the cause. Other annotations and interruption identities are preserved. Public native stack frames keep callable stack suppliers and valid parent links; a truncated parent chain ends with `undefined` so reporters and trace exporters can still format it.
224
+
225
+ The policy matches field names, not arbitrary occurrences of their values in prose. Free text uses only the existing credential-shaped string and key-assignment rules; it does not scan for personal data. Keep sensitive values out of ordinary prose and span names.
226
+
227
+ For native RPC serialization, `schemaSensitiveKeys(group, extraKeys?)` returns a key predicate with `maskFailure(tag: string | undefined, reason: "Fail" | "Die")`. Pass both to `redactingRpcSerialization(wire, sensitive, sensitive.maskFailure)`. The serializer correlates request tags and response IDs, including batches, before masking a whole error or defect root. Unassociated defects use the conservative policy across the host's defect schemas.
228
+
229
+ The masking primitives, `redact`, `redactWire`, `redactText`, `redactCause` and `isSensitiveKey`, live in [`@shivaedev/errors`](https://github.com/ShivaeDev/platform/tree/main/packages/errors#readme).
230
+
231
+ For a native RPC server composed without `appHost`, `requestTracingLayer({ sensitive })` accepts a key predicate; `isSensitiveKey` from `@shivaedev/errors/sensitive.ts` supplies the default credential rules. `redactingErrorReporter(reporter, sensitive?)` from `@shivaedev/errors/redactCause.ts` wraps an Effect error reporter and passes it redacted failure and defect causes while preserving reporting hints such as severity and redacted attributes.
232
+
233
+ ### Calling outside APIs
234
+
235
+ Use Effect's HTTP client with the status, pagination and bounded body helpers of [`@shivaedev/http`](https://github.com/ShivaeDev/platform/tree/main/packages/http#readme).
236
+
237
+ ### Promise callers: one application runtime
238
+
239
+ Build the application Layer once. `runWithServices` supplies an invocation's overrides to subsequent calls on the same runtime, across Promise awaits:
240
+
241
+ ```ts
242
+ import { Context, Layer } from "effect";
243
+ import { makePlatformRuntime } from "@shivaedev/server/runtime/makePlatform.ts";
244
+
245
+ class Greeting extends Context.Service<Greeting, string>()("app/Greeting") {}
246
+
247
+ const runtime = makePlatformRuntime(Layer.succeed(Greeting, "application"));
248
+ const base = await runtime.runPromise(Greeting);
249
+ const request = await runtime.runWithServices(
250
+ Context.make(Greeting, "request"),
251
+ async () => {
252
+ await Promise.resolve();
253
+ return runtime.runPromise(Greeting);
254
+ },
255
+ );
256
+ await runtime.dispose();
257
+ ```
258
+
259
+ `base` is `"application"` and `request` is `"request"`. The application's resource Layer is acquired once across calls. An explicit `developmentCacheKey` shares a runtime between calls with that key during development. Each key belongs to one application runtime definition.
260
+
261
+ A nested `runWithServices` call replaces the outer invocation's overrides for its callback. Merge the contexts explicitly when the nested call must retain those overrides.
262
+
263
+ ### Node subscriptions: combine cancellation and clean up
264
+
265
+ A long-lived response can receive cancellation from a Web request, a procedure and its underlying Node connection:
266
+
267
+ ```ts
268
+ import type { IncomingMessage } from "node:http";
269
+ import { nodeSubscriptionSignal } from "@shivaedev/server/node-http/subscriptionSignal.ts";
270
+
271
+ export async function consumeSubscription(
272
+ request: Request,
273
+ nodeRequest: IncomingMessage,
274
+ procedureSignal: AbortSignal,
275
+ consume: (signal: AbortSignal) => Promise<void>,
276
+ ) {
277
+ const subscription = nodeSubscriptionSignal({
278
+ nodeRequest,
279
+ request,
280
+ signals: [procedureSignal],
281
+ });
282
+ try {
283
+ await consume(subscription.signal);
284
+ } finally {
285
+ subscription.dispose();
286
+ }
287
+ }
288
+ ```
289
+
290
+ The signal aborts on an additional signal, socket close, incomplete request close or an already destroyed connection. Normal completion of a request does not abort a continuing response. Without an explicit `nodeRequest`, the helper can read one from an srvx Web request's `runtime.node.req`. `dispose()` removes Node listeners and can be called repeatedly.
291
+
292
+ ### API
293
+
294
+ Import the module that defines the name; there is no package-root entry. Paths below follow `@shivaedev/server/`.
295
+
296
+ | Module | Names and purpose |
297
+ | --- | --- |
298
+ | `appHost.ts` | `appHost`, `appDatabase`, `AppChanges`: scoped HTTP and PostgreSQL composition with loopback defaults and optional proxy trust. |
299
+ | `otlpTracing.ts` | `otlpTracing`: opt-in Effect OTLP trace export for worker Layers. |
300
+ | `schemaSensitiveKeys.ts`, `RedactionPolicy.ts` | `schemaSensitiveKeys(group, extraKeys?)`, `RedactionPolicy`: derive and provide an app's diagnostic key predicate. |
301
+ | `redactingDiagnostics.ts`, `redactingTracer.ts`, `redactingRpcSerialization.ts` | `redactingDiagnostics(sensitive)`, `redactRecord(values, sensitive)`, `redactingTracer(sensitive)`, `redactingRpcSerialization(wire, sensitive)`: compose native diagnostic and NDJSON boundaries. |
302
+ | `runtime/makePlatform.ts` | `makePlatformRuntime(layer, { developmentCacheKey? })`. |
303
+ | `node-http/subscriptionSignal.ts` | `nodeSubscriptionSignal({ nodeRequest?, request?, signals? })`, returning `{ signal, dispose }`. |
304
+
305
+ ### Install, setup and limits
306
+
307
+ ```sh
308
+ pnpm add @shivaedev/server effect@4.0.5
309
+ ```
310
+
311
+ Effect is the only required peer. The `node-http/`, `rpc-server/` and `runtime/` modules work without the optional peers; a module's import path is its path under `src/`. Every module is server code: the runtime uses Node's `AsyncLocalStorage`, and browser code imports contracts from `@shivaedev/contract`, identity declarations from `@shivaedev/identity` and error schemas from `@shivaedev/errors` instead.
312
+
313
+ Install the optional peers for the selected integration:
314
+
315
+ | Integration | Additional peers |
316
+ | --- | --- |
317
+ | `appHost.ts` | `@effect/platform-node`, `@effect/sql-pg` |
318
+
319
+ - The package needs Node 24 or newer.
320
+ - `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 so it wraps authentication too; see the [native-server example](https://github.com/ShivaeDev/platform/blob/main/docs/framework/request-context.md#request-id-identity-and-logging). Middleware outside that tracing boundary is responsible for its own diagnostics.
321
+ - Redaction recognizes declared field names and common credential shapes. Mark sensitive fields in RPC schemas and configure extra names once with `config.sensitiveKeys`. Keep sensitive values out of ordinary prose.
322
+ - A development cache key is ignored when `NODE_ENV` is `production`. The application owns runtime disposal.
323
+
324
+ 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.
@@ -0,0 +1,15 @@
1
+ import type { Effect, Layer } from "effect";
2
+ import type { Rpc } from "effect/rpc";
3
+ import type { SessionShape } from "@shivaedev/identity/server/session.ts";
4
+ import type { HostPreflight } from "#AppHostInput.ts";
5
+ import type { AppDatabaseOptions, AppHostOptions, AppHttpHostOptions, AppLocalHostOptions } from "#appHost.ts";
6
+ import type { appHostHttp, deferredHost } from "#appHostHttp.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/AppHostFactory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=AppHostFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppHostFactory.js","sourceRoot":"","sources":["../src/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 { SessionShape } from "@shivaedev/identity/server/session.ts";
4
+ import type { AppDatabaseOptions, AppHostOptions, AppHttpHostOptions, AppLocalHostOptions } from "#appHost.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/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,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE/G,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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=AppHostInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppHostInput.js","sourceRoot":"","sources":["../src/AppHostInput.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ import type { Duration } from "effect";
2
+ import type { Migrator } from "effect/sql";
3
+ import type { SchemaComponent } from "@shivaedev/sql/SchemaComponent.ts";
4
+ export interface MigrationOptions<R = never> {
5
+ readonly components?: readonly SchemaComponent<R>[];
6
+ readonly loader: Migrator.Loader<R>;
7
+ readonly lockTimeout?: Duration.Input;
8
+ readonly mode?: "migrate" | "check" | "wait";
9
+ readonly pollInterval?: Duration.Input;
10
+ readonly progressInterval?: Duration.Input;
11
+ readonly release?: string;
12
+ readonly table?: string;
13
+ readonly waitTimeout?: Duration.Input;
14
+ }
15
+ //# sourceMappingURL=MigrationOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MigrationOptions.d.ts","sourceRoot":"","sources":["../src/MigrationOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEzE,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,KAAK;IAC1C,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IACtC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IAC7C,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IACvC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IAC3C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;CACtC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=MigrationOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MigrationOptions.js","sourceRoot":"","sources":["../src/MigrationOptions.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import { Context } from "effect";
2
+ import { type SensitiveKey } from "@shivaedev/errors/sensitive.ts";
3
+ export declare const RedactionPolicy: Context.Reference<SensitiveKey>;
4
+ //# sourceMappingURL=RedactionPolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RedactionPolicy.d.ts","sourceRoot":"","sources":["../src/RedactionPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEnF,eAAO,MAAM,eAAe,iCAA+G,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Context } from "effect";
2
+ import { isSensitiveKey } from "@shivaedev/errors/sensitive.ts";
3
+ export const RedactionPolicy = Context.Reference("@shivaedev/server/RedactionPolicy", { defaultValue: () => isSensitiveKey });
4
+ //# sourceMappingURL=RedactionPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RedactionPolicy.js","sourceRoot":"","sources":["../src/RedactionPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,cAAc,EAAqB,MAAM,gCAAgC,CAAC;AAEnF,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC,SAAS,CAAe,mCAAmC,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { Context, type Effect, Layer } from "effect";
2
+ import type { Rpc } from "effect/rpc";
3
+ import type { SessionPolicy, SessionShape } from "@shivaedev/identity/server/session.ts";
4
+ import type { AppHostFactory } from "#AppHostFactory.ts";
5
+ import type { HostPreflight } from "#AppHostInput.ts";
6
+ import { type DatabaseConfig } from "#databaseLayer.ts";
7
+ import type { HostOptions, HostPolicy } from "#hostOptions.ts";
8
+ import type { MigrationOptions } from "#MigrationOptions.ts";
9
+ declare const AppChanges_base: Context.ServiceClass<AppChanges, "@shivaedev/server/AppChanges", {
10
+ resync: Effect.Effect<number, never, never>;
11
+ stream: (keys: readonly import("@shivaedev/contract/keys.ts").Key[], context?: import("@shivaedev/contract/keys.ts").KeyContext) => import("effect/Stream").Stream<{
12
+ readonly _tag: "Changed";
13
+ readonly keys: readonly ({
14
+ readonly _tag: "List";
15
+ readonly collection: string;
16
+ } | {
17
+ readonly _tag: "Item";
18
+ readonly collection: string;
19
+ readonly id: string | number;
20
+ })[];
21
+ } | {
22
+ readonly _tag: "Resync";
23
+ }, never, never>;
24
+ }>;
25
+ export declare class AppChanges extends AppChanges_base {
26
+ }
27
+ export interface AppDatabaseOptions<R = never> {
28
+ readonly config?: DatabaseConfig;
29
+ readonly migrations: MigrationOptions<R>;
30
+ }
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> & {
33
+ readonly migrations: AppDatabaseOptions<TMigrations>["migrations"];
34
+ readonly policy?: undefined;
35
+ readonly sessions: SessionPolicy<TSession>;
36
+ };
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> & {
38
+ readonly migrations: AppDatabaseOptions<TMigrations>["migrations"];
39
+ readonly policy: "loopback";
40
+ readonly sessions?: never;
41
+ };
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> & {
43
+ readonly migrations?: undefined;
44
+ };
45
+ export declare const appHost: AppHostFactory;
46
+ export {};
47
+ //# sourceMappingURL=appHost.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appHost.d.ts","sourceRoot":"","sources":["../src/appHost.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { Context, Layer } from "effect";
2
+ import { appHostHttp, deferredHost, migratedHost } from "#appHostHttp.ts";
3
+ import { databaseLayer } from "#databaseLayer.ts";
4
+ export class AppChanges extends Context.Service()("@shivaedev/server/AppChanges") {
5
+ }
6
+ export function appDatabase(options) {
7
+ return databaseLayer(options, AppChanges);
8
+ }
9
+ export const appHost = (options) => {
10
+ if ("application" in options) {
11
+ return deferredHost(options.application, appDatabase(options), AppChanges).pipe(Layer.provideMerge(options.preflight ?? Layer.empty));
12
+ }
13
+ return options.migrations === undefined
14
+ ? appHostHttp(options, AppChanges).pipe(Layer.provideMerge(options.preflight ?? Layer.empty))
15
+ : migratedHost({ ...options, migrations: options.migrations }, appDatabase({ ...options, migrations: options.migrations }), AppChanges).pipe(Layer.provideMerge(options.preflight ?? Layer.empty));
16
+ };
17
+ //# sourceMappingURL=appHost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appHost.js","sourceRoot":"","sources":["../src/appHost.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,KAAK,EAAE,MAAM,QAAQ,CAAC;AAMrD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAuB,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvE,MAAM,OAAO,UAAW,SAAQ,OAAO,CAAC,OAAO,EAAqD,CAAC,8BAA8B,CAAC;CAAG;AAMvI,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,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACvI,CAAC;IACD,OAAO,OAAO,CAAC,UAAU,KAAK,SAAS;QACtC,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7F,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,EAAE,UAAU,CAAC,CAAC,IAAI,CAC1I,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC,CACpD,CAAC;AACL,CAAC,CAAC"}