firefly-compiler 0.4.34 → 0.4.36

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 (80) hide show
  1. package/bin/Release.ff +47 -4
  2. package/compiler/Compiler.ff +1 -0
  3. package/core/Crypto.ff +95 -0
  4. package/core/NodeSystem.ff +4 -1
  5. package/core/Pair.ff +9 -0
  6. package/crypto/SubtleCrypto.ff +149 -0
  7. package/experimental/s3/S3.ff +93 -0
  8. package/experimental/s3/S3TestAuthorizationHeader.ff +39 -0
  9. package/experimental/s3/S3TestPut.ff +16 -0
  10. package/output/js/ff/compiler/Builder.mjs +2 -0
  11. package/output/js/ff/compiler/Compiler.mjs +3 -1
  12. package/output/js/ff/compiler/Dependencies.mjs +2 -0
  13. package/output/js/ff/compiler/DependencyLock.mjs +2 -0
  14. package/output/js/ff/compiler/Deriver.mjs +2 -0
  15. package/output/js/ff/compiler/Dictionaries.mjs +2 -0
  16. package/output/js/ff/compiler/Environment.mjs +2 -0
  17. package/output/js/ff/compiler/Inference.mjs +2 -0
  18. package/output/js/ff/compiler/JsEmitter.mjs +2 -0
  19. package/output/js/ff/compiler/JsImporter.mjs +2 -0
  20. package/output/js/ff/compiler/LspHook.mjs +2 -0
  21. package/output/js/ff/compiler/Main.mjs +2 -0
  22. package/output/js/ff/compiler/ModuleCache.mjs +2 -0
  23. package/output/js/ff/compiler/Parser.mjs +2 -0
  24. package/output/js/ff/compiler/Patterns.mjs +2 -0
  25. package/output/js/ff/compiler/Resolver.mjs +2 -0
  26. package/output/js/ff/compiler/Substitution.mjs +2 -0
  27. package/output/js/ff/compiler/Syntax.mjs +2 -0
  28. package/output/js/ff/compiler/Token.mjs +2 -0
  29. package/output/js/ff/compiler/Tokenizer.mjs +2 -0
  30. package/output/js/ff/compiler/Unification.mjs +2 -0
  31. package/output/js/ff/compiler/Wildcards.mjs +2 -0
  32. package/output/js/ff/compiler/Workspace.mjs +2 -0
  33. package/output/js/ff/core/Any.mjs +2 -0
  34. package/output/js/ff/core/Array.mjs +2 -0
  35. package/output/js/ff/core/AssetSystem.mjs +2 -0
  36. package/output/js/ff/core/Atomic.mjs +2 -0
  37. package/output/js/ff/core/Bool.mjs +2 -0
  38. package/output/js/ff/core/BrowserSystem.mjs +2 -0
  39. package/output/js/ff/core/Buffer.mjs +2 -0
  40. package/output/js/ff/core/BuildSystem.mjs +2 -0
  41. package/output/js/ff/core/Channel.mjs +2 -0
  42. package/output/js/ff/core/Char.mjs +2 -0
  43. package/output/js/ff/core/Core.mjs +2 -0
  44. package/output/js/ff/core/Crypto.mjs +275 -0
  45. package/output/js/ff/core/Duration.mjs +2 -0
  46. package/output/js/ff/core/Equal.mjs +2 -0
  47. package/output/js/ff/core/Error.mjs +2 -0
  48. package/output/js/ff/core/FileHandle.mjs +2 -0
  49. package/output/js/ff/core/Float.mjs +2 -0
  50. package/output/js/ff/core/HttpClient.mjs +2 -0
  51. package/output/js/ff/core/Instant.mjs +2 -0
  52. package/output/js/ff/core/Int.mjs +2 -0
  53. package/output/js/ff/core/IntMap.mjs +2 -0
  54. package/output/js/ff/core/JsSystem.mjs +2 -0
  55. package/output/js/ff/core/JsValue.mjs +2 -0
  56. package/output/js/ff/core/Json.mjs +2 -0
  57. package/output/js/ff/core/List.mjs +2 -0
  58. package/output/js/ff/core/Lock.mjs +2 -0
  59. package/output/js/ff/core/Log.mjs +2 -0
  60. package/output/js/ff/core/Map.mjs +2 -0
  61. package/output/js/ff/core/NodeSystem.mjs +11 -1
  62. package/output/js/ff/core/Nothing.mjs +2 -0
  63. package/output/js/ff/core/Option.mjs +2 -0
  64. package/output/js/ff/core/Ordering.mjs +2 -0
  65. package/output/js/ff/core/Pair.mjs +10 -0
  66. package/output/js/ff/core/Path.mjs +2 -0
  67. package/output/js/ff/core/Random.mjs +2 -0
  68. package/output/js/ff/core/RbMap.mjs +2 -0
  69. package/output/js/ff/core/Serializable.mjs +2 -0
  70. package/output/js/ff/core/Set.mjs +2 -0
  71. package/output/js/ff/core/Show.mjs +2 -0
  72. package/output/js/ff/core/SourceLocation.mjs +2 -0
  73. package/output/js/ff/core/Stream.mjs +2 -0
  74. package/output/js/ff/core/String.mjs +2 -0
  75. package/output/js/ff/core/StringMap.mjs +2 -0
  76. package/output/js/ff/core/Task.mjs +2 -0
  77. package/output/js/ff/core/Try.mjs +2 -0
  78. package/output/js/ff/core/Unit.mjs +2 -0
  79. package/package.json +1 -1
  80. package/vscode/package.json +1 -1
