@livestore/utils-dev 0.4.0 → 0.5.0-dev.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 (76) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/node/DockerCompose/DockerCompose.d.ts +52 -0
  3. package/dist/node/DockerCompose/DockerCompose.d.ts.map +1 -0
  4. package/dist/node/DockerCompose/DockerCompose.js +158 -0
  5. package/dist/node/DockerCompose/DockerCompose.js.map +1 -0
  6. package/dist/node/DockerCompose/DockerCompose.test.d.ts +2 -0
  7. package/dist/node/DockerCompose/DockerCompose.test.d.ts.map +1 -0
  8. package/dist/node/{DockerComposeService/DockerComposeService.test.js → DockerCompose/DockerCompose.test.js} +16 -16
  9. package/dist/node/DockerCompose/DockerCompose.test.js.map +1 -0
  10. package/dist/node/DockerCompose/mod.d.ts +2 -0
  11. package/dist/node/DockerCompose/mod.d.ts.map +1 -0
  12. package/dist/node/DockerCompose/mod.js +2 -0
  13. package/dist/node/DockerCompose/mod.js.map +1 -0
  14. package/dist/node/FileLogger.d.ts +15 -8
  15. package/dist/node/FileLogger.d.ts.map +1 -1
  16. package/dist/node/FileLogger.js +63 -79
  17. package/dist/node/FileLogger.js.map +1 -1
  18. package/dist/node/cmd-log.d.ts.map +1 -1
  19. package/dist/node/cmd-log.js +19 -8
  20. package/dist/node/cmd-log.js.map +1 -1
  21. package/dist/node/cmd.d.ts +10 -12
  22. package/dist/node/cmd.d.ts.map +1 -1
  23. package/dist/node/cmd.js +73 -36
  24. package/dist/node/cmd.js.map +1 -1
  25. package/dist/node/cmd.test.js +17 -17
  26. package/dist/node/cmd.test.js.map +1 -1
  27. package/dist/node/mod.d.ts +4 -5
  28. package/dist/node/mod.d.ts.map +1 -1
  29. package/dist/node/mod.js +58 -55
  30. package/dist/node/mod.js.map +1 -1
  31. package/dist/node/workspace.d.ts +2 -2
  32. package/dist/node/workspace.d.ts.map +1 -1
  33. package/dist/node/workspace.js +7 -7
  34. package/dist/node/workspace.js.map +1 -1
  35. package/dist/node-vitest/Vitest.d.ts +17 -8
  36. package/dist/node-vitest/Vitest.d.ts.map +1 -1
  37. package/dist/node-vitest/Vitest.js +5 -5
  38. package/dist/node-vitest/Vitest.js.map +1 -1
  39. package/dist/node-vitest/Vitest.test.d.ts +3 -5
  40. package/dist/node-vitest/Vitest.test.d.ts.map +1 -1
  41. package/dist/node-vitest/Vitest.test.js +14 -3
  42. package/dist/node-vitest/Vitest.test.js.map +1 -1
  43. package/dist/wrangler/WranglerDevServer.d.ts +15 -20
  44. package/dist/wrangler/WranglerDevServer.d.ts.map +1 -1
  45. package/dist/wrangler/WranglerDevServer.js +77 -71
  46. package/dist/wrangler/WranglerDevServer.js.map +1 -1
  47. package/dist/wrangler/WranglerDevServer.test.js +28 -28
  48. package/dist/wrangler/WranglerDevServer.test.js.map +1 -1
  49. package/dist/wrangler/mod.d.ts +1 -1
  50. package/dist/wrangler/mod.d.ts.map +1 -1
  51. package/dist/wrangler/mod.js +1 -1
  52. package/dist/wrangler/mod.js.map +1 -1
  53. package/package.json +19 -37
  54. package/src/node/{DockerComposeService/DockerComposeService.test.ts → DockerCompose/DockerCompose.test.ts} +18 -18
  55. package/src/node/DockerCompose/DockerCompose.ts +328 -0
  56. package/src/node/DockerCompose/mod.ts +1 -0
  57. package/src/node/FileLogger.ts +89 -114
  58. package/src/node/cmd-log.ts +21 -10
  59. package/src/node/cmd.test.ts +19 -17
  60. package/src/node/cmd.ts +117 -86
  61. package/src/node/mod.ts +112 -104
  62. package/src/node/workspace.ts +9 -10
  63. package/src/node-vitest/Vitest.test.ts +22 -3
  64. package/src/node-vitest/Vitest.ts +32 -42
  65. package/src/wrangler/WranglerDevServer.test.ts +33 -37
  66. package/src/wrangler/WranglerDevServer.ts +145 -129
  67. package/src/wrangler/mod.ts +1 -6
  68. package/dist/node/DockerComposeService/DockerComposeService.d.ts +0 -63
  69. package/dist/node/DockerComposeService/DockerComposeService.d.ts.map +0 -1
  70. package/dist/node/DockerComposeService/DockerComposeService.js +0 -149
  71. package/dist/node/DockerComposeService/DockerComposeService.js.map +0 -1
  72. package/dist/node/DockerComposeService/DockerComposeService.test.d.ts +0 -2
  73. package/dist/node/DockerComposeService/DockerComposeService.test.d.ts.map +0 -1
  74. package/dist/node/DockerComposeService/DockerComposeService.test.js.map +0 -1
  75. package/src/node/DockerComposeService/DockerComposeService.ts +0 -343
  76. /package/src/node/{DockerComposeService → DockerCompose}/test-fixtures/docker-compose.yml +0 -0
