@shivaedev/local-postgres 0.10.0 → 0.12.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 (95) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +48 -10
  3. package/dist/server/AppPostgresVersionMismatch.d.ts +11 -0
  4. package/dist/server/AppPostgresVersionMismatch.d.ts.map +1 -0
  5. package/dist/server/AppPostgresVersionMismatch.js +11 -0
  6. package/dist/server/AppPostgresVersionMismatch.js.map +1 -0
  7. package/dist/server/PostgresBinaries.d.ts +11 -0
  8. package/dist/server/PostgresBinaries.d.ts.map +1 -0
  9. package/dist/server/PostgresBinaries.js +4 -0
  10. package/dist/server/PostgresBinaries.js.map +1 -0
  11. package/dist/server/PostgresSettingError.d.ts +11 -0
  12. package/dist/server/PostgresSettingError.d.ts.map +1 -0
  13. package/dist/server/PostgresSettingError.js +11 -0
  14. package/dist/server/PostgresSettingError.js.map +1 -0
  15. package/dist/server/{clientConnection.d.ts → adapters/clientConnection.d.ts} +2 -2
  16. package/dist/server/adapters/clientConnection.d.ts.map +1 -0
  17. package/dist/server/{clientConnection.js → adapters/clientConnection.js} +1 -1
  18. package/dist/server/adapters/clientConnection.js.map +1 -0
  19. package/dist/server/adapters/docker.d.ts +8 -0
  20. package/dist/server/adapters/docker.d.ts.map +1 -0
  21. package/dist/server/{localDocker.js → adapters/docker.js} +3 -3
  22. package/dist/server/adapters/docker.js.map +1 -0
  23. package/dist/server/adapters/ensureConnections.d.ts +11 -0
  24. package/dist/server/adapters/ensureConnections.d.ts.map +1 -0
  25. package/dist/server/{localConnections.js → adapters/ensureConnections.js} +5 -13
  26. package/dist/server/adapters/ensureConnections.js.map +1 -0
  27. package/dist/server/adapters/hostPostgresBinaries.d.ts +4 -0
  28. package/dist/server/adapters/hostPostgresBinaries.d.ts.map +1 -0
  29. package/dist/server/adapters/hostPostgresBinaries.js +20 -0
  30. package/dist/server/adapters/hostPostgresBinaries.js.map +1 -0
  31. package/dist/server/{localContainer.d.ts → adapters/localContainer.d.ts} +4 -4
  32. package/dist/server/adapters/localContainer.d.ts.map +1 -0
  33. package/dist/server/{localContainer.js → adapters/localContainer.js} +3 -3
  34. package/dist/server/adapters/localContainer.js.map +1 -0
  35. package/dist/server/adapters/localSql.d.ts +6 -0
  36. package/dist/server/adapters/localSql.d.ts.map +1 -0
  37. package/dist/server/adapters/localSql.js +15 -0
  38. package/dist/server/adapters/localSql.js.map +1 -0
  39. package/dist/server/{runCommand.d.ts → adapters/runCommand.d.ts} +1 -1
  40. package/dist/server/adapters/runCommand.d.ts.map +1 -0
  41. package/dist/server/{runCommand.js → adapters/runCommand.js} +1 -1
  42. package/dist/server/adapters/runCommand.js.map +1 -0
  43. package/dist/server/appPostgres.d.ts +22 -0
  44. package/dist/server/appPostgres.d.ts.map +1 -0
  45. package/dist/server/appPostgres.js +50 -0
  46. package/dist/server/appPostgres.js.map +1 -0
  47. package/dist/server/assertLocalDatabase.d.ts +1 -1
  48. package/dist/server/assertLocalDatabase.d.ts.map +1 -1
  49. package/dist/server/assertLocalDatabase.js +1 -1
  50. package/dist/server/assertLocalDatabase.js.map +1 -1
  51. package/dist/server/dockerEnvironment.d.ts +10 -0
  52. package/dist/server/dockerEnvironment.d.ts.map +1 -0
  53. package/dist/server/dockerEnvironment.js +6 -0
  54. package/dist/server/dockerEnvironment.js.map +1 -0
  55. package/dist/server/localPostgres.d.ts +5 -5
  56. package/dist/server/localPostgres.d.ts.map +1 -1
  57. package/dist/server/localPostgres.js +7 -16
  58. package/dist/server/localPostgres.js.map +1 -1
  59. package/dist/server/migrateAppPostgres.d.ts +6 -0
  60. package/dist/server/migrateAppPostgres.d.ts.map +1 -0
  61. package/dist/server/migrateAppPostgres.js +31 -0
  62. package/dist/server/migrateAppPostgres.js.map +1 -0
  63. package/dist/server/prepareAppPostgresData.d.ts +6 -0
  64. package/dist/server/prepareAppPostgresData.d.ts.map +1 -0
  65. package/dist/server/prepareAppPostgresData.js +35 -0
  66. package/dist/server/prepareAppPostgresData.js.map +1 -0
  67. package/package.json +6 -6
  68. package/src/server/AppPostgresVersionMismatch.ts +11 -0
  69. package/src/server/PostgresBinaries.ts +9 -0
  70. package/src/server/PostgresSettingError.ts +11 -0
  71. package/src/server/{clientConnection.ts → adapters/clientConnection.ts} +2 -2
  72. package/src/server/{localDocker.ts → adapters/docker.ts} +3 -4
  73. package/src/server/{localConnections.ts → adapters/ensureConnections.ts} +7 -16
  74. package/src/server/adapters/hostPostgresBinaries.ts +27 -0
  75. package/src/server/{localContainer.ts → adapters/localContainer.ts} +5 -5
  76. package/src/server/adapters/localSql.ts +20 -0
  77. package/src/server/{runCommand.ts → adapters/runCommand.ts} +1 -1
  78. package/src/server/appPostgres.ts +80 -0
  79. package/src/server/assertLocalDatabase.ts +1 -1
  80. package/src/server/dockerEnvironment.ts +8 -0
  81. package/src/server/localPostgres.ts +9 -21
  82. package/src/server/migrateAppPostgres.ts +35 -0
  83. package/src/server/prepareAppPostgresData.ts +35 -0
  84. package/dist/server/clientConnection.d.ts.map +0 -1
  85. package/dist/server/clientConnection.js.map +0 -1
  86. package/dist/server/localConnections.d.ts +0 -18
  87. package/dist/server/localConnections.d.ts.map +0 -1
  88. package/dist/server/localConnections.js.map +0 -1
  89. package/dist/server/localContainer.d.ts.map +0 -1
  90. package/dist/server/localContainer.js.map +0 -1
  91. package/dist/server/localDocker.d.ts +0 -12
  92. package/dist/server/localDocker.d.ts.map +0 -1
  93. package/dist/server/localDocker.js.map +0 -1
  94. package/dist/server/runCommand.d.ts.map +0 -1
  95. package/dist/server/runCommand.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { Effect } from "effect";