package/bin/Release.ff CHANGED
@@ -1,6 +1,49 @@
1
1
  nodeMain(system: NodeSystem) {
2
- let result = system.execute("npm", ["-v"])
3
- Log.trace("exitCode: " + result.exitCode)
4
- Log.trace("out: " + result.standardOut.toString())
5
- Log.trace("err: " + result.standardError.toString())
2
+ run(system, "node", ["output/js/ff/compiler/Main.mjs", "bootstrap"], system.path(".."))
3
+ run(system, "node", ["output/js/ff/compiler/Main.mjs", "bootstrap"], system.path(".."))
4
+ run(system, "node", ["output/js/ff/compiler/Main.mjs", "bootstrap"], system.path(".."))
5
+ bumpMinorVersion(system, system.path("../package.json"))
6
+ bumpMinorVersion(system, system.path("../vscode/package.json"))
7
+ run(system, "npm", ["publish"], system.path(".."))
8
+ run(system, "vsce", ["publish"], system.path("../vscode"))
9
+ // tar gz core etc. and upload to s3
10
+ }
11
+
12
+ run(system: NodeSystem, command: String, arguments: List[String], workingDirectory: Path) {
13
+ system.writeLine("")
14
+ system.writeLine(command + " " + arguments.join(" "))
15
+ let out = system.execute(command, arguments, workingDirectory = Some(workingDirectory))
16
+ system.writeBuffer(out.standardOut)
17
+ system.writeErrorBuffer(out.standardError)
18
+ if(out.exitCode != 0) {
19
+ system.writeErrorLine("Exit code: " + out.exitCode)
20
+ system.exit(1)
21
+ }
22
+ }
23
+
24
+ bumpMinorVersion(system: NodeSystem, packageJsonPath: Path) {
25
+ let prefix = " \"version\": \""
26
+ mutable bumps = 0
27
+ system.writeLine("")
28
+ system.writeLine("Bumping version in " + packageJsonPath.absolute())
29
+ let newContent = packageJsonPath.readText().lines().map {
30
+ | line {
31
+ line.removeFirst(prefix).flatMap {_.removeLast("\",")} | Some(v)
32
+ } {
33
+ v.split('.') | [major, minor, patch]
34
+ } {
35
+ patch.getInt() | Some(p)
36
+ } =>
37
+ bumps += 1
38
+ let newVersion = major + "." + minor + "." + (p + 1)
39
+ system.writeLine("Will bump version: " + v + " to " + newVersion)
40
+ prefix + newVersion + "\","
41
+ | line =>
42
+ line
43
+ }.join("\n")
44
+ if(bumps != 1) {
45
+ system.writeErrorLine("Failed to bump version.")
46
+ system.exit(1)
47
+ }
48
+ packageJsonPath.writeText(newContent)
6
49
  }
@@ -66,6 +66,7 @@ coreImports: List[DImport] =
66
66
  "Channel"
67
67
  "Char"
68
68
  "Core"
69
+ "Crypto"
69
70
  "Duration"
