@effect/platform 0.0.0 → 0.2.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/Command.d.ts +251 -0
  2. package/Command.d.ts.map +1 -0
  3. package/Command.js +164 -0
  4. package/Command.js.map +1 -0
  5. package/CommandExecutor.d.ts +140 -0
  6. package/CommandExecutor.d.ts.map +1 -0
  7. package/CommandExecutor.js +40 -0
  8. package/CommandExecutor.js.map +1 -0
  9. package/Console.d.ts +114 -12
  10. package/Console.d.ts.map +1 -1
  11. package/Console.js +109 -1
  12. package/Console.js.map +1 -1
  13. package/Error.d.ts +1 -1
  14. package/Error.d.ts.map +1 -1
  15. package/FileSystem.d.ts +246 -47
  16. package/FileSystem.d.ts.map +1 -1
  17. package/FileSystem.js +24 -1
  18. package/FileSystem.js.map +1 -1
  19. package/Path.d.ts +59 -0
  20. package/Path.d.ts.map +1 -0
  21. package/{FileSystem/File.js → Path.js} +14 -24
  22. package/Path.js.map +1 -0
  23. package/internal/command.d.ts +2 -0
  24. package/internal/command.d.ts.map +1 -0
  25. package/internal/command.js +184 -0
  26. package/internal/command.js.map +1 -0
  27. package/internal/commandExecutor.d.ts +2 -0
  28. package/internal/commandExecutor.d.ts.map +1 -0
  29. package/internal/commandExecutor.js +55 -0
  30. package/internal/commandExecutor.js.map +1 -0
  31. package/internal/console.js +63 -3
  32. package/internal/console.js.map +1 -1
  33. package/internal/fileSystem.js +3 -3
  34. package/internal/fileSystem.js.map +1 -1
  35. package/internal/path.d.ts +2 -0
  36. package/internal/path.d.ts.map +1 -0
  37. package/internal/path.js +97 -0
  38. package/internal/path.js.map +1 -0
  39. package/mjs/Command.mjs +139 -0
  40. package/mjs/Command.mjs.map +1 -0
  41. package/mjs/CommandExecutor.mjs +27 -0
  42. package/mjs/CommandExecutor.mjs.map +1 -0
  43. package/mjs/Console.mjs +90 -0
  44. package/mjs/Console.mjs.map +1 -1
  45. package/mjs/FileSystem.mjs +19 -0
  46. package/mjs/FileSystem.mjs.map +1 -1
  47. package/mjs/Path.mjs +20 -0
  48. package/mjs/Path.mjs.map +1 -0
  49. package/mjs/internal/command.mjs +159 -0
  50. package/mjs/internal/command.mjs.map +1 -0
  51. package/mjs/internal/commandExecutor.mjs +42 -0
  52. package/mjs/internal/commandExecutor.mjs.map +1 -0
  53. package/mjs/internal/console.mjs +44 -2
  54. package/mjs/internal/console.mjs.map +1 -1
  55. package/mjs/internal/fileSystem.mjs +3 -3
  56. package/mjs/internal/fileSystem.mjs.map +1 -1
  57. package/mjs/internal/path.mjs +87 -0
  58. package/mjs/internal/path.mjs.map +1 -0
  59. package/package.json +5 -4
  60. package/src/Command.ts +278 -0
  61. package/src/CommandExecutor.ts +191 -0
  62. package/src/Console.ts +132 -12
  63. package/src/Error.ts +1 -1
  64. package/src/FileSystem.ts +356 -119
  65. package/src/Path.ts +64 -0
  66. package/src/internal/command.ts +211 -0
  67. package/src/internal/commandExecutor.ts +69 -0
  68. package/src/internal/console.ts +92 -14
  69. package/src/internal/fileSystem.ts +4 -5
  70. package/src/internal/path.ts +101 -0
  71. package/FileSystem/File.d.ts +0 -91
  72. package/FileSystem/File.d.ts.map +0 -1
  73. package/FileSystem/File.js.map +0 -1
  74. package/mjs/FileSystem/File.mjs +0 -28
  75. package/mjs/FileSystem/File.mjs.map +0 -1
  76. package/src/FileSystem/File.ts +0 -125