2
- import { LocalPostgresError } from "#LocalPostgresError.ts";
2
+ import { LocalPostgresError } from "#server/LocalPostgresError.ts";
3
3
  export const assertLocalDatabase = Effect.fn("LocalPostgres.assertLocalDatabase")(function* (value, names) {
4
4
  const message = `Use a local database on 127.0.0.1:55432 named ${names.join(" or ")}.`;
5
5
  const url = yield* Effect.try({ catch: () => new LocalPostgresError({ message }), try: () => new URL(value) });
@@ -1 +1 @@
1
- {"version":3,"file":"assertLocalDatabase.js","sourceRoot":"","sources":["../../src/server/assertLocalDatabase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,EAAE,CAAC,mCAAmC,CAAC,CAAC,QAAQ,CAAC,EAAE,KAAa,EAAE,KAAwB;IACnI,MAAM,OAAO,GAAG,iDAAiD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;IACvF,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,kBAAkB,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC/G,IACC,CAAC,CAAC,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;WACxG,GAAG,CAAC,IAAI,KAAK,OAAO;WACpB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;WAC1F,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EACxC,CAAC;QACF,OAAO,KAAK,CAAC,CAAC,IAAI,kBAAkB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"assertLocalDatabase.js","sourceRoot":"","sources":["../../src/server/assertLocalDatabase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,EAAE,CAAC,mCAAmC,CAAC,CAAC,QAAQ,CAAC,EAAE,KAAa,EAAE,KAAwB;IACnI,MAAM,OAAO,GAAG,iDAAiD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;IACvF,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,kBAAkB,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC/G,IACC,CAAC,CAAC,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;WACxG,GAAG,CAAC,IAAI,KAAK,OAAO;WACpB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;WAC1F,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EACxC,CAAC;QACF,OAAO,KAAK,CAAC,CAAC,IAAI,kBAAkB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { Config } from "effect";
2
+ export type DockerEnvironment = Readonly<{
3
+ "DOCKER_CONTEXT"?: string | undefined;
4
+ "DOCKER_HOST"?: string | undefined;
5
+ }>;
6
+ export declare const dockerEnvironment: Config.Config<{
7
+ DOCKER_CONTEXT: string;
8
+ DOCKER_HOST: string;
9
+ }>;
10
+ //# sourceMappingURL=dockerEnvironment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dockerEnvironment.d.ts","sourceRoot":"","sources":["../../src/server/dockerEnvironment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC,CAAC;AAExH,eAAO,MAAM,iBAAiB;;;EAG5B,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Config } from "effect";
2
+ export const dockerEnvironment = Config.all({
3
+ "DOCKER_CONTEXT": Config.String("DOCKER_CONTEXT").pipe(Config.withDefault("")),
4
+ "DOCKER_HOST": Config.String("DOCKER_HOST").pipe(Config.withDefault("")),
5
+ });
6
+ //# sourceMappingURL=dockerEnvironment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dockerEnvironment.js","sourceRoot":"","sources":["../../src/server/dockerEnvironment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAC;IAC3C,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IAC9E,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;CACxE,CAAC,CAAC"}
@@ -1,15 +1,15 @@
1
1
  import { Effect } from "effect";
2
- import { LocalPostgresError } from "#LocalPostgresError.ts";
3
- import { type DockerEnvironment } from "#localDocker.ts";
4
- import { PostgresVersionMismatch } from "#PostgresVersionMismatch.ts";
2
+ import type { DockerEnvironment } from "#server/dockerEnvironment.ts";
3
+ import { LocalPostgresError } from "#server/LocalPostgresError.ts";
4
+ import { PostgresVersionMismatch } from "#server/PostgresVersionMismatch.ts";
5
5
  export declare const LOCAL_SERVER = "postgresql://postgres:postgres@127.0.0.1:55432";
6
6
  export interface ReadinessOptions {
7
7
  readonly attempts?: number;
8
8
  readonly delayMillis?: number;
9
9
  }
10
10
  export declare function localPostgres(environment: DockerEnvironment, { attempts, delayMillis }?: ReadinessOptions): {
11
- prepareDatabases: (values: readonly string[]) => Effect.Effect<undefined, LocalPostgresError | import("./PostgresCommandError.ts").PostgresCommandError | import("#localConnections.ts").PostgresSettingError | PostgresVersionMismatch, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
11
+ prepareDatabases: (values: readonly string[]) => Effect.Effect<undefined, LocalPostgresError | import("./PostgresCommandError.ts").PostgresCommandError | import("./PostgresSettingError.ts").PostgresSettingError | PostgresVersionMismatch, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
12
12
  sql: (value: string | URL, query: string) => Effect.Effect<string, LocalPostgresError | import("./PostgresCommandError.ts").PostgresCommandError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
13
- startPostgres: (connection?: any) => Effect.Effect<void, LocalPostgresError | import("./PostgresCommandError.ts").PostgresCommandError | import("#localConnections.ts").PostgresSettingError | PostgresVersionMismatch, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
13
+ startPostgres: (connection?: any) => Effect.Effect<void, LocalPostgresError | import("./PostgresCommandError.ts").PostgresCommandError | import("./PostgresSettingError.ts").PostgresSettingError | PostgresVersionMismatch, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
14
14
  };
15
15
  //# sourceMappingURL=localPostgres.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"localPostgres.d.ts","sourceRoot":"","sources":["../../src/server/localPostgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAY,MAAM,QAAQ,CAAC;AAG1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAG5D,OAAO,EAAE,KAAK,iBAAiB,EAAU,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAGtE,eAAO,MAAM,YAAY,mDAAmD,CAAC;AAE7E,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,iBAAiB,EAAE,EAAE,QAAa,EAAE,WAAkB,EAAE,GAAE,gBAAqB;;;;EAuDzH"}
1
+ {"version":3,"file":"localPostgres.d.ts","sourceRoot":"","sources":["../../src/server/localPostgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAY,MAAM,QAAQ,CAAC;AAO1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAE7E,eAAO,MAAM,YAAY,mDAAmD,CAAC;AAE7E,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,iBAAiB,EAAE,EAAE,QAAa,EAAE,WAAkB,EAAE,GAAE,gBAAqB;;;;EAuDzH"}
@@ -1,12 +1,11 @@
1
1
  import { Effect, Schedule } from "effect";
2
- import { assertLocalDatabase } from "#assertLocalDatabase.ts";
3
- import { clientConnection } from "#clientConnection.ts";
4
- import { LocalPostgresError } from "#LocalPostgresError.ts";
5
- import { ensureConnections } from "#localConnections.ts";
6
- import { sqlInContainer, startContainer } from "#localContainer.ts";
7
- import { docker } from "#localDocker.ts";
8
- import { PostgresVersionMismatch } from "#PostgresVersionMismatch.ts";
9
- import { missingCommand, runCommand } from "#runCommand.ts";
2
+ import { docker } from "#server/adapters/docker.ts";
3
+ import { ensureConnections } from "#server/adapters/ensureConnections.ts";
4
+ import { startContainer } from "#server/adapters/localContainer.ts";
5
+ import { localSql } from "#server/adapters/localSql.ts";
6
+ import { assertLocalDatabase } from "#server/assertLocalDatabase.ts";
7
+ import { LocalPostgresError } from "#server/LocalPostgresError.ts";
8
+ import { PostgresVersionMismatch } from "#server/PostgresVersionMismatch.ts";
10
9
  export const LOCAL_SERVER = "postgresql://postgres:postgres@127.0.0.1:55432";
11
10
  export function localPostgres(environment, { attempts = 30, delayMillis = 1000 } = {}) {
12
11
  function localDocker(args, options) {
@@ -58,12 +57,4 @@ export function localPostgres(environment, { attempts = 30, delayMillis = 1000 }
58
57
  });
59
58
  return { prepareDatabases, sql, startPostgres };
60
59
  }
61
- function localSql(localDocker) {
62
- return Effect.fn("LocalPostgres.sql")(function* (value, query) {
63
- const parsed = yield* Effect.try({ catch: () => new LocalPostgresError({ message: "Invalid local database URL." }), try: () => new URL(value) });
64
- const { url, options } = yield* clientConnection(yield* assertLocalDatabase(parsed.toString(), [parsed.pathname.slice(1)]));
65
- const args = ["-X", "--set", "ON_ERROR_STOP=1", "-At", "-c", query];
66
- return yield* runCommand("psql", [...args, "--dbname", url.toString()], options).pipe(Effect.catchTag("PostgresCommandError", (error) => missingCommand(error) ? sqlInContainer(localDocker, url, args, options) : Effect.fail(error)));
67
- });
68
- }
69
60
  //# sourceMappingURL=localPostgres.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"localPostgres.js","sourceRoot":"","sources":["../../src/server/localPostgres.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"localPostgres.js","sourceRoot":"","sources":["../../src/server/localPostgres.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Effect, FileSystem, Path } from "effect";
2
+ import type { AppPostgresInstance } from "#server/appPostgres.ts";
3
+ import { PostgresBinaries } from "#server/PostgresBinaries.ts";
4
+ export declare const backupAppPostgres: (instance: AppPostgresInstance) => Effect.Effect<string, import("effect/PlatformError").PlatformError | import("./PostgresCommandError.ts").PostgresCommandError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | FileSystem.FileSystem | Path.Path | PostgresBinaries>;
5
+ export declare function migrateAppPostgres<A, E, R>(instance: AppPostgresInstance, migration: Effect.Effect<A, E, R>): Effect.Effect<A, E | import("effect/PlatformError").PlatformError | import("./PostgresCommandError.ts").PostgresCommandError, R | import("effect/process/ChildProcessSpawner").ChildProcessSpawner | FileSystem.FileSystem | Path.Path | PostgresBinaries>;
6
+ //# sourceMappingURL=migrateAppPostgres.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrateAppPostgres.d.ts","sourceRoot":"","sources":["../../src/server/migrateAppPostgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE/D,eAAO,MAAM,iBAAiB,4RAyB5B,CAAC;AAEH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,8PAE3G"}
@@ -0,0 +1,31 @@
1
+ import { Clock, Effect, FileSystem, Path } from "effect";
2
+ import { runCommand } from "#server/adapters/runCommand.ts";
3
+ import { PostgresBinaries } from "#server/PostgresBinaries.ts";
4
+ export const backupAppPostgres = Effect.fn("LocalPostgres.backupAppPostgres")(function* (instance) {
5
+ const fs = yield* FileSystem.FileSystem;
6
+ const path = yield* Path.Path;
7
+ const binaries = yield* PostgresBinaries;
8
+ const directory = path.join(instance.dataDirectory, "backups");
9
+ yield* fs.makeDirectory(directory, { mode: 0o700, recursive: true });
10
+ const timestamp = yield* Clock.currentTimeMillis;
11
+ const backup = yield* Effect.scoped(Effect.gen(function* () {
12
+ const staging = yield* fs.makeTempDirectoryScoped({ directory, prefix: `backup-${timestamp}-` });
13
+ const file = path.join(staging, "dump.partial");
14
+ yield* runCommand(binaries.pgDump, ["--format=custom", "--file", file, "--dbname", instance.connectionUrl]);
15
+ const completed = `${staging}.dump`;
16
+ yield* fs.rename(file, completed);
17
+ return completed;
18
+ }));
19
+ const files = (yield* fs.readDirectory(directory))
20
+ .filter((name) => /^backup-\d+-.+\.dump$/u.test(name))
21
+ .sort()
22
+ .reverse();
23
+ for (const file of files.slice(instance.backupsToKeep)) {
24
+ yield* fs.remove(path.join(directory, file));
25
+ }
26
+ return backup;
27
+ });
28
+ export function migrateAppPostgres(instance, migration) {
29
+ return backupAppPostgres(instance).pipe(Effect.andThen(migration));
30
+ }
31
+ //# sourceMappingURL=migrateAppPostgres.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrateAppPostgres.js","sourceRoot":"","sources":["../../src/server/migrateAppPostgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAE5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE/D,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,EAAE,CAAC,iCAAiC,CAAC,CAAC,QAAQ,CAAC,EAAE,QAA6B;IACrH,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;IACxC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;IAC9B,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,gBAAgB,CAAC;IACzC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IAC/D,KAAK,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;IACjD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAClC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACnB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,uBAAuB,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,SAAS,GAAG,EAAE,CAAC,CAAC;QACjG,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QAChD,KAAK,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,iBAAiB,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;QAC5G,MAAM,SAAS,GAAG,GAAG,OAAO,OAAO,CAAC;QACpC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAClC,OAAO,SAAS,CAAC;IAClB,CAAC,CAAC,CACF,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;SAChD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SACrD,IAAI,EAAE;SACN,OAAO,EAAE,CAAC;IACZ,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACxD,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC,CAAC,CAAC;AAEH,MAAM,UAAU,kBAAkB,CAAU,QAA6B,EAAE,SAAiC;IAC3G,OAAO,iBAAiB,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;AACpE,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Effect, FileSystem, Path } from "effect";
2
+ import { AppPostgresVersionMismatch } from "#server/AppPostgresVersionMismatch.ts";
3
+ import { LocalPostgresError } from "#server/LocalPostgresError.ts";
4
+ import { PostgresBinaries } from "#server/PostgresBinaries.ts";
5
+ export declare const prepareAppPostgresData: (dataDirectory: string) => Effect.Effect<undefined, AppPostgresVersionMismatch | LocalPostgresError | import("effect/PlatformError").PlatformError | import("./PostgresCommandError.ts").PostgresCommandError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | FileSystem.FileSystem | Path.Path | PostgresBinaries>;
6
+ //# sourceMappingURL=prepareAppPostgresData.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepareAppPostgresData.d.ts","sourceRoot":"","sources":["../../src/server/prepareAppPostgresData.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AAEnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE/D,eAAO,MAAM,sBAAsB,yUA4BjC,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { Effect, FileSystem, Path } from "effect";
2
+ import { AppPostgresVersionMismatch } from "#server/AppPostgresVersionMismatch.ts";
3
+ import { runCommand } from "#server/adapters/runCommand.ts";
4
+ import { LocalPostgresError } from "#server/LocalPostgresError.ts";
5
+ import { PostgresBinaries } from "#server/PostgresBinaries.ts";
6
+ export const prepareAppPostgresData = Effect.fn("LocalPostgres.prepareAppPostgresData")(function* (dataDirectory) {
7
+ const binaries = yield* PostgresBinaries;
8
+ const fs = yield* FileSystem.FileSystem;
9
+ const path = yield* Path.Path;
10
+ const version = yield* runCommand(binaries.postgres, ["--version"]);
11
+ const expectedMajor = /\b(?<major>\d+)\./u.exec(version)?.groups?.major;
12
+ if (!expectedMajor) {
13
+ return yield* new LocalPostgresError({ message: `Cannot read PostgreSQL major version from ${version}.` });
14
+ }
15
+ const versionFile = path.join(dataDirectory, "PG_VERSION");
16
+ if (yield* fs.exists(versionFile)) {
17
+ const observedMajor = (yield* fs.readFileString(versionFile)).trim();
18
+ if (observedMajor !== expectedMajor) {
19
+ return yield* new AppPostgresVersionMismatch({ dataDirectory, expectedMajor, observedMajor });
20
+ }
21
+ return;
22
+ }
23
+ yield* fs.makeDirectory(dataDirectory, { recursive: true });
24
+ yield* runCommand(binaries.initdb, [
25
+ "--pgdata",
26
+ dataDirectory,
27
+ "--username",
28
+ "postgres",
29
+ "--auth-local=trust",
30
+ "--auth-host=reject",
31
+ "--encoding=UTF8",
32
+ "--locale=C",
33
+ ]);
34
+ });
35
+ //# sourceMappingURL=prepareAppPostgresData.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepareAppPostgresData.js","sourceRoot":"","sources":["../../src/server/prepareAppPostgresData.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE/D,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC,EAAE,CAAC,sCAAsC,CAAC,CAAC,QAAQ,CAAC,EAAE,aAAqB;IACvH,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,gBAAgB,CAAC;IACzC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;IACxC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;IAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IACpE,MAAM,aAAa,GAAG,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC;IACxE,IAAI,CAAC,aAAa,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC,CAAC,IAAI,kBAAkB,CAAC,EAAE,OAAO,EAAE,6CAA6C,OAAO,GAAG,EAAE,CAAC,CAAC;IAC5G,CAAC;IACD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IAC3D,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QACnC,MAAM,aAAa,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACrE,IAAI,aAAa,KAAK,aAAa,EAAE,CAAC;YACrC,OAAO,KAAK,CAAC,CAAC,IAAI,0BAA0B,CAAC,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC;QAC/F,CAAC;QACD,OAAO;IACR,CAAC;IACD,KAAK,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,KAAK,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE;QAClC,UAAU;QACV,aAAa;QACb,YAAY;QACZ,UAAU;QACV,oBAAoB;QACpB,oBAAoB;QACpB,iBAAiB;QACjB,YAAY;KACZ,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/local-postgres",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "Repeatable local PostgreSQL preparation with one shared persistent service",
5
5
  "homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/local-postgres#readme",
6
6
  "bugs": {
@@ -17,9 +17,9 @@
17
17
  "imports": {
18
18
  "#test/*": "./src/test-support/*",
19
19
  "#*.ts": {
20
- "source": "./src/server/*.ts",
21
- "types": "./dist/server/*.d.ts",
22
- "default": "./dist/server/*.js"
20
+ "source": "./src/*.ts",
21
+ "types": "./dist/*.d.ts",
22
+ "default": "./dist/*.js"
23
23
  }
24
24
  },
25
25
  "exports": {
@@ -41,8 +41,8 @@
41
41
  ],
42
42
  "devDependencies": {
43
43
  "@effect/platform-node": "4.0.6",
44
- "@shivaedev/quality": "0.56.0",
45
- "@shivaedev/test-story": "0.34.0",
44
+ "@shivaedev/quality": "0.57.1",
45
+ "@shivaedev/test-story": "0.36.0",
46
46
  "@types/node": "24.19.2",
47
47
  "effect": "4.0.6",
48
48
  "typescript": "7.0.2",
@@ -0,0 +1,11 @@
1
+ import { Schema } from "effect";
2
+
3
+ export class AppPostgresVersionMismatch extends Schema.TaggedError<AppPostgresVersionMismatch>()("AppPostgresVersionMismatch", {
4
+ dataDirectory: Schema.String,
5
+ expectedMajor: Schema.String,
6
+ observedMajor: Schema.String,
7
+ }) {
8
+ override get message() {
9
+ return `PostgreSQL ${this.expectedMajor} cannot open ${this.dataDirectory}: its data belongs to PostgreSQL ${this.observedMajor}.`;
10
+ }
11
+ }
@@ -0,0 +1,9 @@
1
+ import { Context } from "effect";
2
+
3
+ export interface PostgresExecutables {
4
+ readonly initdb: string;
5
+ readonly pgDump: string;
6
+ readonly postgres: string;
7
+ }
8
+
9
+ export class PostgresBinaries extends Context.Service<PostgresBinaries, PostgresExecutables>()("@shivaedev/local-postgres/PostgresBinaries") {}
@@ -0,0 +1,11 @@
1
+ import { Schema } from "effect";
2
+
3
+ export class PostgresSettingError extends Schema.TaggedError<PostgresSettingError>()("PostgresSettingError", {
4
+ cause: Schema.Unknown,
5
+ container: Schema.Literal("development-postgres"),
6
+ setting: Schema.Literal("max_connections"),
7
+ }) {
8
+ override get message() {
9
+ return "Could not set max_connections to at least 500 in container development-postgres.";
10
+ }
11
+ }
@@ -1,6 +1,6 @@
1
1
  import { Effect } from "effect";
2
- import { LocalPostgresError } from "#LocalPostgresError.ts";
3
- import type { CommandOptions } from "#runCommand.ts";
2
+ import { LocalPostgresError } from "#server/LocalPostgresError.ts";
3
+ import type { CommandOptions } from "./runCommand.ts";
4
4
 
5
5
  export const clientConnection = Effect.fn("LocalPostgres.clientConnection")(function* (value: URL, options: CommandOptions = {}) {
6
6
  const url = new URL(value);
@@ -1,8 +1,7 @@
1
1
  import { Effect } from "effect";
2
- import { LocalPostgresError } from "#LocalPostgresError.ts";
3
- import { type CommandOptions, runCommand } from "#runCommand.ts";
4
-
5
- export type DockerEnvironment = Readonly<{ "DOCKER_CONTEXT"?: string | undefined; "DOCKER_HOST"?: string | undefined }>;
2
+ import type { DockerEnvironment } from "#server/dockerEnvironment.ts";
3
+ import { LocalPostgresError } from "#server/LocalPostgresError.ts";
4
+ import { type CommandOptions, runCommand } from "./runCommand.ts";
6
5
 
7
6
  export const docker = Effect.fn("LocalPostgres.docker")(function* (
8
7
  environment: DockerEnvironment,
@@ -1,20 +1,11 @@
1
- import { Effect, Schema } from "effect";
1
+ import { Effect } from "effect";
2
2
  import type { ChildProcessSpawner } from "effect/process";
3
- import { LocalPostgresError } from "#LocalPostgresError.ts";
4
- import { POSTGRES_IMAGE } from "#localContainer.ts";
5
- import type { docker as localDocker } from "#localDocker.ts";
6
- import type { PostgresCommandError } from "#PostgresCommandError.ts";
7
- import type { PostgresVersionMismatch } from "#PostgresVersionMismatch.ts";
8
-
9
- export class PostgresSettingError extends Schema.TaggedError<PostgresSettingError>()("PostgresSettingError", {
10
- cause: Schema.Unknown,
11
- container: Schema.Literal("development-postgres"),
12
- setting: Schema.Literal("max_connections"),
13
- }) {
14
- override get message() {
15
- return "Could not set max_connections to at least 500 in container development-postgres.";
16
- }
17
- }
3
+ import { LocalPostgresError } from "#server/LocalPostgresError.ts";
4
+ import type { PostgresCommandError } from "#server/PostgresCommandError.ts";
5
+ import { PostgresSettingError } from "#server/PostgresSettingError.ts";
6
+ import type { PostgresVersionMismatch } from "#server/PostgresVersionMismatch.ts";
7
+ import type { docker as localDocker } from "./docker.ts";
8
+ import { POSTGRES_IMAGE } from "./localContainer.ts";
18
9
 
19
10
  type Query = (query: string) => Effect.Effect<string, LocalPostgresError | PostgresCommandError, ChildProcessSpawner.ChildProcessSpawner>;
20
11
 
@@ -0,0 +1,27 @@
1
+ import { Effect, Layer, Path } from "effect";
2
+ import { missingCommand, runCommand } from "#server/adapters/runCommand.ts";
3
+ import { PostgresBinaries, type PostgresExecutables } from "#server/PostgresBinaries.ts";
4
+
5
+ export function hostPostgresBinaries(directory?: string) {
6
+ return Layer.effect(
7
+ PostgresBinaries,
8
+ Effect.gen(function* () {
9
+ const path = yield* Path.Path;
10
+ const bin =
11
+ directory
12
+ ?? (yield* runCommand("postgres", ["--version"]).pipe(
13
+ Effect.as(""),
14
+ Effect.catchTag("PostgresCommandError", (error) => (missingCommand(error) ? runCommand("pg_config", ["--bindir"]) : Effect.fail(error))),
15
+ ));
16
+ const executables: PostgresExecutables = {
17
+ initdb: bin ? path.join(bin, "initdb") : "initdb",
18
+ pgDump: bin ? path.join(bin, "pg_dump") : "pg_dump",
19
+ postgres: bin ? path.join(bin, "postgres") : "postgres",
20
+ };
21
+ for (const command of Object.values(executables)) {
22
+ yield* runCommand(command, ["--version"]);
23
+ }
24
+ return executables;
25
+ }),
26
+ );
27
+ }
@@ -1,9 +1,9 @@
1
1
  import { Effect } from "effect";
2
- import { clientConnection } from "#clientConnection.ts";
3
- import { LocalPostgresError } from "#LocalPostgresError.ts";
4
- import type { docker as runDocker } from "#localDocker.ts";
5
- import { PostgresCommandError } from "#PostgresCommandError.ts";
6
- import type { CommandOptions } from "#runCommand.ts";
2
+ import { LocalPostgresError } from "#server/LocalPostgresError.ts";
3
+ import { PostgresCommandError } from "#server/PostgresCommandError.ts";
4
+ import { clientConnection } from "./clientConnection.ts";
5
+ import type { docker as runDocker } from "./docker.ts";
6
+ import type { CommandOptions } from "./runCommand.ts";
7
7
 
8
8
  export const POSTGRES_IMAGE = "postgres:18.6-alpine@sha256:77f585114c32fbca283dc835b0596f4e52b51b4c6662d7810b2f4084f60a1873";
9
9
  const CONTAINER = "development-postgres";
@@ -0,0 +1,20 @@
1
+ import { Effect } from "effect";
2
+ import { assertLocalDatabase } from "#server/assertLocalDatabase.ts";
3
+ import { LocalPostgresError } from "#server/LocalPostgresError.ts";
4
+ import { clientConnection } from "./clientConnection.ts";
5
+ import type { docker } from "./docker.ts";
6
+ import { sqlInContainer } from "./localContainer.ts";
7
+ import { type CommandOptions, missingCommand, runCommand } from "./runCommand.ts";
8
+
9
+ export function localSql(localDocker: (args: readonly string[], options?: CommandOptions) => ReturnType<typeof docker>) {
10
+ return Effect.fn("LocalPostgres.sql")(function* (value: string | URL, query: string) {
11
+ const parsed = yield* Effect.try({ catch: () => new LocalPostgresError({ message: "Invalid local database URL." }), try: () => new URL(value) });
12
+ const { url, options } = yield* clientConnection(yield* assertLocalDatabase(parsed.toString(), [parsed.pathname.slice(1)]));
13
+ const args = ["-X", "--set", "ON_ERROR_STOP=1", "-At", "-c", query];
14
+ return yield* runCommand("psql", [...args, "--dbname", url.toString()], options).pipe(
15
+ Effect.catchTag("PostgresCommandError", (error) =>
16
+ missingCommand(error) ? sqlInContainer(localDocker, url, args, options) : Effect.fail(error),
17
+ ),
18
+ );
19
+ });
20
+ }
@@ -1,6 +1,6 @@
1
1
  import { Effect, PlatformError, Stream } from "effect";
2
2
  import { ChildProcess, ChildProcessSpawner } from "effect/process";
3
- import { PostgresCommandError } from "#PostgresCommandError.ts";
3
+ import { PostgresCommandError } from "#server/PostgresCommandError.ts";
4
4
 
5
5
  export type CommandOptions = Pick<ChildProcess.CommandOptions, "env" | "extendEnv">;
6
6
 
@@ -0,0 +1,80 @@
1
+ import { Deferred, Effect, FileSystem, Path, Stream } from "effect";
2
+ import { ChildProcess, ChildProcessSpawner } from "effect/process";
3
+ import { LocalPostgresError } from "#server/LocalPostgresError.ts";
4
+ import { PostgresBinaries } from "#server/PostgresBinaries.ts";
5
+ import { PostgresCommandError } from "#server/PostgresCommandError.ts";
6
+ import { prepareAppPostgresData } from "#server/prepareAppPostgresData.ts";
7
+
8
+ export interface AppPostgresOptions {
9
+ readonly backupsToKeep?: number;
10
+ readonly dataDirectory: string;
11
+ }
12
+
13
+ export interface AppPostgresInstance {
14
+ readonly backupsToKeep: number;
15
+ readonly connectionUrl: string;
16
+ readonly dataDirectory: string;
17
+ readonly socketDirectory: string;
18
+ }
19
+
20
+ export const appPostgres = Effect.fn("LocalPostgres.appPostgres")(function* ({ dataDirectory, backupsToKeep = 5 }: AppPostgresOptions) {
21
+ if (!Number.isSafeInteger(backupsToKeep) || backupsToKeep < 1) {
22
+ return yield* new LocalPostgresError({ message: "backupsToKeep must be a positive integer." });
23
+ }
24
+ const fs = yield* FileSystem.FileSystem;
25
+ const path = yield* Path.Path;
26
+ const binaries = yield* PostgresBinaries;
27
+ const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
28
+ const directory = path.resolve(dataDirectory);
29
+ yield* prepareAppPostgresData(directory);
30
+ const socketDirectory = yield* fs.makeTempDirectoryScoped({ prefix: "app-postgres-" });
31
+ yield* fs.chmod(socketDirectory, 0o700);
32
+ const child = yield* spawner.spawn(
33
+ ChildProcess.make(
34
+ binaries.postgres,
35
+ [
36
+ "-D",
37
+ directory,
38
+ "-h",
39
+ "",
40
+ "-k",
41
+ socketDirectory,
42
+ "-c",
43
+ "unix_socket_permissions=0700",
44
+ "-c",
45
+ "logging_collector=off",
46
+ "-c",
47
+ "log_destination=stderr",
48
+ "-c",
49
+ "lc_messages=C",
50
+ ],
51
+ { env: { "LC_ALL": "C" }, extendEnv: true, killSignal: "SIGINT", stdin: "ignore", stdout: "ignore" },
52
+ ),
53
+ );
54
+ const ready = yield* Deferred.make<void>();
55
+ let diagnostics = "";
56
+ yield* child.stderr.pipe(
57
+ Stream.decodeText,
58
+ Stream.splitLines,
59
+ Stream.runForEach((line) => {
60
+ diagnostics = line;
61
+ return line.includes("database system is ready to accept connections") ? Deferred.succeed(ready, undefined) : Effect.void;
62
+ }),
63
+ Effect.forkScoped,
64
+ );
65
+ yield* Effect.raceFirst(
66
+ Deferred.await(ready),
67
+ Effect.flatMap(child.exitCode, (code) =>
68
+ Effect.fail(
69
+ new PostgresCommandError({
70
+ command: binaries.postgres,
71
+ exitCode: Number(code),
72
+ message: diagnostics || "PostgreSQL exited before becoming ready.",
73
+ }),
74
+ ),
75
+ ),
76
+ ).pipe(Effect.timeout("30 seconds"));
77
+ const connection = new URL("postgresql://postgres@localhost/postgres");
78
+ connection.searchParams.set("host", socketDirectory);
79
+ return { backupsToKeep, connectionUrl: connection.toString(), dataDirectory: directory, socketDirectory } satisfies AppPostgresInstance;
80
+ });
@@ -1,5 +1,5 @@
1
1
  import { Effect } from "effect";
2
- import { LocalPostgresError } from "#LocalPostgresError.ts";
2
+ import { LocalPostgresError } from "#server/LocalPostgresError.ts";
3
3
 
4
4
  export const assertLocalDatabase = Effect.fn("LocalPostgres.assertLocalDatabase")(function* (value: string, names: readonly string[]) {
5
5
  const message = `Use a local database on 127.0.0.1:55432 named ${names.join(" or ")}.`;
@@ -0,0 +1,8 @@
1
+ import { Config } from "effect";
2
+
3
+ export type DockerEnvironment = Readonly<{ "DOCKER_CONTEXT"?: string | undefined; "DOCKER_HOST"?: string | undefined }>;
4
+
5
+ export const dockerEnvironment = Config.all({
6
+ "DOCKER_CONTEXT": Config.String("DOCKER_CONTEXT").pipe(Config.withDefault("")),
7
+ "DOCKER_HOST": Config.String("DOCKER_HOST").pipe(Config.withDefault("")),
8
+ });
@@ -1,12 +1,13 @@
1
1
  import { Effect, Schedule } from "effect";
2
- import { assertLocalDatabase } from "#assertLocalDatabase.ts";
3
- import { clientConnection } from "#clientConnection.ts";
4
- import { LocalPostgresError } from "#LocalPostgresError.ts";
5
- import { ensureConnections } from "#localConnections.ts";
6
- import { sqlInContainer, startContainer } from "#localContainer.ts";
7
- import { type DockerEnvironment, docker } from "#localDocker.ts";
8
- import { PostgresVersionMismatch } from "#PostgresVersionMismatch.ts";
9
- import { type CommandOptions, missingCommand, runCommand } from "#runCommand.ts";
2
+ import { docker } from "#server/adapters/docker.ts";
3
+ import { ensureConnections } from "#server/adapters/ensureConnections.ts";
4
+ import { startContainer } from "#server/adapters/localContainer.ts";
5
+ import { localSql } from "#server/adapters/localSql.ts";
6
+ import type { CommandOptions } from "#server/adapters/runCommand.ts";
7
+ import { assertLocalDatabase } from "#server/assertLocalDatabase.ts";
8
+ import type { DockerEnvironment } from "#server/dockerEnvironment.ts";
9
+ import { LocalPostgresError } from "#server/LocalPostgresError.ts";
10
+ import { PostgresVersionMismatch } from "#server/PostgresVersionMismatch.ts";
10
11
 
11
12
  export const LOCAL_SERVER = "postgresql://postgres:postgres@127.0.0.1:55432";
12
13
 
@@ -71,16 +72,3 @@ export function localPostgres(environment: DockerEnvironment, { attempts = 30, d
71
72
  });
72
73
  return { prepareDatabases, sql, startPostgres };
73
74
  }
74
-
75
- function localSql(localDocker: (args: readonly string[], options?: CommandOptions) => ReturnType<typeof docker>) {
76
- return Effect.fn("LocalPostgres.sql")(function* (value: string | URL, query: string) {
77
- const parsed = yield* Effect.try({ catch: () => new LocalPostgresError({ message: "Invalid local database URL." }), try: () => new URL(value) });
78
- const { url, options } = yield* clientConnection(yield* assertLocalDatabase(parsed.toString(), [parsed.pathname.slice(1)]));
79
- const args = ["-X", "--set", "ON_ERROR_STOP=1", "-At", "-c", query];
80
- return yield* runCommand("psql", [...args, "--dbname", url.toString()], options).pipe(
81
- Effect.catchTag("PostgresCommandError", (error) =>
82
- missingCommand(error) ? sqlInContainer(localDocker, url, args, options) : Effect.fail(error),
83
- ),
84
- );
85
- });
86
- }
@@ -0,0 +1,35 @@
1
+ import { Clock, Effect, FileSystem, Path } from "effect";
2
+ import { runCommand } from "#server/adapters/runCommand.ts";
3
+ import type { AppPostgresInstance } from "#server/appPostgres.ts";
4
+ import { PostgresBinaries } from "#server/PostgresBinaries.ts";
5
+
6
+ export const backupAppPostgres = Effect.fn("LocalPostgres.backupAppPostgres")(function* (instance: AppPostgresInstance) {
7
+ const fs = yield* FileSystem.FileSystem;
8
+ const path = yield* Path.Path;
9
+ const binaries = yield* PostgresBinaries;
10
+ const directory = path.join(instance.dataDirectory, "backups");
11
+ yield* fs.makeDirectory(directory, { mode: 0o700, recursive: true });
12
+ const timestamp = yield* Clock.currentTimeMillis;
13
+ const backup = yield* Effect.scoped(
14
+ Effect.gen(function* () {
15
+ const staging = yield* fs.makeTempDirectoryScoped({ directory, prefix: `backup-${timestamp}-` });
16
+ const file = path.join(staging, "dump.partial");
17
+ yield* runCommand(binaries.pgDump, ["--format=custom", "--file", file, "--dbname", instance.connectionUrl]);
18
+ const completed = `${staging}.dump`;
19
+ yield* fs.rename(file, completed);
20
+ return completed;
21
+ }),
22
+ );
23
+ const files = (yield* fs.readDirectory(directory))
24
+ .filter((name) => /^backup-\d+-.+\.dump$/u.test(name))
25
+ .sort()
26
+ .reverse();
27
+ for (const file of files.slice(instance.backupsToKeep)) {
28
+ yield* fs.remove(path.join(directory, file));
29
+ }
30
+ return backup;
31
+ });
32
+
33
+ export function migrateAppPostgres<A, E, R>(instance: AppPostgresInstance, migration: Effect.Effect<A, E, R>) {
34
+ return backupAppPostgres(instance).pipe(Effect.andThen(migration));
35
+ }