@shivaedev/server 0.10.0 → 0.11.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 (72) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +23 -18
  3. package/dist/appDatabase.d.ts +14 -0
  4. package/dist/appDatabase.d.ts.map +1 -0
  5. package/dist/{databaseLayer.js → appDatabase.js} +6 -6
  6. package/dist/appDatabase.js.map +1 -0
  7. package/dist/appHost.d.ts +1 -14
  8. package/dist/appHost.d.ts.map +1 -1
  9. package/dist/appHost.js +5 -10
  10. package/dist/appHost.js.map +1 -1
  11. package/dist/appHostHttp.d.ts +29 -29
  12. package/dist/appHostHttp.d.ts.map +1 -1
  13. package/dist/appHostHttp.js +7 -7
  14. package/dist/appHostHttp.js.map +1 -1
  15. package/dist/bearerSocketRpc.d.ts +5 -0
  16. package/dist/bearerSocketRpc.d.ts.map +1 -0
  17. package/dist/bearerSocketRpc.js +69 -0
  18. package/dist/bearerSocketRpc.js.map +1 -0
  19. package/dist/hostChanges.d.ts +1 -2
  20. package/dist/hostChanges.d.ts.map +1 -1
  21. package/dist/hostChanges.js +4 -3
  22. package/dist/hostChanges.js.map +1 -1
  23. package/dist/hostRpcRoutes.d.ts +2 -3
  24. package/dist/hostRpcRoutes.d.ts.map +1 -1
  25. package/dist/hostRpcRoutes.js +4 -2
  26. package/dist/hostRpcRoutes.js.map +1 -1
  27. package/dist/otlpHttpClient.js +2 -2
  28. package/dist/otlpHttpClient.js.map +1 -1
  29. package/dist/redactingDiagnostics.d.ts +0 -2
  30. package/dist/redactingDiagnostics.d.ts.map +1 -1
  31. package/dist/redactingDiagnostics.js +1 -4
  32. package/dist/redactingDiagnostics.js.map +1 -1
  33. package/dist/redactingTracer.d.ts.map +1 -1
  34. package/dist/redactingTracer.js +6 -5
  35. package/dist/redactingTracer.js.map +1 -1
  36. package/dist/safeOtlpSerialization.d.ts +0 -2
  37. package/dist/safeOtlpSerialization.d.ts.map +1 -1
  38. package/dist/safeOtlpSerialization.js +5 -12
  39. package/dist/safeOtlpSerialization.js.map +1 -1
  40. package/dist/socketRpc.d.ts.map +1 -1
  41. package/dist/socketRpc.js +6 -4
  42. package/dist/socketRpc.js.map +1 -1
  43. package/package.json +9 -9
  44. package/src/{databaseLayer.ts → appDatabase.ts} +6 -6
  45. package/src/appHost.ts +5 -11
  46. package/src/appHostHttp.ts +8 -11
  47. package/src/bearerSocketRpc.ts +80 -0
  48. package/src/hostChanges.ts +4 -8
  49. package/src/hostRpcRoutes.ts +4 -6
  50. package/src/otlpHttpClient.ts +2 -2
  51. package/src/redactingDiagnostics.ts +1 -5
  52. package/src/redactingTracer.ts +7 -5
  53. package/src/safeOtlpSerialization.ts +5 -12
  54. package/src/socketRpc.ts +6 -6
  55. package/dist/databaseLayer.d.ts +0 -14
  56. package/dist/databaseLayer.d.ts.map +0 -1
  57. package/dist/databaseLayer.js.map +0 -1
  58. package/dist/redactOtlpUrl.d.ts +0 -2
  59. package/dist/redactOtlpUrl.d.ts.map +0 -1
  60. package/dist/redactOtlpUrl.js +0 -41
  61. package/dist/redactOtlpUrl.js.map +0 -1
  62. package/dist/schemaSensitiveAst.d.ts +0 -7
  63. package/dist/schemaSensitiveAst.d.ts.map +0 -1
  64. package/dist/schemaSensitiveAst.js +0 -102
  65. package/dist/schemaSensitiveAst.js.map +0 -1
  66. package/dist/schemaSensitiveKeys.d.ts +0 -6
  67. package/dist/schemaSensitiveKeys.d.ts.map +0 -1
  68. package/dist/schemaSensitiveKeys.js +0 -47
  69. package/dist/schemaSensitiveKeys.js.map +0 -1
  70. package/src/redactOtlpUrl.ts +0 -48
  71. package/src/schemaSensitiveAst.ts +0 -106
  72. package/src/schemaSensitiveKeys.ts +0 -49
