@shivaedev/server 0.5.0 → 0.6.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"databaseLayer.d.ts","sourceRoot":"","sources":["../src/databaseLayer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,MAAM,EAA2B,KAAK,EAAE,QAAQ,EAAY,MAAM,QAAQ,CAAC;AACpF,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAG3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAIzE,OAAO,EAAE,KAAK,sBAAsB,EAAmB,MAAM,mCAAmC,CAAC;AAEjG,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGlE,MAAM,WAAW,cAAe,SAAQ,iBAAiB;IACxD,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,UAAU,+UAmDjG"}
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,44 +1,18 @@
1
1
  import { createHash } from "node:crypto";
2
- import { createConnection } from "node:net";
3
2
  import * as PgClient from "@effect/sql-pg/PgClient";
4
- import { Config, Duration, Effect, Fiber, Layer, Redacted, Schedule } from "effect";
3
+ import { Config, Context, Duration, Effect, Fiber, Layer, Option, Redacted, Schedule } from "effect";
5
4
  import * as Reactivity from "effect/reactivity/Reactivity";
5
+ import { Migrator } from "effect/sql";
6
6
  import { makeLiveServer } from "@shivaedev/contract/makeLiveServer.ts";
7
7
  import { assertPostgresMigrations, postgresMigrationError } from "@shivaedev/sql/assertPostgresMigrations.ts";
8
8
  import { coordinateWorkerRelease } from "@shivaedev/sql/coordinateWorkerRelease.ts";
9
9
  import { migratePostgres } from "@shivaedev/sql/migrations.ts";
10
10
  import { pendingPostgresMigrations } from "@shivaedev/sql/pendingPostgresMigrations.ts";
11
11
  import { postgresChanges } from "@shivaedev/sql/postgresChanges.ts";
12
+ import { postgresLayer } from "@shivaedev/sql/postgresLayer.ts";
12
13
  import { WorkerRelease } from "@shivaedev/sql/WorkerRelease.ts";
13
- import { databaseAddress } from "./databaseAddress.js";
14
14
  export function databaseLayer(options, changesService) {
15
- const pool = Layer.unwrap(Effect.gen(function* () {
16
- const url = options.config?.databaseUrl ?? (yield* Config.Redacted("DATABASE_URL"));
17
- const address = databaseAddress(url);
18
- const disconnected = new Set();
19
- // Native pool shutdown sends Terminate without waiting for its sockets to close.
20
- yield* Effect.addFinalizer(() => Effect.promise(() => Promise.all([...disconnected])));
21
- return PgClient.layer({
22
- stream: () => {
23
- const target = new URL(Redacted.value(url));
24
- const host = address.host ?? target.searchParams.getAll("host").at(-1) ?? (decodeURIComponent(target.hostname) || "localhost");
25
- const port = address.port ?? 5432;
26
- const socket = createConnection(host.startsWith("/") ? { path: `${host}/.s.PGSQL.${port}` } : { host, noDelay: true, port });
27
- const closed = new Promise((resolve) => socket.once("close", () => {
28
- disconnected.delete(closed);
29
- resolve();
30
- }));
31
- disconnected.add(closed);
32
- return socket;
33
- },
34
- transformQueryNames: options.config?.transformQueryNames,
35
- transformResultNames: options.config?.transformResultNames,
36
- url,
37
- ...address,
38
- ...(options.config?.maxConnections === undefined ? {} : { maxConnections: options.config.maxConnections }),
39
- ...(options.config?.applicationName === undefined ? {} : { applicationName: options.config.applicationName }),
40
- });
41
- }));
15
+ const pool = Layer.unwrap(Effect.map(options.config?.databaseUrl === undefined ? Config.Redacted("DATABASE_URL") : Effect.succeed(options.config.databaseUrl), (url) => postgresLayer(url, options.config)));
42
16
  const prepared = Layer.effectDiscard(prepareMigrations(options.migrations)).pipe(Layer.provideMerge(pool));
43
17
  const live = Layer.effect(changesService, makeLiveServer).pipe(Layer.provideMerge(Reactivity.layer));
44
18
  const migrations = options.migrations;
@@ -53,7 +27,15 @@ export function databaseLayer(options, changesService) {
53
27
  const url = options.config?.databaseUrl ?? (yield* Config.Redacted("DATABASE_URL"));
54
28
  const name = yield* Config.String("APP_NAME").pipe(Config.withDefault(new URL(Redacted.value(url)).pathname));
55
29
  const channel = changes?.channel ?? `changes_${createHash("sha256").update(name).digest("hex").slice(0, 32)}`;
56
- return postgresChanges({ ...changes, channel, client, resync: hints.resync });
30
+ const listenUrl = options.config?.listenDatabaseUrl ?? Option.getOrUndefined(yield* Config.Redacted("LISTEN_DATABASE_URL").pipe(Config.option));
31
+ const listenerClient = listenUrl === undefined
32
+ ? client
33
+ : yield* Effect.map(Layer.build(postgresLayer(listenUrl, { applicationName: options.config?.applicationName, maxConnections: 1 })), (context) => Context.get(context, PgClient.PgClient));
34
+ let connectionSetting = options.config?.databaseUrl === undefined ? "DATABASE_URL" : "config.databaseUrl";
35
+ if (listenUrl !== undefined) {
36
+ connectionSetting = options.config?.listenDatabaseUrl === undefined ? "LISTEN_DATABASE_URL" : "config.listenDatabaseUrl";
37
+ }
38
+ return postgresChanges({ ...changes, channel, client, connectionSetting, listenerClient, resync: hints.resync });
57
39
  })).pipe(Layer.provideMerge(base));
58
40
  }