@@ -0,0 +1,211 @@
1
+ import * as Chunk from "@effect/data/Chunk"
2
+ import { dual } from "@effect/data/Function"
3
+ import * as HashMap from "@effect/data/HashMap"
4
+ import * as Option from "@effect/data/Option"
5
+ import type ReadonlyArray from "@effect/data/ReadonlyArray"
6
+ import * as Effect from "@effect/io/Effect"
7
+ import type * as Command from "@effect/platform/Command"
8
+ import type * as CommandExecutor from "@effect/platform/CommandExecutor"
9
+ import type { PlatformError } from "@effect/platform/Error"
10
+ import * as commandExecutor from "@effect/platform/internal/commandExecutor"
11
+ import * as Stream from "@effect/stream/Stream"
12
+
13
+ /** @internal */
14
+ export const CommandTypeId: Command.CommandTypeId = Symbol.for("@effect/platform/Command") as Command.CommandTypeId
15
+
16
+ /** @internal */
17
+ export const isCommand = (u: unknown): u is Command.Command => typeof u === "object" && u != null && CommandTypeId in u
18
+
19
+ /** @internal */
20
+ export const env: {
21
+ (environment: Record<string, string>): (self: Command.Command) => Command.Command
22
+ (self: Command.Command, environment: Record<string, string>): Command.Command
23
+ } = dual<
24
+ (environment: Record<string, string>) => (self: Command.Command) => Command.Command,
25
+ (self: Command.Command, environment: Record<string, string>) => Command.Command
26
+ >(2, (self, environment) => {
27
+ switch (self._tag) {
28
+ case "StandardCommand": {
29
+ return { ...self, env: HashMap.union(self.env, HashMap.fromIterable(Object.entries(environment))) }
30
+ }
31
+ case "PipedCommand": {
32
+ return pipeTo(env(self.left, environment), env(self.right, environment))
33
+ }
34
+ }
35
+ })
36
+
37
+ /** @internal */
38
+ export const exitCode = (
39
+ self: Command.Command
40
+ ): Effect.Effect<CommandExecutor.CommandExecutor, PlatformError, CommandExecutor.ExitCode> =>
41
+ Effect.flatMap(commandExecutor.CommandExecutor, (executor) => executor.exitCode(self))
42
+
43
+ /** @internal */
44
+ export const feed = dual<
45
+ (input: string) => (self: Command.Command) => Command.Command,
46
+ (self: Command.Command, input: string) => Command.Command
47
+ >(2, (self, input) => stdin(self, Stream.fromChunk(Chunk.of(new TextEncoder().encode(input)))))
48
+
49
+ /** @internal */
50
+ export const flatten = (self: Command.Command): ReadonlyArray.NonEmptyReadonlyArray<Command.StandardCommand> =>
51
+ Array.from(flattenLoop(self)) as unknown as ReadonlyArray.NonEmptyReadonlyArray<
52
+ Command.StandardCommand
53
+ >
54
+
55
+ /** @internal */
56
+ const flattenLoop = (self: Command.Command): Chunk.NonEmptyChunk<Command.StandardCommand> => {
57
+ switch (self._tag) {
58
+ case "StandardCommand": {
59
+ return Chunk.of(self)
60
+ }
61
+ case "PipedCommand": {
62
+ return Chunk.appendAll(
63
+ flattenLoop(self.left),
64
+ flattenLoop(self.right)
65
+ ) as Chunk.NonEmptyChunk<Command.StandardCommand>
66
+ }
67
+ }
68
+ }
69
+
70
+ /** @internal */
71
+ export const lines = (
72
+ command: Command.Command,
73
+ encoding = "utf-8"
74
+ ): Effect.Effect<CommandExecutor.CommandExecutor, PlatformError, ReadonlyArray<string>> =>
75
+ Effect.flatMap(commandExecutor.CommandExecutor, (executor) => executor.lines(command, encoding))
76
+
77
+ /** @internal */
78
+ export const make = (command: string, ...args: Array<string>): Command.Command => ({
79
+ [CommandTypeId]: CommandTypeId,
80
+ _tag: "StandardCommand",
81
+ command,
82
+ args,
83
+ env: HashMap.empty(),
84
+ cwd: Option.none(),
85
+ // The initial process input here does not matter, we just want the child
86
+ // process to default to `"pipe"` for the stdin stream.
87
+ stdin: Option.some(Stream.empty),
88
+ stdout: "pipe",
89
+ stderr: "pipe",
90
+ gid: Option.none(),
91
+ uid: Option.none()
92
+ })
93
+
94
+ /** @internal */
95
+ export const pipeTo = dual<
96
+ (into: Command.Command) => (self: Command.Command) => Command.Command,
97
+ (self: Command.Command, into: Command.Command) => Command.Command
98
+ >(2, (self, into) => ({
99
+ [CommandTypeId]: CommandTypeId,
100
+ _tag: "PipedCommand",
101
+ left: self,
102
+ right: into
103
+ }))
104
+
105
+ /** @internal */
106
+ export const stderr: {
107
+ (stderr: Command.Command.Output): (self: Command.Command) => Command.Command
108
+ (self: Command.Command, stderr: Command.Command.Output): Command.Command
109
+ } = dual<
110
+ (stderr: Command.Command.Output) => (self: Command.Command) => Command.Command,
111
+ (self: Command.Command, stderr: Command.Command.Output) => Command.Command
112
+ >(2, (self, output) => {
113
+ switch (self._tag) {
114
+ case "StandardCommand": {
115
+ return { ...self, stderr: output }
116
+ }
117
+ // For piped commands it only makes sense to provide `stderr` for the
118
+ // right-most command as the rest will be piped in.
119
+ case "PipedCommand": {
120
+ return { ...self, right: stderr(self.right, output) }
121
+ }
122
+ }
123
+ })
124
+
125
+ /** @internal */
126
+ export const stdin: {
127
+ (stdin: Command.Command.Input): (self: Command.Command) => Command.Command
128
+ (self: Command.Command, stdin: Command.Command.Input): Command.Command
129
+ } = dual<
130
+ (stdin: Command.Command.Input) => (self: Command.Command) => Command.Command,
131
+ (self: Command.Command, stdin: Command.Command.Input) => Command.Command
132
+ >(2, (self, input) => {
133
+ switch (self._tag) {
134
+ case "StandardCommand": {
135
+ return { ...self, stdin: Option.some(input) }
136
+ }
137
+ // For piped commands it only makes sense to provide `stdin` for the
138
+ // left-most command as the rest will be piped in.
139
+ case "PipedCommand": {
140
+ return { ...self, left: stdin(self.left, input) }
141
+ }
142
+ }
143
+ })
144
+
145
+ /** @internal */
146
+ export const stdout: {
147
+ (stdout: Command.Command.Output): (self: Command.Command) => Command.Command
148
+ (self: Command.Command, stdout: Command.Command.Output): Command.Command
149
+ } = dual<
150
+ (stdout: Command.Command.Output) => (self: Command.Command) => Command.Command,
151
+ (self: Command.Command, stdout: Command.Command.Output) => Command.Command
152
+ >(2, (self, output) => {
153
+ switch (self._tag) {
154
+ case "StandardCommand": {
155
+ return { ...self, stdout: output }
156
+ }
157
+ // For piped commands it only makes sense to provide `stderr` for the
158
+ // right-most command as the rest will be piped in.
159
+ case "PipedCommand": {
160
+ return { ...self, right: stdout(self.right, output) }
161
+ }
162
+ }
163
+ })
164
+
165
+ /** @internal */
166
+ export const start = (
167
+ command: Command.Command
168
+ ): Effect.Effect<CommandExecutor.CommandExecutor, PlatformError, CommandExecutor.Process> =>
169
+ Effect.flatMap(commandExecutor.CommandExecutor, (executor) => executor.start(command))
170
+
171
+ /** @internal */
172
+ export const stream = (
173
+ command: Command.Command
174
+ ): Stream.Stream<CommandExecutor.CommandExecutor, PlatformError, Uint8Array> =>
175
+ Stream.flatMap(commandExecutor.CommandExecutor, (process) => process.stream(command))
176
+
177
+ /** @internal */
178
+ export const streamLines = (
179
+ command: Command.Command
180
+ ): Stream.Stream<CommandExecutor.CommandExecutor, PlatformError, string> =>
181
+ Stream.flatMap(commandExecutor.CommandExecutor, (process) => process.streamLines(command))
182
+
183
+ /** @internal */
184
+ export const string = dual<
185
+ (
186
+ encoding?: string
187
+ ) => (command: Command.Command) => Effect.Effect<CommandExecutor.CommandExecutor, PlatformError, string>,
188
+ (command: Command.Command, encoding?: string) => Effect.Effect<CommandExecutor.CommandExecutor, PlatformError, string>
189
+ >(
190
+ (args) => isCommand(args[0]),
191
+ (command, encoding) =>
192
+ Effect.flatMap(commandExecutor.CommandExecutor, (executor) => executor.string(command, encoding))
193
+ )
194
+
195
+ /** @internal */
196
+ export const workingDirectory: {
197
+ (cwd: string): (self: Command.Command) => Command.Command
198
+ (self: Command.Command, cwd: string): Command.Command
199
+ } = dual<
200
+ (cwd: string) => (self: Command.Command) => Command.Command,
201
+ (self: Command.Command, cwd: string) => Command.Command
202
+ >(2, (self, cwd) => {
203
+ switch (self._tag) {
204
+ case "StandardCommand": {
205
+ return { ...self, cwd: Option.some(cwd) }
206
+ }
207
+ case "PipedCommand": {
208
+ return pipeTo(workingDirectory(self.left, cwd), workingDirectory(self.right, cwd))
209
+ }
210
+ }
211
+ })
@@ -0,0 +1,69 @@
1
+ import * as Brand from "@effect/data/Brand"
2
+ import * as Chunk from "@effect/data/Chunk"
3
+ import { Tag } from "@effect/data/Context"
4
+ import { pipe } from "@effect/data/Function"
5
+ import * as Effect from "@effect/io/Effect"
6
+ import type * as _CommandExecutor from "@effect/platform/CommandExecutor"
7
+ import * as Sink from "@effect/stream/Sink"
8
+ import * as Stream from "@effect/stream/Stream"
9
+
10
+ /** @internal */
11
+ export const ProcessTypeId: _CommandExecutor.ProcessTypeId = Symbol.for(
12
+ "@effect/platform/Process"
13
+ ) as _CommandExecutor.ProcessTypeId
14
+
15
+ /** @internal */
16
+ export const ExitCode = Brand.nominal<_CommandExecutor.ExitCode>()
17
+
18
+ /** @internal */
19
+ export const ProcessId = Brand.nominal<_CommandExecutor.Process.Id>()
20
+
21
+ /** @internal */
22
+ export const CommandExecutor = Tag<_CommandExecutor.CommandExecutor>()
23
+
24
+ /** @internal */
25
+ export const makeExecutor = (start: _CommandExecutor.CommandExecutor["start"]): _CommandExecutor.CommandExecutor => {
26
+ const stream: _CommandExecutor.CommandExecutor["stream"] = (command) =>
27
+ pipe(
28
+ Stream.fromEffect(start(command)),
29
+ Stream.flatMap((process) => process.stdout)
30
+ )
31
+ const streamLines: _CommandExecutor.CommandExecutor["streamLines"] = (command, encoding) => {
32
+ const decoder = new TextDecoder(encoding)
33
+ return Stream.splitLines(
34
+ Stream.mapChunks(stream(command), Chunk.map((bytes) => decoder.decode(bytes)))
35
+ )
36
+ }
37
+ return {
38
+ start,
39
+ exitCode: (command) => Effect.flatMap(start(command), (process) => process.exitCode),
40
+ stream,
41
+ string: (command, encoding = "utf-8") => {
42
+ const decoder = new TextDecoder(encoding)
43
+ return pipe(
44
+ start(command),
45
+ Effect.flatMap((process) => Stream.run(process.stdout, collectUint8Array)),
46
+ Effect.map((bytes) => decoder.decode(bytes))
47
+ )
48
+ },
49
+ lines: (command, encoding = "utf-8") => {
50
+ return pipe(
51
+ streamLines(command, encoding),
52
+ Stream.runCollect,
53
+ Effect.map(Chunk.toReadonlyArray)
54
+ )
55
+ },
56
+ streamLines
57
+ }
58
+ }
59
+
60
+ const collectUint8Array: Sink.Sink<never, never, Uint8Array, never, Uint8Array> = Sink.foldLeftChunks(
61
+ new Uint8Array(),
62
+ (bytes, chunk: Chunk.Chunk<Uint8Array>) =>
63
+ Chunk.reduce(chunk, bytes, (acc, curr) => {
64
+ const newArray = new Uint8Array(acc.length + curr.length)
65
+ newArray.set(acc)
66
+ newArray.set(curr, acc.length)
67
+ return newArray
68
+ })
69
+ )
@@ -52,14 +52,12 @@ const consoleImpl = Console.of({
52
52
  })