@@ -0,0 +1,80 @@
1
+ import { Effect, Option, Schema, type Scope } from "effect";
2
+ import { Headers, HttpServerRequest, HttpServerResponse } from "effect/http";
3
+ import * as Socket from "effect/socket/Socket";
4
+ import { SocketAuthentication } from "@shivaedev/contract/socketAuthentication.ts";
5
+ import { Unauthorized } from "@shivaedev/errors/taxonomy.ts";
6
+ import { recheckSession } from "@shivaedev/identity/server/recheckSession.ts";
7
+ import { resolveSession, type SessionPolicy, type SessionShape } from "@shivaedev/identity/server/session.ts";
8
+ import { makeSocketSession, SocketSession } from "@shivaedev/identity/server/socketSession.ts";
9
+
10
+ export const bearerSocketRpc = Effect.fnUntraced(function* <TSession extends SessionShape>(
11
+ handler: Effect.Effect<HttpServerResponse.HttpServerResponse, never, HttpServerRequest.HttpServerRequest | Scope.Scope>,
12
+ policy: SessionPolicy<TSession>,
13
+ ) {
14
+ const request = yield* HttpServerRequest.HttpServerRequest;
15
+ const socket = yield* Effect.orDie(request.upgrade);
16
+ const reader = yield* Effect.orDie(socket.reader);
17
+ const writer = yield* socket.writer;
18
+ function close(code: number, reason: string) {
19
+ return writer.write(new Socket.CloseEvent(code, reason)).pipe(Effect.as(HttpServerResponse.empty()));
20
+ }
21
+ function unauthorized() {
22
+ return close(1008, "Authentication required");
23
+ }
24
+ function unavailable() {
25
+ return close(1011, "Authentication unavailable");
26
+ }
27
+ return yield* Effect.gen(function* () {
28
+ const frames = yield* reader.pull.pipe(Effect.timeout("5 seconds"));
29
+ const frame = frames[0];
30
+ const auth =
31
+ typeof frame === "string" && frame.length <= 8192
32
+ ? Schema.decodeUnknownOption(Schema.fromJsonString(SocketAuthentication))(frame)
33
+ : Option.none();
34
+ if (Option.isNone(auth)) {
35
+ return yield* new Unauthorized({ message: "Authentication required" });
36
+ }
37
+ const authenticated = request.modify({ headers: Headers.set(request.headers, "authorization", `Bearer ${auth.value.token}`) });
38
+ let buffered = frames.slice(1);
39
+ const authenticatedSocket: Socket.Socket = {
40
+ ...socket,
41
+ reader: Effect.succeed({
42
+ ...reader,
43
+ pull: Effect.suspend(() => {
44
+ if (buffered.length === 0) {
45
+ return reader.pull;
46
+ }
47
+ const [first, ...rest] = buffered;
48
+ buffered = [];
49
+ return first === undefined ? reader.pull : Effect.succeed([first, ...rest] as const);
50
+ }),
51
+ }),
52
+ };
53
+ const transport = new Proxy(authenticated, {
54
+ get: (target, key, receiver) => (key === "upgrade" ? Effect.succeed(authenticatedSocket) : Reflect.get(target, key, receiver)),
55
+ });
56
+ return yield* Effect.gen(function* () {
57
+ const initial = yield* resolveSession(policy, Headers.empty, "$connect");
58
+ if (Option.isNone(initial)) {
59
+ return yield* new Unauthorized({ message: "Authentication required" });
60
+ }
61
+ const session = yield* makeSocketSession(policy.streamRevalidationInterval ?? "30 seconds");
62
+ const check = recheckSession(policy, Headers.empty, "$connect").pipe(
63
+ Effect.flatMap((current) =>
64
+ Option.isSome(current) && current.value.user.id === initial.value.user.id
65
+ ? Effect.void
66
+ : Effect.fail(new Unauthorized({ message: "Authentication required" })),
67
+ ),
68
+ );
69
+ return yield* Effect.raceFirst(handler, session.monitor(check)).pipe(Effect.provideService(SocketSession, session));
70
+ }).pipe(Effect.provideService(HttpServerRequest.HttpServerRequest, transport));
71
+ }).pipe(
72
+ Effect.catchTags({
73
+ AuthUnavailable: unavailable,
74
+ Forbidden: unauthorized,
75
+ TimeoutError: unauthorized,
76
+ Unauthorized: unauthorized,
77
+ }),
78
+ Effect.catchTag("SocketError", () => Effect.succeed(HttpServerResponse.empty())),
79
+ );
80
+ });
@@ -1,6 +1,7 @@
1
1
  import { Context, Effect, Layer, Option, Stream } from "effect";
2
2
  import { Headers } from "effect/http";
3
3
  import { Rpc, type RpcGroup } from "effect/rpc";
4
+ import { LiveServer } from "@shivaedev/contract/LiveServer.ts";
4
5
  import { CurrentViewer, type Viewer } from "@shivaedev/contract/readPolicy.ts";
5
6
  import type { QueryReference } from "@shivaedev/contract/serverMetadata.ts";
6
7
  import { Unauthorized } from "@shivaedev/errors/taxonomy.ts";
@@ -8,17 +9,12 @@ import { recheckSession } from "@shivaedev/identity/server/recheckSession.ts";
8
9
  import { revalidateStream } from "@shivaedev/identity/server/revalidateStream.ts";
9
10
  import type { SessionPolicy, SessionShape } from "@shivaedev/identity/server/session.ts";
10
11
  import { resolveChanges } from "@shivaedev/identity/server/sessionKeys.ts";
11
- import type { AppChanges } from "#appHost.ts";
12
12
  import { rerunQuery } from "#rerunQuery.ts";
13
13
 