59
41
  function prepareMigrations(migrations) {
@@ -89,8 +71,8 @@ function waitForMigrations(migrations) {
89
71
  return yield* Effect.fail(postgresMigrationError(pending));
90
72
  }).pipe(Effect.retry({
91
73
  schedule: Schedule.max([Schedule.spaced(migrations.pollInterval ?? "1 second"), Schedule.during(migrations.waitTimeout ?? "5 minutes")]),
92
- while: (error) => error._tag === "MigrationError" && error.kind === "BadState",
93
- }), Effect.tapError((error) => error._tag === "MigrationError" && error.kind === "BadState" ? log("Timed out waiting for database migrations") : Effect.void));
74
+ while: (error) => error instanceof Migrator.MigrationError && error.kind === "BadState",
75
+ }), Effect.tapError((error) => error instanceof Migrator.MigrationError && error.kind === "BadState" ? log("Timed out waiting for database migrations") : Effect.void));
94
76
  if (progress !== undefined) {
95
77
  yield* Fiber.interrupt(progress);
96
78
  yield* Effect.logInfo("Database migrations current");
@@ -1 +1 @@
1
- {"version":3,"file":"databaseLayer.js","sourceRoot":"","sources":["../src/databaseLayer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"databaseLayer.js","sourceRoot":"","sources":["../src/databaseLayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACrG,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AAC9G,OAAO,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAkC,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AACxH,OAAO,EAA+B,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACjG,OAAO,EAAwB,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAShE,MAAM,UAAU,aAAa,CAAO,OAAiC,EAAE,cAAiC;IACvG,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CACxB,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAC5I,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAClC,CACD,CAAC;IACF,MAAM,QAAQ,GAAG,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3G,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IACrG,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IACtC,MAAM,MAAM,GACX,UAAU,CAAC,IAAI,KAAK,MAAM,IAAI,UAAU,CAAC,OAAO,KAAK,SAAS;QAC7D,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,uBAAuB,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,YAAY,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;QACrH,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC;IAChB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC1E,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;IACxC,OAAO,KAAK,CAAC,MAAM,CAClB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACnB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACxC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,cAAc,CAAC;QACpC,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,WAAW,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;QACpF,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC9G,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,WAAW,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QAC9G,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,iBAAiB,IAAI,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAChJ,MAAM,cAAc,GACnB,SAAS,KAAK,SAAS;YACtB,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CACjB,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,eAAe,EAAE,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC,EAC9G,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,CACpD,CAAC;QACL,IAAI,iBAAiB,GAAG,OAAO,CAAC,MAAM,EAAE,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,oBAAoB,CAAC;QAC1G,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC7B,iBAAiB,GAAG,OAAO,CAAC,MAAM,EAAE,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,0BAA0B,CAAC;QAC1H,CAAC;QACD,OAAO,eAAe,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAClH,CAAC,CAAC,CACF,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,iBAAiB,CAAO,UAAkD;IAClF,QAAQ,UAAU,CAAC,IAAI,EAAE,CAAC;QACzB,KAAK,OAAO,EAAE,CAAC;YACd,MAAM,MAAM,GAAG,EAAE,GAAG,UAAU,EAAE,CAAC;YACjC,OAAO,MAAM,CAAC,OAAO,CAAC;YACtB,OAAO,wBAAwB,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC;QACD,KAAK,MAAM;YACV,OAAO,iBAAiB,CAAC,UAAU,CAAC,CAAC;QACtC;YACC,OAAO,eAAe,CAAC,EAAE,GAAG,UAAU,EAAE,WAAW,EAAE,UAAU,CAAC,WAAW,IAAI,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpH,CAAC;AACF,CAAC;AAED,SAAS,iBAAiB,CAAO,UAAkD;IAClF,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC1B,MAAM,gBAAgB,GAAG,QAAQ,CAAC,eAAe,CAAC,UAAU,CAAC,gBAAgB,IAAI,YAAY,CAAC,CAAC;QAC/F,IAAI,OAAO,GAA8B,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;QAC5E,IAAI,QAAwC,CAAC;QAC7C,SAAS,GAAG,CAAC,OAAe;YAC3B,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAC1B,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,UAAU,EAAE,iBAAiB,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CACnI,CAAC;QACH,CAAC;QACD,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC1B,OAAO,GAAG,KAAK,CAAC,CAAC,yBAAyB,CAAC,UAAU,CAAC,CAAC;YACvD,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxE,OAAO;YACR,CAAC;YACD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC5B,KAAK,CAAC,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;gBAC9C,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACvI,MAAM,CAAC,UAAU,CACjB,CAAC;YACH,CAAC;YACD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC,IAAI,CACN,MAAM,CAAC,KAAK,CAAC;YACZ,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,YAAY,IAAI,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,IAAI,WAAW,CAAC,CAAC,CAAC;YACxI,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,YAAY,QAAQ,CAAC,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;SACvF,CAAC,EACF,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CACzB,KAAK,YAAY,QAAQ,CAAC,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CACtI,CACD,CAAC;QACF,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC5B,KAAK,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YACjC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC;QACtD,CAAC;IACF,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { Layer } from "effect";
2
2
  import type { Rpc, RpcGroup } from "effect/rpc";
3
- import { type SessionPolicy, type SessionShape } from "@shivaedev/identity/server/session.ts";
3
+ import type { SessionPolicy, SessionShape } from "@shivaedev/identity/server/session.ts";
4
4
  import type { AppChanges } from "./appHost.ts";
5
5
  export declare function hostChanges<R extends Rpc.Any, TSession extends SessionShape>(group: RpcGroup.RpcGroup<R>, changesService: typeof AppChanges, sessions?: SessionPolicy<TSession>): Layer.Layer<Rpc.ToHandler<Extract<R, {
6
6
  readonly _tag: `${string}.$changes`;
@@ -1 +1 @@
1
- {"version":3,"file":"hostChanges.d.ts","sourceRoot":"","sources":["../src/hostChanges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,EAAkB,MAAM,QAAQ,CAAC;AAEhE,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAIhD,OAAO,EAAkB,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAE9G,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,wBAAgB,WAAW,CAAC,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE,QAAQ,SAAS,YAAY,EAC3E,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAC3B,cAAc,EAAE,OAAO,UAAU,EACjC,QAAQ,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC;mBAsCoC,GAAG,MAAM,WAAW;mBAG1F"}
1
+ {"version":3,"file":"hostChanges.d.ts","sourceRoot":"","sources":["../src/hostChanges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,EAAkB,MAAM,QAAQ,CAAC;AAEhE,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAKhD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAGzF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,wBAAgB,WAAW,CAAC,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE,QAAQ,SAAS,YAAY,EAC3E,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAC3B,cAAc,EAAE,OAAO,UAAU,EACjC,QAAQ,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC;mBAsCoC,GAAG,MAAM,WAAW;mBAG1F"}
@@ -2,8 +2,9 @@ import { Context, Effect, Layer, Option, Stream } from "effect";
2
2
  import { Headers } from "effect/http";
3
3
  import { CurrentViewer } from "@shivaedev/contract/readPolicy.ts";
4
4
  import { Unauthorized } from "@shivaedev/errors/taxonomy.ts";
5
- import { resolveSession } from "@shivaedev/identity/server/session.ts";
5
+ import { recheckSession } from "@shivaedev/identity/server/recheckSession.ts";
6
6
  import { resolveChanges } from "@shivaedev/identity/server/sessionKeys.ts";
7
+ import { revalidateSession } from "@shivaedev/identity/server/socketSession.ts";
7
8
  export function hostChanges(group, changesService, sessions) {
8
9
  return Layer.effectContext(Effect.gen(function* () {
9
10
  const changes = yield* Effect.serviceOption(changesService);
@@ -45,15 +46,14 @@ function authorizeSession(sessions, tag, viewer, policy) {
45
46
  if (sessions === undefined) {
46
47
  return policy;
47
48
  }
48
- return resolveSession(sessions, Headers.empty, tag).pipe(Effect.map((current) => Option.isNone(viewer) || (Option.isSome(current) && current.value.user.id === viewer.value.id)), Effect.catch(() => Effect.succeed(false)), Effect.flatMap((allowed) => (allowed ? policy : Effect.succeed(false))));
49
+ return recheckSession(sessions, Headers.empty, tag).pipe(Effect.map((current) => Option.isNone(viewer) || (Option.isSome(current) && current.value.user.id === viewer.value.id)), Effect.catch(() => Effect.succeed(false)), Effect.flatMap((allowed) => (allowed ? policy : Effect.succeed(false))));
49
50
  }
50
51
  function sessionRevoked(sessions, tag, id) {
51
52
  return Effect.gen(function* () {
52
- yield* Effect.sleep(sessions.streamRevalidationInterval ?? "30 seconds");
53
- const current = yield* resolveSession(sessions, Headers.empty, tag).pipe(Effect.catchTag("AuthUnavailable", () => Effect.succeed(undefined)));
53
+ const current = yield* recheckSession(sessions, Headers.empty, tag).pipe(Effect.catchTag("AuthUnavailable", () => Effect.succeed(undefined)));
54
54
  if (current !== undefined && (Option.isNone(current) || current.value.user.id !== id)) {
55
55
  return yield* new Unauthorized({ message: "Authentication required" });
56
56
  }
57
- }).pipe(Effect.forever);
57
+ }).pipe((check) => revalidateSession(check, sessions.streamRevalidationInterval ?? "30 seconds"));
58
58
  }
59
59
  //# sourceMappingURL=hostChanges.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hostChanges.js","sourceRoot":"","sources":["../src/hostChanges.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hostChanges.js","sourceRoot":"","sources":["../src/hostChanges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAe,MAAM,mCAAmC,CAAC;AAE/E,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AAE9E,OAAO,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAGhF,MAAM,UAAU,WAAW,CAC1B,KAA2B,EAC3B,cAAiC,EACjC,QAAkC;IAElC,OAAO,KAAK,CAAC,aAAa,CACzB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACnB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,EAAS,CAAC;QAChD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAmB,CAAC;QAC5C,SAAS,SAAS,CAAC,GAAY,EAAE,OAAkC;YAClE,OAAO,MAAM,CAAC,MAAM,CACnB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBACnB,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;gBACtE,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,aAAa,CAAC;gBACpC,MAAM,UAAU,GAAG,gBAAgB,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;gBACzF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;oBACpC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,GAAG,YAAY,EAAE,UAAU,EAAE,EAAE,OAAO,CAAC;oBACnE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAW,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC5E,IAAI,QAAQ,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;oBACrD,OAAO,MAAM,CAAC;gBACf,CAAC;gBACD,OAAO,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,cAAc,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1F,CAAC,CAAC,CACF,CAAC;QACH,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBACrC,SAAS;YACV,CAAC;YACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACjD,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACtD,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;gBAChC,SAAS;YACV,CAAC;YACD,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE;gBACrB,OAAO,EAAE,QAAQ;gBACjB,OAAO,EAAE,CAAC,EAAE,OAAO,EAAmD,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC;gBAClG,GAAG,EAAE,GAAG,CAAC,IAAI;aACb,CAAC,CAAC;QACJ,CAAC;QACD,OAAO,OAAO,CAAC,UAAU,CAAqE,QAAQ,CAAC,CAAC;IACzG,CAAC,CAAC,CACF,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CACxB,QAA6C,EAC7C,GAAW,EACX,MAA6B,EAC7B,MAA8B;IAE9B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,MAAM,CAAC;IACf,CAAC;IACD,OAAO,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,CACvD,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EACvH,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EACzC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CACvE,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAgC,QAAiC,EAAE,GAAW,EAAE,EAAU;IAChH,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC1B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC9I,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YACvF,OAAO,KAAK,CAAC,CAAC,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC,CAAC;QACxE,CAAC;IACF,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,0BAA0B,IAAI,YAAY,CAAC,CAAC,CAAC;AACnG,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"socketRpc.d.ts","sourceRoot":"","sources":["../src/socketRpc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAW,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAG7E,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAC1F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,wBAAgB,SAAS,CAAC,QAAQ,SAAS,YAAY,EACtD,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,KAAK,EAAE,iBAAiB,CAAC,iBAAiB,GAAG,KAAK,CAAC,KAAK,CAAC,EACvH,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,EAC5B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,aAAa,EAAE,SAAS,MAAM,EAAE,kHAiBhC"}
1
+ {"version":3,"file":"socketRpc.d.ts","sourceRoot":"","sources":["../src/socketRpc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAW,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAG7E,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAE1F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,wBAAgB,SAAS,CAAC,QAAQ,SAAS,YAAY,EACtD,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,KAAK,EAAE,iBAAiB,CAAC,iBAAiB,GAAG,KAAK,CAAC,KAAK,CAAC,EACvH,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,EAC5B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,aAAa,EAAE,SAAS,MAAM,EAAE,kHAmBhC"}
package/dist/socketRpc.js CHANGED
@@ -3,6 +3,7 @@ import { Headers, HttpServerRequest, HttpServerResponse } from "effect/http";
3
3
  import * as HttpStatus from "effect/http/HttpStatus";
4
4
  import { localTransport } from "@shivaedev/identity/server/local.ts";
5
5
  import { resolveSession } from "@shivaedev/identity/server/session.ts";
6
+ import { makeSocketSession, SocketSession } from "@shivaedev/identity/server/socketSession.ts";
6
7
  export function socketRpc(handler, policy, trustedProxy, nativeOrigins) {
7
8
  return Effect.gen(function* () {
8
9
  const request = yield* HttpServerRequest.HttpServerRequest;
@@ -11,6 +12,8 @@ export function socketRpc(handler, policy, trustedProxy, nativeOrigins) {
11
12
  }
12
13
  if (policy.policy !== "loopback") {
13
14
  yield* resolveSession(policy.sessions, Headers.empty, "$connect");
15
+ const session = yield* makeSocketSession(policy.sessions.streamRevalidationInterval ?? "30 seconds");
16
+ return yield* Effect.provideService(handler, SocketSession, session);
14
17
  }
15
18
  return yield* handler;
16
19
  }).pipe(Effect.catchTags({
@@ -1 +1 @@
1
- {"version":3,"file":"socketRpc.js","sourceRoot":"","sources":["../src/socketRpc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAqB,MAAM,uCAAuC,CAAC;AAG1F,MAAM,UAAU,SAAS,CACxB,OAAuH,EACvH,MAA4B,EAC5B,YAAgC,EAChC,aAAgC;IAEhC,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC1B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,iBAAiB,CAAC;QAC3D,IAAI,CAAC,cAAc,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3D,OAAO,kBAAkB,CAAC,IAAI,CAAC,iCAAiC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACpH,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAClC,KAAK,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC;IACvB,CAAC,CAAC,CAAC,IAAI,CACN,MAAM,CAAC,SAAS,CAAC;QAChB,eAAe,EAAE,eAAe;QAChC,SAAS,EAAE,SAAS;KACpB,CAAC,CACF,CAAC;AACH,CAAC;AAED,SAAS,eAAe;IACvB,OAAO,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3G,CAAC;AACD,SAAS,SAAS;IACjB,OAAO,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;AAClG,CAAC"}
1
+ {"version":3,"file":"socketRpc.js","sourceRoot":"","sources":["../src/socketRpc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAqB,MAAM,uCAAuC,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AAG/F,MAAM,UAAU,SAAS,CACxB,OAAuH,EACvH,MAA4B,EAC5B,YAAgC,EAChC,aAAgC;IAEhC,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC1B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,iBAAiB,CAAC;QAC3D,IAAI,CAAC,cAAc,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3D,OAAO,kBAAkB,CAAC,IAAI,CAAC,iCAAiC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACpH,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAClC,KAAK,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YAClE,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,0BAA0B,IAAI,YAAY,CAAC,CAAC;YACrG,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC;IACvB,CAAC,CAAC,CAAC,IAAI,CACN,MAAM,CAAC,SAAS,CAAC;QAChB,eAAe,EAAE,eAAe;QAChC,SAAS,EAAE,SAAS;KACpB,CAAC,CACF,CAAC;AACH,CAAC;AAED,SAAS,eAAe;IACvB,OAAO,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3G,CAAC;AACD,SAAS,SAAS;IACjB,OAAO,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;AAClG,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/server",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "description": "The Effect application host: HTTP and RPC serving, health, OTLP export, database and migrations, and development mode",
5
5
  "keywords": [
6
6
  "effect"
@@ -45,22 +45,22 @@
45
45
  ],
46
46
  "dependencies": {
47
47
  "@shivaedev/changes": "0.5.1",
48
- "@shivaedev/contract": "0.21.0",
49
- "@shivaedev/errors": "0.1.1",
50
- "@shivaedev/http": "0.2.0",
51
- "@shivaedev/identity": "0.4.0",
48
+ "@shivaedev/contract": "0.22.0",
49
+ "@shivaedev/errors": "0.1.2",
50
+ "@shivaedev/http": "0.3.0",
51
+ "@shivaedev/identity": "0.5.1",
52
52
  "@shivaedev/local-postgres": "0.7.0",
53
- "@shivaedev/sql": "0.25.0"
53
+ "@shivaedev/sql": "0.26.1"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@effect/platform-node": "4.0.6",
57
57
  "@effect/sql-pg": "4.0.6",
58
58
  "@effect/vitest": "4.0.6",
59
- "@shivaedev/jobs": "0.22.1",
60
- "@shivaedev/quality": "0.45.0",
61
- "@shivaedev/test": "0.10.1",
62
- "@shivaedev/test-sql": "0.11.0",
63
- "@shivaedev/test-story": "0.24.0",
59
+ "@shivaedev/jobs": "0.23.1",
60
+ "@shivaedev/quality": "0.47.0",
61
+ "@shivaedev/test": "0.11.0",
62
+ "@shivaedev/test-sql": "0.13.0",
63
+ "@shivaedev/test-story": "0.25.1",
64
64
  "@types/node": "24.19.2",
65
65
  "@types/pg": "8.20.0",
66
66
  "better-auth": "1.7.12",
@@ -30,6 +30,7 @@ export interface AppHostFactory {
30
30
  TPreflightRequirements = never,
31
31
  TRouteError = never,
32
32
  TRouteRequirements = HostRouteRequirements,
33
+ TMigrationError = never,
33
34
  >(
34
35
  options: AppHostInput<
35
36
  TRpcs,
@@ -47,8 +48,9 @@ export interface AppHostFactory {
47
48
  TPreflightError,
48
49
  TPreflightRequirements,
49
50
  TRouteError,
50
- TRouteRequirements
51
- > & { readonly migrations: AppDatabaseOptions<TMigrations>["migrations"] },
51
+ TRouteRequirements,
52
+ TMigrationError
53
+ > & { readonly migrations: AppDatabaseOptions<TMigrations, TMigrationError>["migrations"] },
52
54
  ): PreflightHost<
53
55
  ReturnType<
54
56
  typeof deferredHost<
@@ -64,7 +66,8 @@ export interface AppHostFactory {
64
66
  TApplicationError,
65
67
  TApplicationRequirements,
66
68
  TRouteError,
67
- TRouteRequirements
69
+ TRouteRequirements,
70
+ TMigrationError
68
71
  >
69
72
  >,
70
73
  NoInfer<TPreflight>,
@@ -25,9 +25,10 @@ export type AppHostInput<
25
25
  TPreflightRequirements = never,
26
26
  TRouteError = never,
27
27
  TRouteRequirements = HostRouteRequirements,
28
+ TMigrationError = never,
28
29
  > = HostPreflight<TPreflight, TPreflightError, TPreflightRequirements> &
29
30
  (
30
- | (AppDatabaseOptions<TMigrations> & {
31
+ | (AppDatabaseOptions<TMigrations, TMigrationError> & {
31
32
  readonly application: Effect.Effect<
32
33
  AppHttpHostOptions<
33
34
  TRpcs,
@@ -62,7 +63,8 @@ export type AppHostInput<
62
63
  TPreflightError,
63
64
  TPreflightRequirements,
64
65
  TRouteError,
65
- TRouteRequirements
66
+ TRouteRequirements,
67
+ TMigrationError
66
68
  >
67
69
  | AppLocalHostOptions<
68
70
  TRpcs,
@@ -77,7 +79,8 @@ export type AppHostInput<
77
79
  TPreflightError,
78
80
  TPreflightRequirements,
79
81
  TRouteError,
80
- TRouteRequirements
82
+ TRouteRequirements,
83
+ TMigrationError
81
84
  >
82
85
  | AppHttpHostOptions<
83
86
  TRpcs,
@@ -2,8 +2,8 @@ import type { Duration } from "effect";
2
2
  import type { Migrator } from "effect/sql";
3
3
  import type { SchemaComponent } from "@shivaedev/sql/SchemaComponent.ts";
4
4
 
5
- export interface MigrationOptions<R = never> {
6
- readonly components?: readonly SchemaComponent<R>[];
5
+ export interface MigrationOptions<R = never, E = never> {
6
+ readonly components?: readonly SchemaComponent<R, E>[];
7
7
  readonly loader: Migrator.Loader<R>;
8
8
  readonly lockTimeout?: Duration.Input;
9
9
  readonly mode?: "migrate" | "check" | "wait";
package/src/appHost.ts CHANGED
@@ -11,12 +11,12 @@ import type { HostCoreOptions, HostPolicy, HostRouteRequirements, HostRoutes } f
11
11
  import type { MigrationOptions } from "#MigrationOptions.ts";
12
12
 
13
13
  export class AppChanges extends Context.Service<AppChanges, Effect.Success<typeof makeLiveServer>>()("@shivaedev/server/AppChanges") {}
14
- export interface AppDatabaseOptions<R = never> {
14
+ export interface AppDatabaseOptions<R = never, E = never> {
15
15
  readonly config?: DatabaseConfig;
16
- readonly migrations: MigrationOptions<R>;
16
+ readonly migrations: MigrationOptions<R, E>;
17
17
  }
18
18
 
19
- export function appDatabase<R>(options: AppDatabaseOptions<R>) {
19
+ export function appDatabase<R, E = never>(options: AppDatabaseOptions<R, E>) {
20
20
  return databaseLayer(options, AppChanges);
21
21
  }
22
22
 
@@ -35,10 +35,11 @@ export type AppHostOptions<
35
35
  TPreflightRequirements = never,
36
36
  TRouteError = never,
37
37
  TRouteRequirements = HostRouteRequirements,
38
+ TMigrationError = never,
38
39
  > = HostPreflight<TPreflight, TPreflightError, TPreflightRequirements> &
39
40
  HostCoreOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements> &
40
41
  HostRoutes<TRouteError, TRouteRequirements> & {
41
- readonly migrations: AppDatabaseOptions<TMigrations>["migrations"];
42
+ readonly migrations: AppDatabaseOptions<TMigrations, TMigrationError>["migrations"];
42
43
  readonly policy?: undefined;
43
44
  readonly sessions: SessionPolicy<TSession>;
44
45
  };
@@ -57,10 +58,11 @@ export type AppLocalHostOptions<
57
58
  TPreflightRequirements = never,
58
59
  TRouteError = never,
59
60
  TRouteRequirements = HostRouteRequirements,
61
+ TMigrationError = never,
60
62
  > = HostPreflight<TPreflight, TPreflightError, TPreflightRequirements> &
61
63
  HostCoreOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements> &
62
64
  HostRoutes<TRouteError, TRouteRequirements> & {
63
- readonly migrations: AppDatabaseOptions<TMigrations>["migrations"];
65
+ readonly migrations: AppDatabaseOptions<TMigrations, TMigrationError>["migrations"];
64
66
  readonly policy: "loopback";
65
67
  readonly sessions?: never;
66
68
  };
@@ -100,6 +102,7 @@ export const appHost: AppHostFactory = <
100
102
  TPreflightRequirements = never,
101
103
  TRouteError = never,
102
104
  TRouteRequirements = HostRouteRequirements,
105
+ TMigrationError = never,
103
106
  >(
104
107
  options: AppHostInput<
105
108
  TRpcs,
@@ -117,7 +120,8 @@ export const appHost: AppHostFactory = <
117
120
  TPreflightError,
118
121
  TPreflightRequirements,
119
122
  TRouteError,
120
- TRouteRequirements
123
+ TRouteRequirements,
124
+ TMigrationError
121
125
  >,
122
126
  ) => {
123
127
  if ("application" in options) {
@@ -82,6 +82,7 @@ export function migratedHost<
82
82
  TSession extends SessionShape,
83
83
  TRouteError = never,
84
84
  TRouteRequirements = HostRouteRequirements,
85
+ TMigrationError = never,
85
86
  >(
86
87
  options: HostOptions<
87
88
  TRpcs,
@@ -95,9 +96,9 @@ export function migratedHost<
95
96
  TRouteRequirements
96
97
  > &
97
98
  HostPolicy<TSession> & {
98
- readonly migrations: MigrationOptions<TMigrations>;
99
+ readonly migrations: MigrationOptions<TMigrations, TMigrationError>;
99
100
  },
100
- database: ReturnType<typeof databaseLayer<TMigrations>>,
101
+ database: ReturnType<typeof databaseLayer<TMigrations, TMigrationError>>,
101
102
  changesService: typeof AppChanges,
102
103
  ) {
103
104
  const services = Layer.mergeAll(options.services ?? Layer.empty);
@@ -118,6 +119,7 @@ export function deferredHost<
118
119
  TApplicationRequirements,
119
120
  TRouteError = never,
120
121
  TRouteRequirements = HostRouteRequirements,
122
+ TMigrationError = never,
121
123
  >(
122
124
  application: Effect.Effect<
123
125
  AppHttpHostOptions<
@@ -138,7 +140,7 @@ export function deferredHost<
138
140
  TApplicationError,
139
141
  TApplicationRequirements
140
142
  >,
141
- database: ReturnType<typeof databaseLayer<TMigrations>>,
143
+ database: ReturnType<typeof databaseLayer<TMigrations, TMigrationError>>,
142
144
  changesService: typeof AppChanges,
143
145
  ) {
144
146
  return Layer.unwrap(Effect.map(application, (options) => appHostHttp(options, changesService))).pipe(Layer.provideMerge(database));
@@ -1,57 +1,29 @@
1
1
  import { createHash } from "node:crypto";
2
- import { createConnection } from "node:net";
3
2
  import * as PgClient from "@effect/sql-pg/PgClient";
4
- import { Config, Duration, Effect, Fiber, Layer, Redacted, Schedule } from "effect";
3
+ import { Config, Context, Duration, Effect, Fiber, Layer, Option, Redacted, Schedule } from "effect";
5
4
  import * as Reactivity from "effect/reactivity/Reactivity";
5
+ import { Migrator } from "effect/sql";
6
6
  import { makeLiveServer } from "@shivaedev/contract/makeLiveServer.ts";
7
7
  import { assertPostgresMigrations, postgresMigrationError } from "@shivaedev/sql/assertPostgresMigrations.ts";
8
- import type { SqlNameTransforms } from "@shivaedev/sql/clientOptions.ts";
9
8
  import { coordinateWorkerRelease } from "@shivaedev/sql/coordinateWorkerRelease.ts";
10
9
  import { migratePostgres } from "@shivaedev/sql/migrations.ts";
11
10
  import { type PendingPostgresMigrations, pendingPostgresMigrations } from "@shivaedev/sql/pendingPostgresMigrations.ts";
12
11
  import { type PostgresChangesOptions, postgresChanges } from "@shivaedev/sql/postgresChanges.ts";
12
+ import { type PostgresOptions, postgresLayer } from "@shivaedev/sql/postgresLayer.ts";
13
13
  import { WorkerRelease } from "@shivaedev/sql/WorkerRelease.ts";
14
14
  import type { AppChanges, AppDatabaseOptions } from "#appHost.ts";
15
- import { databaseAddress } from "./databaseAddress.ts";
16
15
 
17
- export interface DatabaseConfig extends SqlNameTransforms {
18
- readonly applicationName?: string;
19
- readonly changes?: Partial<Omit<PostgresChangesOptions, "client" | "resync">>;
16
+ export interface DatabaseConfig extends PostgresOptions {
17
+ readonly changes?: Partial<Omit<PostgresChangesOptions, "client" | "listenerClient" | "connectionSetting" | "resync">>;
20
18
  readonly databaseUrl?: Redacted.Redacted<string>;
21
- readonly maxConnections?: number;
19
+ readonly listenDatabaseUrl?: Redacted.Redacted<string>;
22
20
  }
23
21
 
24
- export function databaseLayer<R>(options: AppDatabaseOptions<R>, changesService: typeof AppChanges) {
22
+ export function databaseLayer<R, E>(options: AppDatabaseOptions<R, E>, changesService: typeof AppChanges) {
25
23
  const pool = Layer.unwrap(
26
- Effect.gen(function* () {
27
- const url = options.config?.databaseUrl ?? (yield* Config.Redacted("DATABASE_URL"));
28
- const address = databaseAddress(url);
29
- const disconnected = new Set<Promise<void>>();
30
- // Native pool shutdown sends Terminate without waiting for its sockets to close.
31
- yield* Effect.addFinalizer(() => Effect.promise(() => Promise.all([...disconnected])));
32
- return PgClient.layer({
33
- stream: () => {
34
- const target = new URL(Redacted.value(url));
35
- const host = address.host ?? target.searchParams.getAll("host").at(-1) ?? (decodeURIComponent(target.hostname) || "localhost");
36
- const port = address.port ?? 5432;
37
- const socket = createConnection(host.startsWith("/") ? { path: `${host}/.s.PGSQL.${port}` } : { host, noDelay: true, port });
38
- const closed = new Promise<void>((resolve) =>
39
- socket.once("close", () => {
40
- disconnected.delete(closed);
41
- resolve();
42
- }),
43
- );
44
- disconnected.add(closed);
45
- return socket;
46
- },
47
- transformQueryNames: options.config?.transformQueryNames,
48
- transformResultNames: options.config?.transformResultNames,
49
- url,
50
- ...address,
51
- ...(options.config?.maxConnections === undefined ? {} : { maxConnections: options.config.maxConnections }),
52
- ...(options.config?.applicationName === undefined ? {} : { applicationName: options.config.applicationName }),
53
- });
54
- }),
24
+ Effect.map(options.config?.databaseUrl === undefined ? Config.Redacted("DATABASE_URL") : Effect.succeed(options.config.databaseUrl), (url) =>
25
+ postgresLayer(url, options.config),
26
+ ),
55
27
  );
56
28
  const prepared = Layer.effectDiscard(prepareMigrations(options.migrations)).pipe(Layer.provideMerge(pool));
57
29
  const live = Layer.effect(changesService, makeLiveServer).pipe(Layer.provideMerge(Reactivity.layer));
@@ -69,12 +41,24 @@ export function databaseLayer<R>(options: AppDatabaseOptions<R>, changesService:
69
41
  const url = options.config?.databaseUrl ?? (yield* Config.Redacted("DATABASE_URL"));
70
42
  const name = yield* Config.String("APP_NAME").pipe(Config.withDefault(new URL(Redacted.value(url)).pathname));
71
43
  const channel = changes?.channel ?? `changes_${createHash("sha256").update(name).digest("hex").slice(0, 32)}`;
72
- return postgresChanges({ ...changes, channel, client, resync: hints.resync });
44
+ const listenUrl = options.config?.listenDatabaseUrl ?? Option.getOrUndefined(yield* Config.Redacted("LISTEN_DATABASE_URL").pipe(Config.option));
45
+ const listenerClient =
46
+ listenUrl === undefined
47
+ ? client
48
+ : yield* Effect.map(
49
+ Layer.build(postgresLayer(listenUrl, { applicationName: options.config?.applicationName, maxConnections: 1 })),
50
+ (context) => Context.get(context, PgClient.PgClient),
51
+ );
52
+ let connectionSetting = options.config?.databaseUrl === undefined ? "DATABASE_URL" : "config.databaseUrl";
53
+ if (listenUrl !== undefined) {
54
+ connectionSetting = options.config?.listenDatabaseUrl === undefined ? "LISTEN_DATABASE_URL" : "config.listenDatabaseUrl";
55
+ }
56
+ return postgresChanges({ ...changes, channel, client, connectionSetting, listenerClient, resync: hints.resync });
73
57
  }),
74
58
  ).pipe(Layer.provideMerge(base));
75
59
  }
76
60
 
77
- function prepareMigrations<R>(migrations: AppDatabaseOptions<R>["migrations"]) {
61
+ function prepareMigrations<R, E>(migrations: AppDatabaseOptions<R, E>["migrations"]) {
78
62
  switch (migrations.mode) {
79
63
  case "check": {
80
64
  const schema = { ...migrations };
@@ -88,7 +72,7 @@ function prepareMigrations<R>(migrations: AppDatabaseOptions<R>["migrations"]) {
88
72
  }
89
73
  }
90
74
 
91
- function waitForMigrations<R>(migrations: AppDatabaseOptions<R>["migrations"]) {
75
+ function waitForMigrations<R, E>(migrations: AppDatabaseOptions<R, E>["migrations"]) {
92
76
  return Effect.gen(function* () {
93
77
  const progressInterval = Duration.fromInputUnsafe(migrations.progressInterval ?? "30 seconds");
94
78
  let pending: PendingPostgresMigrations = { components: [], migrations: [] };
@@ -113,10 +97,10 @@ function waitForMigrations<R>(migrations: AppDatabaseOptions<R>["migrations"]) {
113
97
  }).pipe(
114
98
  Effect.retry({
115
99
  schedule: Schedule.max([Schedule.spaced(migrations.pollInterval ?? "1 second"), Schedule.during(migrations.waitTimeout ?? "5 minutes")]),
116
- while: (error) => error._tag === "MigrationError" && error.kind === "BadState",
100
+ while: (error) => error instanceof Migrator.MigrationError && error.kind === "BadState",
117
101
  }),
118
102
  Effect.tapError((error) =>
119
- error._tag === "MigrationError" && error.kind === "BadState" ? log("Timed out waiting for database migrations") : Effect.void,
103
+ error instanceof Migrator.MigrationError && error.kind === "BadState" ? log("Timed out waiting for database migrations") : Effect.void,
120
104
  ),
121
105
  );
122
106
  if (progress !== undefined) {
@@ -4,8 +4,10 @@ import type { Rpc, RpcGroup } from "effect/rpc";
4
4
  import { CurrentViewer, type Viewer } from "@shivaedev/contract/readPolicy.ts";
5
5
  import type { QueryReference } from "@shivaedev/contract/serverMetadata.ts";
6
6
  import { Unauthorized } from "@shivaedev/errors/taxonomy.ts";
7
- import { resolveSession, type SessionPolicy, type SessionShape } from "@shivaedev/identity/server/session.ts";
7
+ import { recheckSession } from "@shivaedev/identity/server/recheckSession.ts";
8
+ import type { SessionPolicy, SessionShape } from "@shivaedev/identity/server/session.ts";
8
9
  import { resolveChanges } from "@shivaedev/identity/server/sessionKeys.ts";
10
+ import { revalidateSession } from "@shivaedev/identity/server/socketSession.ts";
9
11
  import type { AppChanges } from "./appHost.ts";
10
12
 
11
13
  export function hostChanges<R extends Rpc.Any, TSession extends SessionShape>(
@@ -63,7 +65,7 @@ function authorizeSession<TSession extends SessionShape>(
63
65
  if (sessions === undefined) {
64
66
  return policy;
65
67
  }
66
- return resolveSession(sessions, Headers.empty, tag).pipe(
68
+ return recheckSession(sessions, Headers.empty, tag).pipe(
67
69
  Effect.map((current) => Option.isNone(viewer) || (Option.isSome(current) && current.value.user.id === viewer.value.id)),
68
70
  Effect.catch(() => Effect.succeed(false)),
69
71
  Effect.flatMap((allowed) => (allowed ? policy : Effect.succeed(false))),
@@ -72,10 +74,9 @@ function authorizeSession<TSession extends SessionShape>(
72
74
 
73
75
  function sessionRevoked<TSession extends SessionShape>(sessions: SessionPolicy<TSession>, tag: string, id: string) {
74
76
  return Effect.gen(function* () {
75
- yield* Effect.sleep(sessions.streamRevalidationInterval ?? "30 seconds");
76
- const current = yield* resolveSession(sessions, Headers.empty, tag).pipe(Effect.catchTag("AuthUnavailable", () => Effect.succeed(undefined)));
77
+ const current = yield* recheckSession(sessions, Headers.empty, tag).pipe(Effect.catchTag("AuthUnavailable", () => Effect.succeed(undefined)));
77
78
  if (current !== undefined && (Option.isNone(current) || current.value.user.id !== id)) {
78
79
  return yield* new Unauthorized({ message: "Authentication required" });
79
80
  }
80
- }).pipe(Effect.forever);
81
+ }).pipe((check) => revalidateSession(check, sessions.streamRevalidationInterval ?? "30 seconds"));
81
82
  }
package/src/socketRpc.ts CHANGED
@@ -3,6 +3,7 @@ import { Headers, HttpServerRequest, HttpServerResponse } from "effect/http";
3
3
  import * as HttpStatus from "effect/http/HttpStatus";
4
4
  import { localTransport } from "@shivaedev/identity/server/local.ts";
5
5
  import { resolveSession, type SessionShape } from "@shivaedev/identity/server/session.ts";
6
+ import { makeSocketSession, SocketSession } from "@shivaedev/identity/server/socketSession.ts";
6
7
  import type { HostPolicy } from "#hostOptions.ts";
7
8
 
8
9
  export function socketRpc<TSession extends SessionShape>(
@@ -18,6 +19,8 @@ export function socketRpc<TSession extends SessionShape>(
18
19
  }
19
20
  if (policy.policy !== "loopback") {
20
21
  yield* resolveSession(policy.sessions, Headers.empty, "$connect");
22
+ const session = yield* makeSocketSession(policy.sessions.streamRevalidationInterval ?? "30 seconds");
23
+ return yield* Effect.provideService(handler, SocketSession, session);
21
24
  }
22
25
  return yield* handler;
23
26
  }).pipe(
@@ -1,4 +0,0 @@
1
- import type { PgPoolConfig } from "@effect/sql-pg/PgClient";
2
- import { Redacted } from "effect";
3
- export declare function databaseAddress(value: Redacted.Redacted<string>): Pick<PgPoolConfig, "host" | "port">;
4
- //# sourceMappingURL=databaseAddress.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"databaseAddress.d.ts","sourceRoot":"","sources":["../src/databaseAddress.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC,CAqBrG"}