@effect/platform 0.48.8 → 0.48.10

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 (130) hide show
  1. package/dist/cjs/Command.js.map +1 -1
  2. package/dist/cjs/CommandExecutor.js +6 -1
  3. package/dist/cjs/CommandExecutor.js.map +1 -1
  4. package/dist/cjs/Error.js +1 -1
  5. package/dist/cjs/Error.js.map +1 -1
  6. package/dist/cjs/Http/Body.js.map +1 -1
  7. package/dist/cjs/Http/Client.js.map +1 -1
  8. package/dist/cjs/Http/ClientRequest.js.map +1 -1
  9. package/dist/cjs/Http/IncomingMessage.js +31 -1
  10. package/dist/cjs/Http/IncomingMessage.js.map +1 -1
  11. package/dist/cjs/Http/Multipart.js.map +1 -1
  12. package/dist/cjs/Http/Multiplex.js.map +1 -1
  13. package/dist/cjs/Http/Router.js.map +1 -1
  14. package/dist/cjs/Http/ServerResponse.js.map +1 -1
  15. package/dist/cjs/Path.js +6 -1
  16. package/dist/cjs/Path.js.map +1 -1
  17. package/dist/cjs/WorkerError.js +2 -1
  18. package/dist/cjs/WorkerError.js.map +1 -1
  19. package/dist/cjs/internal/command.js +60 -31
  20. package/dist/cjs/internal/command.js.map +1 -1
  21. package/dist/cjs/internal/commandExecutor.js +4 -1
  22. package/dist/cjs/internal/commandExecutor.js.map +1 -1
  23. package/dist/cjs/internal/http/body.js +59 -14
  24. package/dist/cjs/internal/http/body.js.map +1 -1
  25. package/dist/cjs/internal/http/clientRequest.js +13 -1
  26. package/dist/cjs/internal/http/clientRequest.js.map +1 -1
  27. package/dist/cjs/internal/http/clientResponse.js +10 -1
  28. package/dist/cjs/internal/http/clientResponse.js.map +1 -1
  29. package/dist/cjs/internal/http/multipart.js +80 -24
  30. package/dist/cjs/internal/http/multipart.js.map +1 -1
  31. package/dist/cjs/internal/http/multiplex.js +12 -0
  32. package/dist/cjs/internal/http/multiplex.js.map +1 -1
  33. package/dist/cjs/internal/http/router.js +10 -1
  34. package/dist/cjs/internal/http/router.js.map +1 -1
  35. package/dist/cjs/internal/http/serverRequest.js +14 -2
  36. package/dist/cjs/internal/http/serverRequest.js.map +1 -1
  37. package/dist/cjs/internal/http/serverResponse.js +9 -2
  38. package/dist/cjs/internal/http/serverResponse.js.map +1 -1
  39. package/dist/cjs/internal/path.js +4 -1
  40. package/dist/cjs/internal/path.js.map +1 -1
  41. package/dist/dts/Command.d.ts +5 -3
  42. package/dist/dts/Command.d.ts.map +1 -1
  43. package/dist/dts/CommandExecutor.d.ts +13 -1
  44. package/dist/dts/CommandExecutor.d.ts.map +1 -1
  45. package/dist/dts/Error.d.ts.map +1 -1
  46. package/dist/dts/Http/Body.d.ts +2 -1
  47. package/dist/dts/Http/Body.d.ts.map +1 -1
  48. package/dist/dts/Http/Client.d.ts +2 -1
  49. package/dist/dts/Http/Client.d.ts.map +1 -1
  50. package/dist/dts/Http/ClientRequest.d.ts +2 -1
  51. package/dist/dts/Http/ClientRequest.d.ts.map +1 -1
  52. package/dist/dts/Http/IncomingMessage.d.ts +6 -1
  53. package/dist/dts/Http/IncomingMessage.d.ts.map +1 -1
  54. package/dist/dts/Http/Multipart.d.ts +8 -3
  55. package/dist/dts/Http/Multipart.d.ts.map +1 -1
  56. package/dist/dts/Http/Multiplex.d.ts +2 -1
  57. package/dist/dts/Http/Multiplex.d.ts.map +1 -1
  58. package/dist/dts/Http/Router.d.ts +3 -2
  59. package/dist/dts/Http/Router.d.ts.map +1 -1
  60. package/dist/dts/Http/ServerResponse.d.ts +2 -1
  61. package/dist/dts/Http/ServerResponse.d.ts.map +1 -1
  62. package/dist/dts/Path.d.ts +11 -0
  63. package/dist/dts/Path.d.ts.map +1 -1
  64. package/dist/dts/WorkerError.d.ts.map +1 -1
  65. package/dist/dts/internal/http/router.d.ts.map +1 -1
  66. package/dist/esm/Command.js.map +1 -1
  67. package/dist/esm/CommandExecutor.js +5 -0
  68. package/dist/esm/CommandExecutor.js.map +1 -1
  69. package/dist/esm/Error.js +1 -1
  70. package/dist/esm/Error.js.map +1 -1
  71. package/dist/esm/Http/Body.js.map +1 -1
  72. package/dist/esm/Http/Client.js.map +1 -1
  73. package/dist/esm/Http/ClientRequest.js.map +1 -1
  74. package/dist/esm/Http/IncomingMessage.js +29 -0
  75. package/dist/esm/Http/IncomingMessage.js.map +1 -1
  76. package/dist/esm/Http/Multipart.js.map +1 -1
  77. package/dist/esm/Http/Multiplex.js.map +1 -1
  78. package/dist/esm/Http/Router.js.map +1 -1
  79. package/dist/esm/Http/ServerResponse.js.map +1 -1
  80. package/dist/esm/Path.js +5 -0
  81. package/dist/esm/Path.js.map +1 -1
  82. package/dist/esm/WorkerError.js +2 -1
  83. package/dist/esm/WorkerError.js.map +1 -1
  84. package/dist/esm/internal/command.js +60 -31
  85. package/dist/esm/internal/command.js.map +1 -1
  86. package/dist/esm/internal/commandExecutor.js +3 -0
  87. package/dist/esm/internal/commandExecutor.js.map +1 -1
  88. package/dist/esm/internal/http/body.js +59 -14
  89. package/dist/esm/internal/http/body.js.map +1 -1
  90. package/dist/esm/internal/http/clientRequest.js +13 -1
  91. package/dist/esm/internal/http/clientRequest.js.map +1 -1
  92. package/dist/esm/internal/http/clientResponse.js +10 -1
  93. package/dist/esm/internal/http/clientResponse.js.map +1 -1
  94. package/dist/esm/internal/http/multipart.js +80 -24
  95. package/dist/esm/internal/http/multipart.js.map +1 -1
  96. package/dist/esm/internal/http/multiplex.js +12 -0
  97. package/dist/esm/internal/http/multiplex.js.map +1 -1
  98. package/dist/esm/internal/http/router.js +10 -1
  99. package/dist/esm/internal/http/router.js.map +1 -1
  100. package/dist/esm/internal/http/serverRequest.js +14 -2
  101. package/dist/esm/internal/http/serverRequest.js.map +1 -1
  102. package/dist/esm/internal/http/serverResponse.js +9 -2
  103. package/dist/esm/internal/http/serverResponse.js.map +1 -1
  104. package/dist/esm/internal/path.js +3 -0
  105. package/dist/esm/internal/path.js.map +1 -1
  106. package/package.json +3 -3
  107. package/src/Command.ts +5 -3
  108. package/src/CommandExecutor.ts +16 -1
  109. package/src/Error.ts +5 -1
  110. package/src/Http/Body.ts +2 -1
  111. package/src/Http/Client.ts +2 -1
  112. package/src/Http/ClientRequest.ts +2 -1
  113. package/src/Http/IncomingMessage.ts +32 -1
  114. package/src/Http/Multipart.ts +9 -5
  115. package/src/Http/Multiplex.ts +2 -1
  116. package/src/Http/Router.ts +3 -2
  117. package/src/Http/ServerResponse.ts +2 -1
  118. package/src/Path.ts +13 -0
  119. package/src/WorkerError.ts +2 -1
  120. package/src/internal/command.ts +72 -34
  121. package/src/internal/commandExecutor.ts +4 -0
  122. package/src/internal/http/body.ts +62 -14
  123. package/src/internal/http/clientRequest.ts +13 -1
  124. package/src/internal/http/clientResponse.ts +11 -1
  125. package/src/internal/http/multipart.ts +61 -24
  126. package/src/internal/http/multiplex.ts +13 -0
  127. package/src/internal/http/router.ts +10 -1
  128. package/src/internal/http/serverRequest.ts +11 -2
  129. package/src/internal/http/serverResponse.ts +11 -2
  130. package/src/internal/path.ts +6 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect/platform",