70
71
  "Equal"
71
72
  "Error"
package/core/Crypto.ff ADDED
@@ -0,0 +1,95 @@
1
+ capability Crypto {}
2
+
3
+ extend self: Crypto {
4
+
5
+ randomUuid(): String
6
+ target js async """
7
+ return self_.randomUUID();
8
+ """
9
+
10
+ randomBuffer(size: Int): Buffer {
11
+ let buffer = Buffer.new(size)
12
+ self.randomizeBuffer(buffer)
13
+ buffer
14
+ }
15
+
16
+ randomizeBuffer(buffer: Buffer): Unit
17
+ target js async """
18
+ self_.getRandomValues(new Uint8Array(buffer_.buffer, buffer_.byteOffset, buffer_.byteLength));
19
+ """
20
+
21
+ hmacSha256(key: Buffer, buffer: Buffer): Buffer
22
+ target js async """
23
+ const cryptoKey = await self_.subtle.importKey(
24
+ 'raw',
25
+ key_,
26
+ {name: 'HMAC', hash: {name: 'SHA-256'}},
27
+ false,
28
+ ['sign']
29
+ );
30
+ const signature = await self_.subtle.sign(
31
+ 'HMAC',
32
+ cryptoKey,
33
+ buffer_
34
+ );
35
+ return new DataView(signature);
36
+ """
37
+
38
+ sha256(buffer: Buffer): Buffer
39
+ target js async """
40
+ let hash = await self_.subtle.digest('SHA-256', buffer_);
41
+ return new DataView(hash);
42
+ """
43
+
44
+ makePasswordHash(password: String, iterations: Int = 100000): String {
45
+ let salt = self.randomBuffer(16)
46
+ let hash = internalMakePasswordHash(salt, password.toBuffer(), iterations)
47
+ "PSG_" + iterations + "_" + salt.toHex() + "_" + hash.toHex()
48
+ }
49
+
50
+ checkPasswordHash(password: String, passwordHash: String): Bool {
51
+ passwordHash.split('_').{
52
+ | ["PSG", iterationsText, saltText, hashText] {iterationsText.getInt() | Some(iterations)} =>
53
+ let computedHash = internalMakePasswordHash(Buffer.fromHex(saltText), password.toBuffer(), iterations)
54
+ let hash = Buffer.fromHex(hashText)
55
+ self.constantTimeEquals(computedHash, hash)
56
+ | _ => False
57
+ }
58
+ }
59
+
60
+ constantTimeEquals(buffer1: Buffer, buffer2: Buffer): Bool {
61
+ if(buffer1.size() != buffer2.size()) {False} else:
62
+ mutable v = 0
63
+ mutable i = 0
64
+ while {i < buffer1.size()} {
65
+ v = v.bitOr(buffer1.grabUint8(i).bitXor(buffer2.grabUint8(i)))
66
+ }
67
+ v == 0
68
+ }
69
+
70
+ }
71
+
72
+ internalMakePasswordHash(salt: Buffer, password: Buffer, iterations: Int): Buffer
73
+ target js async """
74
+ const keyMaterial = await crypto.subtle.importKey(
75
+ 'raw',
76
+ password_,
77
+ {name: 'PBKDF2'},
78
+ false,
79
+ ['deriveKey']
80
+ );
81
+ const derivedKey = await crypto.subtle.deriveKey(
82
+ {
83
+ name: 'PBKDF2',
84
+ salt: salt_,
85
+ iterations: iterations_,
86
+ hash: 'SHA-256'
87
+ },
88
+ keyMaterial,
89
+ {name: 'AES-GCM', length: 256},
90
+ true,
91
+ ['encrypt', 'decrypt']
92
+ );
93
+ const hashBuffer = await crypto.subtle.exportKey('raw', derivedKey);
94
+ return new DataView(hashBuffer);
95
+ """
@@ -45,6 +45,9 @@ extend self: NodeSystem {
45
45
  mainTask(): Task
46
46
  target js async "return self_.task_"
47
47
 
48
+ crypto()
49
+ target js async "return (typeof globalThis !== 'undefined' ? globalThis : window).crypto"
50
+
48
51
  js(): JsSystem
49
52
  target js async "return typeof globalThis !== 'undefined' ? globalThis : window"
50
53
 
@@ -156,7 +159,7 @@ extend self: NodeSystem {
156
159
  const o = Buffer.concat(out);
157
160
  const e = Buffer.concat(err);
158
161
  resolve(ProcessResult(
159
- size > maxBuffer_ ? -1 : code,
162
+ code,
160
163
  new DataView(o.buffer, o.byteOffset, o.byteLength),
161
164
  new DataView(e.buffer, e.byteOffset, e.byteLength),
162
165
  ));
package/core/Pair.ff CHANGED
@@ -49,3 +49,12 @@ extend self[A: Order, B]: Pair[A, B] {
49
49
  }
50
50
 
51
51
  }
52
+
53
+
54
+ extend self: Pair[String, String] {
55
+
56
+ join(separator: String = ""): String {
57
+ self.first + separator + self.second
58
+ }
59
+
60
+ }
@@ -0,0 +1,149 @@
1
+ import Crypto from ff:core
2
+
3
+ capability SubtleCrypto(crypto: Crypto)
4
+
5
+ data CryptoKey {}
6
+
7
+ data CryptoKeyUsages(
8
+ encrypt: Bool = False
9
+ decrypt: Bool = False
10
+ sign: Bool = False
11
+ verify: Bool = False
12
+ deriveKey: Bool = False
13
+ deriveBits: Bool = False
14
+ wrapKey: Bool = False
15
+ unwrapKey: Bool = False
16
+ )
17
+
18
+ class CryptoCipher {
19
+ RsaOaep(label: Option[String] = None)
20
+ AesCtr(counter: Buffer, length: Int)
21
+ AesCbc(initializationVector: Buffer)
22
+ AesGcm(initializationVector: Buffer, additionalData: Option[Buffer] = None, tagLength: Int = 128)
23
+ }
24
+
25
+ class CryptoDeriver {
26
+ Ecdh(public: CryptoKey)
27
+ Hkdf(hash: CryptoDigest, salt: Buffer, info: Buffer)
28
+ Pbkdf2(hash: CryptoDigest, salt: Buffer, iterations: Int)
29
+ }
30
+
31
+ class CryptoGenerator {
32
+ HmacGenerator(hash: CryptoDigest, length: Option[Int])
33
+ AesCtrGenerator(length: Int)
34
+ AesCbcGenerator(length: Int)
35
+ AesGcmGenerator(length: Int)
36
+ AesKwGenerator(length: Int)
37
+ HkdfGenerator(hash: CryptoDigest, salt: Buffer, info: Buffer)
38
+ Pbkdf2Generator(hash: CryptoDigest, salt: Buffer, iterations: Int)
39
+ }
40
+
41
+ class CryptoSigner {
42
+ RsassaPkcs1V15
43
+ RsaPss(saltLength: Int)
44
+ Ecdsa(hash: CryptoDigest)
45
+ Hmac
46
+ }
47
+
48
+ data CryptoDigest {
49
+ Sha512
50
+ Sha384
51
+ Sha256
52
+ Sha1
53
+ }
54
+
55
+ extend self: SubtleCrypto {
56
+
57
+ encrypt(algorithm: CryptoCipher, key: CryptoKey, data: Buffer): Buffer
58
+ target js async """
59
+ const a = internalAlgorithm_(algorithm_);
60
+ return new DataView(await self_.encrypt(a, key_, data_));
61
+ """
62
+
63
+ decrypt(algorithm: CryptoCipher, key: CryptoKey, data: Buffer): Buffer
64
+ target js async """
65
+ const a = internalAlgorithm_(algorithm_);
66
+ return new DataView(await self_.decrypt(a, key_, data_));
67
+ """
68
+
69
+ sign(algorithm: CryptoSigner, key: CryptoKey, data: Buffer): Buffer
70
+ target js async """
71
+ const a = internalAlgorithm_(algorithm_);
72
+ return new DataView(await self_.sign(a, key_, data_));
73
+ """
74
+
75
+ verify(algorithm: CryptoSigner, key: CryptoKey, data: Buffer): Bool
76
+ target js async """
77
+ const a = internalAlgorithm_(algorithm_);
78
+ return await self_.verify(a, key_, data_);
79
+ """
80
+
81
+ digest(algorithm: CryptoDigest, data: Buffer): Buffer
82
+ target js async """
83
+ const a = internalAlgorithm_(algorithm_);
84
+ return new DataView(await self_.digest(a, data_));
85
+ """
86
+
87
+ deriveBits(algorithm: CryptoDeriver, key: CryptoKey, bits: Int): Buffer
88
+ target js async """
89
+ const a = internalAlgorithm_(algorithm_);
90
+ return new DataView(await self_.deriveBits(a, key_, bits_));
91
+ """
92
+
93
+ deriveKey(
94
+ algorithm: CryptoDeriver
95
+ baseKey: CryptoKey
96
+ derivedKeyAlgorithm: CryptoGenerator
97
+ extractable: Bool
98
+ keyUsages: CryptoKeyUsages
99
+ ): CryptoKey
100
+ target js async """
101
+ const a = internalAlgorithm_(algorithm_);
102
+ const d = internalAlgorithm_(derivedKeyAlgorithm_);
103
+ const u = internalKeyUsages_(keyUsages_);
104
+ return await self_.deriveKey(a, baseKey_, d, extractable_, u);
105
+ """
106
+
107
+ }
108
+
109
+ internalAlgorithm(algorithm: JsValue): JsValue
110
+ target js sync """
111
+ if(algorithm_.Sha512) return 'SHA-512';
112
+ if(algorithm_.Sha384) return 'SHA-384';
113
+ if(algorithm_.Sha256) return 'SHA-256';
114
+ if(algorithm_.Sha1) return 'SHA-1';
115
+ if(algorithm_.RsassaPkcs1V15) return 'RSASSA-PKCS1-v1_5';
116
+ if(algorithm_.RsaPss) return {name: 'RSA-PSS', saltLength: algorithm_.saltLength_};
117
+ if(algorithm_.Ecdsa) return {name: 'ECDSA', hash: internalAlgorithm_(algorithm_.hash_)};
118
+ if(algorithm_.Hmac) return 'HMAC';
119
+ if(algorithm_.Ecdh) return {name: 'ECDH', public: algorithm_.public_};
120
+ if(algorithm_.Hkdf) return {name: 'HKDF', hash: internalAlgorithm_(algorithm_.hash_), salt: algorithm_.salt_, info: algorithm_.info_};
121
+ if(algorithm_.Pbkdf2) return {name: 'PBKDF2', hash: internalAlgorithm_(algorithm_.hash_), salt: algorithm_.salt_, iterations: algorithm_.iterations_};
122
+ if(algorithm_.RsaOaep) return {name: "RSA-OAEP", label: algorithm_.label_.value_};
123
+ if(algorithm_.AesCtr) return {name: "AES-CTR", counter: algorithm_.counter_, length: algorithm_.length_};
124
+ if(algorithm_.AesCbc) return {name: "AES-CBC", iv: algorithm_.initializationVector_};
125
+ if(algorithm_.AesGcm) return {name: "AES-GCM", iv: algorithm_.initializationVector_, additionalData: algorithm_.value_, tagLength: algorithm_.tagLength_};
126
+ // Turns out, generateKey has different parameters - think about naming
127
+ if(algorithm_.HmacGenerator) return {name: 'HMAC', hash: internalAlgorithm_(algorithm_.hash_), length: algorithm_.length_.value_};
128
+ if(algorithm_.AesCtrGenerator) return {name: 'AES-CTR', length: algorithm_.length_};
129
+ if(algorithm_.AesCbcGenerator) return {name: 'AES-CBC', length: algorithm_.length_};
130
+ if(algorithm_.AesGcmGenerator) return {name: 'AES-GCM', length: algorithm_.length_};
131
+ if(algorithm_.AesKwGenerator) return {name: 'AES-KW', length: algorithm_.length_};
132
+ if(algorithm_.HkdfGenerator) return {name: 'HKDF', hash: internalAlgorithm_(algorithm_.hash_), salt: algorithm_.salt_, info: algorithm_.info_};
133
+ if(algorithm_.Pbkdf2Generator) return {name: 'PBKDF2', hash: internalAlgorithm_(algorithm_.hash_), salt: algorithm_.salt_, iterations: algorithm_.iterations_};
134
+ throw new Error('No such algorithm');
135
+ """
136
+
137
+ internalKeyUsages(keyUsages: JsValue): JsValue
138
+ target js sync """
139
+ const u = [];
140
+ if(keyUsages_.encrypt_) u.push('encrypt');
141
+ if(keyUsages_.decrypt_) u.push('decrypt');
142
+ if(keyUsages_.sign_) u.push('sign');
143
+ if(keyUsages_.verify_) u.push('verify');
144
+ if(keyUsages_.deriveKey_) u.push('deriveKey');
145
+ if(keyUsages_.deriveBits_) u.push('deriveBits');
146
+ if(keyUsages_.wrapKey_) u.push('wrapKey');
147
+ if(keyUsages_.unwrapKey_) u.push('unwrapKey');
148
+ return u;
149
+ """
@@ -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 = Digest.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
+ }
@@ -0,0 +1,39 @@
1
+ import S3
2
+
3
+ nodeMain(system: NodeSystem) {
4
+ // Trying to reproduce the result from an example here
5
+ // https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html
6
+ 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"
7
+ let amzDate = "20130524T000000Z" // TODO
8
+ let headerDate = "Fri, 24 May 2013 00:00:00 GMT" // TODO
9
+ let bucket = "examplebucket"
10
+ let body = "Welcome to Amazon S3.".toBuffer()
11
+ let actualHeader = S3.makeS3AuthorizationHeader(
12
+ system = system
13
+ accessKeyId = "AKIAIOSFODNN7EXAMPLE"
14
+ secretAccessKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
15
+ region = "us-east-1"
16
+ bucket = bucket
17
+ encodedKey = S3.encode("test$file.text")
18
+ body = body
19
+ canonicalHeaders = [
20
+ Pair("date", headerDate)
21
+ Pair("host", bucket + ".s3.amazonaws.com")
22
+ Pair("x-amz-date", amzDate)
23
+ Pair("x-amz-content-sha256", system.crypto().sha256(body).toHex())
24
+ Pair("x-amz-storage-class", "REDUCED_REDUNDANCY")
25
+ ]
26
+ amzDate = amzDate
27
+ )
28
+ system.writeLine("")
29
+ system.writeLine("actual : " + actualHeader)
30
+ system.writeLine("")
31
+ system.writeLine("expected: " + expectedHeader)
32
+
33
+ system.writeLine("")
34
+ if(actualHeader == expectedHeader) {
35
+ system.writeLine("Test passed")
36
+ } else {
37
+ system.writeLine("Test failed")
38
+ }
39
+ }
@@ -0,0 +1,16 @@
1
+ import S3
2
+
3
+ nodeMain(system: NodeSystem) {
4
+ S3.put(system,
5
+ accessKeyId = ""
6
+ secretAccessKey = ""
7
+ region = "eu-central-1"
8
+ bucket = "firefly-site"
9
+ objectKey = "tmp/test4"
10
+ "Hello S3 3".toBuffer()
11
+ headers = [
12
+ //Pair("x-amz-storage-class", "REDUCED_REDUNDANCY")
13
+ Pair("Content-Type", "text/plain")
14
+ ]
15
+ )
16
+ }
@@ -46,6 +46,8 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
46
46
 