14
- export function hostChanges<R extends Rpc.Any, TSession extends SessionShape>(
15
- group: RpcGroup.RpcGroup<R>,
16
- changesService: typeof AppChanges,
17
- sessions?: SessionPolicy<TSession>,
18
- ) {
14
+ export function hostChanges<R extends Rpc.Any, TSession extends SessionShape>(group: RpcGroup.RpcGroup<R>, sessions?: SessionPolicy<TSession>) {
19
15
  return Layer.effectContext(
20
16
  Effect.gen(function* () {
21
- const changes = yield* Effect.serviceOption(changesService);
17
+ const changes = yield* Effect.serviceOption(LiveServer);
22
18
  const services = yield* Effect.context<never>();
23
19
  const handlers = new Map<string, unknown>();
24
20
  function subscribe(rpc: Rpc.AnyWithProps, queries: readonly QueryReference[], options: Parameters<Rpc.Handler<string>["handler"]>[1]) {
@@ -28,7 +24,7 @@ export function hostChanges<R extends Rpc.Any, TSession extends SessionShape>(
28
24
  const viewer = yield* CurrentViewer;
29
25
  const authorized = authorizeSession(sessions, rpc._tag, viewer, subscription.authorized);
30
26
  const stream = Option.isSome(changes)
31
- ? changes.value.subscribe({ ...subscription, authorized }, context, rerunQuery(group, options))
27
+ ? Stream.unwrap(changes.value.subscribe({ ...subscription, authorized }, context, rerunQuery(group, options)))
32
28
  : Stream.concat(Stream.succeed({ _tag: "Resync" } as const), Stream.never);
33
29
  if (sessions === undefined || Option.isNone(viewer)) {
34
30
  return stream;
@@ -2,10 +2,11 @@ import { ByteSize, Effect, Layer } from "effect";
2
2
  import { HttpEffect, HttpIncomingMessage, HttpRouter, HttpServerRequest, HttpServerResponse } from "effect/http";
3
3
  import * as HttpStatus from "effect/http/HttpStatus";
4
4
  import { type Rpc, type RpcGroup, RpcSerialization } from "effect/rpc";
5
+ import { validateReadPolicies } from "@shivaedev/contract/validateReadPolicies.ts";
6
+ import type { schemaSensitiveKeys } from "@shivaedev/errors/schemaSensitiveKeys.ts";
5
7
  import type { Authenticated, MaybeAuthenticated, RequestTracing } from "@shivaedev/identity/middleware.ts";
6
8
  import { localRpcGuard } from "@shivaedev/identity/server/local.ts";
7
9
  import { authenticatedLayer, maybeAuthenticatedLayer, type SessionShape } from "@shivaedev/identity/server/session.ts";
8
- import type { AppChanges } from "#appHost.ts";
9
10
  import { boundedRpcRequest } from "#boundedRpcRequest.ts";
10
11
  import { hostChanges } from "#hostChanges.ts";
11
12
  import type { HostPolicy } from "#hostOptions.ts";
@@ -13,7 +14,6 @@ import { hostRpc, rpcCacheControl } from "#hostRpc.ts";
13
14
  import type { hostTransport } from "#hostTransport.ts";
14
15
  import { redactingRpcSerialization } from "#redactingRpcSerialization.ts";
15
16
  import { rpcRequestTracing } from "#rpcRequestTracing.ts";
16
- import type { schemaSensitiveKeys } from "#schemaSensitiveKeys.ts";
17
17
  import { socketRpc } from "#socketRpc.ts";
18
18
 
19
19
  export function hostRpcRoutes<TRpcs extends Rpc.Any, THandlers, TError, TRequirements, TSession extends SessionShape>(
@@ -22,7 +22,6 @@ export function hostRpcRoutes<TRpcs extends Rpc.Any, THandlers, TError, TRequire
22
22
  readonly handlers: Layer.Layer<THandlers, TError, TRequirements>;
23
23
  readonly rpcPath?: HttpRouter.PathInput;
24
24
  } & HostPolicy<TSession>,
25
- changesService: typeof AppChanges,
26
25
  { bodySize, trustedProxy, nativeOrigins }: Effect.Success<ReturnType<typeof hostTransport>>,
27
26
  sensitive: ReturnType<typeof schemaSensitiveKeys>,
28
27
  ) {
@@ -32,6 +31,7 @@ export function hostRpcRoutes<TRpcs extends Rpc.Any, THandlers, TError, TRequire
32
31
  : Layer.mergeAll(authenticatedLayer(options.sessions), maybeAuthenticatedLayer(options.sessions), rpcRequestTracing(sensitive));
33
32
  return HttpRouter.use((router) =>
34
33
  Effect.gen(function* () {
34
+ yield* validateReadPolicies(options.group);
35
35
  const wire = redactingRpcSerialization(yield* RpcSerialization.RpcSerialization, sensitive, sensitive.maskFailure, sensitive.forRpc);
36
36
  const httpGroup = options.group.omit(...[...options.group.requests.keys()].filter((tag) => tag.endsWith(".$changes")));
37
37
  const handler = yield* hostRpc(httpGroup).pipe(Effect.provideService(RpcSerialization.RpcSerialization, wire));
@@ -62,9 +62,7 @@ export function hostRpcRoutes<TRpcs extends Rpc.Any, THandlers, TError, TRequire
62
62
  Layer.provide(
63
63
  Layer.merge(
64
64
  middleware,
65
- hostChanges(options.group, changesService, options.policy === "loopback" ? undefined : options.sessions).pipe(
66
- Layer.provideMerge(options.handlers),
67
- ),
65
+ hostChanges(options.group, options.policy === "loopback" ? undefined : options.sessions).pipe(Layer.provideMerge(options.handlers)),
68
66
  ),
69
67
  ),
70
68
  Layer.provide(RpcSerialization.layerNdjson),
@@ -1,8 +1,8 @@
1
1
  import { Effect, Layer } from "effect";
2
2
  import { FetchHttpClient, HttpClient, HttpClientError, type HttpClientRequest } from "effect/http";
3
3
  import * as HttpStatus from "effect/http/HttpStatus";
4
+ import { redactText } from "@shivaedev/errors/sensitive.ts";
4
5
  import { RedactionPolicy } from "#RedactionPolicy.ts";
5
- import { redactOtlpText } from "#safeOtlpSerialization.ts";
6
6
 
7
7
  function timeoutError(request: HttpClientRequest.HttpClientRequest) {
8
8
  return new HttpClientError.HttpClientError({
@@ -44,7 +44,7 @@ export function otlpHttpClient(timeout = 10_000) {
44
44
  return warnOnce(
45
45
  response.text.pipe(
46
46
  Effect.orElseSucceed(() => "Unable to read collector response"),
47
- Effect.map((body) => ({ "otlp.response": redactOtlpText(body, "", sensitive), "otlp.status": response.status })),
47
+ Effect.map((body) => ({ "otlp.response": redactText(body, sensitive), "otlp.status": response.status })),
48
48
  ),
49
49
  );
50
50
  }),
@@ -1,12 +1,8 @@
1
1
  import { Context, Effect, ErrorReporter, Layer, Logger, References } from "effect";
2
- import { redact } from "@shivaedev/errors/redact.ts";
2
+ import { redact, redactRecord } from "@shivaedev/errors/redact.ts";
3
3
  import { redactDiagnosticCause, redactingErrorReporter } from "@shivaedev/errors/redactCause.ts";
4
- import type { SensitiveKey } from "@shivaedev/errors/sensitive.ts";
5
4
  import { type HostRedactionPolicy, redactionForRpc } from "#RedactionPolicy.ts";
6
5
 
7
- export function redactRecord(values: Readonly<Record<string, unknown>>, sensitive: SensitiveKey): Record<string, unknown> {
8
- return Object.fromEntries(Object.entries(values).map(([key, value]) => [key, sensitive(key) ? "<redacted>" : redact(value, sensitive)]));
9
- }
10
6
  function requestErrorReporter(reporter: ErrorReporter.ErrorReporter, policy: HostRedactionPolicy): ErrorReporter.ErrorReporter {
11
7
  return {
12
8
  [ErrorReporter.TypeId]: ErrorReporter.TypeId,
@@ -1,9 +1,8 @@
1
1
  import { Effect, Exit, Layer, Option, Tracer } from "effect";
2
- import { redact } from "@shivaedev/errors/redact.ts";
2
+ import { redactRecord } from "@shivaedev/errors/redact.ts";
3
3
  import { redactDiagnosticCause } from "@shivaedev/errors/redactCause.ts";
4
- import { REDACTED, type SensitiveKey } from "@shivaedev/errors/sensitive.ts";
4
+ import type { SensitiveKey } from "@shivaedev/errors/sensitive.ts";
5
5
  import { type HostRedactionPolicy, redactionForRpc } from "#RedactionPolicy.ts";
6
- import { redactRecord } from "#redactingDiagnostics.ts";
7
6
 
8
7
  function redactLinks(values: readonly Tracer.SpanLink[], sensitive: SensitiveKey) {
9
8
  return values.map((link) => ({ ...link, attributes: redactRecord(link.attributes, sensitive) }));
@@ -11,6 +10,9 @@ function redactLinks(values: readonly Tracer.SpanLink[], sensitive: SensitiveKey
11
10
  function redactSpan(span: Tracer.Span, policy: HostRedactionPolicy) {
12
11
  const end = span.end.bind(span);
13
12
  const attribute = span.attribute.bind(span);
13
+ function safeAttribute(key: string, value: unknown) {
14
+ return attribute(key, redactRecord({ [key]: value }, sensitive)[key]);
15
+ }
14
16
  const event = span.event.bind(span);
15
17
  const addLinks = span.addLinks.bind(span);
16
18
  function sensitive(key: string) {
@@ -18,10 +20,10 @@ function redactSpan(span: Tracer.Span, policy: HostRedactionPolicy) {
18
20
  }
19
21
  return Object.assign(span, {
20
22
  addLinks: (values: readonly Tracer.SpanLink[]) => addLinks(redactLinks(values, sensitive)),
21
- attribute: (key: string, value: unknown) => attribute(key, sensitive(key) ? REDACTED : redact(value, sensitive)),
23
+ attribute: safeAttribute,
22
24
  end: (time: bigint, exit: Exit.Exit<unknown, unknown>) => {
23
25
  for (const [key, value] of span.attributes) {
24
- attribute(key, sensitive(key) ? REDACTED : redact(value, sensitive));
26
+ safeAttribute(key, value);
25
27
  }
26
28
  end(time, Exit.isFailure(exit) ? Exit.failCause(redactDiagnosticCause(exit.cause, sensitive)) : exit);
27
29
  },
@@ -1,20 +1,13 @@
1
1
  import { Effect, Layer } from "effect";
2
2
  import type { OtlpResource, OtlpTracer } from "effect/observability";
3
3
  import { OtlpSerialization } from "effect/observability";
4
- import { isSensitiveKey, REDACTED, redactText, type SensitiveKey } from "@shivaedev/errors/sensitive.ts";
4
+ import { REDACTED, redactText, type SensitiveKey } from "@shivaedev/errors/sensitive.ts";
5
5
  import { type HostRedactionPolicy, RedactionPolicy, redactionForRpc } from "#RedactionPolicy.ts";
6
- import { redactOtlpUrl } from "#redactOtlpUrl.ts";
7
6
 
8
- function otlpSensitive(sensitive: SensitiveKey): SensitiveKey {
9
- return (key) => sensitive(key) || ["db.user", "db.user.name", "db.connection_string"].includes(key.toLowerCase());
10
- }
11
- export function redactOtlpText(value: string, key = "", sensitive: SensitiveKey = isSensitiveKey) {
12
- return redactText(redactOtlpUrl(value, key), otlpSensitive(sensitive));
13
- }
14
7
  function attributeValue(value: OtlpResource.AnyValue, key: string, sensitive: SensitiveKey): OtlpResource.AnyValue {
15
8
  return {
16
9
  ...value,
17
- ...(typeof value.stringValue === "string" ? { stringValue: redactOtlpText(value.stringValue, key, sensitive) } : {}),
10
+ ...(typeof value.stringValue === "string" ? { stringValue: redactText(value.stringValue, sensitive, undefined, key) } : {}),
18
11
  ...(value.arrayValue ? { arrayValue: { values: value.arrayValue.values.map((item) => attributeValue(item, key, sensitive)) } } : {}),
19
12
  ...(value.kvlistValue ? { kvlistValue: { values: attributes(value.kvlistValue.values, sensitive) } } : {}),
20
13
  };
@@ -38,7 +31,7 @@ function spanName(span: { readonly name: string; readonly kind: number; readonly
38
31
  }
39
32
 
40
33
  function redactTraces(data: OtlpTracer.TraceData, policy: HostRedactionPolicy): OtlpTracer.TraceData {
41
- const resourceSensitive = otlpSensitive(policy);
34
+ const resourceSensitive = policy;
42
35
  return {
43
36
  ...data,
44
37
  resourceSpans: data.resourceSpans.map((resource) => ({
@@ -48,9 +41,9 @@ function redactTraces(data: OtlpTracer.TraceData, policy: HostRedactionPolicy):
48
41
  ...scope,
49
42
  spans: scope.spans.map((span) => {
50
43
  const method = span.attributes.find(({ key }) => key === "rpc.method")?.value.stringValue;
51
- const sensitive = otlpSensitive(redactionForRpc(policy, method));
44
+ const sensitive = redactionForRpc(policy, method);
52
45
  function text(value: string) {
53
- return redactOtlpText(value, "", sensitive);
46
+ return redactText(value, sensitive);
54
47
  }
55
48
  return {
56
49
  ...span,
package/src/socketRpc.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import { Effect, type Scope } from "effect";
2
2
  import { Headers, HttpServerRequest, HttpServerResponse } from "effect/http";
3
3
  import * as HttpStatus from "effect/http/HttpStatus";
4
+ import { isAuthUnavailable, isForbidden } from "@shivaedev/errors/taxonomy.ts";
4
5
  import { localTransport } from "@shivaedev/identity/server/local.ts";
5
6
  import { resolveSession, type SessionShape } from "@shivaedev/identity/server/session.ts";
6
7
  import { makeSocketSession, SocketSession } from "@shivaedev/identity/server/socketSession.ts";
8
+ import { bearerSocketRpc } from "#bearerSocketRpc.ts";
7
9
  import type { HostPolicy } from "#hostOptions.ts";
8
10
 
9
11
  export function socketRpc<TSession extends SessionShape>(
@@ -18,17 +20,15 @@ export function socketRpc<TSession extends SessionShape>(
18
20
  return HttpServerResponse.text("Local same-origin requests only", { status: HttpStatus.fromLiteral("Forbidden") });
19
21
  }
20
22
  if (policy.policy !== "loopback") {
23
+ if (new URL(request.url, "http://localhost").searchParams.get("auth") === "frame") {
24
+ return yield* bearerSocketRpc(handler, policy.sessions);
25
+ }
21
26
  yield* resolveSession(policy.sessions, Headers.empty, "$connect");
22
27
  const session = yield* makeSocketSession(policy.sessions.streamRevalidationInterval ?? "30 seconds");
23
28
  return yield* Effect.provideService(handler, SocketSession, session);
24
29
  }
25
30
  return yield* handler;
26
- }).pipe(
27
- Effect.catchTags({
28
- AuthUnavailable: authUnavailable,
29
- Forbidden: forbidden,
30
- }),
31
- );
31
+ }).pipe(Effect.catchIf(isAuthUnavailable, authUnavailable), Effect.catchIf(isForbidden, forbidden));
32
32
  }
33
33
 
34
34
  function authUnavailable() {
@@ -1,14 +0,0 @@
1
- import * as PgClient from "@effect/sql-pg/PgClient";
2
- import { Config, Layer, Redacted } from "effect";
3
- import * as Reactivity from "effect/reactivity/Reactivity";
4
- import { Migrator } from "effect/sql";
5
- import { type PostgresChangesOptions } from "@shivaedev/sql/postgresChanges.ts";
6
- import { type PostgresOptions } from "@shivaedev/sql/postgresLayer.ts";
7
- import type { AppChanges, AppDatabaseOptions } from "#appHost.ts";
8
- export interface DatabaseConfig extends PostgresOptions {
9
- readonly changes?: Partial<Omit<PostgresChangesOptions, "client" | "listenerClient" | "connectionSetting" | "resync">>;
10
- readonly databaseUrl?: Redacted.Redacted<string>;
11
- readonly listenDatabaseUrl?: Redacted.Redacted<string>;
12
- }
13
- export declare function databaseLayer<R, E>(options: AppDatabaseOptions<R, E>, changesService: typeof AppChanges): Layer.Layer<AppChanges | PgClient.PgClient | import("@effect/sql-pg/PgPool").PgPool | Reactivity.Reactivity | import("effect/sql/SqlClient").SqlClient, E | Config.ConfigError | Migrator.MigrationError | import("@shivaedev/sql/PostgresListenerError.ts").PostgresListenerError | import("effect/Schema").SchemaError | import("effect/sql/SqlError").SqlError, Exclude<Exclude<R, import("effect/Scope").Scope>, PgClient.PgClient | import("@effect/sql-pg/PgPool").PgPool | import("effect/sql/SqlClient").SqlClient>>;
14
- //# sourceMappingURL=databaseLayer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"databaseLayer.d.ts","sourceRoot":"","sources":["../src/databaseLayer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAoC,KAAK,EAAU,QAAQ,EAAY,MAAM,QAAQ,CAAC;AACrG,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAMtC,OAAO,EAAE,KAAK,sBAAsB,EAAmB,MAAM,mCAAmC,CAAC;AACjG,OAAO,EAAE,KAAK,eAAe,EAAiB,MAAM,iCAAiC,CAAC;AAEtF,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAElE,MAAM,WAAW,cAAe,SAAQ,eAAe;IACtD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,QAAQ,GAAG,gBAAgB,GAAG,mBAAmB,GAAG,QAAQ,CAAC,CAAC,CAAC;IACvH,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;CACvD;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,UAAU,ggBAqCvG"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"databaseLayer.js","sourceRoot":"","sources":["../src/databaseLayer.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export declare function redactOtlpUrl(value: string, key?: string): string;
2
- //# sourceMappingURL=redactOtlpUrl.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"redactOtlpUrl.d.ts","sourceRoot":"","sources":["../src/redactOtlpUrl.ts"],"names":[],"mappings":"AA6BA,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAK,GAAG,MAAM,CAkB7D"}
@@ -1,41 +0,0 @@
1
- import { REDACTED } from "@shivaedev/errors/sensitive.ts";
2
- function query(value) {
3
- return value
4
- .split("&")
5
- .map((part) => (part === "" ? part : `${part.split("=", 1)[0]}=${REDACTED}`))
6
- .join("&");
7
- }
8
- function url(value) {
9
- const fragment = value.indexOf("#");
10
- const target = fragment === -1 ? value : value.slice(0, fragment);
11
- const separator = target.indexOf("?");
12
- return ((separator === -1 ? target : `${target.slice(0, separator + 1)}${query(target.slice(separator + 1))}`).replaceAll(/(?<authority>(?:\b[a-z][a-z0-9+.-]*:)?\/\/)[^/?#]*@/giu, `$<authority>${REDACTED}@`) + (fragment === -1 ? "" : `#${REDACTED}`));
13
- }
14
- function structured(value) {
15
- try {
16
- return JSON.stringify(JSON.parse(value, (key, item) => (typeof item === "string" ? redactOtlpUrl(item, key) : item)));
17
- }
18
- catch {
19
- return undefined;
20
- }
21
- }
22
- export function redactOtlpUrl(value, key = "") {
23
- if (/(?:^|[._-])(?:fragment|userinfo|username|password)$/iu.test(key)) {
24
- return REDACTED;
25
- }
26
- if (/(?:^|[._-])query$/iu.test(key)) {
27
- return url(`?${value}`).slice(1);
28
- }
29
- if (/(?:^|[._-])(?:url|uri|target)(?:$|[._-])/iu.test(key) || /(?:^|[._-])(?:referer|referrer|location|origin)$/iu.test(key)) {
30
- return url(value);
31
- }
32
- if (/^\s*[[{]/u.test(value)) {
33
- const redacted = structured(value);
34
- if (redacted !== undefined) {
35
- return redacted;
36
- }
37
- }
38
- // Quotes and whitespace can belong to secret values, so free text has no safe closing delimiter.
39
- return value.replaceAll(/(?:[a-z][a-z0-9+.-]*:\/\/|[/?#]).*/gisu, url);
40
- }
41
- //# sourceMappingURL=redactOtlpUrl.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"redactOtlpUrl.js","sourceRoot":"","sources":["../src/redactOtlpUrl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAE1D,SAAS,KAAK,CAAC,KAAa;IAC3B,OAAO,KAAK;SACV,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC;SAC5E,IAAI,CAAC,GAAG,CAAC,CAAC;AACb,CAAC;AAED,SAAS,GAAG,CAAC,KAAa;IACzB,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAClE,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtC,OAAO,CACN,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,UAAU,CAChH,wDAAwD,EACxD,eAAe,QAAQ,GAAG,CAC1B,GAAG,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,CAAC,CAC3C,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAChC,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,GAAW,EAAE,IAAa,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxI,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,GAAG,GAAG,EAAE;IACpD,IAAI,uDAAuD,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACvE,OAAO,QAAQ,CAAC;IACjB,CAAC;IACD,IAAI,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACrC,OAAO,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,4CAA4C,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,oDAAoD,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9H,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;IACD,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,QAAQ,CAAC;QACjB,CAAC;IACF,CAAC;IACD,iGAAiG;IACjG,OAAO,KAAK,CAAC,UAAU,CAAC,wCAAwC,EAAE,GAAG,CAAC,CAAC;AACxE,CAAC"}
@@ -1,7 +0,0 @@
1
- import { type SchemaAST } from "effect";
2
- export declare function marked(ast: SchemaAST.AST, seen?: Set<SchemaAST.AST>): boolean;
3
- export declare function collectEncodedKeys(ast: SchemaAST.AST, keys: Set<string>): void;
4
- export declare function maskedValue(ast: SchemaAST.AST, keys: ReadonlySet<string>, seen?: Set<SchemaAST.AST>): boolean;
5
- export declare function collect(ast: SchemaAST.AST, nodes: Set<SchemaAST.AST>, encodings?: boolean): void;
6
- export declare function collectFieldKeys(properties: SchemaAST.Objects["propertySignatures"], keys: Set<string>, sensitive: (ast: SchemaAST.AST) => boolean): void;
7
- //# sourceMappingURL=schemaSensitiveAst.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schemaSensitiveAst.d.ts","sourceRoot":"","sources":["../src/schemaSensitiveAst.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AAsBnD,wBAAgB,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,IAAI,qBAA2B,GAAG,OAAO,CAenF;AAOD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,QAcvE;AAOD,wBAAgB,WAAW,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,qBAA2B,GAAG,OAAO,CAmBnH;AACD,wBAAgB,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,SAAS,UAAO,QAQtF;AAMD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,SAAS,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,KAAK,OAAO,QAMlJ"}
@@ -1,102 +0,0 @@
1
- import { Predicate } from "effect";
2
- import { isSensitiveKey } from "@shivaedev/errors/sensitive.ts";
3
- function children(ast) {
4
- switch (ast._tag) {
5
- case "Objects":
6
- return [...ast.propertySignatures.map((property) => property.type), ...ast.indexSignatures.flatMap((index) => [index.parameter, index.type])];
7
- case "Arrays":
8
- return [...ast.elements, ...ast.rest];
9
- case "Union":
10
- return ast.types;
11
- case "Declaration":
12
- return ast.typeParameters;
13
- case "Suspend":
14
- return [ast.thunk()];
15
- default:
16
- return [];
17
- }
18
- }
19
- function sensitiveCheck(check) {
20
- return check.annotations?.sensitive === true || (check._tag === "FilterGroup" && check.checks.some(sensitiveCheck));
21
- }
22
- export function marked(ast, seen = new Set()) {
23
- if (seen.has(ast)) {
24
- return false;
25
- }
26
- seen.add(ast);
27
- if (ast.annotations?.sensitive === true
28
- || ast.context?.annotations?.sensitive === true
29
- || ast.checks?.some(sensitiveCheck)
30
- || (Predicate.hasProperty(ast.annotations?.representation, "id") && ast.annotations.representation.id === "effect/schema/Redacted")) {
31
- return true;
32
- }
33
- const nested = ast._tag === "Objects" ? ast.indexSignatures.map((index) => index.type) : children(ast);
34
- return (ast.encoding?.some((link) => marked(link.to, seen)) ?? false) || nested.some((type) => marked(type, seen));
35
- }
36
- function containsSensitive(ast, keys) {
37
- return (marked(ast)
38
- || propertiesOf(ast).some((property) => typeof property.name === "string" && (keys.has(property.name) || isSensitiveKey(property.name))));
39
- }
40
- export function collectEncodedKeys(ast, keys) {
41
- let source = ast;
42
- let sensitive = false;
43
- for (const link of ast.encoding ?? []) {
44
- sensitive ||= containsSensitive(source, keys);
45
- if (sensitive) {
46
- for (const property of propertiesOf(link.to)) {
47
- if (typeof property.name === "string") {
48
- keys.add(property.name);
49
- }
50
- }
51
- }
52
- source = link.to;
53
- }
54
- }
55
- function fixedOutput(ast) {
56
- if (ast._tag === "Union") {
57
- return ast.types.every(fixedOutput);
58
- }
59
- return ast._tag === "Objects" && ast.indexSignatures.length === 0;
60
- }
61
- export function maskedValue(ast, keys, seen = new Set()) {
62
- if (seen.has(ast)) {
63
- return false;
64
- }
65
- seen.add(ast);
66
- if (marked(ast)) {
67
- return true;
68
- }
69
- let source = ast;
70
- let sensitive = false;
71
- for (const link of ast.encoding ?? []) {
72
- sensitive ||= containsSensitive(source, keys);
73
- if (sensitive && !fixedOutput(link.to)) {
74
- return true;
75
- }
76
- source = link.to;
77
- }
78
- const nested = ast._tag === "Objects" ? ast.indexSignatures.map((index) => index.type) : children(ast);
79
- return nested.some((type) => maskedValue(type, keys, seen));
80
- }
81
- export function collect(ast, nodes, encodings = true) {
82
- if (nodes.has(ast)) {
83
- return;
84
- }
85
- nodes.add(ast);
86
- for (const child of [...children(ast), ...(encodings ? (ast.encoding?.map((link) => link.to) ?? []) : [])]) {
87
- collect(child, nodes, encodings);
88
- }
89
- }
90
- function propertiesOf(ast) {
91
- const nodes = new Set();
92
- collect(ast, nodes, false);
93
- return [...nodes].flatMap((node) => (node._tag === "Objects" ? node.propertySignatures : []));
94
- }
95
- export function collectFieldKeys(properties, keys, sensitive) {
96
- for (const property of properties) {
97
- if (typeof property.name === "string" && sensitive(property.type)) {
98
- keys.add(property.name);
99
- }
100
- }
101
- }
102
- //# sourceMappingURL=schemaSensitiveAst.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schemaSensitiveAst.js","sourceRoot":"","sources":["../src/schemaSensitiveAst.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAkB,MAAM,QAAQ,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,SAAS,QAAQ,CAAC,GAAkB;IACnC,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,SAAS;YACb,OAAO,CAAC,GAAG,GAAG,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/I,KAAK,QAAQ;YACZ,OAAO,CAAC,GAAG,GAAG,CAAC,QAAQ,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;QACvC,KAAK,OAAO;YACX,OAAO,GAAG,CAAC,KAAK,CAAC;QAClB,KAAK,aAAa;YACjB,OAAO,GAAG,CAAC,cAAc,CAAC;QAC3B,KAAK,SAAS;YACb,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;QACtB;YACC,OAAO,EAAE,CAAC;IACZ,CAAC;AACF,CAAC;AACD,SAAS,cAAc,CAAC,KAA6B;IACpD,OAAO,KAAK,CAAC,WAAW,EAAE,SAAS,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;AACrH,CAAC;AACD,MAAM,UAAU,MAAM,CAAC,GAAkB,EAAE,IAAI,GAAG,IAAI,GAAG,EAAiB;IACzE,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACd,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACd,IACC,GAAG,CAAC,WAAW,EAAE,SAAS,KAAK,IAAI;WAChC,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,KAAK,IAAI;WAC5C,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,CAAC;WAChC,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE,cAAc,EAAE,IAAI,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,KAAK,wBAAwB,CAAC,EAClI,CAAC;QACF,OAAO,IAAI,CAAC;IACb,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACvG,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AACpH,CAAC;AACD,SAAS,iBAAiB,CAAC,GAAkB,EAAE,IAAyB;IACvE,OAAO,CACN,MAAM,CAAC,GAAG,CAAC;WACR,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CACxI,CAAC;AACH,CAAC;AACD,MAAM,UAAU,kBAAkB,CAAC,GAAkB,EAAE,IAAiB;IACvE,IAAI,MAAM,GAAG,GAAG,CAAC;IACjB,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACvC,SAAS,KAAK,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC9C,IAAI,SAAS,EAAE,CAAC;YACf,KAAK,MAAM,QAAQ,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC9C,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACvC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACzB,CAAC;YACF,CAAC;QACF,CAAC;QACD,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAClB,CAAC;AACF,CAAC;AACD,SAAS,WAAW,CAAC,GAAkB;IACtC,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC1B,OAAO,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,CAAC;AACnE,CAAC;AACD,MAAM,UAAU,WAAW,CAAC,GAAkB,EAAE,IAAyB,EAAE,IAAI,GAAG,IAAI,GAAG,EAAiB;IACzG,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACd,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACd,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC;IACb,CAAC;IACD,IAAI,MAAM,GAAG,GAAG,CAAC;IACjB,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACvC,SAAS,KAAK,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC9C,IAAI,SAAS,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC;QACb,CAAC;QACD,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAClB,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACvG,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAC7D,CAAC;AACD,MAAM,UAAU,OAAO,CAAC,GAAkB,EAAE,KAAyB,EAAE,SAAS,GAAG,IAAI;IACtF,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO;IACR,CAAC;IACD,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAC5G,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IAClC,CAAC;AACF,CAAC;AACD,SAAS,YAAY,CAAC,GAAkB;IACvC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAiB,CAAC;IACvC,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3B,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/F,CAAC;AACD,MAAM,UAAU,gBAAgB,CAAC,UAAmD,EAAE,IAAiB,EAAE,SAA0C;IAClJ,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACnE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;IACF,CAAC;AACF,CAAC"}
@@ -1,6 +0,0 @@
1
- import { Rpc, type RpcGroup } from "effect/rpc";
2
- export declare function schemaSensitiveKeys<R extends Rpc.Any>(group: RpcGroup.RpcGroup<R>, extra?: readonly string[]): ((key: string) => boolean) & {
3
- forRpc: (tag: string | undefined) => (key: string) => boolean;
4
- maskFailure: (tag: string | undefined, reason: "Fail" | "Die") => boolean;
5
- };
6
- //# sourceMappingURL=schemaSensitiveKeys.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schemaSensitiveKeys.d.ts","sourceRoot":"","sources":["../src/schemaSensitiveKeys.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAgChD,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,GAAE,SAAS,MAAM,EAAO,UAOxF,MAAM;kBAIf,MAAM,GAAG,SAAS,WAJT,MAAM;uBAKV,MAAM,GAAG,SAAS,UAAU,MAAM,GAAG,KAAK;EAG9D"}
@@ -1,47 +0,0 @@
1
- import { Rpc } from "effect/rpc";
2
- import { isSensitiveKey } from "@shivaedev/errors/sensitive.ts";
3
- import { collect, collectEncodedKeys, collectFieldKeys, marked, maskedValue } from "#schemaSensitiveAst.ts";
4
- function rpcSensitiveKeys(rpc, extra) {
5
- const keys = new Set(extra);
6
- const nodes = new Set();
7
- const schemas = [
8
- rpc.payloadSchema,
9
- rpc.successSchema,
10
- rpc.errorSchema,
11
- rpc.defectSchema,
12
- ...[...rpc.middlewares].map((m) => m.error),
13
- ];
14
- for (const schema of schemas) {
15
- collect(schema.ast, nodes);
16
- }
17
- const properties = [...nodes].flatMap((ast) => (ast._tag === "Objects" ? ast.propertySignatures : []));
18
- collectFieldKeys(properties, keys, marked);
19
- let previousSize;
20
- do {
21
- previousSize = keys.size;
22
- collectFieldKeys(properties, keys, (ast) => maskedValue(ast, keys));
23
- for (const ast of nodes) {
24
- collectEncodedKeys(ast, keys);
25
- }
26
- } while (keys.size !== previousSize);
27
- return Object.assign((key) => keys.has(key) || isSensitiveKey(key), {
28
- die: maskedValue(rpc.defectSchema.ast, keys),
29
- fail: [rpc.errorSchema, ...[...rpc.middlewares].map((m) => m.error)].some((schema) => maskedValue(schema.ast, keys)),
30
- });
31
- }
32
- export function schemaSensitiveKeys(group, extra = []) {
33
- const policies = new Map();
34
- for (const rpc of group.requests.values()) {
35
- if (Rpc.isRpc(rpc)) {
36
- policies.set(rpc._tag, rpcSensitiveKeys(rpc, extra));
37
- }
38
- }
39
- function sensitive(key) {
40
- return extra.includes(key) || isSensitiveKey(key) || [...policies.values()].some((policy) => policy(key));
41
- }
42
- return Object.assign(sensitive, {
43
- forRpc: (tag) => (tag === undefined ? sensitive : (policies.get(tag) ?? sensitive)),
44
- maskFailure: (tag, reason) => [...policies].some(([method, policy]) => (tag === undefined || tag === method) && (reason === "Fail" ? policy.fail : policy.die)),
45
- });
46
- }
47
- //# sourceMappingURL=schemaSensitiveKeys.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schemaSensitiveKeys.js","sourceRoot":"","sources":["../src/schemaSensitiveKeys.ts"],"names":[],"mappings":"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"}