53
53
  },
54
54
  group(options) {
55
- return (self) =>
56
- Effect.acquireUseRelease(
57
- options?.collapsed ?
58
- Effect.sync(() => console.groupCollapsed(options?.label)) :
59
- Effect.sync(() => console.group(options?.label)),
60
- () => self,
61
- () => Effect.sync(() => console.groupEnd())
62
- )
55
+ return Effect.acquireRelease(
56
+ options?.collapsed ?
57
+ Effect.sync(() => console.groupCollapsed(options?.label)) :
58
+ Effect.sync(() => console.group(options?.label)),
59
+ () => Effect.sync(() => console.groupEnd())
60
+ )
63
61
  },
64
62
  info(...args) {
65
63
  return Effect.sync(() => {
@@ -77,12 +75,10 @@ const consoleImpl = Console.of({
77
75
  })
78
76
  },
79
77
  time(label) {
80
- return (self) =>
81
- Effect.acquireUseRelease(
82
- Effect.sync(() => console.time(label)),
83
- () => self,
84
- () => Effect.sync(() => console.timeEnd(label))
85
- )
78
+ return Effect.acquireRelease(
79
+ Effect.sync(() => console.time(label)),
80
+ () => Effect.sync(() => console.timeEnd(label))
81
+ )
86
82
  },
87
83
  timeLog(label, ...args) {
88
84
  return Effect.sync(() => {
@@ -98,8 +94,90 @@ const consoleImpl = Console.of({
98
94
  return Effect.sync(() => {
99
95
  console.warn(...args)
100
96
  })
97
+ },
98
+ withGroup(options) {
99
+ return (self) =>
100
+ Effect.acquireUseRelease(
101
+ options?.collapsed ?
102
+ Effect.sync(() => console.groupCollapsed(options?.label)) :
103
+ Effect.sync(() => console.group(options?.label)),
104
+ () => self,
105
+ () => Effect.sync(() => console.groupEnd())
106
+ )
107
+ },
108
+ withTime(label) {
109
+ return (self) =>
110
+ Effect.acquireUseRelease(
111
+ Effect.sync(() => console.time(label)),
112
+ () => self,
113
+ () => Effect.sync(() => console.timeEnd(label))
114
+ )
101
115
  }
102
116
  })
103
117
 
104
118
  /** @internal */
105
119
  export const layer = Layer.succeed(Console, consoleImpl)
120
+
121
+ /** @internal */
122
+ export const assert = (condition: boolean, ...args: ReadonlyArray<any>) =>
123
+ Effect.flatMap(Console, (_) => _.assert(condition, ...args))
124
+
125
+ /** @internal */
126
+ export const clear = () => Effect.flatMap(Console, (_) => _.clear())
127
+
128
+ /** @internal */
129
+ export const count = (label?: string) => Effect.flatMap(Console, (_) => _.count(label))
130
+
131
+ /** @internal */
132
+ export const countReset = (label?: string) => Effect.flatMap(Console, (_) => _.countReset(label))
133
+
134
+ /** @internal */
135
+ export const debug = (...args: ReadonlyArray<any>) => Effect.flatMap(Console, (_) => _.debug(...args))
136
+
137
+ /** @internal */
138
+ export const dir = (...args: ReadonlyArray<any>) => Effect.flatMap(Console, (_) => _.dir(...args))
139
+
140
+ /** @internal */
141
+ export const dirxml = (...args: ReadonlyArray<any>) => Effect.flatMap(Console, (_) => _.dirxml(...args))
142
+
143
+ /** @internal */
144
+ export const error = (...args: ReadonlyArray<any>) => Effect.flatMap(Console, (_) => _.error(...args))
145
+
146
+ /** @internal */
147
+ export const group = (options?: { label?: string; collapsed?: boolean }) =>
148
+ Effect.flatMap(Console, (_) => _.group(options))
149
+
150
+ /** @internal */
151
+ export const info = (...args: ReadonlyArray<any>) => Effect.flatMap(Console, (_) => _.info(...args))
152
+
153
+ /** @internal */
154
+ export const log = (...args: ReadonlyArray<any>) => Effect.flatMap(Console, (_) => _.log(...args))
155
+
156
+ /** @internal */
157
+ export const table = (tabularData: any, properties?: ReadonlyArray<string>) =>
158
+ Effect.flatMap(Console, (_) => _.table(tabularData, properties))
159
+
160
+ /** @internal */
161
+ export const time = (label?: string) => Effect.flatMap(Console, (_) => _.time(label))
162
+
163
+ /** @internal */
164
+ export const timeLog = (label?: string, ...args: ReadonlyArray<any>) =>
165
+ Effect.flatMap(Console, (_) => _.timeLog(label, ...args))
166
+
167
+ /** @internal */
168
+ export const trace = (...args: ReadonlyArray<any>) => Effect.flatMap(Console, (_) => _.trace(...args))
169
+
170
+ /** @internal */
171
+ export const warn = (...args: ReadonlyArray<any>) => Effect.flatMap(Console, (_) => _.warn(...args))
172
+
173
+ /** @internal */
174
+ export const withGroup = (options?: { label?: string; collapsed?: boolean }) =>
175
+ <R, E, A>(
176
+ self: Effect.Effect<R, E, A>
177
+ ) => Effect.flatMap(Console, (_) => _.withGroup(options)(self))
178
+
179
+ /** @internal */
180
+ export const withTime = (label?: string) =>
181
+ <R, E, A>(
182
+ self: Effect.Effect<R, E, A>
183
+ ) => Effect.flatMap(Console, (_) => _.withTime(label)(self))
@@ -2,8 +2,7 @@ import { Tag } from "@effect/data/Context"
2
2
  import { pipe } from "@effect/data/Function"
3
3
  import * as Option from "@effect/data/Option"
4
4
  import * as Effect from "@effect/io/Effect"
5
- import type { FileSystem, Size as Size_, StreamOptions } from "@effect/platform/FileSystem"
6
- import type { File } from "@effect/platform/FileSystem/File"
5
+ import type { File, FileSystem, Size as Size_, StreamOptions } from "@effect/platform/FileSystem"
7
6
  import * as Sink from "@effect/stream/Sink"
8
7
  import * as Stream from "@effect/stream/Stream"
9
8
 
@@ -36,13 +35,13 @@ export const make = (impl: Omit<FileSystem, "stream" | "sink">): FileSystem => {
36
35
  const stream = (file: File, {
37
36
  bufferSize = 4,
38
37
  bytesToRead,
39
- chunkSize = Size(16n * 1024n),
40
- offset = Size(0n)
38
+ chunkSize = Size(64 * 1024),
39
+ offset = Size(0)
41
40
  }: StreamOptions = {}) =>
42
41
  Stream.bufferChunks(
43
42
  Stream.unfoldEffect(offset, (position) => {
44
43
  if (bytesToRead !== undefined && bytesToRead <= position - offset) {
45
- return Effect.succeedNone()
44
+ return Effect.succeed(Option.none())
46
45
  }
47
46
 
48
47
  const toRead = bytesToRead !== undefined && bytesToRead - (position - offset) < chunkSize
@@ -0,0 +1,101 @@
1
+ import { Tag } from "@effect/data/Context"
2
+ import { identity } from "@effect/data/Function"
3
+ import * as Effect from "@effect/io/Effect"
4
+ import * as Layer from "@effect/io/Layer"
5
+ import { BadArgument } from "@effect/platform/Error"
6
+ import type { Path as _Path } from "@effect/platform/Path"
7
+ import * as PathB from "path-browserify"
8
+
9
+ /** @internal */
10
+ export const Path = Tag<_Path>()
11
+
12
+ /** @internal */
13
+ export const layer = Layer.succeed(
14
+ Path,
15
+ Path.of({
16
+ ...PathB,
17
+ fromFileUrl,
18
+ toFileUrl,
19
+ toNamespacedPath: identity
20
+ })
21
+ )
22
+
23
+ /**
24
+ * The following functions are adapted from the Node.js source code:
25
+ * https://github.com/nodejs/node/blob/main/lib/internal/url.js
26
+ *
27
+ * The following license applies to these functions:
28
+ * - MIT
29
+ */
30
+
31
+ function fromFileUrl(url: URL): Effect.Effect<never, BadArgument, string> {
32
+ if (url.protocol !== "file:") {
33
+ return Effect.fail(BadArgument({
34
+ module: "Path",
35
+ method: "fromFileUrl",
36
+ message: "URL must be of scheme file"
37
+ }))
38
+ } else if (url.hostname !== "") {
39
+ return Effect.fail(BadArgument({
40
+ module: "Path",
41
+ method: "fromFileUrl",
42
+ message: "Invalid file URL host"
43
+ }))
44
+ }
45
+ const pathname = url.pathname
46
+ for (let n = 0; n < pathname.length; n++) {
47
+ if (pathname[n] === "%") {
48
+ const third = pathname.codePointAt(n + 2)! | 0x20
49
+ if (pathname[n + 1] === "2" && third === 102) {
50
+ return Effect.fail(BadArgument({
51
+ module: "Path",
52
+ method: "fromFileUrl",
53
+ message: "must not include encoded / characters"
54
+ }))
55
+ }
56
+ }
57
+ }
58
+ return Effect.succeed(decodeURIComponent(pathname))
59
+ }
60
+
61
+ const CHAR_FORWARD_SLASH = 47
62
+
63
+ function toFileUrl(filepath: string) {
64
+ const outURL = new URL("file://")
65
+ let resolved = PathB.resolve(filepath)
66
+ // path.resolve strips trailing slashes so we must add them back
67
+ const filePathLast = filepath.charCodeAt(filepath.length - 1)
68
+ if (
69
+ (filePathLast === CHAR_FORWARD_SLASH) &&
70
+ resolved[resolved.length - 1] !== "/"
71
+ ) {
72
+ resolved += "/"
73
+ }
74
+ outURL.pathname = encodePathChars(resolved)
75
+ return Effect.succeed(outURL)
76
+ }
77
+
78
+ const percentRegEx = /%/g
79
+ const backslashRegEx = /\\/g
80
+ const newlineRegEx = /\n/g
81
+ const carriageReturnRegEx = /\r/g
82
+ const tabRegEx = /\t/g
83
+
84
+ function encodePathChars(filepath: string) {
85
+ if (filepath.includes("%")) {
86
+ filepath = filepath.replace(percentRegEx, "%25")
87
+ }
88
+ if (filepath.includes("\\")) {
89
+ filepath = filepath.replace(backslashRegEx, "%5C")
90
+ }
91
+ if (filepath.includes("\n")) {
92
+ filepath = filepath.replace(newlineRegEx, "%0A")
93
+ }
94
+ if (filepath.includes("\r")) {
95
+ filepath = filepath.replace(carriageReturnRegEx, "%0D")
96
+ }
97
+ if (filepath.includes("\t")) {
98
+ filepath = filepath.replace(tabRegEx, "%09")
99
+ }
100
+ return filepath
101
+ }
@@ -1,91 +0,0 @@
1
- /**
2
- * @since 1.0.0
3
- */
4
- import * as Brand from "@effect/data/Brand";
5
- import type { Option } from "@effect/data/Option";
6
- import type * as Effect from "@effect/io/Effect";
7
- import type { PlatformError } from "@effect/platform/Error";
8
- import type { Size } from "@effect/platform/FileSystem";
9
- /**
10
- * @since 1.0.0
11
- * @category type id
12
- */
13
- export declare const FileTypeId: unique symbol;
14
- /**
15
- * @since 1.0.0
16
- * @category type id
17
- */
18
- export type FileTypeId = typeof FileTypeId;
19
- /**
20
- * @since 1.0.0
21
- * @category guard
22
- */
23
- export declare const isFile: (u: unknown) => u is File;
24
- /**
25
- * @since 1.0.0
26
- * @category model
27
- */
28
- export interface File {
29
- readonly [FileTypeId]: FileTypeId;
30
- readonly fd: File.Descriptor;
31
- readonly stat: Effect.Effect<never, PlatformError, File.Info>;
32
- readonly read: (buffer: Uint8Array, options?: FileReadOptions) => Effect.Effect<never, PlatformError, Size>;
33
- readonly readAlloc: (size: Size, options?: FileReadOptions) => Effect.Effect<never, PlatformError, Option<Uint8Array>>;
34
- readonly truncate: (length?: Size) => Effect.Effect<never, PlatformError, void>;
35
- readonly write: (buffer: Uint8Array) => Effect.Effect<never, PlatformError, Size>;
36
- readonly writeAll: (buffer: Uint8Array) => Effect.Effect<never, PlatformError, void>;
37
- }
38
- /**
39
- * @since 1.0.0
40
- * @category constructor
41
- */
42
- export declare const make: (impl: Omit<File, FileTypeId>) => File;
43
- /**
44
- * @since 1.0.0
45
- */
46
- export declare namespace File {
47
- /**
48
- * @since 1.0.0
49
- * @category model
50
- */
51
- type Descriptor = Brand.Branded<number, "FileDescriptor">;
52
- /**
53
- * @since 1.0.0
54
- * @category model
55
- */
56
- type Type = "File" | "Directory" | "SymbolicLink" | "BlockDevice" | "CharacterDevice" | "FIFO" | "Socket" | "Unknown";
57
- /**
58
- * @since 1.0.0
59
- * @category model
60
- */
61
- interface Info {
62
- readonly type: Type;
63
- readonly mtime: Option<Date>;
64
- readonly atime: Option<Date>;
65
- readonly birthtime: Option<Date>;
66
- readonly dev: number;
67
- readonly ino: Option<number>;
68
- readonly mode: number;
69
- readonly nlink: Option<number>;
70
- readonly uid: Option<number>;
71
- readonly gid: Option<number>;
72
- readonly rdev: Option<number>;
73
- readonly size: Size;
74
- readonly blksize: Option<Size>;
75
- readonly blocks: Option<number>;
76
- }
77
- }
78
- /**
79
- * @since 1.0.0
80
- * @category constructor
81
- */
82
- export declare const Descriptor: Brand.Brand.Constructor<File.Descriptor>;
83
- /**
84
- * @since 1.0.0
85
- * @category model
86
- */
87
- export interface FileReadOptions {
88
- readonly offset?: Size;
89
- readonly length?: Size;
90
- }
91
- //# sourceMappingURL=File.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"File.d.ts","sourceRoot":"","sources":["../src/FileSystem/File.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"File.js","names":["Brand","_interopRequireWildcard","require","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","FileTypeId","Symbol","for","exports","isFile","u","make","impl","Descriptor","nominal"],"sources":["../src/FileSystem/File.ts"],"sourcesContent":[null],"mappings":";;;;;;AAGA,IAAAA,KAAA,gBAAAC,uBAAA,eAAAC,OAAA;AAA2C,SAAAC,yBAAAC,WAAA,eAAAC,OAAA,kCAAAC,iBAAA,OAAAD,OAAA,QAAAE,gBAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,CAAAC,WAAA,WAAAA,WAAA,GAAAG,gBAAA,GAAAD,iBAAA,KAAAF,WAAA;AAAA,SAAAH,wBAAAO,GAAA,EAAAJ,WAAA,SAAAA,WAAA,IAAAI,GAAA,IAAAA,GAAA,CAAAC,UAAA,WAAAD,GAAA,QAAAA,GAAA,oBAAAA,GAAA,wBAAAA,GAAA,4BAAAE,OAAA,EAAAF,GAAA,UAAAG,KAAA,GAAAR,wBAAA,CAAAC,WAAA,OAAAO,KAAA,IAAAA,KAAA,CAAAC,GAAA,CAAAJ,GAAA,YAAAG,KAAA,CAAAE,GAAA,CAAAL,GAAA,SAAAM,MAAA,WAAAC,qBAAA,GAAAC,MAAA,CAAAC,cAAA,IAAAD,MAAA,CAAAE,wBAAA,WAAAC,GAAA,IAAAX,GAAA,QAAAW,GAAA,kBAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAd,GAAA,EAAAW,GAAA,SAAAI,IAAA,GAAAR,qBAAA,GAAAC,MAAA,CAAAE,wBAAA,CAAAV,GAAA,EAAAW,GAAA,cAAAI,IAAA,KAAAA,IAAA,CAAAV,GAAA,IAAAU,IAAA,CAAAC,GAAA,KAAAR,MAAA,CAAAC,cAAA,CAAAH,MAAA,EAAAK,GAAA,EAAAI,IAAA,YAAAT,MAAA,CAAAK,GAAA,IAAAX,GAAA,CAAAW,GAAA,SAAAL,MAAA,CAAAJ,OAAA,GAAAF,GAAA,MAAAG,KAAA,IAAAA,KAAA,CAAAa,GAAA,CAAAhB,GAAA,EAAAM,MAAA,YAAAA,MAAA;AAH3C;;;;AASA;;;;AAIO,MAAMW,UAAU,gBAAkBC,MAAM,CAACC,GAAG,CACjD,kCAAkC,CACnC;AAQD;;;;AAAAC,OAAA,CAAAH,UAAA,GAAAA,UAAA;AAIO,MAAMI,MAAM,GAAIC,CAAU,IAAgB,OAAOA,CAAC,KAAK,QAAQ,IAAIA,CAAC,KAAK,IAAI,IAAIL,UAAU,IAAIK,CAAC;AA6BvG;;;;AAAAF,OAAA,CAAAC,MAAA,GAAAA,MAAA;AAIO,MAAME,IAAI,GAAIC,IAA4B,KAAY;EAC3D,CAACP,UAAU,GAAGA,UAAU;EACxB,GAAGO;CACJ,CAAC;AAgDF;;;;AAAAJ,OAAA,CAAAG,IAAA,GAAAA,IAAA;AAIO,MAAME,UAAU,gBAAGjC,KAAK,CAACkC,OAAO,EAAmB;AAAAN,OAAA,CAAAK,UAAA,GAAAA,UAAA"}
@@ -1,28 +0,0 @@
1
- /**
2
- * @since 1.0.0
3
- */
4
- import * as Brand from "@effect/data/Brand";
5
- /**
6
- * @since 1.0.0
7
- * @category type id
8
- */
9
- export const FileTypeId = /*#__PURE__*/Symbol.for("@effect/platform/FileSystem/File");
10
- /**
11
- * @since 1.0.0
12
- * @category guard
13
- */
14
- export const isFile = u => typeof u === "object" && u !== null && FileTypeId in u;
15
- /**
16
- * @since 1.0.0
17
- * @category constructor
18
- */
19
- export const make = impl => ({
20
- [FileTypeId]: FileTypeId,
21
- ...impl
22
- });
23
- /**
24
- * @since 1.0.0
25
- * @category constructor
26
- */
27
- export const Descriptor = /*#__PURE__*/Brand.nominal();
28
- //# sourceMappingURL=File.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"File.mjs","names":["Brand","FileTypeId","Symbol","for","isFile","u","make","impl","Descriptor","nominal"],"sources":["../../src/FileSystem/File.ts"],"sourcesContent":[null],"mappings":"AAAA;;;AAGA,OAAO,KAAKA,KAAK,MAAM,oBAAoB;AAM3C;;;;AAIA,OAAO,MAAMC,UAAU,gBAAkBC,MAAM,CAACC,GAAG,CACjD,kCAAkC,CACnC;AAQD;;;;AAIA,OAAO,MAAMC,MAAM,GAAIC,CAAU,IAAgB,OAAOA,CAAC,KAAK,QAAQ,IAAIA,CAAC,KAAK,IAAI,IAAIJ,UAAU,IAAII,CAAC;AA6BvG;;;;AAIA,OAAO,MAAMC,IAAI,GAAIC,IAA4B,KAAY;EAC3D,CAACN,UAAU,GAAGA,UAAU;EACxB,GAAGM;CACJ,CAAC;AAgDF;;;;AAIA,OAAO,MAAMC,UAAU,gBAAGR,KAAK,CAACS,OAAO,EAAmB"}