@@ -1,149 +0,0 @@
1
- import { objectToString, omitUndefineds } from '@livestore/utils';
2
- import { Command, Duration, Effect, Fiber, Schedule, Schema, Stream, } from '@livestore/utils/effect';
3
- export class DockerComposeError extends Schema.TaggedError('~@livestore/utils-dev/DockerComposeError')('DockerComposeError', {
4
- cause: Schema.Defect,
5
- note: Schema.String,
6
- }) {
7
- }
8
- const generateProjectName = () => `ls-test-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
9
- export class DockerComposeService extends Effect.Service()('DockerComposeService', {
10
- scoped: (args) => Effect.gen(function* () {
11
- const { cwd, serviceName } = args;
12
- const projectName = args.projectName ?? generateProjectName();
13
- const commandExecutorContext = yield* Effect.context();
14
- const baseComposeArgs = ['-p', projectName];
15
- const pull = Effect.gen(function* () {
16
- yield* Effect.log(`Pulling Docker Compose images in ${cwd}`);
17
- // TODO (@IMax153) Refactor the effect command related code below as there is probably a much more elegant way to accomplish what we want here in a more effect idiomatic way.
18
- const pullCommand = Command.make('docker', 'compose', ...baseComposeArgs, 'pull').pipe(Command.workingDirectory(cwd), Command.stdout('pipe'), Command.stderr('pipe'));
19
- const process = yield* pullCommand.pipe(Command.start, Effect.provide(commandExecutorContext));
20
- const stdoutFiber = yield* process.stdout.pipe(Stream.decodeText('utf8'), Stream.runFold('', (acc, chunk) => acc + chunk), Effect.fork);
21
- const stderrFiber = yield* process.stderr.pipe(Stream.decodeText('utf8'), Stream.runFold('', (acc, chunk) => acc + chunk), Effect.fork);
22
- const exitCode = yield* process.exitCode;
23
- const stdout = yield* Fiber.join(stdoutFiber);
24
- const stderr = yield* Fiber.join(stderrFiber);
25
- const exitCodeNumber = Number(exitCode);
26
- if (exitCodeNumber !== 0) {
27
- const stdoutLog = stdout.length > 0 ? stdout : '<empty stdout>';
28
- const stderrLog = stderr.length > 0 ? stderr : '<empty stderr>';
29
- const failureMessage = [
30
- `Docker compose pull failed with exit code ${exitCodeNumber} in ${cwd}`,
31
- `stdout:\n${stdoutLog}`,
32
- `stderr:\n${stderrLog}`,
33
- ].join('\n');
34
- yield* Effect.logError(failureMessage);
35
- return yield* new DockerComposeError({
36
- cause: new Error(`Docker compose pull failed with exit code ${exitCodeNumber}`),
37
- note: failureMessage,
38
- });
39
- }
40
- yield* Effect.log(`Successfully pulled Docker Compose images`);
41
- }).pipe(Effect.retry({
42
- schedule: Schedule.exponentialBackoff10Sec,
43
- while: Schema.is(DockerComposeError),
44
- }), Effect.withSpan('pullDockerComposeImages'), Effect.scoped);
45
- const start = Effect.fn('startDockerCompose')(function* (options = {}) {
46
- const { detached = true, healthCheck } = options;
47
- // Build start command
48
- const startArgs = ['docker', 'compose', ...baseComposeArgs, 'up'];
49
- if (detached === true)
50
- startArgs.push('-d');
51
- if (serviceName !== undefined)
52
- startArgs.push(serviceName);
53
- const command = yield* Command.make(startArgs[0], ...startArgs.slice(1)).pipe(Command.workingDirectory(cwd), Command.env(options.env ?? {}), Command.stderr('inherit'), Command.stdout('inherit'), Command.start, Effect.mapError((cause) => new DockerComposeError({
54
- cause,
55
- note: `Failed to start Docker Compose services in ${cwd}`,
56
- })), Effect.provide(commandExecutorContext));
57
- // Wait for command completion
58
- yield* command.exitCode.pipe(Effect.flatMap((exitCode) => exitCode === 0
59
- ? Effect.void
60
- : Effect.fail(new DockerComposeError({
61
- cause: new Error(`Docker compose exited with code ${exitCode}`),
62
- note: `Docker Compose failed to start with exit code ${exitCode}. Env: ${JSON.stringify(options.env)}`,
63
- }))), Effect.provide(commandExecutorContext));
64
- // Perform health check if requested
65
- if (healthCheck !== undefined) {
66
- yield* performHealthCheck(healthCheck).pipe(Effect.provide(commandExecutorContext));
67
- }
68
- yield* Effect.log(`Docker Compose services started successfully in ${cwd}`);
69
- });
70
- const stop = Effect.gen(function* () {
71
- yield* Effect.log(`Stopping Docker Compose services in ${cwd}`);
72
- const stopCommand = serviceName !== undefined
73
- ? Command.make('docker', 'compose', ...baseComposeArgs, 'stop', serviceName)
74
- : Command.make('docker', 'compose', ...baseComposeArgs, 'stop');
75
- yield* stopCommand.pipe(Command.workingDirectory(cwd), Command.exitCode, Effect.flatMap((exitCode) => exitCode === 0
76
- ? Effect.void
77
- : Effect.fail(new DockerComposeError({
78
- cause: new Error(`Docker compose stop exited with code ${exitCode}`),
79
- note: `Failed to stop Docker Compose services`,
80
- }))), Effect.provide(commandExecutorContext));
81
- yield* Effect.log(`Docker Compose services stopped successfully`);
82
- }).pipe(Effect.withSpan('stopDockerCompose'));
83
- const logs = (options = {}) => Effect.gen(function* () {
84
- const { follow = false, tail, since } = options;
85
- const logsArgs = ['docker', 'compose', ...baseComposeArgs, 'logs'];
86
- if (follow === true)
87
- logsArgs.push('-f');
88
- if (tail !== undefined)
89
- logsArgs.push('--tail', tail.toString());
90
- if (since !== undefined)
91
- logsArgs.push('--since', since);
92
- if (serviceName !== undefined)
93
- logsArgs.push(serviceName);
94
- const command = yield* Command.make(logsArgs[0], ...logsArgs.slice(1)).pipe(Command.workingDirectory(cwd), Command.start, Effect.mapError((cause) => new DockerComposeError({
95
- cause,
96
- note: `Failed to read Docker Compose logs in ${cwd}`,
97
- })), Effect.provide(commandExecutorContext));
98
- return command.stdout.pipe(Stream.decodeText('utf8'), Stream.splitLines, Stream.mapError((cause) => new DockerComposeError({
99
- cause,
100
- note: `Error reading Docker Compose logs in ${cwd}`,
101
- })));
102
- }).pipe(Stream.unwrapScoped);
103
- const down = Effect.fn('downDockerCompose')(function* (options) {
104
- yield* Effect.log(`Tearing down Docker Compose services in ${cwd}`);
105
- const downArgs = ['docker', 'compose', ...baseComposeArgs, 'down'];
106
- if (options?.volumes === true)
107
- downArgs.push('-v');
108
- if (options?.removeOrphans === true)
109
- downArgs.push('--remove-orphans');
110
- if (serviceName !== undefined)
111
- downArgs.push(serviceName);
112
- yield* Command.make(downArgs[0], ...downArgs.slice(1)).pipe(Command.workingDirectory(cwd), Command.env(options?.env ?? {}), Command.exitCode, Effect.flatMap((exitCode) => exitCode === 0
113
- ? Effect.void
114
- : Effect.fail(new DockerComposeError({
115
- cause: new Error(`Docker compose down exited with code ${exitCode}`),
116
- note: `Failed to tear down Docker Compose services`,
117
- }))), Effect.provide(commandExecutorContext));
118
- yield* Effect.log(`Docker Compose services torn down successfully`);
119
- });
120
- // Register cleanup finalizer to ensure containers are removed when scope closes
121
- yield* Effect.addFinalizer(() => down({ volumes: true, removeOrphans: true }).pipe(Effect.tap(() => Effect.log(`Docker Compose cleanup completed for project ${projectName}`)), Effect.catchAll((error) => Effect.log('Docker Compose cleanup failed for project', projectName, objectToString(error)))));
122
- return { pull, start, stop, down, logs, projectName };
123
- }),
124
- }) {
125
- }
126
- const performHealthCheck = ({ url, timeout = Duration.minutes(2), interval = Duration.seconds(2), }) => Effect.gen(function* () {
127
- yield* Effect.log(`Performing health check on ${url}`);
128
- const checkHealth = Command.make('curl', '-f', '-s', url).pipe(Command.exitCode, Effect.map((code) => code === 0), Effect.catchAll(() => Effect.succeed(false)));
129
- const healthCheck = checkHealth.pipe(Effect.repeat({
130
- while: (healthy) => healthy === false,
131
- schedule: Schedule.fixed(interval),
132
- }), Effect.timeout(timeout), Effect.mapError(() => new DockerComposeError({
133
- cause: new Error('Health check timeout'),
134
- note: `Health check failed for ${url} after ${Duration.toMillis(timeout)}ms`,
135
- })));
136
- yield* healthCheck;
137
- yield* Effect.log(`Health check passed for ${url}`);
138
- });
139
- // Convenience function for scoped Docker Compose operations with automatic cleanup
140
- export const startDockerComposeServicesScoped = (args) => Effect.gen(function* () {
141
- const dockerCompose = yield* DockerComposeService;
142
- // Start the services
143
- yield* dockerCompose.start({
144
- ...omitUndefineds({ healthCheck: args.healthCheck !== undefined ? args.healthCheck : undefined }),
145
- });
146
- // Add cleanup finalizer to the current scope
147
- yield* Effect.addFinalizer(() => dockerCompose.stop.pipe(Effect.orDie));
148
- });
149
- //# sourceMappingURL=DockerComposeService.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DockerComposeService.js","sourceRoot":"","sources":["../../../src/node/DockerComposeService/DockerComposeService.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=DockerComposeService.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DockerComposeService.test.d.ts","sourceRoot":"","sources":["../../../src/node/DockerComposeService/DockerComposeService.test.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"DockerComposeService.test.js","sourceRoot":"","sources":["../../../src/node/DockerComposeService/DockerComposeService.test.ts"],"names":[],"mappings":"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"}
@@ -1,343 +0,0 @@
1
- import { objectToString, omitUndefineds } from '@livestore/utils'
2
- import {
3
- Command,
4
- type CommandExecutor,
5
- Duration,
6
- Effect,
7
- Fiber,
8
- type PlatformError,
9
- Schedule,
10
- Schema,
11
- type Scope,
12
- Stream,
13
- } from '@livestore/utils/effect'
14
-
15
- export class DockerComposeError extends Schema.TaggedError<DockerComposeError>('~@livestore/utils-dev/DockerComposeError')('DockerComposeError', {
16
- cause: Schema.Defect,
17
- note: Schema.String,
18
- }) {}
19
-
20
- export interface DockerComposeArgs {
21
- readonly cwd: string
22
- readonly serviceName?: string
23
- /** Unique project name to isolate this compose instance. If not provided, a random one is generated. */
24
- readonly projectName?: string
25
- }
26
-
27
- export interface StartOptions {
28
- readonly detached?: boolean
29
- readonly env?: Record<string, string>
30
- readonly healthCheck?: {
31
- readonly url: string
32
- readonly timeout?: Duration.Duration
33
- readonly interval?: Duration.Duration
34
- }
35
- }
36
-
37
- export interface LogsOptions {
38
- readonly follow?: boolean
39
- readonly tail?: number
40
- readonly since?: string
41
- }
42
-
43
- export interface DockerComposeOperations {
44
- readonly pull: Effect.Effect<void, DockerComposeError | PlatformError.PlatformError>
45
- readonly start: (
46
- options?: StartOptions,
47
- ) => Effect.Effect<void, DockerComposeError | PlatformError.PlatformError, Scope.Scope>
48
- readonly stop: Effect.Effect<void, DockerComposeError | PlatformError.PlatformError>
49
- readonly down: (options?: {
50
- readonly env?: Record<string, string>
51
- readonly volumes?: boolean
52
- readonly removeOrphans?: boolean
53
- }) => Effect.Effect<void, DockerComposeError | PlatformError.PlatformError>
54
- readonly logs: (
55
- options?: LogsOptions,
56
- ) => Stream.Stream<string, DockerComposeError | PlatformError.PlatformError, Scope.Scope>
57
- /** The unique project name used to isolate this compose instance */
58
- readonly projectName: string
59
- }
60
-
61
- const generateProjectName = (): string => `ls-test-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
62
-
63
- export class DockerComposeService extends Effect.Service<DockerComposeService>()('DockerComposeService', {
64
- scoped: (args: DockerComposeArgs) =>
65
- Effect.gen(function* () {
66
- const { cwd, serviceName } = args
67
- const projectName = args.projectName ?? generateProjectName()
68
-
69
- const commandExecutorContext = yield* Effect.context<CommandExecutor.CommandExecutor>()
70
-
71
- const baseComposeArgs = ['-p', projectName]
72
-
73
- const pull = Effect.gen(function* () {
74
- yield* Effect.log(`Pulling Docker Compose images in ${cwd}`)
75
-
76
- // TODO (@IMax153) Refactor the effect command related code below as there is probably a much more elegant way to accomplish what we want here in a more effect idiomatic way.
77
- const pullCommand = Command.make('docker', 'compose', ...baseComposeArgs, 'pull').pipe(
78
- Command.workingDirectory(cwd),
79
- Command.stdout('pipe'),
80
- Command.stderr('pipe'),
81
- )
82
-
83
- const process = yield* pullCommand.pipe(Command.start, Effect.provide(commandExecutorContext))
84
-
85
- const stdoutFiber = yield* process.stdout.pipe(
86
- Stream.decodeText('utf8'),
87
- Stream.runFold('', (acc, chunk) => acc + chunk),
88
- Effect.fork,
89
- )
90
-
91
- const stderrFiber = yield* process.stderr.pipe(
92
- Stream.decodeText('utf8'),
93
- Stream.runFold('', (acc, chunk) => acc + chunk),
94
- Effect.fork,
95
- )
96
-
97
- const exitCode = yield* process.exitCode
98
- const stdout = yield* Fiber.join(stdoutFiber)
99
- const stderr = yield* Fiber.join(stderrFiber)
100
-
101
- const exitCodeNumber = Number(exitCode)
102
-
103
- if (exitCodeNumber !== 0) {
104
- const stdoutLog = stdout.length > 0 ? stdout : '<empty stdout>'
105
- const stderrLog = stderr.length > 0 ? stderr : '<empty stderr>'
106
- const failureMessage = [
107
- `Docker compose pull failed with exit code ${exitCodeNumber} in ${cwd}`,
108
- `stdout:\n${stdoutLog}`,
109
- `stderr:\n${stderrLog}`,
110
- ].join('\n')
111
-
112
- yield* Effect.logError(failureMessage)
113
-
114
- return yield* new DockerComposeError({
115
- cause: new Error(`Docker compose pull failed with exit code ${exitCodeNumber}`),
116
- note: failureMessage,
117
- })
118
- }
119
-
120
- yield* Effect.log(`Successfully pulled Docker Compose images`)
121
- }).pipe(
122
- Effect.retry({
123
- schedule: Schedule.exponentialBackoff10Sec,
124
- while: Schema.is(DockerComposeError),
125
- }),
126
- Effect.withSpan('pullDockerComposeImages'),
127
- Effect.scoped,
128
- )
129
-
130
- const start = Effect.fn('startDockerCompose')(function* (options: StartOptions = {}) {
131
- const { detached = true, healthCheck } = options
132
-
133
- // Build start command
134
- const startArgs = ['docker', 'compose', ...baseComposeArgs, 'up']
135
- if (detached === true) startArgs.push('-d')
136
- if (serviceName !== undefined) startArgs.push(serviceName)
137
-
138
- const command = yield* Command.make(startArgs[0]!, ...startArgs.slice(1)).pipe(
139
- Command.workingDirectory(cwd),
140
- Command.env(options.env ?? {}),
141
- Command.stderr('inherit'),
142
- Command.stdout('inherit'),
143
- Command.start,
144
- Effect.mapError(
145
- (cause) =>
146
- new DockerComposeError({
147
- cause,
148
- note: `Failed to start Docker Compose services in ${cwd}`,
149
- }),
150
- ),
151
- Effect.provide(commandExecutorContext),
152
- )
153
-
154
- // Wait for command completion
155
- yield* command.exitCode.pipe(
156
- Effect.flatMap((exitCode) =>
157
- exitCode === 0
158
- ? Effect.void
159
- : Effect.fail(
160
- new DockerComposeError({
161
- cause: new Error(`Docker compose exited with code ${exitCode}`),
162
- note: `Docker Compose failed to start with exit code ${exitCode}. Env: ${JSON.stringify(options.env)}`,
163
- }),
164
- ),
165
- ),
166
- Effect.provide(commandExecutorContext),
167
- )
168
-
169
- // Perform health check if requested
170
- if (healthCheck !== undefined) {
171
- yield* performHealthCheck(healthCheck).pipe(Effect.provide(commandExecutorContext))
172
- }
173
-
174
- yield* Effect.log(`Docker Compose services started successfully in ${cwd}`)
175
- })
176
-
177
- const stop = Effect.gen(function* () {
178
- yield* Effect.log(`Stopping Docker Compose services in ${cwd}`)
179
-
180
- const stopCommand =
181
- serviceName !== undefined
182
- ? Command.make('docker', 'compose', ...baseComposeArgs, 'stop', serviceName)
183
- : Command.make('docker', 'compose', ...baseComposeArgs, 'stop')
184
-
185
- yield* stopCommand.pipe(
186
- Command.workingDirectory(cwd),
187
- Command.exitCode,
188
- Effect.flatMap((exitCode: number) =>
189
- exitCode === 0
190
- ? Effect.void
191
- : Effect.fail(
192
- new DockerComposeError({
193
- cause: new Error(`Docker compose stop exited with code ${exitCode}`),
194
- note: `Failed to stop Docker Compose services`,
195
- }),
196
- ),
197
- ),
198
- Effect.provide(commandExecutorContext),
199
- )
200
-
201
- yield* Effect.log(`Docker Compose services stopped successfully`)
202
- }).pipe(Effect.withSpan('stopDockerCompose'))
203
-
204
- const logs = (options: LogsOptions = {}) =>
205
- Effect.gen(function* () {
206
- const { follow = false, tail, since } = options
207
-
208
- const logsArgs = ['docker', 'compose', ...baseComposeArgs, 'logs']
209
- if (follow === true) logsArgs.push('-f')
210
- if (tail !== undefined) logsArgs.push('--tail', tail.toString())
211
- if (since !== undefined) logsArgs.push('--since', since)
212
- if (serviceName !== undefined) logsArgs.push(serviceName)
213
-
214
- const command = yield* Command.make(logsArgs[0]!, ...logsArgs.slice(1)).pipe(
215
- Command.workingDirectory(cwd),
216
- Command.start,
217
- Effect.mapError(
218
- (cause) =>
219
- new DockerComposeError({
220
- cause,
221
- note: `Failed to read Docker Compose logs in ${cwd}`,
222
- }),
223
- ),
224
- Effect.provide(commandExecutorContext),
225
- )
226
-
227
- return command.stdout.pipe(
228
- Stream.decodeText('utf8'),
229
- Stream.splitLines,
230
- Stream.mapError(
231
- (cause) =>
232
- new DockerComposeError({
233
- cause,
234
- note: `Error reading Docker Compose logs in ${cwd}`,
235
- }),
236
- ),
237
- )
238
- }).pipe(Stream.unwrapScoped)
239
-
240
- const down = Effect.fn('downDockerCompose')(function* (options?: {
241
- readonly env?: Record<string, string>
242
- readonly volumes?: boolean
243
- readonly removeOrphans?: boolean
244
- }) {
245
- yield* Effect.log(`Tearing down Docker Compose services in ${cwd}`)
246
-
247
- const downArgs = ['docker', 'compose', ...baseComposeArgs, 'down']
248
- if (options?.volumes === true) downArgs.push('-v')
249
- if (options?.removeOrphans === true) downArgs.push('--remove-orphans')
250
- if (serviceName !== undefined) downArgs.push(serviceName)
251
-
252
- yield* Command.make(downArgs[0]!, ...downArgs.slice(1)).pipe(
253
- Command.workingDirectory(cwd),
254
- Command.env(options?.env ?? {}),
255
- Command.exitCode,
256
- Effect.flatMap((exitCode: number) =>
257
- exitCode === 0
258
- ? Effect.void
259
- : Effect.fail(
260
- new DockerComposeError({
261
- cause: new Error(`Docker compose down exited with code ${exitCode}`),
262
- note: `Failed to tear down Docker Compose services`,
263
- }),
264
- ),
265
- ),
266
- Effect.provide(commandExecutorContext),
267
- )
268
-
269
- yield* Effect.log(`Docker Compose services torn down successfully`)
270
- })
271
-
272
- // Register cleanup finalizer to ensure containers are removed when scope closes
273
- yield* Effect.addFinalizer(() =>
274
- down({ volumes: true, removeOrphans: true }).pipe(
275
- Effect.tap(() => Effect.log(`Docker Compose cleanup completed for project ${projectName}`)),
276
- Effect.catchAll((error) =>
277
- Effect.log('Docker Compose cleanup failed for project', projectName, objectToString(error)),
278
- ),
279
- ),
280
- )
281
-
282
- return { pull, start, stop, down, logs, projectName }
283
- }),
284
- }) {}
285
-
286
- const performHealthCheck = ({
287
- url,
288
- timeout = Duration.minutes(2),
289
- interval = Duration.seconds(2),
290
- }: {
291
- url: string
292
- timeout?: Duration.Duration
293
- interval?: Duration.Duration
294
- }): Effect.Effect<void, DockerComposeError, CommandExecutor.CommandExecutor | Scope.Scope> =>
295
- Effect.gen(function* () {
296
- yield* Effect.log(`Performing health check on ${url}`)
297
-
298
- const checkHealth = Command.make('curl', '-f', '-s', url).pipe(
299
- Command.exitCode,
300
- Effect.map((code: number) => code === 0),
301
- Effect.catchAll(() => Effect.succeed(false)),
302
- )
303
-
304
- const healthCheck = checkHealth.pipe(
305
- Effect.repeat({
306
- while: (healthy: boolean) => healthy === false,
307
- schedule: Schedule.fixed(interval),
308
- }),
309
- Effect.timeout(timeout),
310
- Effect.mapError(
311
- () =>
312
- new DockerComposeError({
313
- cause: new Error('Health check timeout'),
314
- note: `Health check failed for ${url} after ${Duration.toMillis(timeout)}ms`,
315
- }),
316
- ),
317
- )
318
-
319
- yield* healthCheck
320
- yield* Effect.log(`Health check passed for ${url}`)
321
- })
322
-
323
- // Convenience function for scoped Docker Compose operations with automatic cleanup
324
- export const startDockerComposeServicesScoped = (
325
- args: DockerComposeArgs & {
326
- healthCheck?: StartOptions['healthCheck']
327
- },
328
- ): Effect.Effect<
329
- void,
330
- DockerComposeError | PlatformError.PlatformError,
331
- DockerComposeService | CommandExecutor.CommandExecutor | Scope.Scope
332
- > =>
333
- Effect.gen(function* () {
334
- const dockerCompose = yield* DockerComposeService
335
-
336
- // Start the services
337
- yield* dockerCompose.start({
338
- ...omitUndefineds({ healthCheck: args.healthCheck !== undefined ? args.healthCheck : undefined }),
339
- })
340
-
341
- // Add cleanup finalizer to the current scope
342
- yield* Effect.addFinalizer(() => dockerCompose.stop.pipe(Effect.orDie))
343
- })