3
- "version": "0.48.8",
3
+ "version": "0.48.10",
4
4
  "description": "Unified interfaces for common platform-specific services",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -16,8 +16,8 @@
16
16
  "path-browserify": "^1.0.1"
17
17
  },
18
18
  "peerDependencies": {
19
- "@effect/schema": "^0.64.5",
20
- "effect": "^2.4.7"
19
+ "@effect/schema": "^0.64.7",
20
+ "effect": "^2.4.9"
21
21
  },
22
22
  "main": "./dist/cjs/index.js",
23
23
  "module": "./dist/esm/index.js",
package/src/Command.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import type { Effect } from "effect/Effect"
5
5
  import type { HashMap } from "effect/HashMap"
6
+ import type { Inspectable } from "effect/Inspectable"
6
7
  import type { Option } from "effect/Option"
7
8
  import type { Pipeable } from "effect/Pipeable"
8
9
  import type { NonEmptyReadonlyArray } from "effect/ReadonlyArray"
@@ -37,8 +38,9 @@ export declare namespace Command {
37
38
  * @since 1.0.0
38
39
  * @category models
39
40
  */
40
- export interface Proto {
41
+ export interface Proto extends Pipeable, Inspectable {
41
42
  readonly [CommandTypeId]: CommandTypeId
43
+ readonly _tag: string
42
44
  }
43
45
  /**
44
46
  * Configures the pipe that is established between the parent and child
@@ -80,7 +82,7 @@ export type CommandOutput = "inherit" | "pipe" | Sink<Uint8Array, Uint8Array>
80
82
  * @since 1.0.0
81
83
  * @category models
82
84
  */
83
- export interface StandardCommand extends Command.Proto, Pipeable {
85
+ export interface StandardCommand extends Command.Proto {
84
86
  readonly _tag: "StandardCommand"
85
87
  readonly command: string
86
88
  readonly args: ReadonlyArray<string>
@@ -98,7 +100,7 @@ export interface StandardCommand extends Command.Proto, Pipeable {
98
100
  * @since 1.0.0
99
101
  * @category models
100
102
  */
101
- export interface PipedCommand extends Command.Proto, Pipeable {
103
+ export interface PipedCommand extends Command.Proto {
102
104
  readonly _tag: "PipedCommand"
103
105
  readonly left: Command
104
106
  readonly right: Command
@@ -4,6 +4,7 @@
4
4
  import type * as Brand from "effect/Brand"
5
5
  import type { Tag } from "effect/Context"
6
6
  import type { Effect } from "effect/Effect"
7
+ import type { Inspectable } from "effect/Inspectable"
7
8
  import type { Scope } from "effect/Scope"
8
9
  import type { Sink } from "effect/Sink"
9
10
  import type { Stream } from "effect/Stream"
@@ -11,11 +12,25 @@ import type { Command } from "./Command.js"
11
12
  import type { PlatformError } from "./Error.js"
12
13
  import * as internal from "./internal/commandExecutor.js"
13
14
 
15
+ /**
16
+ * @since 1.0.0
17
+ * @category type ids
18
+ */
19
+ export const TypeId: unique symbol = internal.TypeId
20
+
21
+ /**
22
+ * @since 1.0.0
23
+ * @category type ids
24
+ */
25
+ export type TypeId = typeof TypeId
26
+
14
27
  /**
15
28
  * @since 1.0.0
16
29
  * @category models
17
30
  */
18
31
  export interface CommandExecutor {
32
+ readonly [TypeId]: TypeId
33
+
19
34
  /**
20
35
  * Returns the exit code of the command after the process has completed
21
36
  * execution.
@@ -70,7 +85,7 @@ export type ProcessTypeId = typeof ProcessTypeId
70
85
  * @since 1.0.0
71
86
  * @category models
72
87
  */
73
- export interface Process {
88
+ export interface Process extends Inspectable {
74
89
  readonly [ProcessTypeId]: ProcessTypeId
75
90
  /**
76
91
  * The process identifier.
package/src/Error.ts CHANGED
@@ -74,7 +74,11 @@ export const RefailError = <const TypeId extends symbol, const Tag extends strin
74
74
  }
75
75
  }
76
76
  get message() {
77
- return String(Predicate.hasProperty(this.error, "message") ? this.error.message : this.error)
77
+ return Predicate.hasProperty(this.error, "message")
78
+ ? this.error.message as string
79
+ : Predicate.hasProperty(this.error, "toJSON") && typeof this.error.toJSON === "function"
80
+ ? JSON.stringify(this.error.toJSON())
81
+ : String(this.error)
78
82
  }
79
83
  }
80
84
  ;(Base.prototype as any)[typeId] = typeId
package/src/Http/Body.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  import type * as ParseResult from "@effect/schema/ParseResult"
5
5
  import type * as Schema from "@effect/schema/Schema"
6
6
  import type * as Effect from "effect/Effect"
7
+ import type { Inspectable } from "effect/Inspectable"
7
8
  import * as Predicate from "effect/Predicate"
8
9
  import type * as Stream_ from "effect/Stream"
9
10
  import type * as PlatformError from "../Error.js"
@@ -43,7 +44,7 @@ export declare namespace Body {
43
44
  * @since 1.0.0
44
45
  * @category models
45
46
  */
46
- export interface Proto {
47
+ export interface Proto extends Inspectable {
47
48
  readonly [TypeId]: TypeId
48
49
  readonly _tag: string
49
50
  readonly contentType?: string | undefined
@@ -5,6 +5,7 @@ import type * as ParseResult from "@effect/schema/ParseResult"
5
5
  import type * as Schema from "@effect/schema/Schema"
6
6
  import type * as Context from "effect/Context"
7
7
  import type * as Effect from "effect/Effect"
8
+ import type { Inspectable } from "effect/Inspectable"
8
9
  import type * as Layer from "effect/Layer"
9
10
  import type { Pipeable } from "effect/Pipeable"
10
11
  import type * as Predicate from "effect/Predicate"
@@ -31,7 +32,7 @@ export type TypeId = typeof TypeId
31
32
  * @since 1.0.0
32
33
  * @category models
33
34
  */
34
- export interface Client<R, E, A> extends Pipeable {
35
+ export interface Client<R, E, A> extends Pipeable, Inspectable {
35
36
  (request: ClientRequest.ClientRequest): Effect.Effect<A, E, R>
36
37
  readonly [TypeId]: TypeId
37
38
  readonly preprocess: Client.Preprocess<R, E>
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import type * as Schema from "@effect/schema/Schema"
5
5
  import type * as Effect from "effect/Effect"
6
+ import type { Inspectable } from "effect/Inspectable"
6
7
  import type { Pipeable } from "effect/Pipeable"
7
8
  import type * as Stream from "effect/Stream"
8
9
  import type * as PlatformError from "../Error.js"
@@ -29,7 +30,7 @@ export type TypeId = typeof TypeId
29
30
  * @since 1.0.0
30
31
  * @category models
31
32
  */
32
- export interface ClientRequest extends Pipeable {
33
+ export interface ClientRequest extends Pipeable, Inspectable {
33
34
  readonly [TypeId]: TypeId
34
35
  readonly method: Method
35
36
  readonly url: string
@@ -7,6 +7,7 @@ import * as Effect from "effect/Effect"
7
7
  import * as FiberRef from "effect/FiberRef"
8
8
  import { dual, flow } from "effect/Function"
9
9
  import * as Global from "effect/GlobalValue"
10
+ import type { Inspectable } from "effect/Inspectable"
10
11
  import * as Option from "effect/Option"
11
12
  import type * as Stream from "effect/Stream"
12
13
  import * as Tracer from "effect/Tracer"
@@ -31,7 +32,7 @@ export type TypeId = typeof TypeId
31
32
  * @since 1.0.0
32
33
  * @category models
33
34
  */
34
- export interface IncomingMessage<E> {
35
+ export interface IncomingMessage<E> extends Inspectable {
35
36
  readonly [TypeId]: TypeId
36
37
  readonly headers: Headers.Headers
37
38
  readonly remoteAddress: Option.Option<string>
@@ -190,3 +191,33 @@ export const withMaxBodySize = dual<
190
191
  (size: Option.Option<FileSystem.SizeInput>) => <R, E, A>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>,
191
192
  <R, E, A>(effect: Effect.Effect<A, E, R>, size: Option.Option<FileSystem.SizeInput>) => Effect.Effect<A, E, R>
192
193
  >(2, (effect, size) => Effect.locally(effect, maxBodySize, Option.map(size, FileSystem.Size)))
194
+
195
+ /**
196
+ * @since 1.0.0
197
+ */
198
+ export const inspect = <E>(self: IncomingMessage<E>, that: object): object => {
199
+ const contentType = self.headers["content-type"] ?? ""
200
+ let body: unknown
201
+ if (contentType.includes("application/json")) {
202
+ try {
203
+ body = Effect.runSync(self.json)
204
+ } catch (_) {
205
+ //
206
+ }
207
+ } else if (contentType.includes("text/") || contentType.includes("urlencoded")) {
208
+ try {
209
+ body = Effect.runSync(self.text)
210
+ } catch (_) {
211
+ //
212
+ }
213
+ }
214
+ const obj: any = {
215
+ ...that,
216
+ headers: self.headers,
217
+ remoteAddress: self.remoteAddress.toJSON()
218
+ }
219
+ if (body !== undefined) {
220
+ obj.body = body
221
+ }
222
+ return obj
223
+ }
@@ -3,10 +3,12 @@
3
3
  */
4
4
  import type * as ParseResult from "@effect/schema/ParseResult"
5
5
  import type * as Schema from "@effect/schema/Schema"
6
+ import type { YieldableError } from "effect/Cause"
6
7
  import type * as Channel from "effect/Channel"
7
8
  import type * as Chunk from "effect/Chunk"
8
9
  import type * as Effect from "effect/Effect"
9
10
  import type * as FiberRef from "effect/FiberRef"
11
+ import type { Inspectable } from "effect/Inspectable"
10
12
  import type * as Option from "effect/Option"
11
13
  import type * as Scope from "effect/Scope"
12
14
  import type * as Stream from "effect/Stream"
@@ -47,7 +49,7 @@ export declare namespace Part {
47
49
  * @since 1.0.0
48
50
  * @category models
49
51
  */
50
- export interface Proto {
52
+ export interface Proto extends Inspectable {
51
53
  readonly [TypeId]: TypeId
52
54
  readonly _tag: string
53
55
  }
@@ -130,7 +132,7 @@ export type ErrorTypeId = typeof ErrorTypeId
130
132
  * @since 1.0.0
131
133
  * @category errors
132
134
  */
133
- export interface MultipartError {
135
+ export interface MultipartError extends YieldableError {
134
136
  readonly [ErrorTypeId]: ErrorTypeId
135
137
  readonly _tag: "MultipartError"
136
138
  readonly reason: "FileTooLarge" | "FieldTooLarge" | "BodyTooLarge" | "TooManyParts" | "InternalError" | "Parse"
@@ -141,9 +143,11 @@ export interface MultipartError {
141
143
  * @since 1.0.0
142
144
  * @category errors
143
145
  */
144
- export const MultipartError: (
145
- reason: MultipartError["reason"],
146
- error: unknown
146
+ export const MultipartError: new(
147
+ options: {
148
+ readonly reason: MultipartError["reason"]
149
+ readonly error: unknown
150
+ }
147
151
  ) => MultipartError = internal.MultipartError
148
152
 
149
153
  /**
@@ -2,6 +2,7 @@
2
2
  * @since 1.0.0
3
3
  */
4
4
  import type * as Effect from "effect/Effect"
5
+ import type { Inspectable } from "effect/Inspectable"
5
6
  import * as internal from "../internal/http/multiplex.js"
6
7
  import type * as App from "./App.js"
7
8
  import type * as Error from "./ServerError.js"
@@ -23,7 +24,7 @@ export type TypeId = typeof TypeId
23
24
  * @since 1.0.0
24
25
  * @category models
25
26
  */
26
- export interface Multiplex<R, E> extends App.Default<R, E | Error.RouteNotFound> {
27
+ export interface Multiplex<R, E> extends App.Default<R, E | Error.RouteNotFound>, Inspectable {
27
28
  readonly [TypeId]: TypeId
28
29
  readonly apps: ReadonlyArray<
29
30
  readonly [
@@ -7,6 +7,7 @@ import type * as Cause from "effect/Cause"
7
7
  import type * as Chunk from "effect/Chunk"
8
8
  import type * as Context from "effect/Context"
9
9
  import type * as Effect from "effect/Effect"
10
+ import type { Inspectable } from "effect/Inspectable"
10
11
  import type * as Option from "effect/Option"
11
12
  import type * as Scope from "effect/Scope"
12
13
  import * as internal from "../internal/http/router.js"
@@ -32,7 +33,7 @@ export type TypeId = typeof TypeId
32
33
  * @since 1.0.0
33
34
  * @category models
34
35
  */
35
- export interface Router<R, E> extends App.Default<Exclude<R, RouteContext>, E | Error.RouteNotFound> {
36
+ export interface Router<R, E> extends App.Default<Exclude<R, RouteContext>, E | Error.RouteNotFound>, Inspectable {
36
37
  readonly [TypeId]: TypeId
37
38
  readonly routes: Chunk.Chunk<Route<R, E>>
38
39
  readonly mounts: Chunk.Chunk<
@@ -76,7 +77,7 @@ export type PathInput = `/${string}` | "*"
76
77
  * @since 1.0.0
77
78
  * @category models
78
79
  */
79
- export interface Route<R, E> {
80
+ export interface Route<R, E> extends Inspectable {
80
81
  readonly [RouteTypeId]: RouteTypeId
81
82
  readonly method: Method.Method | "*"
82
83
  readonly path: PathInput
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import type * as Schema from "@effect/schema/Schema"
5
5
  import type * as Effect from "effect/Effect"
6
+ import type { Inspectable } from "effect/Inspectable"
6
7
  import type * as Stream from "effect/Stream"
7
8
  import type * as PlatformError from "../Error.js"
8
9
  import type * as FileSystem from "../FileSystem.js"
@@ -29,7 +30,7 @@ export type TypeId = typeof TypeId
29
30
  * @since 1.0.0
30
31
  * @category models
31
32
  */
32
- export interface ServerResponse extends Effect.Effect<ServerResponse> {
33
+ export interface ServerResponse extends Effect.Effect<ServerResponse>, Inspectable {
33
34
  readonly [TypeId]: TypeId
34
35
  readonly status: number
35
36
  readonly statusText?: string | undefined
package/src/Path.ts CHANGED
@@ -8,11 +8,24 @@ import type { Layer } from "effect/Layer"
8
8
  import type { BadArgument } from "./Error.js"
9
9
  import * as internal from "./internal/path.js"
10
10
 
11
+ /**
12
+ * @since 1.0.0
13
+ * @category type ids
14
+ */
15
+ export const TypeId: unique symbol = internal.TypeId
16
+
17
+ /**
18
+ * @since 1.0.0
19
+ * @category type ids
20
+ */
21
+ export type TypeId = typeof TypeId
22
+
11
23
  /**
12
24
  * @since 1.0.0
13
25
  * @category model
14
26
  */
15
27
  export interface Path {
28
+ readonly [TypeId]: TypeId
16
29
  readonly sep: string
17
30
  readonly basename: (path: string, suffix?: string) => string
18
31
  readonly dirname: (path: string) => string
@@ -78,7 +78,8 @@ export class WorkerError extends Schema.TaggedError<WorkerError>()("WorkerError"
78
78
  * @since 1.0.0
79
79
  */
80
80
  get message() {
81
- return `${this.reason}: ${String(this.error)}`
81
+ const message = this.error instanceof Error ? this.error.message : String(this.error)
82
+ return `${this.reason}: ${message}`
82
83
  }
83
84
  }
84
85
 
@@ -2,6 +2,7 @@ import * as Chunk from "effect/Chunk"
2
2
  import * as Effect from "effect/Effect"
3
3
  import { dual } from "effect/Function"
4
4
  import * as HashMap from "effect/HashMap"
5
+ import * as Inspectable from "effect/Inspectable"
5
6
  import * as Option from "effect/Option"
6
7
  import { pipeArguments } from "effect/Pipeable"
7
8
  import type * as ReadonlyArray from "effect/ReadonlyArray"
@@ -28,7 +29,7 @@ export const env: {
28
29
  >(2, (self, environment) => {
29
30
  switch (self._tag) {
30
31
  case "StandardCommand": {
31
- return { ...self, env: HashMap.union(self.env, HashMap.fromIterable(Object.entries(environment))) }
32
+ return makeStandard({ ...self, env: HashMap.union(self.env, HashMap.fromIterable(Object.entries(environment))) })
32
33
  }
33
34
  case "PipedCommand": {
34
35
  return pipeTo(env(self.left, environment), env(self.right, environment))
@@ -76,7 +77,7 @@ export const runInShell = dual<
76
77
  >(2, (self: Command.Command, shell: boolean | string): Command.Command => {
77
78
  switch (self._tag) {
78
79
  case "StandardCommand": {
79
- return { ...self, shell }
80
+ return makeStandard({ ...self, shell })
80
81
  }
81
82
  case "PipedCommand": {
82
83
  return pipeTo(
@@ -94,40 +95,77 @@ export const lines = (
94
95
  ): Effect.Effect<ReadonlyArray<string>, PlatformError, CommandExecutor.CommandExecutor> =>
95
96
  Effect.flatMap(commandExecutor.CommandExecutor, (executor) => executor.lines(command, encoding))
96
97
 
97
- /** @internal */
98
- export const make = (command: string, ...args: Array<string>): Command.Command => ({
98
+ const Proto = {
99
99
  [CommandTypeId]: CommandTypeId,
100
- _tag: "StandardCommand",
101
- command,
102
- args,
103
- env: HashMap.empty(),
104
- cwd: Option.none(),
105
- shell: false,
106
- // The initial process input here does not matter, we just want the child
107
- // process to default to `"pipe"` for the stdin stream.
108
- stdin: Option.some(Stream.empty),
109
- stdout: "pipe",
110
- stderr: "pipe",
111
- gid: Option.none(),
112
- uid: Option.none(),
113
100
  pipe() {
114
101
  return pipeArguments(this, arguments)
102
+ },
103
+ ...Inspectable.BaseProto
104
+ }
105
+
106
+ const StandardProto = {
107
+ ...Proto,
108
+ _tag: "StandardCommand",
109
+ toJSON(this: Command.StandardCommand) {
110
+ return {
111
+ _id: "@effect/platform/Command",
112
+ _tag: this._tag,
113
+ command: this.command,
114
+ args: this.args,
115
+ env: Object.fromEntries(this.env),
116
+ cwd: this.cwd.toJSON(),
117
+ shell: this.shell,
118
+ gid: this.gid.toJSON(),
119
+ uid: this.uid.toJSON()
120
+ }
115
121
  }
116
- })
122
+ }
123
+
124
+ const makeStandard = (options: Omit<Command.StandardCommand, keyof Command.Command.Proto>): Command.StandardCommand =>
125
+ Object.assign(Object.create(StandardProto), options)
126
+
127
+ const PipedProto = {
128
+ ...Proto,
129
+ _tag: "PipedCommand",
130
+ toJSON(this: Command.PipedCommand) {
131
+ return {
132
+ _id: "@effect/platform/Command",
133
+ _tag: this._tag,
134
+ left: this.left.toJSON(),
135
+ right: this.right.toJSON()
136
+ }
137
+ }
138
+ }
139
+
140
+ const makePiped = (options: Omit<Command.PipedCommand, keyof Command.Command.Proto>): Command.PipedCommand =>
141
+ Object.assign(Object.create(PipedProto), options)
142
+
143
+ /** @internal */
144
+ export const make = (command: string, ...args: Array<string>): Command.Command =>
145
+ makeStandard({
146
+ command,
147
+ args,
148
+ env: HashMap.empty(),
149
+ cwd: Option.none(),
150
+ shell: false,
151
+ // The initial process input here does not matter, we just want the child
152
+ // process to default to `"pipe"` for the stdin stream.
153
+ stdin: Option.some(Stream.empty),
154
+ stdout: "pipe",
155
+ stderr: "pipe",
156
+ gid: Option.none(),
157
+ uid: Option.none()
158
+ })
117
159
 
118
160
  /** @internal */
119
161
  export const pipeTo = dual<
120
162
  (into: Command.Command) => (self: Command.Command) => Command.Command,
121
163
  (self: Command.Command, into: Command.Command) => Command.Command
122
- >(2, (self, into) => ({
123
- [CommandTypeId]: CommandTypeId,
124
- _tag: "PipedCommand",
125
- left: self,
126
- right: into,
127
- pipe() {
128
- return pipeArguments(this, arguments)
129
- }
130
- }))
164
+ >(2, (self, into) =>
165
+ makePiped({
166
+ left: self,
167
+ right: into
168
+ }))
131
169
 
132
170
  /** @internal */
133
171
  export const stderr: {
@@ -139,12 +177,12 @@ export const stderr: {
139
177
  >(2, (self, output) => {
140
178
  switch (self._tag) {
141
179
  case "StandardCommand": {
142
- return { ...self, stderr: output }
180
+ return makeStandard({ ...self, stderr: output })
143
181
  }
144
182
  // For piped commands it only makes sense to provide `stderr` for the
145
183
  // right-most command as the rest will be piped in.
146
184
  case "PipedCommand": {
147
- return { ...self, right: stderr(self.right, output) }
185
+ return makePiped({ ...self, right: stderr(self.right, output) })
148
186
  }
149
187
  }
150
188
  })
@@ -159,12 +197,12 @@ export const stdin: {
159
197
  >(2, (self, input) => {
160
198
  switch (self._tag) {
161
199
  case "StandardCommand": {
162
- return { ...self, stdin: Option.some(input) }
200
+ return makeStandard({ ...self, stdin: Option.some(input) })
163
201
  }
164
202
  // For piped commands it only makes sense to provide `stdin` for the
165
203
  // left-most command as the rest will be piped in.
166
204
  case "PipedCommand": {
167
- return { ...self, left: stdin(self.left, input) }
205
+ return makePiped({ ...self, left: stdin(self.left, input) })
168
206
  }
169
207
  }
170
208
  })
@@ -179,12 +217,12 @@ export const stdout: {
179
217
  >(2, (self, output) => {
180
218
  switch (self._tag) {
181
219
  case "StandardCommand": {
182
- return { ...self, stdout: output }
220
+ return makeStandard({ ...self, stdout: output })
183
221
  }
184
222
  // For piped commands it only makes sense to provide `stderr` for the
185
223
  // right-most command as the rest will be piped in.
186
224
  case "PipedCommand": {
187
- return { ...self, right: stdout(self.right, output) }
225
+ return makePiped({ ...self, right: stdout(self.right, output) })
188
226
  }
189
227
  }
190
228
  })
@@ -229,7 +267,7 @@ export const workingDirectory: {
229
267
  >(2, (self, cwd) => {
230
268
  switch (self._tag) {
231
269
  case "StandardCommand": {
232
- return { ...self, cwd: Option.some(cwd) }
270
+ return makeStandard({ ...self, cwd: Option.some(cwd) })
233
271
  }
234
272
  case "PipedCommand": {
235
273
  return pipeTo(workingDirectory(self.left, cwd), workingDirectory(self.right, cwd))
@@ -7,6 +7,9 @@ import * as Sink from "effect/Sink"
7
7
  import * as Stream from "effect/Stream"
8
8
  import type * as _CommandExecutor from "../CommandExecutor.js"
9
9
 
10
+ /** @internal */
11
+ export const TypeId: _CommandExecutor.TypeId = Symbol.for("@effect/platform/CommandExecutor") as _CommandExecutor.TypeId
12
+
10
13
  /** @internal */
11
14
  export const ProcessTypeId: _CommandExecutor.ProcessTypeId = Symbol.for(
12
15
  "@effect/platform/Process"
@@ -32,6 +35,7 @@ export const makeExecutor = (start: _CommandExecutor.CommandExecutor["start"]):
32
35
  )
33
36
  }
34
37
  return {
38
+ [TypeId]: TypeId,
35
39
  start,
36
40
  exitCode: (command) => Effect.scoped(Effect.flatMap(start(command), (process) => process.exitCode)),
37
41
  stream,