@livestore/utils-dev 0.4.0-dev.1 → 0.4.0-dev.11

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 (68) hide show
  1. package/dist/.tsbuildinfo.json +1 -1
  2. package/dist/node/DockerComposeService/DockerComposeService.d.ts +58 -0
  3. package/dist/node/DockerComposeService/DockerComposeService.d.ts.map +1 -0
  4. package/dist/node/DockerComposeService/DockerComposeService.js +144 -0
  5. package/dist/node/DockerComposeService/DockerComposeService.js.map +1 -0
  6. package/dist/node/DockerComposeService/DockerComposeService.test.d.ts +2 -0
  7. package/dist/node/DockerComposeService/DockerComposeService.test.d.ts.map +1 -0
  8. package/dist/node/DockerComposeService/DockerComposeService.test.js +64 -0
  9. package/dist/node/DockerComposeService/DockerComposeService.test.js.map +1 -0
  10. package/dist/node/cmd-log.d.ts +21 -0
  11. package/dist/node/cmd-log.d.ts.map +1 -0
  12. package/dist/node/cmd-log.js +50 -0
  13. package/dist/node/cmd-log.js.map +1 -0
  14. package/dist/node/cmd.d.ts +36 -0
  15. package/dist/node/cmd.d.ts.map +1 -0
  16. package/dist/node/cmd.js +234 -0
  17. package/dist/node/cmd.js.map +1 -0
  18. package/dist/node/cmd.test.d.ts +2 -0
  19. package/dist/node/cmd.test.d.ts.map +1 -0
  20. package/dist/node/cmd.test.js +101 -0
  21. package/dist/node/cmd.test.js.map +1 -0
  22. package/dist/node/mod.d.ts +4 -26
  23. package/dist/node/mod.d.ts.map +1 -1
  24. package/dist/node/mod.js +51 -59
  25. package/dist/node/mod.js.map +1 -1
  26. package/dist/node-vitest/Vitest.d.ts +41 -7
  27. package/dist/node-vitest/Vitest.d.ts.map +1 -1
  28. package/dist/node-vitest/Vitest.js +82 -5
  29. package/dist/node-vitest/Vitest.js.map +1 -1
  30. package/dist/node-vitest/Vitest.test.d.ts +2 -0
  31. package/dist/node-vitest/Vitest.test.d.ts.map +1 -0
  32. package/dist/node-vitest/Vitest.test.js +70 -0
  33. package/dist/node-vitest/Vitest.test.js.map +1 -0
  34. package/dist/wrangler/WranglerDevServer.d.ts +52 -0
  35. package/dist/wrangler/WranglerDevServer.d.ts.map +1 -0
  36. package/dist/wrangler/WranglerDevServer.js +90 -0
  37. package/dist/wrangler/WranglerDevServer.js.map +1 -0
  38. package/dist/wrangler/WranglerDevServer.test.d.ts +2 -0
  39. package/dist/wrangler/WranglerDevServer.test.d.ts.map +1 -0
  40. package/dist/wrangler/WranglerDevServer.test.js +77 -0
  41. package/dist/wrangler/WranglerDevServer.test.js.map +1 -0
  42. package/dist/wrangler/fixtures/cf-worker.d.ts +8 -0
  43. package/dist/wrangler/fixtures/cf-worker.d.ts.map +1 -0
  44. package/dist/wrangler/fixtures/cf-worker.js +11 -0
  45. package/dist/wrangler/fixtures/cf-worker.js.map +1 -0
  46. package/dist/wrangler/mod.d.ts +2 -0
  47. package/dist/wrangler/mod.d.ts.map +1 -0
  48. package/dist/wrangler/mod.js +2 -0
  49. package/dist/wrangler/mod.js.map +1 -0
  50. package/package.json +11 -10
  51. package/src/node/DockerComposeService/DockerComposeService.test.ts +91 -0
  52. package/src/node/DockerComposeService/DockerComposeService.ts +328 -0
  53. package/src/node/DockerComposeService/test-fixtures/docker-compose.yml +4 -0
  54. package/src/node/cmd-log.ts +92 -0
  55. package/src/node/cmd.test.ts +129 -0
  56. package/src/node/cmd.ts +419 -0
  57. package/src/node/mod.ts +62 -116
  58. package/src/node-vitest/Vitest.test.ts +112 -0
  59. package/src/node-vitest/Vitest.ts +193 -17
  60. package/src/wrangler/WranglerDevServer.test.ts +133 -0
  61. package/src/wrangler/WranglerDevServer.ts +180 -0
  62. package/src/wrangler/fixtures/cf-worker.ts +11 -0
  63. package/src/wrangler/fixtures/wrangler.toml +11 -0
  64. package/src/wrangler/mod.ts +6 -0
  65. package/dist/node-vitest/polyfill.d.ts +0 -2
  66. package/dist/node-vitest/polyfill.d.ts.map +0 -1
  67. package/dist/node-vitest/polyfill.js +0 -3
  68. package/dist/node-vitest/polyfill.js.map +0 -1
