@effect/platform 0.0.0 → 0.1.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.
- package/Console.d.ts +114 -12
- package/Console.d.ts.map +1 -1
- package/Console.js +109 -1
- package/Console.js.map +1 -1
- package/Error.d.ts +1 -1
- package/Error.d.ts.map +1 -1
- package/FileSystem.d.ts +246 -47
- package/FileSystem.d.ts.map +1 -1
- package/FileSystem.js +24 -1
- package/FileSystem.js.map +1 -1
- package/Path.d.ts +59 -0
- package/Path.d.ts.map +1 -0
- package/{FileSystem/File.js → Path.js} +14 -24
- package/Path.js.map +1 -0
- package/internal/console.js +63 -3
- package/internal/console.js.map +1 -1
- package/internal/fileSystem.js +2 -2
- package/internal/fileSystem.js.map +1 -1
- package/internal/path.d.ts +2 -0
- package/internal/path.d.ts.map +1 -0
- package/internal/path.js +97 -0
- package/internal/path.js.map +1 -0
- package/mjs/Console.mjs +90 -0
- package/mjs/Console.mjs.map +1 -1
- package/mjs/FileSystem.mjs +19 -0
- package/mjs/FileSystem.mjs.map +1 -1
- package/mjs/Path.mjs +20 -0
- package/mjs/Path.mjs.map +1 -0
- package/mjs/internal/console.mjs +44 -2
- package/mjs/internal/console.mjs.map +1 -1
- package/mjs/internal/fileSystem.mjs +2 -2
- package/mjs/internal/fileSystem.mjs.map +1 -1
- package/mjs/internal/path.mjs +87 -0
- package/mjs/internal/path.mjs.map +1 -0
- package/package.json +5 -4
- package/src/Console.ts +132 -12
- package/src/Error.ts +1 -1
- package/src/FileSystem.ts +356 -119
- package/src/Path.ts +64 -0
- package/src/internal/console.ts +92 -14
- package/src/internal/fileSystem.ts +3 -4
- package/src/internal/path.ts +101 -0
- package/FileSystem/File.d.ts +0 -91
- package/FileSystem/File.d.ts.map +0 -1
- package/FileSystem/File.js.map +0 -1
- package/mjs/FileSystem/File.mjs +0 -28
- package/mjs/FileSystem/File.mjs.map +0 -1
- package/src/FileSystem/File.ts +0 -125
|
@@ -0,0 +1,87 @@
|
|
|
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 * as PathB from "path-browserify";
|
|
7
|
+
/** @internal */
|
|
8
|
+
export const Path = /*#__PURE__*/Tag();
|
|
9
|
+
/** @internal */
|
|
10
|
+
export const layer = /*#__PURE__*/Layer.succeed(Path, /*#__PURE__*/Path.of({
|
|
11
|
+
...PathB,
|
|
12
|
+
fromFileUrl,
|
|
13
|
+
toFileUrl,
|
|
14
|
+
toNamespacedPath: identity
|
|
15
|
+
}));
|
|
16
|
+
/**
|
|
17
|
+
* The following functions are adapted from the Node.js source code:
|
|
18
|
+
* https://github.com/nodejs/node/blob/main/lib/internal/url.js
|
|
19
|
+
*
|
|
20
|
+
* The following license applies to these functions:
|
|
21
|
+
* - MIT
|
|
22
|
+
*/
|
|
23
|
+
function fromFileUrl(url) {
|
|
24
|
+
if (url.protocol !== "file:") {
|
|
25
|
+
return Effect.fail(BadArgument({
|
|
26
|
+
module: "Path",
|
|
27
|
+
method: "fromFileUrl",
|
|
28
|
+
message: "URL must be of scheme file"
|
|
29
|
+
}));
|
|
30
|
+
} else if (url.hostname !== "") {
|
|
31
|
+
return Effect.fail(BadArgument({
|
|
32
|
+
module: "Path",
|
|
33
|
+
method: "fromFileUrl",
|
|
34
|
+
message: "Invalid file URL host"
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
const pathname = url.pathname;
|
|
38
|
+
for (let n = 0; n < pathname.length; n++) {
|
|
39
|
+
if (pathname[n] === "%") {
|
|
40
|
+
const third = pathname.codePointAt(n + 2) | 0x20;
|
|
41
|
+
if (pathname[n + 1] === "2" && third === 102) {
|
|
42
|
+
return Effect.fail(BadArgument({
|
|
43
|
+
module: "Path",
|
|
44
|
+
method: "fromFileUrl",
|
|
45
|
+
message: "must not include encoded / characters"
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return Effect.succeed(decodeURIComponent(pathname));
|
|
51
|
+
}
|
|
52
|
+
const CHAR_FORWARD_SLASH = 47;
|
|
53
|
+
function toFileUrl(filepath) {
|
|
54
|
+
const outURL = new URL("file://");
|
|
55
|
+
let resolved = PathB.resolve(filepath);
|
|
56
|
+
// path.resolve strips trailing slashes so we must add them back
|
|
57
|
+
const filePathLast = filepath.charCodeAt(filepath.length - 1);
|
|
58
|
+
if (filePathLast === CHAR_FORWARD_SLASH && resolved[resolved.length - 1] !== "/") {
|
|
59
|
+
resolved += "/";
|
|
60
|
+
}
|
|
61
|
+
outURL.pathname = encodePathChars(resolved);
|
|
62
|
+
return Effect.succeed(outURL);
|
|
63
|
+
}
|
|
64
|
+
const percentRegEx = /%/g;
|
|
65
|
+
const backslashRegEx = /\\/g;
|
|
66
|
+
const newlineRegEx = /\n/g;
|
|
67
|
+
const carriageReturnRegEx = /\r/g;
|
|
68
|
+
const tabRegEx = /\t/g;
|
|
69
|
+
function encodePathChars(filepath) {
|
|
70
|
+
if (filepath.includes("%")) {
|
|
71
|
+
filepath = filepath.replace(percentRegEx, "%25");
|
|
72
|
+
}
|
|
73
|
+
if (filepath.includes("\\")) {
|
|
74
|
+
filepath = filepath.replace(backslashRegEx, "%5C");
|
|
75
|
+
}
|
|
76
|
+
if (filepath.includes("\n")) {
|
|
77
|
+
filepath = filepath.replace(newlineRegEx, "%0A");
|
|
78
|
+
}
|
|
79
|
+
if (filepath.includes("\r")) {
|
|
80
|
+
filepath = filepath.replace(carriageReturnRegEx, "%0D");
|
|
81
|
+
}
|
|
82
|
+
if (filepath.includes("\t")) {
|
|
83
|
+
filepath = filepath.replace(tabRegEx, "%09");
|
|
84
|
+
}
|
|
85
|
+
return filepath;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=path.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.mjs","names":["Tag","identity","Effect","Layer","BadArgument","PathB","Path","layer","succeed","of","fromFileUrl","toFileUrl","toNamespacedPath","url","protocol","fail","module","method","message","hostname","pathname","n","length","third","codePointAt","decodeURIComponent","CHAR_FORWARD_SLASH","filepath","outURL","URL","resolved","resolve","filePathLast","charCodeAt","encodePathChars","percentRegEx","backslashRegEx","newlineRegEx","carriageReturnRegEx","tabRegEx","includes","replace"],"sources":["../../src/internal/path.ts"],"sourcesContent":[null],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect/platform",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/effect-ts/platform.git"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@effect/data": "^0.12.
|
|
11
|
-
"@effect/io": "^0.26.
|
|
12
|
-
"@effect/stream": "^0.22.
|
|
10
|
+
"@effect/data": "^0.12.8",
|
|
11
|
+
"@effect/io": "^0.26.1",
|
|
12
|
+
"@effect/stream": "^0.22.1",
|
|
13
|
+
"path-browserify": "^1.0.1"
|
|
13
14
|
},
|
|
14
15
|
"publishConfig": {
|
|
15
16
|
"access": "public"
|
package/src/Console.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import type * as Context from "@effect/data/Context"
|
|
5
5
|
import type { Effect } from "@effect/io/Effect"
|
|
6
6
|
import type { Layer } from "@effect/io/Layer"
|
|
7
|
+
import type { Scope } from "@effect/io/Scope"
|
|
7
8
|
import * as internal from "@effect/platform/internal/console"
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -11,25 +12,30 @@ import * as internal from "@effect/platform/internal/console"
|
|
|
11
12
|
* @category model
|
|
12
13
|
*/
|
|
13
14
|
export interface Console {
|
|
14
|
-
assert(condition: boolean, ...args:
|
|
15
|
+
assert(condition: boolean, ...args: ReadonlyArray<any>): Effect<never, never, void>
|
|
15
16
|
clear(): Effect<never, never, void>
|
|
16
17
|
count(label?: string): Effect<never, never, void>
|
|
17
18
|
countReset(label?: string): Effect<never, never, void>
|
|
18
|
-
debug(...args:
|
|
19
|
-
dir(...args:
|
|
20
|
-
dirxml(...args:
|
|
21
|
-
error(...args:
|
|
19
|
+
debug(...args: ReadonlyArray<any>): Effect<never, never, void>
|
|
20
|
+
dir(...args: ReadonlyArray<any>): Effect<never, never, void>
|
|
21
|
+
dirxml(...args: ReadonlyArray<any>): Effect<never, never, void>
|
|
22
|
+
error(...args: ReadonlyArray<any>): Effect<never, never, void>
|
|
22
23
|
group(options?: {
|
|
23
24
|
readonly label?: string
|
|
24
25
|
readonly collapsed?: boolean
|
|
25
|
-
}):
|
|
26
|
-
info(...args:
|
|
27
|
-
log(...args:
|
|
26
|
+
}): Effect<Scope, never, void>
|
|
27
|
+
info(...args: ReadonlyArray<any>): Effect<never, never, void>
|
|
28
|
+
log(...args: ReadonlyArray<any>): Effect<never, never, void>
|
|
28
29
|
table(tabularData: any, properties?: ReadonlyArray<string>): Effect<never, never, void>
|
|
29
|
-
time(label?: string):
|
|
30
|
-
timeLog(label?: string, ...args:
|
|
31
|
-
trace(...args:
|
|
32
|
-
warn(...args:
|
|
30
|
+
time(label?: string): Effect<Scope, never, void>
|
|
31
|
+
timeLog(label?: string, ...args: ReadonlyArray<any>): Effect<never, never, void>
|
|
32
|
+
trace(...args: ReadonlyArray<any>): Effect<never, never, void>
|
|
33
|
+
warn(...args: ReadonlyArray<any>): Effect<never, never, void>
|
|
34
|
+
withGroup(options?: {
|
|
35
|
+
readonly label?: string
|
|
36
|
+
readonly collapsed?: boolean
|
|
37
|
+
}): <R, E, A>(self: Effect<R, E, A>) => Effect<R, E, A>
|
|
38
|
+
withTime(label?: string): <R, E, A>(self: Effect<R, E, A>) => Effect<R, E, A>
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
/**
|
|
@@ -43,3 +49,117 @@ export const Console: Context.Tag<Console, Console> = internal.Console
|
|
|
43
49
|
* @category layer
|
|
44
50
|
*/
|
|
45
51
|
export const layer: Layer<never, never, Console> = internal.layer
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @since 1.0.0
|
|
55
|
+
* @category accessor
|
|
56
|
+
*/
|
|
57
|
+
export const assert: (condition: boolean, ...args: ReadonlyArray<any>) => Effect<Console, never, void> = internal.assert
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @since 1.0.0
|
|
61
|
+
* @category accessor
|
|
62
|
+
*/
|
|
63
|
+
export const clear: () => Effect<Console, never, void> = internal.clear
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @since 1.0.0
|
|
67
|
+
* @category accessor
|
|
68
|
+
*/
|
|
69
|
+
export const count: (label?: string) => Effect<Console, never, void> = internal.count
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @since 1.0.0
|
|
73
|
+
* @category accessor
|
|
74
|
+
*/
|
|
75
|
+
export const countReset: (label?: string) => Effect<Console, never, void> = internal.countReset
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @since 1.0.0
|
|
79
|
+
* @category accessor
|
|
80
|
+
*/
|
|
81
|
+
export const debug: (...args: ReadonlyArray<any>) => Effect<Console, never, void> = internal.debug
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @since 1.0.0
|
|
85
|
+
* @category accessor
|
|
86
|
+
*/
|
|
87
|
+
export const dir: (...args: ReadonlyArray<any>) => Effect<Console, never, void> = internal.dir
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @since 1.0.0
|
|
91
|
+
* @category accessor
|
|
92
|
+
*/
|
|
93
|
+
export const dirxml: (...args: ReadonlyArray<any>) => Effect<Console, never, void> = internal.dirxml
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @since 1.0.0
|
|
97
|
+
* @category accessor
|
|
98
|
+
*/
|
|
99
|
+
export const error: (...args: ReadonlyArray<any>) => Effect<Console, never, void> = internal.error
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @since 1.0.0
|
|
103
|
+
* @category accessor
|
|
104
|
+
*/
|
|
105
|
+
export const group: (
|
|
106
|
+
options?: { label?: string; collapsed?: boolean }
|
|
107
|
+
) => Effect<Console | Scope, never, void> = internal.group
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @since 1.0.0
|
|
111
|
+
* @category accessor
|
|
112
|
+
*/
|
|
113
|
+
export const info: (...args: ReadonlyArray<any>) => Effect<Console, never, void> = internal.info
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @since 1.0.0
|
|
117
|
+
* @category accessor
|
|
118
|
+
*/
|
|
119
|
+
export const log: (...args: ReadonlyArray<any>) => Effect<Console, never, void> = internal.log
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @since 1.0.0
|
|
123
|
+
* @category accessor
|
|
124
|
+
*/
|
|
125
|
+
export const table: (tabularData: any, properties?: ReadonlyArray<string>) => Effect<Console, never, void> =
|
|
126
|
+
internal.table
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @since 1.0.0
|
|
130
|
+
* @category accessor
|
|
131
|
+
*/
|
|
132
|
+
export const time: (label?: string) => Effect<Console | Scope, never, void> = internal.time
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @since 1.0.0
|
|
136
|
+
* @category accessor
|
|
137
|
+
*/
|
|
138
|
+
export const timeLog: (label?: string, ...args: ReadonlyArray<any>) => Effect<Console, never, void> = internal.timeLog
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @since 1.0.0
|
|
142
|
+
* @category accessor
|
|
143
|
+
*/
|
|
144
|
+
export const trace: (...args: ReadonlyArray<any>) => Effect<Console, never, void> = internal.trace
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @since 1.0.0
|
|
148
|
+
* @category accessor
|
|
149
|
+
*/
|
|
150
|
+
export const warn: (...args: ReadonlyArray<any>) => Effect<Console, never, void> = internal.warn
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @since 1.0.0
|
|
154
|
+
* @category accessor
|
|
155
|
+
*/
|
|
156
|
+
export const withGroup: (
|
|
157
|
+
options?: { label?: string; collapsed?: boolean }
|
|
158
|
+
) => <R, E, A>(self: Effect<R, E, A>) => Effect<Console | R, E, A> = internal.withGroup
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @since 1.0.0
|
|
162
|
+
* @category accessor
|
|
163
|
+
*/
|
|
164
|
+
export const withTime: (label?: string) => <R, E, A>(self: Effect<R, E, A>) => Effect<Console | R, E, A> =
|
|
165
|
+
internal.withTime
|
package/src/Error.ts
CHANGED
|
@@ -33,7 +33,7 @@ export namespace PlatformError {
|
|
|
33
33
|
export interface Base extends Data.Case {
|
|
34
34
|
readonly [PlatformErrorTypeId]: typeof PlatformErrorTypeId
|
|
35
35
|
readonly _tag: string
|
|
36
|
-
readonly module: "FileSystem"
|
|
36
|
+
readonly module: "FileSystem" | "Path"
|
|
37
37
|
readonly method: string
|
|
38
38
|
readonly message: string
|
|
39
39
|
}
|