47
47
  import * as ff_core_Core from "../../ff/core/Core.mjs"
48
48
 
49
+ import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
50
+
49
51
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
50
52
 
51
53
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"
@@ -46,6 +46,8 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
46
46
 
47
47
  import * as ff_core_Core from "../../ff/core/Core.mjs"
48
48
 
49
+ import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
50
+
49
51
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
50
52
 
51
53
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"
@@ -117,7 +119,7 @@ export function Compiler(emitTarget_, task_, compilerModulePath_, jsOutputPath_,
117
119
  return {emitTarget_, task_, compilerModulePath_, jsOutputPath_, packagePaths_, singleFilePackages_, virtualFiles_, cache_, lspHook_, phaseDurationDelta_, phaseDurations_};
118
120
  }
119
121
 
120
- export const coreImports_ = ff_core_List.List_map(["Any", "Array", "AssetSystem", "Atomic", "Bool", "BrowserSystem", "Buffer", "BuildSystem", "Channel", "Char", "Core", "Duration", "Equal", "Error", "FileHandle", "Float", "HttpClient", "Instant", "Int", "IntMap", "Json", "JsValue", "JsSystem", "List", "Lock", "Log", "Map", "NodeSystem", "Nothing", "Option", "Ordering", "Pair", "Path", "Random", "Serializable", "Set", "Show", "SourceLocation", "Stream", "String", "StringMap", "Task", "Try", "Unit"], ((moduleName_) => {
122
+ export const coreImports_ = ff_core_List.List_map(["Any", "Array", "AssetSystem", "Atomic", "Bool", "BrowserSystem", "Buffer", "BuildSystem", "Channel", "Char", "Core", "Crypto", "Duration", "Equal", "Error", "FileHandle", "Float", "HttpClient", "Instant", "Int", "IntMap", "Json", "JsValue", "JsSystem", "List", "Lock", "Log", "Map", "NodeSystem", "Nothing", "Option", "Ordering", "Pair", "Path", "Random", "Serializable", "Set", "Show", "SourceLocation", "Stream", "String", "StringMap", "Task", "Try", "Unit"], ((moduleName_) => {
121
123
  return ff_compiler_Syntax.DImport(ff_compiler_Syntax.Location("<prelude>", 1, 1), moduleName_, ff_compiler_Syntax.PackagePair("ff", "core"), [], moduleName_)
122
124
  }));
123
125
 
@@ -36,6 +36,8 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
36
36
 
37
37
  import * as ff_core_Core from "../../ff/core/Core.mjs"
38
38
 
39
+ import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
40
+
39
41
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
40
42
 
41
43
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"
@@ -24,6 +24,8 @@ 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 ff_core_Crypto from "../../ff/core/Crypto.mjs"
28
+
27
29
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
28
30
 
29
31
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"
@@ -26,6 +26,8 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
26
26
 
27
27
  import * as ff_core_Core from "../../ff/core/Core.mjs"
28
28
 
29
+ import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
30
+
29
31
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
30
32
 
31
33
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"
@@ -30,6 +30,8 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
30
30
 
31
31
  import * as ff_core_Core from "../../ff/core/Core.mjs"
32
32
 
33
+ import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
34
+
33
35
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
34
36
 
35
37
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"
@@ -26,6 +26,8 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
26
26
 
27
27
  import * as ff_core_Core from "../../ff/core/Core.mjs"
28
28
 
29
+ import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
30
+
29
31
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
30
32
 
31
33
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"
@@ -34,6 +34,8 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
34
34
 
35
35
  import * as ff_core_Core from "../../ff/core/Core.mjs"
36
36
 
37
+ import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
38
+
37
39
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
38
40
 
39
41
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"
@@ -30,6 +30,8 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
30
30
 
31
31
  import * as ff_core_Core from "../../ff/core/Core.mjs"
32
32
 
33
+ import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
34
+
33
35
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
34
36
 
35
37
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"
@@ -26,6 +26,8 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
26
26
 
27
27
  import * as ff_core_Core from "../../ff/core/Core.mjs"
28
28
 
29
+ import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
30
+
29
31
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
30
32
 
31
33
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"
@@ -30,6 +30,8 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
30
30
 
31
31
  import * as ff_core_Core from "../../ff/core/Core.mjs"
32
32
 
33
+ import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
34
+
33
35
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
34
36
 
35
37
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"
@@ -50,6 +50,8 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
50
50
 
51
51
  import * as ff_core_Core from "../../ff/core/Core.mjs"
52
52
 
53
+ import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
54
+
53
55
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
54
56
 
55
57
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"
@@ -26,6 +26,8 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
26
26
 
27
27
  import * as ff_core_Core from "../../ff/core/Core.mjs"
28
28
 
29
+ import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
30
+
29
31
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
30
32
 
31
33
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"
@@ -32,6 +32,8 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
32
32
 
33
33
  import * as ff_core_Core from "../../ff/core/Core.mjs"
34
34
 
35
+ import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
36
+
35
37
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
36
38
 
37
39
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"
@@ -26,6 +26,8 @@ import * as ff_core_Char from "../../ff/core/Char.mjs"
26
26
 
27
27
  import * as ff_core_Core from "../../ff/core/Core.mjs"
28
28
 
29
+ import * as ff_core_Crypto from "../../ff/core/Crypto.mjs"
30
+
29
31
  import * as ff_core_Duration from "../../ff/core/Duration.mjs"
30
32
 
31
33
  import * as ff_core_Equal from "../../ff/core/Equal.mjs"