@@ -0,0 +1,58 @@
1
+ import { type CommandExecutor, Duration, Effect, type PlatformError, Schema, type Scope, Stream } from '@livestore/utils/effect';
2
+ declare const DockerComposeError_base: Schema.TaggedErrorClass<DockerComposeError, "DockerComposeError", {
3
+ readonly _tag: Schema.tag<"DockerComposeError">;
4
+ } & {
5
+ cause: typeof Schema.Defect;
6
+ note: typeof Schema.String;
7
+ }>;
8
+ export declare class DockerComposeError extends DockerComposeError_base {
9
+ }
10
+ export interface DockerComposeArgs {
11
+ readonly cwd: string;
12
+ readonly serviceName?: string;
13
+ }
14
+ export interface StartOptions {
15
+ readonly detached?: boolean;
16
+ readonly env?: Record<string, string>;
17
+ readonly healthCheck?: {
18
+ readonly url: string;
19
+ readonly timeout?: Duration.Duration;
20
+ readonly interval?: Duration.Duration;
21
+ };
22
+ }
23
+ export interface LogsOptions {
24
+ readonly follow?: boolean;
25
+ readonly tail?: number;
26
+ readonly since?: string;
27
+ }
28
+ export interface DockerComposeOperations {
29
+ readonly pull: Effect.Effect<void, DockerComposeError | PlatformError.PlatformError>;
30
+ readonly start: (options?: StartOptions) => Effect.Effect<void, DockerComposeError | PlatformError.PlatformError, Scope.Scope>;
31
+ readonly stop: Effect.Effect<void, DockerComposeError | PlatformError.PlatformError>;
32
+ readonly down: (options?: {
33
+ readonly env?: Record<string, string>;
34
+ readonly volumes?: boolean;
35
+ readonly removeOrphans?: boolean;
36
+ }) => Effect.Effect<void, DockerComposeError | PlatformError.PlatformError>;
37
+ readonly logs: (options?: LogsOptions) => Stream.Stream<string, DockerComposeError | PlatformError.PlatformError, Scope.Scope>;
38
+ }
39
+ declare const DockerComposeService_base: Effect.Service.Class<DockerComposeService, "DockerComposeService", {
40
+ readonly scoped: (args: DockerComposeArgs) => Effect.Effect<{
41
+ pull: Effect.Effect<undefined, PlatformError.PlatformError | DockerComposeError, never>;
42
+ start: (options?: StartOptions) => Effect.Effect<void, PlatformError.PlatformError | DockerComposeError, Scope.Scope>;
43
+ stop: Effect.Effect<void, PlatformError.PlatformError | DockerComposeError, never>;
44
+ down: (options?: {
45
+ readonly env?: Record<string, string>;
46
+ readonly volumes?: boolean;
47
+ readonly removeOrphans?: boolean;
48
+ }) => Effect.Effect<void, PlatformError.PlatformError | DockerComposeError, never>;
49
+ logs: (options?: LogsOptions) => Stream.Stream<string, DockerComposeError, never>;
50
+ }, never, CommandExecutor.CommandExecutor>;
51
+ }>;
52
+ export declare class DockerComposeService extends DockerComposeService_base {
53
+ }
54
+ export declare const startDockerComposeServicesScoped: (args: DockerComposeArgs & {
55
+ healthCheck?: StartOptions["healthCheck"];
56
+ }) => Effect.Effect<void, DockerComposeError | PlatformError.PlatformError, DockerComposeService | CommandExecutor.CommandExecutor | Scope.Scope>;
57
+ export {};
58
+ //# sourceMappingURL=DockerComposeService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DockerComposeService.d.ts","sourceRoot":"","sources":["../../../src/node/DockerComposeService/DockerComposeService.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,eAAe,EACpB,QAAQ,EACR,MAAM,EAEN,KAAK,aAAa,EAElB,MAAM,EACN,KAAK,KAAK,EACV,MAAM,EACP,MAAM,yBAAyB,CAAA;;;;;;;AAEhC,qBAAa,kBAAmB,SAAQ,uBAGtC;CAAG;AAEL,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,QAAQ,CAAC,WAAW,CAAC,EAAE;QACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;QACpB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAA;QACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAA;KACtC,CAAA;CACF;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,kBAAkB,GAAG,aAAa,CAAC,aAAa,CAAC,CAAA;IACpF,QAAQ,CAAC,KAAK,EAAE,CACd,OAAO,CAAC,EAAE,YAAY,KACnB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,kBAAkB,GAAG,aAAa,CAAC,aAAa,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;IACvF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,kBAAkB,GAAG,aAAa,CAAC,aAAa,CAAC,CAAA;IACpF,QAAQ,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE;QACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;QAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KACjC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,kBAAkB,GAAG,aAAa,CAAC,aAAa,CAAC,CAAA;IAC3E,QAAQ,CAAC,IAAI,EAAE,CACb,OAAO,CAAC,EAAE,WAAW,KAClB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,aAAa,CAAC,aAAa,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;CAC1F;;4BAGgB,iBAAiB;;0BA+DJ,YAAY;;yBAgHZ;YACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;YACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;YAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;SACjC;yBAzCsB,WAAW;;;AA3IxC,qBAAa,oBAAqB,SAAQ,yBAmNxC;CAAG;AAyCL,eAAO,MAAM,gCAAgC,GAC3C,MAAM,iBAAiB,GAAG;IACxB,WAAW,CAAC,EAAE,YAAY,CAAC,aAAa,CAAC,CAAA;CAC1C,KACA,MAAM,CAAC,MAAM,CACd,IAAI,EACJ,kBAAkB,GAAG,aAAa,CAAC,aAAa,EAChD,oBAAoB,GAAG,eAAe,CAAC,eAAe,GAAG,KAAK,CAAC,KAAK,CAYlE,CAAA"}
@@ -0,0 +1,144 @@
1
+ import { omitUndefineds } from '@livestore/utils';
2
+ import { Command, Duration, Effect, Fiber, Schedule, Schema, Stream, } from '@livestore/utils/effect';
3
+ export class DockerComposeError extends Schema.TaggedError()('DockerComposeError', {
4
+ cause: Schema.Defect,
5
+ note: Schema.String,
6
+ }) {
7
+ }
8
+ export class DockerComposeService extends Effect.Service()('DockerComposeService', {
9
+ scoped: (args) => Effect.gen(function* () {
10
+ const { cwd, serviceName } = args;
11
+ const commandExecutorContext = yield* Effect.context();
12
+ const pull = Effect.gen(function* () {
13
+ yield* Effect.log(`Pulling Docker Compose images in ${cwd}`);
14
+ // 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.
15
+ const pullCommand = Command.make('docker', 'compose', 'pull').pipe(Command.workingDirectory(cwd), Command.stdout('pipe'), Command.stderr('pipe'));
16
+ const process = yield* pullCommand.pipe(Command.start, Effect.provide(commandExecutorContext));
17
+ const stdoutFiber = yield* process.stdout.pipe(Stream.decodeText('utf8'), Stream.runFold('', (acc, chunk) => acc + chunk), Effect.fork);
18
+ const stderrFiber = yield* process.stderr.pipe(Stream.decodeText('utf8'), Stream.runFold('', (acc, chunk) => acc + chunk), Effect.fork);
19
+ const exitCode = yield* process.exitCode;
20
+ const stdout = yield* Fiber.join(stdoutFiber);
21
+ const stderr = yield* Fiber.join(stderrFiber);
22
+ const exitCodeNumber = Number(exitCode);
23
+ if (exitCodeNumber !== 0) {
24
+ const stdoutLog = stdout.length > 0 ? stdout : '<empty stdout>';
25
+ const stderrLog = stderr.length > 0 ? stderr : '<empty stderr>';
26
+ const failureMessage = [
27
+ `Docker compose pull failed with exit code ${exitCodeNumber} in ${cwd}`,
28
+ `stdout:\n${stdoutLog}`,
29
+ `stderr:\n${stderrLog}`,
30
+ ].join('\n');
31
+ yield* Effect.logError(failureMessage);
32
+ return yield* new DockerComposeError({
33
+ cause: new Error(`Docker compose pull failed with exit code ${exitCodeNumber}`),
34
+ note: failureMessage,
35
+ });
36
+ }
37
+ yield* Effect.log(`Successfully pulled Docker Compose images`);
38
+ }).pipe(Effect.retry({
39
+ schedule: Schedule.exponentialBackoff10Sec,
40
+ while: Schema.is(DockerComposeError),
41
+ }), Effect.withSpan('pullDockerComposeImages'), Effect.scoped);
42
+ const start = (options = {}) => Effect.gen(function* () {
43
+ const { detached = true, healthCheck } = options;
44
+ // Build start command
45
+ const baseArgs = ['docker', 'compose', 'up'];
46
+ if (detached)
47
+ baseArgs.push('-d');
48
+ if (serviceName)
49
+ baseArgs.push(serviceName);
50
+ const command = yield* Command.make(baseArgs[0], ...baseArgs.slice(1)).pipe(Command.workingDirectory(cwd), Command.env(options.env ?? {}), Command.stderr('inherit'), Command.stdout('inherit'), Command.start, Effect.catchAll((cause) => Effect.fail(new DockerComposeError({
51
+ cause,
52
+ note: `Failed to start Docker Compose services in ${cwd}`,
53
+ }))), Effect.provide(commandExecutorContext));
54
+ // Wait for command completion
55
+ yield* command.exitCode.pipe(Effect.flatMap((exitCode) => exitCode === 0
56
+ ? Effect.void
57
+ : Effect.fail(new DockerComposeError({
58
+ cause: new Error(`Docker compose exited with code ${exitCode}`),
59
+ note: `Docker Compose failed to start with exit code ${exitCode}. Env: ${JSON.stringify(options.env)}`,
60
+ }))), Effect.provide(commandExecutorContext));
61
+ // Perform health check if requested
62
+ if (healthCheck) {
63
+ yield* performHealthCheck(healthCheck).pipe(Effect.provide(commandExecutorContext));
64
+ }
65
+ yield* Effect.log(`Docker Compose services started successfully in ${cwd}`);
66
+ }).pipe(Effect.withSpan('startDockerCompose'));
67
+ const stop = Effect.gen(function* () {
68
+ yield* Effect.log(`Stopping Docker Compose services in ${cwd}`);
69
+ const stopCommand = serviceName
70
+ ? Command.make('docker', 'compose', 'stop', serviceName)
71
+ : Command.make('docker', 'compose', 'stop');
72
+ yield* stopCommand.pipe(Command.workingDirectory(cwd), Command.exitCode, Effect.flatMap((exitCode) => exitCode === 0
73
+ ? Effect.void
74
+ : Effect.fail(new DockerComposeError({
75
+ cause: new Error(`Docker compose stop exited with code ${exitCode}`),
76
+ note: `Failed to stop Docker Compose services`,
77
+ }))), Effect.provide(commandExecutorContext));
78
+ yield* Effect.log(`Docker Compose services stopped successfully`);
79
+ }).pipe(Effect.withSpan('stopDockerCompose'));
80
+ const logs = (options = {}) => Effect.gen(function* () {
81
+ const { follow = false, tail, since } = options;
82
+ const baseArgs = ['docker', 'compose', 'logs'];
83
+ if (follow)
84
+ baseArgs.push('-f');
85
+ if (tail)
86
+ baseArgs.push('--tail', tail.toString());
87
+ if (since)
88
+ baseArgs.push('--since', since);
89
+ if (serviceName)
90
+ baseArgs.push(serviceName);
91
+ const command = yield* Command.make(baseArgs[0], ...baseArgs.slice(1)).pipe(Command.workingDirectory(cwd), Command.start, Effect.catchAll((cause) => Effect.fail(new DockerComposeError({
92
+ cause,
93
+ note: `Failed to read Docker Compose logs in ${cwd}`,
94
+ }))), Effect.provide(commandExecutorContext));
95
+ return command.stdout.pipe(Stream.decodeText('utf8'), Stream.splitLines, Stream.mapError((cause) => new DockerComposeError({
96
+ cause,
97
+ note: `Error reading Docker Compose logs in ${cwd}`,
98
+ })));
99
+ }).pipe(Stream.unwrapScoped);
100
+ const down = (options) => Effect.gen(function* () {
101
+ yield* Effect.log(`Tearing down Docker Compose services in ${cwd}`);
102
+ const baseArgs = ['docker', 'compose', 'down'];
103
+ if (options?.volumes)
104
+ baseArgs.push('-v');
105
+ if (options?.removeOrphans)
106
+ baseArgs.push('--remove-orphans');
107
+ if (serviceName)
108
+ baseArgs.push(serviceName);
109
+ yield* Command.make(baseArgs[0], ...baseArgs.slice(1)).pipe(Command.workingDirectory(cwd), Command.env(options?.env ?? {}), Command.exitCode, Effect.flatMap((exitCode) => exitCode === 0
110
+ ? Effect.void
111
+ : Effect.fail(new DockerComposeError({
112
+ cause: new Error(`Docker compose down exited with code ${exitCode}`),
113
+ note: `Failed to tear down Docker Compose services`,
114
+ }))), Effect.provide(commandExecutorContext));
115
+ yield* Effect.log(`Docker Compose services torn down successfully`);
116
+ }).pipe(Effect.withSpan('downDockerCompose'));
117
+ return { pull, start, stop, down, logs };
118
+ }),
119
+ }) {
120
+ }
121
+ const performHealthCheck = ({ url, timeout = Duration.minutes(2), interval = Duration.seconds(2), }) => Effect.gen(function* () {
122
+ yield* Effect.log(`Performing health check on ${url}`);
123
+ const checkHealth = Command.make('curl', '-f', '-s', url).pipe(Command.exitCode, Effect.map((code) => code === 0), Effect.catchAll(() => Effect.succeed(false)));
124
+ const healthCheck = checkHealth.pipe(Effect.repeat({
125
+ while: (healthy) => !healthy,
126
+ schedule: Schedule.fixed(interval),
127
+ }), Effect.timeout(timeout), Effect.catchAll(() => Effect.fail(new DockerComposeError({
128
+ cause: new Error('Health check timeout'),
129
+ note: `Health check failed for ${url} after ${Duration.toMillis(timeout)}ms`,
130
+ }))));
131
+ yield* healthCheck;
132
+ yield* Effect.log(`Health check passed for ${url}`);
133
+ });
134
+ // Convenience function for scoped Docker Compose operations with automatic cleanup
135
+ export const startDockerComposeServicesScoped = (args) => Effect.gen(function* () {
136
+ const dockerCompose = yield* DockerComposeService;
137
+ // Start the services
138
+ yield* dockerCompose.start({
139
+ ...omitUndefineds({ healthCheck: args.healthCheck ? args.healthCheck : undefined }),
140
+ });
141
+ // Add cleanup finalizer to the current scope
142
+ yield* Effect.addFinalizer(() => dockerCompose.stop.pipe(Effect.orDie));
143
+ });
144
+ //# sourceMappingURL=DockerComposeService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DockerComposeService.js","sourceRoot":"","sources":["../../../src/node/DockerComposeService/DockerComposeService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=DockerComposeService.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DockerComposeService.test.d.ts","sourceRoot":"","sources":["../../../src/node/DockerComposeService/DockerComposeService.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,64 @@
1
+ import path from 'node:path';
2
+ import { Duration, Effect, Layer, Stream } from '@livestore/utils/effect';
3
+ import { PlatformNode } from '@livestore/utils/node';
4
+ import { Vitest } from '@livestore/utils-dev/node-vitest';
5
+ import { expect } from 'vitest';
6
+ import { DockerComposeService } from "./DockerComposeService.js";
7
+ const testTimeout = 30_000;
8
+ const testFixturePath = path.join(import.meta.dirname, 'test-fixtures');
9
+ const DockerComposeTest = (args = {}) => DockerComposeService.Default({
10
+ cwd: testFixturePath,
11
+ ...args,
12
+ });
13
+ Vitest.describe('DockerComposeService', { timeout: testTimeout }, () => {
14
+ Vitest.describe('Basic Operations', () => {
15
+ const withBasicTest = (args = {}) => Vitest.makeWithTestCtx({
16
+ timeout: testTimeout,
17
+ makeLayer: () => DockerComposeTest(args).pipe(Layer.provide(PlatformNode.NodeContext.layer)),
18
+ });
19
+ Vitest.scopedLive('can pull docker images', (test) => Effect.gen(function* () {
20
+ const dockerCompose = yield* DockerComposeService;
21
+ // Test that pull operation works (should succeed for hello-world image)
22
+ yield* dockerCompose.pull;
23
+ }).pipe(withBasicTest()(test)));
24
+ Vitest.scopedLive('can start and stop docker compose services', (test) => Effect.gen(function* () {
25
+ const dockerCompose = yield* DockerComposeService;
26
+ // Start the service
27
+ yield* dockerCompose.start({ detached: true });
28
+ // Stop the service
29
+ yield* dockerCompose.stop;
30
+ }).pipe(withBasicTest({ serviceName: 'hello-world' })(test)));
31
+ Vitest.scopedLive('can get logs from docker compose services', (test) => Effect.gen(function* () {
32
+ const dockerCompose = yield* DockerComposeService;
33
+ // Start the service first
34
+ yield* dockerCompose.start({ detached: true });
35
+ // Get logs (should contain at least the "Hello from Docker!" message)
36
+ const firstLogLine = yield* dockerCompose.logs().pipe(Stream.runHead);
37
+ expect(firstLogLine._tag).toBe('Some');
38
+ // Stop the service
39
+ yield* dockerCompose.stop;
40
+ }).pipe(withBasicTest({ serviceName: 'hello-world' })(test)));
41
+ });
42
+ Vitest.describe('Health Check Operations', () => {
43
+ const withHealthCheckTest = (args = {}) => Vitest.makeWithTestCtx({
44
+ timeout: testTimeout,
45
+ makeLayer: () => DockerComposeTest(args).pipe(Layer.provide(PlatformNode.NodeContext.layer)),
46
+ });
47
+ Vitest.scopedLive('handles health check timeout gracefully', (test) => Effect.gen(function* () {
48
+ const dockerCompose = yield* DockerComposeService;
49
+ // Test starting with a health check that will timeout (invalid URL)
50
+ const result = yield* dockerCompose
51
+ .start({
52
+ detached: true,
53
+ healthCheck: {
54
+ url: 'http://localhost:99999/nonexistent',
55
+ timeout: Duration.seconds(2),
56
+ },
57
+ })
58
+ .pipe(Effect.either);
59
+ // Should fail due to health check timeout
60
+ expect(result._tag).toBe('Left');
61
+ }).pipe(withHealthCheckTest({ serviceName: 'hello-world' })(test)));
62
+ });
63
+ });
64
+ //# sourceMappingURL=DockerComposeService.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DockerComposeService.test.js","sourceRoot":"","sources":["../../../src/node/DockerComposeService/DockerComposeService.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAA;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAA0B,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAExF,MAAM,WAAW,GAAG,MAAM,CAAA;AAC1B,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;AAEvE,MAAM,iBAAiB,GAAG,CAAC,OAAmC,EAAE,EAAE,EAAE,CAClE,oBAAoB,CAAC,OAAO,CAAC;IAC3B,GAAG,EAAE,eAAe;IACpB,GAAG,IAAI;CACR,CAAC,CAAA;AAEJ,MAAM,CAAC,QAAQ,CAAC,sBAAsB,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE;IACrE,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QACvC,MAAM,aAAa,GAAG,CAAC,OAAmC,EAAE,EAAE,EAAE,CAC9D,MAAM,CAAC,eAAe,CAAC;YACrB,OAAO,EAAE,WAAW;YACpB,SAAS,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;SAC7F,CAAC,CAAA;QAEJ,MAAM,CAAC,UAAU,CAAC,wBAAwB,EAAE,CAAC,IAAI,EAAE,EAAE,CACnD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,oBAAoB,CAAA;YAEjD,wEAAwE;YACxE,KAAK,CAAC,CAAC,aAAa,CAAC,IAAI,CAAA;QAC3B,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC,CAC/B,CAAA;QAED,MAAM,CAAC,UAAU,CAAC,4CAA4C,EAAE,CAAC,IAAI,EAAE,EAAE,CACvE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,oBAAoB,CAAA;YAEjD,oBAAoB;YACpB,KAAK,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;YAE9C,mBAAmB;YACnB,KAAK,CAAC,CAAC,aAAa,CAAC,IAAI,CAAA;QAC3B,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAC7D,CAAA;QAED,MAAM,CAAC,UAAU,CAAC,2CAA2C,EAAE,CAAC,IAAI,EAAE,EAAE,CACtE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,oBAAoB,CAAA;YAEjD,0BAA0B;YAC1B,KAAK,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;YAE9C,sEAAsE;YACtE,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;YAErE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YAEtC,mBAAmB;YACnB,KAAK,CAAC,CAAC,aAAa,CAAC,IAAI,CAAA;QAC3B,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAC7D,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,MAAM,CAAC,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QAC9C,MAAM,mBAAmB,GAAG,CAAC,OAAmC,EAAE,EAAE,EAAE,CACpE,MAAM,CAAC,eAAe,CAAC;YACrB,OAAO,EAAE,WAAW;YACpB,SAAS,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;SAC7F,CAAC,CAAA;QAEJ,MAAM,CAAC,UAAU,CAAC,yCAAyC,EAAE,CAAC,IAAI,EAAE,EAAE,CACpE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,oBAAoB,CAAA;YAEjD,oEAAoE;YACpE,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,aAAa;iBAChC,KAAK,CAAC;gBACL,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE;oBACX,GAAG,EAAE,oCAAoC;oBACzC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;iBAC7B;aACF,CAAC;iBACD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YAEtB,0CAA0C;YAC1C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAClC,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CACnE,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,21 @@
1
+ import { Effect } from '@livestore/utils/effect';
2
+ export type TCmdLoggingOptions = {
3
+ readonly logDir?: string;
4
+ readonly logFileName?: string;
5
+ readonly logRetention?: number;
6
+ };
7
+ /**
8
+ * Prepares logging directories, archives previous canonical log and prunes archives.
9
+ * Returns the canonical current log path if logging is enabled, otherwise undefined.
10
+ */
11
+ export declare const prepareCmdLogging: (options: TCmdLoggingOptions) => Effect.Effect<string | undefined, never, never>;
12
+ /**
13
+ * Given a command input, applies logging by piping output through `tee` to the
14
+ * canonical log file. Returns the transformed input and whether a shell is required.
15
+ */
16
+ export declare const applyLoggingToCommand: (commandInput: string | (string | undefined)[], options: TCmdLoggingOptions) => Effect.Effect<{
17
+ input: string | string[];
18
+ subshell: boolean;
19
+ logPath?: string;
20
+ }, never, never>;
21
+ //# sourceMappingURL=cmd-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmd-log.d.ts","sourceRoot":"","sources":["../../src/node/cmd-log.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAY,MAAM,yBAAyB,CAAA;AAE1D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAC/B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,KAAK,CAqD3G,CAAA;AAEJ;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,CAClC,YAAY,EAAE,MAAM,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,EAC7C,OAAO,EAAE,kBAAkB,KACxB,MAAM,CAAC,MAAM,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,KAAK,CAahG,CAAA"}
@@ -0,0 +1,50 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { isNotUndefined } from '@livestore/utils';
4
+ import { Effect, identity } from '@livestore/utils/effect';
5
+ /**
6
+ * Prepares logging directories, archives previous canonical log and prunes archives.
7
+ * Returns the canonical current log path if logging is enabled, otherwise undefined.
8
+ */
9
+ export const prepareCmdLogging = Effect.fn('cmd.logging.prepare')(function* ({ logDir, logFileName = 'dev.log', logRetention = 50, }) {
10
+ if (!logDir || logDir === '')
11
+ return undefined;
12
+ const logsDir = logDir;
13
+ const archiveDir = path.join(logsDir, 'archive');
14
+ const currentLogPath = path.join(logsDir, logFileName);
15
+ // Ensure directories exist
16
+ yield* Effect.sync(() => fs.mkdirSync(archiveDir, { recursive: true }));
17
+ // Archive previous log if present
18
+ if (fs.existsSync(currentLogPath)) {
19
+ const safeIso = new Date().toISOString().replaceAll(':', '-');
20
+ const archivedBase = `${path.parse(logFileName).name}-${safeIso}.log`;
21
+ const archivedLog = path.join(archiveDir, archivedBase);
22
+ yield* Effect.try({ try: () => fs.renameSync(currentLogPath, archivedLog), catch: identity }).pipe(Effect.catchAll(() => Effect.try({
23
+ try: () => {
24
+ fs.copyFileSync(currentLogPath, archivedLog);
25
+ fs.truncateSync(currentLogPath, 0);
26
+ },
27
+ catch: identity,
28
+ })), Effect.ignore);
29
+ // Prune archives to retain only the newest N
30
+ yield* Effect.try({ try: () => fs.readdirSync(archiveDir), catch: identity }).pipe(Effect.map((names) => names.filter((n) => n.endsWith('.log'))), Effect.map((names) => names
31
+ .map((name) => ({ name, mtimeMs: fs.statSync(path.join(archiveDir, name)).mtimeMs }))
32
+ .sort((a, b) => b.mtimeMs - a.mtimeMs)), Effect.flatMap((entries) => Effect.forEach(entries.slice(logRetention), (e) => Effect.try({ try: () => fs.unlinkSync(path.join(archiveDir, e.name)), catch: identity }).pipe(Effect.ignore))), Effect.ignore);
33
+ }
34
+ return currentLogPath;
35
+ });
36
+ /**
37
+ * Given a command input, applies logging by piping output through `tee` to the
38
+ * canonical log file. Returns the transformed input and whether a shell is required.
39
+ */
40
+ export const applyLoggingToCommand = Effect.fn('cmd.logging.apply')(function* (commandInput, options) {
41
+ const asArray = Array.isArray(commandInput);
42
+ const parts = asArray ? commandInput.filter(isNotUndefined) : undefined;
43
+ const logPath = yield* prepareCmdLogging(options);
44
+ return {
45
+ input: asArray ? (parts ?? []) : commandInput,
46
+ subshell: false,
47
+ ...(logPath ? { logPath } : {}),
48
+ };
49
+ });
50
+ //# sourceMappingURL=cmd-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmd-log.js","sourceRoot":"","sources":["../../src/node/cmd-log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { type CommandExecutor, Effect, type PlatformError, Schema } from '@livestore/utils/effect';
2
+ export declare const cmd: (commandInput: string | (string | undefined)[], options?: {
3
+ cwd?: string;
4
+ stderr?: 'inherit' | 'pipe';
5
+ stdout?: 'inherit' | 'pipe';
6
+ shell?: boolean;
7
+ env?: Record<string, string | undefined>;
8
+ /**
9
+ * When provided, streams command output to terminal AND to a canonical log file (`${logDir}/dev.log`) in this directory.
10
+ * Also archives the previous run to `${logDir}/archive/dev-<ISO>.log` and keeps only the latest 50 archives.
11
+ */
12
+ logDir?: string;
13
+ /** Optional basename for the canonical log file; defaults to 'dev.log' */
14
+ logFileName?: string;
15
+ /** Optional number of archived logs to retain; defaults to 50 */
16
+ logRetention?: number;
17
+ } | undefined) => Effect.Effect<CommandExecutor.ExitCode, PlatformError.PlatformError | CmdError, CommandExecutor.CommandExecutor>;
18
+ export declare const cmdText: (commandInput: string | (string | undefined)[], options?: {
19
+ cwd?: string;
20
+ stderr?: 'inherit' | 'pipe';
21
+ runInShell?: boolean;
22
+ env?: Record<string, string | undefined>;
23
+ }) => Effect.Effect<string, PlatformError.PlatformError, CommandExecutor.CommandExecutor>;
24
+ declare const CmdError_base: Schema.TaggedErrorClass<CmdError, "CmdError", {
25
+ readonly _tag: Schema.tag<"CmdError">;
26
+ } & {
27
+ command: typeof Schema.String;
28
+ args: Schema.Array$<typeof Schema.String>;
29
+ cwd: typeof Schema.String;
30
+ env: Schema.Record$<typeof Schema.String, Schema.UndefinedOr<typeof Schema.String>>;
31
+ stderr: Schema.Literal<["inherit", "pipe"]>;
32
+ }>;
33
+ export declare class CmdError extends CmdError_base {
34
+ }
35
+ export {};
36
+ //# sourceMappingURL=cmd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmd.d.ts","sourceRoot":"","sources":["../../src/node/cmd.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,eAAe,EACpB,MAAM,EAQN,KAAK,aAAa,EAClB,MAAM,EAEP,MAAM,yBAAyB,CAAA;AAOhC,eAAO,MAAM,GAAG,EAAE,CAChB,YAAY,EAAE,MAAM,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,EAC7C,OAAO,CAAC,EACJ;IACE,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IAC3B,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACxC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,GACD,SAAS,KACV,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,aAAa,CAAC,aAAa,GAAG,QAAQ,EAAE,eAAe,CAAC,eAAe,CAiEhH,CAAA;AAEJ,eAAO,MAAM,OAAO,EAAE,CACpB,YAAY,EAAE,MAAM,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,EAC7C,OAAO,CAAC,EAAE;IACR,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CACzC,KACE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,aAAa,EAAE,eAAe,CAAC,eAAe,CAyBtF,CAAA;;;;;;;;;;AAED,qBAAa,QAAS,SAAQ,aAM5B;CAAG"}