firefly-compiler 0.4.35 → 0.4.40
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/bin/Release.ff +30 -8
- package/compiler/Compiler.ff +1 -1
- package/core/BrowserSystem.ff +3 -0
- package/core/Buffer.ff +3 -3
- package/core/BuildSystem.ff +3 -0
- package/core/Crypto.ff +102 -0
- package/core/Instant.ff +17 -0
- package/core/NodeSystem.ff +3 -0
- package/core/Stream.ff +1 -1
- package/experimental/random/RunLength.ff +3 -3
- package/experimental/s3/S3TestAuthorizationHeader.ff +39 -0
- package/experimental/s3/S3TestPut.ff +16 -0
- package/lsp/LanguageServer.ff +2 -2
- package/output/js/ff/compiler/Builder.mjs +1 -1
- package/output/js/ff/compiler/Compiler.mjs +2 -2
- package/output/js/ff/compiler/Dependencies.mjs +1 -1
- package/output/js/ff/compiler/DependencyLock.mjs +1 -1
- package/output/js/ff/compiler/Deriver.mjs +1 -1
- package/output/js/ff/compiler/Dictionaries.mjs +1 -1
- package/output/js/ff/compiler/Environment.mjs +1 -1
- package/output/js/ff/compiler/Inference.mjs +1 -1
- package/output/js/ff/compiler/JsEmitter.mjs +1 -1
- package/output/js/ff/compiler/JsImporter.mjs +1 -1
- package/output/js/ff/compiler/LspHook.mjs +1 -1
- package/output/js/ff/compiler/Main.mjs +1 -1
- package/output/js/ff/compiler/ModuleCache.mjs +1 -1
- package/output/js/ff/compiler/Parser.mjs +1 -1
- package/output/js/ff/compiler/Patterns.mjs +1 -1
- package/output/js/ff/compiler/Resolver.mjs +1 -1
- package/output/js/ff/compiler/Substitution.mjs +1 -1
- package/output/js/ff/compiler/Syntax.mjs +1 -1
- package/output/js/ff/compiler/Token.mjs +1 -1
- package/output/js/ff/compiler/Tokenizer.mjs +1 -1
- package/output/js/ff/compiler/Unification.mjs +1 -1
- package/output/js/ff/compiler/Wildcards.mjs +1 -1
- package/output/js/ff/compiler/Workspace.mjs +1 -1
- package/output/js/ff/core/Any.mjs +1 -1
- package/output/js/ff/core/Array.mjs +1 -1
- package/output/js/ff/core/AssetSystem.mjs +1 -1
- package/output/js/ff/core/Atomic.mjs +1 -1
- package/output/js/ff/core/Bool.mjs +1 -1
- package/output/js/ff/core/BrowserSystem.mjs +9 -1
- package/output/js/ff/core/Buffer.mjs +8 -8
- package/output/js/ff/core/BuildSystem.mjs +9 -1
- package/output/js/ff/core/Channel.mjs +1 -1
- package/output/js/ff/core/Char.mjs +1 -1
- package/output/js/ff/core/Core.mjs +1 -1
- package/output/js/ff/core/Crypto.mjs +278 -0
- package/output/js/ff/core/Duration.mjs +1 -1
- package/output/js/ff/core/Equal.mjs +1 -1
- package/output/js/ff/core/Error.mjs +1 -1
- package/output/js/ff/core/FileHandle.mjs +1 -1
- package/output/js/ff/core/Float.mjs +1 -1
- package/output/js/ff/core/HttpClient.mjs +1 -1
- package/output/js/ff/core/Instant.mjs +39 -1
- package/output/js/ff/core/Int.mjs +1 -1
- package/output/js/ff/core/IntMap.mjs +1 -1
- package/output/js/ff/core/JsSystem.mjs +1 -1
- package/output/js/ff/core/JsValue.mjs +1 -1
- package/output/js/ff/core/Json.mjs +1 -1
- package/output/js/ff/core/List.mjs +1 -1
- package/output/js/ff/core/Lock.mjs +1 -1
- package/output/js/ff/core/Log.mjs +1 -1
- package/output/js/ff/core/Map.mjs +1 -1
- package/output/js/ff/core/NodeSystem.mjs +9 -1
- package/output/js/ff/core/Nothing.mjs +1 -1
- package/output/js/ff/core/Option.mjs +1 -1
- package/output/js/ff/core/Ordering.mjs +1 -1
- package/output/js/ff/core/Pair.mjs +1 -1
- package/output/js/ff/core/Path.mjs +1 -1
- package/output/js/ff/core/Random.mjs +1 -1
- package/output/js/ff/core/RbMap.mjs +1 -1
- package/output/js/ff/core/Serializable.mjs +1 -1
- package/output/js/ff/core/Set.mjs +1 -1
- package/output/js/ff/core/Show.mjs +1 -1
- package/output/js/ff/core/SourceLocation.mjs +1 -1
- package/output/js/ff/core/Stream.mjs +3 -3
- package/output/js/ff/core/String.mjs +1 -1
- package/output/js/ff/core/StringMap.mjs +1 -1
- package/output/js/ff/core/Task.mjs +1 -1
- package/output/js/ff/core/Try.mjs +1 -1
- package/output/js/ff/core/Unit.mjs +1 -1
- package/package.json +27 -27
- package/s3/.firefly/package.ff +1 -0
- package/s3/S3.ff +93 -0
- package/vscode/package.json +1 -1
- package/core/Digest.ff +0 -51
- package/experimental/s3/S3.ff +0 -126
- package/output/js/ff/core/Digest.mjs +0 -190
|
@@ -28,7 +28,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
28
28
|
|
|
29
29
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
30
30
|
|
|
31
|
-
import * as
|
|
31
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
32
32
|
|
|
33
33
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
34
34
|
|
|
@@ -188,6 +188,10 @@ export function NodeSystem_mainTask(self_) {
|
|
|
188
188
|
throw new Error('Function NodeSystem_mainTask is missing on this target in sync context.');
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
+
export function NodeSystem_crypto(self_) {
|
|
192
|
+
throw new Error('Function NodeSystem_crypto is missing on this target in sync context.');
|
|
193
|
+
}
|
|
194
|
+
|
|
191
195
|
export function NodeSystem_js(self_) {
|
|
192
196
|
throw new Error('Function NodeSystem_js is missing on this target in sync context.');
|
|
193
197
|
}
|
|
@@ -290,6 +294,10 @@ export async function NodeSystem_mainTask$(self_, $task) {
|
|
|
290
294
|
return self_.task_
|
|
291
295
|
}
|
|
292
296
|
|
|
297
|
+
export async function NodeSystem_crypto$(self_, $task) {
|
|
298
|
+
return (typeof globalThis !== 'undefined' ? globalThis : window).crypto
|
|
299
|
+
}
|
|
300
|
+
|
|
293
301
|
export async function NodeSystem_js$(self_, $task) {
|
|
294
302
|
return typeof globalThis !== 'undefined' ? globalThis : window
|
|
295
303
|
}
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
|
@@ -28,7 +28,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
28
28
|
|
|
29
29
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
30
30
|
|
|
31
|
-
import * as
|
|
31
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
32
32
|
|
|
33
33
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
34
34
|
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
|
@@ -24,7 +24,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
24
24
|
|
|
25
25
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
26
26
|
|
|
27
|
-
import * as
|
|
27
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
28
28
|
|
|
29
29
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
30
30
|
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
|
@@ -1098,7 +1098,7 @@ const builder_ = ff_core_Array.new_();
|
|
|
1098
1098
|
ff_core_Stream.Stream_each(self_, ((_w1) => {
|
|
1099
1099
|
ff_core_Array.Array_push(builder_, _w1)
|
|
1100
1100
|
}));
|
|
1101
|
-
return ff_core_Buffer.
|
|
1101
|
+
return ff_core_Buffer.fromBufferList_(ff_core_Array.Array_drain(builder_))
|
|
1102
1102
|
}
|
|
1103
1103
|
|
|
1104
1104
|
export function Stream_toString(self_, encoding_ = "utf8") {
|
|
@@ -1133,7 +1133,7 @@ const builder_ = ff_core_Array.new_();
|
|
|
1133
1133
|
(await ff_core_Stream.Stream_each$(self_, (async (_w1, $task) => {
|
|
1134
1134
|
ff_core_Array.Array_push(builder_, _w1)
|
|
1135
1135
|
}), $task));
|
|
1136
|
-
return ff_core_Buffer.
|
|
1136
|
+
return ff_core_Buffer.fromBufferList_(ff_core_Array.Array_drain(builder_))
|
|
1137
1137
|
}
|
|
1138
1138
|
|
|
1139
1139
|
export async function Stream_toString$(self_, encoding_ = "utf8", $task) {
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
|
@@ -22,7 +22,7 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
|
|
|
22
22
|
|
|
23
23
|
import * as ff_core_Core from "../../ff/core/Core.mjs"
|
|
24
24
|
|
|
25
|
-
import * as
|
|
25
|
+
import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
|
|
26
26
|
|
|
27
27
|
import * as ff_core_Duration from "../../ff/core/Duration.mjs"
|
|
28
28
|
|
package/package.json
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
2
|
+
"name": "firefly-compiler",
|
|
3
|
+
"displayName": "Firefly Compiler",
|
|
4
|
+
"description": "Firefly compiler",
|
|
5
|
+
"author": "Firefly team",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"version": "0.4.40",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/Ahnfelt/firefly-boot"
|
|
11
|
+
},
|
|
12
|
+
"publisher": "firefly-team",
|
|
13
|
+
"categories": [
|
|
14
|
+
"Programming Languages"
|
|
15
|
+
],
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=18.0.0"
|
|
18
|
+
},
|
|
19
|
+
"main": "./vscode/client/out/extension",
|
|
20
|
+
"icon": "./vscode/icons/firefly-logo.png",
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"pkg": "^5.8.0",
|
|
23
|
+
"tar": "^6.1.11",
|
|
24
|
+
"esbuild": "^0.21.3"
|
|
25
|
+
},
|
|
26
|
+
"bin": {
|
|
27
|
+
"firefly": "./bin/firefly.mjs"
|
|
28
|
+
}
|
|
29
29
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
package ff:s3:0.0.0
|
package/s3/S3.ff
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
put(
|
|
2
|
+
system: NodeSystem
|
|
3
|
+
accessKeyId: String
|
|
4
|
+
secretAccessKey: String
|
|
5
|
+
region: String
|
|
6
|
+
bucket: String
|
|
7
|
+
objectKey: String
|
|
8
|
+
body: Buffer
|
|
9
|
+
headers: List[Pair[String, String]]
|
|
10
|
+
): Unit {
|
|
11
|
+
let now = system.mainTask().now()
|
|
12
|
+
let amzDate = toIsoString(now)
|
|
13
|
+
let contentHash = system.crypto().sha256(body).toHex()
|
|
14
|
+
let host = bucket + ".s3.amazonaws.com"
|
|
15
|
+
let encodedKey = encode(objectKey)
|
|
16
|
+
let canonicalHeaders = [
|
|
17
|
+
Pair("host", host)
|
|
18
|
+
Pair("x-amz-date", amzDate)
|
|
19
|
+
Pair("x-amz-content-sha256", contentHash)
|
|
20
|
+
...headers
|
|
21
|
+
]
|
|
22
|
+
let authenticationHeader = makeS3AuthorizationHeader(system, accessKeyId, secretAccessKey, region, bucket, encodedKey, body, canonicalHeaders, amzDate)
|
|
23
|
+
let allHeaders = [...canonicalHeaders, Pair("Authorization", authenticationHeader)]
|
|
24
|
+
|
|
25
|
+
let url = "https://" + host + "/" + encodedKey
|
|
26
|
+
let response = system.httpClient().fetch(url, method = "PUT", headers = allHeaders, body = Some(HttpClient.bodyBuffer(body)), throw = False)
|
|
27
|
+
system.writeLine("" + response.status())
|
|
28
|
+
system.writeLine(response.statusText())
|
|
29
|
+
system.writeLine(response.readText())
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
makeS3AuthorizationHeader(
|
|
33
|
+
system: NodeSystem
|
|
34
|
+
accessKeyId: String
|
|
35
|
+
secretAccessKey: String
|
|
36
|
+
region: String
|
|
37
|
+
bucket: String
|
|
38
|
+
encodedKey: String
|
|
39
|
+
body: Buffer
|
|
40
|
+
canonicalHeaders: List[Pair[String, String]]
|
|
41
|
+
amzDate: String
|
|
42
|
+
): String {
|
|
43
|
+
// CanonicalRequest
|
|
44
|
+
let canonicalQuerystring = "";
|
|
45
|
+
let contentHash = system.crypto().sha256(body).toHex()
|
|
46
|
+
let headers = canonicalHeaders.map {_.mapFirst {_.lower()}.mapSecond {_.trim()}}.sort()
|
|
47
|
+
let signedHeaders = headers.map {_.first}.join(";")
|
|
48
|
+
let canonicalRequest = [
|
|
49
|
+
"PUT"
|
|
50
|
+
"/" + encodedKey
|
|
51
|
+
canonicalQuerystring
|
|
52
|
+
...headers.map {p => p.first + ":" + p.second}
|
|
53
|
+
""
|
|
54
|
+
signedHeaders
|
|
55
|
+
contentHash
|
|
56
|
+
].join("\n")
|
|
57
|
+
|
|
58
|
+
// StringToSign
|
|
59
|
+
let scopeDate = amzDate.slice(0, 8) // YYYYMMDD
|
|
60
|
+
let credentialScope = [scopeDate, region, "s3", "aws4_request"].join("/")
|
|
61
|
+
let algorithm = "AWS4-HMAC-SHA256"
|
|
62
|
+
let stringToSign = [
|
|
63
|
+
algorithm
|
|
64
|
+
amzDate
|
|
65
|
+
credentialScope
|
|
66
|
+
system.crypto().sha256(canonicalRequest.toBuffer()).toHex()
|
|
67
|
+
].join("\n")
|
|
68
|
+
|
|
69
|
+
function hmacSha256(key: Buffer, message: String): Buffer {
|
|
70
|
+
system.crypto().hmacSha256(key, message.toBuffer())
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Signature
|
|
74
|
+
let signingKey = hmacSha256(hmacSha256(hmacSha256(hmacSha256(("AWS4" + secretAccessKey).toBuffer(), scopeDate), region), "s3"), "aws4_request")
|
|
75
|
+
let signature = hmacSha256(signingKey, stringToSign).toHex()
|
|
76
|
+
|
|
77
|
+
algorithm + " Credential=" + accessKeyId + "/" + credentialScope + ",SignedHeaders=" + signedHeaders + ",Signature=" + signature
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
toIsoString(instant: Instant): String
|
|
81
|
+
target js sync """
|
|
82
|
+
const d = new Date(instant_ * 1000);
|
|
83
|
+
return d.toISOString().replaceAll(/[-:]|[.].../g, "");
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
encodeURIComponent(text: String): String
|
|
87
|
+
target js sync """
|
|
88
|
+
return encodeURIComponent(text_);
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
encode(text: String): String {
|
|
92
|
+
text.split('/').map {encodeURIComponent(_)}.join("/")
|
|
93
|
+
}
|
package/vscode/package.json
CHANGED
package/core/Digest.ff
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
class Digest {}
|
|
2
|
-
|
|
3
|
-
hmacSha256(key: Buffer, buffer: Buffer = Buffer.new(0)): Digest {
|
|
4
|
-
new("sha256", Some(key), buffer)
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
sha256(buffer: Buffer = Buffer.new(0)): Digest {
|
|
8
|
-
new("sha256", None, buffer)
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
new(algorithm: String, hmacKey: Option[Buffer] = None, buffer: Buffer = Buffer.new(0)): Digest
|
|
12
|
-
target node sync """
|
|
13
|
-
import * as crypto from 'node:crypto'
|
|
14
|
-
const digest = typeof hmacKey_.value_ !== 'undefined'
|
|
15
|
-
? crypto.createHmac(algorithm_, hmacKey_.value_)
|
|
16
|
-
: crypto.createHash(algorithm_);
|
|
17
|
-
if(buffer_.byteLength > 0) digest.update(buffer_);
|
|
18
|
-
return digest;
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
extend self: Digest {
|
|
22
|
-
|
|
23
|
-
writeText(text: String, encoding: String = "utf8"): Unit
|
|
24
|
-
target node sync """
|
|
25
|
-
self_.update(text_, encoding_);
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
writeBuffer(buffer: Buffer): Unit
|
|
29
|
-
target node sync """
|
|
30
|
-
self_.update(buffer_);
|
|
31
|
-
"""
|
|
32
|
-
|
|
33
|
-
writeStream(stream: Stream[Buffer]): Unit {
|
|
34
|
-
stream.each {self.writeBuffer(_)}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
toBuffer(): Buffer
|
|
38
|
-
target node sync """
|
|
39
|
-
const b = self_.digest();
|
|
40
|
-
return new DataView(b.buffer, b.byteOffset, b.length);
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
toHex(): String {
|
|
44
|
-
self.toBuffer().toHex()
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
toBase64(): String {
|
|
48
|
-
self.toBuffer().toBase64()
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
}
|
package/experimental/s3/S3.ff
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import Digest from ff:core
|
|
2
|
-
|
|
3
|
-
nodeMain(system: NodeSystem) {
|
|
4
|
-
system.writeLine(Digest.sha256("".toBuffer()).toHex())
|
|
5
|
-
system.writeLine(Digest.hmacSha256("key".toBuffer(), "The quick brown fox jumps over the lazy dog".toBuffer()).toHex())
|
|
6
|
-
|
|
7
|
-
// Trying to reproduce the result from an example here
|
|
8
|
-
// https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html
|
|
9
|
-
let expectedHeader = "AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,SignedHeaders=date;host;x-amz-content-sha256;x-amz-date;x-amz-storage-class,Signature=98ad721746da40c64f1a55b78f14c238d841ea1380cd77a1b5971af0ece108bd"
|
|
10
|
-
let amzDate = "20130524T000000Z" // TODO
|
|
11
|
-
let headerDate = "Fri, 24 May 2013 00:00:00 GMT" // TODO
|
|
12
|
-
let bucket = "examplebucket"
|
|
13
|
-
let body = "Welcome to Amazon S3.".toBuffer()
|
|
14
|
-
let actualHeader = makeS3AuthorizationHeader(
|
|
15
|
-
system = system
|
|
16
|
-
accessKeyId = "AKIAIOSFODNN7EXAMPLE"
|
|
17
|
-
secretAccessKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
|
|
18
|
-
region = "us-east-1"
|
|
19
|
-
bucket = bucket
|
|
20
|
-
objectKey = "test%24file.text" // TODO URI encoded "test$file.text"
|
|
21
|
-
body = body
|
|
22
|
-
canonicalHeaders = [
|
|
23
|
-
Pair("date", headerDate)
|
|
24
|
-
Pair("host", bucket + ".s3.amazonaws.com")
|
|
25
|
-
Pair("x-amz-date", amzDate)
|
|
26
|
-
Pair("x-amz-content-sha256", Digest.sha256(body).toHex())
|
|
27
|
-
Pair("x-amz-storage-class", "REDUCED_REDUNDANCY")
|
|
28
|
-
]
|
|
29
|
-
amzDate = amzDate
|
|
30
|
-
)
|
|
31
|
-
system.writeLine("")
|
|
32
|
-
system.writeLine("actual : " + actualHeader)
|
|
33
|
-
system.writeLine("")
|
|
34
|
-
system.writeLine("expected: " + expectedHeader)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
/*put(system,
|
|
39
|
-
accessKeyId = ""
|
|
40
|
-
secretAccessKey = ""
|
|
41
|
-
region = "eu-central-1"
|
|
42
|
-
bucket = "firefly-site"
|
|
43
|
-
objectKey = "tmp/test2"
|
|
44
|
-
"Hello S3".toBuffer()
|
|
45
|
-
)*/
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
put(
|
|
49
|
-
system: NodeSystem
|
|
50
|
-
accessKeyId: String
|
|
51
|
-
secretAccessKey: String
|
|
52
|
-
region: String
|
|
53
|
-
bucket: String
|
|
54
|
-
objectKey: String
|
|
55
|
-
body: Buffer
|
|
56
|
-
): Unit {
|
|
57
|
-
let amzDate = "20240523T122636Z" // TODO
|
|
58
|
-
let headerDate = "Thu May 23 2024 12:20:09 GMT" // TODO
|
|
59
|
-
let contentHash = Digest.sha256(body).toHex()
|
|
60
|
-
let host = bucket + ".s3.amazonaws.com"
|
|
61
|
-
let canonicalHeaders = [
|
|
62
|
-
Pair("date", headerDate)
|
|
63
|
-
Pair("host", host)
|
|
64
|
-
Pair("x-amz-date", amzDate)
|
|
65
|
-
Pair("x-amz-content-sha256", contentHash)
|
|
66
|
-
Pair("x-amz-storage-class", "REDUCED_REDUNDANCY")
|
|
67
|
-
Pair("Content-Type", "text/plain")
|
|
68
|
-
]
|
|
69
|
-
let authenticationHeader = makeS3AuthorizationHeader(system, accessKeyId, secretAccessKey, region, bucket, objectKey, body, canonicalHeaders, amzDate)
|
|
70
|
-
let headers = [...canonicalHeaders, Pair("Authorization", authenticationHeader)]
|
|
71
|
-
|
|
72
|
-
let url = "https://" + host + "/" + objectKey
|
|
73
|
-
let response = system.httpClient().fetch(url, method = "PUT", headers = headers, body = Some(HttpClient.bodyBuffer(body)), throw = False)
|
|
74
|
-
system.writeLine("" + response.status())
|
|
75
|
-
system.writeLine(response.statusText())
|
|
76
|
-
system.writeLine(response.readText())
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
makeS3AuthorizationHeader(
|
|
80
|
-
system: NodeSystem
|
|
81
|
-
accessKeyId: String
|
|
82
|
-
secretAccessKey: String
|
|
83
|
-
region: String
|
|
84
|
-
bucket: String
|
|
85
|
-
objectKey: String
|
|
86
|
-
body: Buffer
|
|
87
|
-
canonicalHeaders: List[Pair[String, String]]
|
|
88
|
-
amzDate: String
|
|
89
|
-
): String {
|
|
90
|
-
let scopeDate = amzDate.slice(0, 8) // YYYYMMDD
|
|
91
|
-
|
|
92
|
-
// CanonicalRequest
|
|
93
|
-
let canonicalQuerystring = "";
|
|
94
|
-
let contentHash = Digest.sha256(body).toHex()
|
|
95
|
-
let headers = canonicalHeaders.map {_.mapFirst {_.lower()}.mapSecond {_.trim()}}.sort()
|
|
96
|
-
let signedHeaders = headers.map {_.first}.join(";")
|
|
97
|
-
let canonicalRequest = [
|
|
98
|
-
"PUT"
|
|
99
|
-
"/" + objectKey
|
|
100
|
-
canonicalQuerystring
|
|
101
|
-
...headers.map {p => p.first + ":" + p.second}
|
|
102
|
-
""
|
|
103
|
-
signedHeaders
|
|
104
|
-
contentHash
|
|
105
|
-
].join("\n")
|
|
106
|
-
|
|
107
|
-
// StringToSign
|
|
108
|
-
let credentialScope = [scopeDate, region, "s3", "aws4_request"].join("/")
|
|
109
|
-
let algorithm = "AWS4-HMAC-SHA256"
|
|
110
|
-
let stringToSign = [
|
|
111
|
-
algorithm
|
|
112
|
-
amzDate
|
|
113
|
-
credentialScope
|
|
114
|
-
Digest.sha256(canonicalRequest.toBuffer()).toHex()
|
|
115
|
-
].join("\n")
|
|
116
|
-
|
|
117
|
-
// Signature
|
|
118
|
-
let signingKey = hmacSha256(hmacSha256(hmacSha256(hmacSha256(("AWS4" + secretAccessKey).toBuffer(), scopeDate), region), "s3"), "aws4_request")
|
|
119
|
-
let signature = hmacSha256(signingKey, stringToSign).toHex()
|
|
120
|
-
|
|
121
|
-
algorithm + " Credential=" + accessKeyId + "/" + credentialScope + ",SignedHeaders=" + signedHeaders + ",Signature=" + signature
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
hmacSha256(key: Buffer, message: String): Buffer {
|
|
125
|
-
Digest.hmacSha256(key, message.toBuffer()).toBuffer()
|
|
126
|
-
}
|