@trayio/commons 3.8.1-beta → 3.9.1
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/dist/buffer/BufferExtensions.js +4 -33
- package/dist/buffer/BufferExtensions.unit.test.js +3 -12
- package/dist/codec/CompositeCodec.js +2 -0
- package/dist/codec/RemoveNullValuesCodec.js +4 -4
- package/dist/codec/TypeCodec.js +8 -7
- package/dist/file/FakeFileStorage.js +1 -0
- package/dist/file/FileStorage.abstract.test.js +10 -19
- package/dist/file/NodeFsFileStorage.js +7 -17
- package/dist/http/Http.js +1 -1
- package/dist/http/HttpClient.abstract.test.js +70 -85
- package/dist/result/Result.js +1 -0
- package/dist/serialization/JsonSerialization.js +3 -5
- package/package.json +1 -1
|
@@ -22,47 +22,18 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
|
-
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
35
|
-
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
36
|
-
var m = o[Symbol.asyncIterator], i;
|
|
37
|
-
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
38
|
-
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
39
|
-
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
40
|
-
};
|
|
41
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
26
|
exports.BufferExtensions = void 0;
|
|
43
27
|
const stream_1 = require("stream");
|
|
44
28
|
const TE = __importStar(require("fp-ts/TaskEither"));
|
|
45
29
|
exports.BufferExtensions = {
|
|
46
|
-
readableToArrayBuffer: (stream) => TE.tryCatch(() =>
|
|
47
|
-
var _a, e_1, _b, _c;
|
|
30
|
+
readableToArrayBuffer: (stream) => TE.tryCatch(async () => {
|
|
48
31
|
const chunks = [];
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
_c = stream_2_1.value;
|
|
52
|
-
_d = false;
|
|
53
|
-
const chunk = _c;
|
|
54
|
-
chunks.push(chunk);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
58
|
-
finally {
|
|
59
|
-
try {
|
|
60
|
-
if (!_d && !_a && (_b = stream_2.return)) yield _b.call(stream_2);
|
|
61
|
-
}
|
|
62
|
-
finally { if (e_1) throw e_1.error; }
|
|
32
|
+
for await (const chunk of stream) {
|
|
33
|
+
chunks.push(chunk);
|
|
63
34
|
}
|
|
64
35
|
const buffer = Buffer.concat(chunks);
|
|
65
36
|
return Uint8Array.from(buffer).buffer;
|
|
66
|
-
}
|
|
37
|
+
}, (error) => error),
|
|
67
38
|
arrayBufferToReadable: (arrayBuffer) => stream_1.Readable.from(Buffer.from(arrayBuffer)),
|
|
68
39
|
};
|
|
@@ -22,26 +22,17 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
26
|
const E = __importStar(require("fp-ts/Either"));
|
|
36
27
|
const util_1 = require("util");
|
|
37
28
|
const BufferExtensions_1 = require("./BufferExtensions");
|
|
38
29
|
describe('Buffer Tests', () => {
|
|
39
|
-
it('should convert a buffer to a stream, then stream back to a buffer', () =>
|
|
30
|
+
it('should convert a buffer to a stream, then stream back to a buffer', async () => {
|
|
40
31
|
const readableStream = BufferExtensions_1.BufferExtensions.arrayBufferToReadable(new util_1.TextEncoder().encode('test').buffer);
|
|
41
|
-
const bufferResult =
|
|
32
|
+
const bufferResult = await BufferExtensions_1.BufferExtensions.readableToArrayBuffer(readableStream)();
|
|
42
33
|
const buffer = E.getOrElse((error) => {
|
|
43
34
|
throw new Error(error.message);
|
|
44
35
|
})(bufferResult);
|
|
45
36
|
expect(buffer).toEqual(new util_1.TextEncoder().encode('test').buffer);
|
|
46
|
-
})
|
|
37
|
+
});
|
|
47
38
|
});
|
|
@@ -27,6 +27,8 @@ exports.CompositeCodec = void 0;
|
|
|
27
27
|
const E = __importStar(require("fp-ts/lib/Either"));
|
|
28
28
|
const function_1 = require("fp-ts/function");
|
|
29
29
|
class CompositeCodec {
|
|
30
|
+
innerCodec;
|
|
31
|
+
outerCodec;
|
|
30
32
|
static fromCodecs(innerCodec, outerCodec) {
|
|
31
33
|
return new CompositeCodec(innerCodec, outerCodec);
|
|
32
34
|
}
|
|
@@ -26,6 +26,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
exports.RemoveNullValuesCodec = void 0;
|
|
27
27
|
const E = __importStar(require("fp-ts/lib/Either"));
|
|
28
28
|
class RemoveNullValuesCodec {
|
|
29
|
+
static instance = new RemoveNullValuesCodec();
|
|
29
30
|
encode(value) {
|
|
30
31
|
return this.removeNullValuesIfPresent(value);
|
|
31
32
|
}
|
|
@@ -62,15 +63,14 @@ class RemoveNullValuesCodec {
|
|
|
62
63
|
}
|
|
63
64
|
if (this.isObject(propertyValue)) {
|
|
64
65
|
const nestedObject = this.removeNullFromObjectIfPresent(propertyValue);
|
|
65
|
-
return
|
|
66
|
+
return { ...acc, [key]: nestedObject };
|
|
66
67
|
}
|
|
67
68
|
if (Array.isArray(propertyValue)) {
|
|
68
69
|
const nestedArray = this.removeNullFromArrayIfPresent(propertyValue);
|
|
69
|
-
return
|
|
70
|
+
return { ...acc, [key]: nestedArray };
|
|
70
71
|
}
|
|
71
|
-
return
|
|
72
|
+
return { ...acc, [key]: propertyValue };
|
|
72
73
|
}, {});
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
exports.RemoveNullValuesCodec = RemoveNullValuesCodec;
|
|
76
|
-
RemoveNullValuesCodec.instance = new RemoveNullValuesCodec();
|
package/dist/codec/TypeCodec.js
CHANGED
|
@@ -36,6 +36,14 @@ class TypeCodec {
|
|
|
36
36
|
static fromDescriptor(descriptor) {
|
|
37
37
|
return new TypeCodec(descriptor);
|
|
38
38
|
}
|
|
39
|
+
static undefined = TypeCodec.fromDescriptor(t.undefined);
|
|
40
|
+
static unknown = TypeCodec.fromDescriptor(t.unknown);
|
|
41
|
+
static emptyRecord = TypeCodec.fromDescriptor(t.type({}));
|
|
42
|
+
static stringRecord = TypeCodec.fromDescriptor(t.record(t.string, t.string));
|
|
43
|
+
// Added support for partial records as IO-TS does not support them
|
|
44
|
+
// https://github.com/gcanti/io-ts/issues/429#issuecomment-862472408
|
|
45
|
+
static partialRecord = (k, type) => t.partial((0, Record_1.map)(() => type)(k.keys));
|
|
46
|
+
descriptor;
|
|
39
47
|
constructor(descriptor) {
|
|
40
48
|
this.descriptor = descriptor;
|
|
41
49
|
}
|
|
@@ -49,10 +57,3 @@ class TypeCodec {
|
|
|
49
57
|
}
|
|
50
58
|
}
|
|
51
59
|
exports.TypeCodec = TypeCodec;
|
|
52
|
-
TypeCodec.undefined = TypeCodec.fromDescriptor(t.undefined);
|
|
53
|
-
TypeCodec.unknown = TypeCodec.fromDescriptor(t.unknown);
|
|
54
|
-
TypeCodec.emptyRecord = TypeCodec.fromDescriptor(t.type({}));
|
|
55
|
-
TypeCodec.stringRecord = TypeCodec.fromDescriptor(t.record(t.string, t.string));
|
|
56
|
-
// Added support for partial records as IO-TS does not support them
|
|
57
|
-
// https://github.com/gcanti/io-ts/issues/429#issuecomment-862472408
|
|
58
|
-
TypeCodec.partialRecord = (k, type) => t.partial((0, Record_1.map)(() => type)(k.keys));
|
|
@@ -22,15 +22,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
26
|
exports.fileStorageTest = void 0;
|
|
36
27
|
const E = __importStar(require("fp-ts/Either"));
|
|
@@ -42,7 +33,7 @@ const fileStorageTest = (fileStorage) => {
|
|
|
42
33
|
describe('FileStorage Tests', () => {
|
|
43
34
|
describe('Writing a file', () => {
|
|
44
35
|
describe("when it's successful", () => {
|
|
45
|
-
it('should write a file, read the file then delete the file', () =>
|
|
36
|
+
it('should write a file, read the file then delete the file', async () => {
|
|
46
37
|
const serialization = new JsonSerialization_1.JsonSerialization();
|
|
47
38
|
const fileContent = { test: 'someValue' };
|
|
48
39
|
const readableStream = new stream_1.Readable({
|
|
@@ -59,9 +50,9 @@ const fileStorageTest = (fileStorage) => {
|
|
|
59
50
|
},
|
|
60
51
|
content: readableStream,
|
|
61
52
|
};
|
|
62
|
-
const writtenFile =
|
|
53
|
+
const writtenFile = await fileStorage.write(file, O.none)();
|
|
63
54
|
expect(writtenFile).toEqual(E.right(file));
|
|
64
|
-
const sharedUrl =
|
|
55
|
+
const sharedUrl = await fileStorage.getSharedUrl(file.key)();
|
|
65
56
|
expect(sharedUrl).toEqual(E.right(expect.objectContaining({
|
|
66
57
|
url: expect.any(String),
|
|
67
58
|
})));
|
|
@@ -70,12 +61,12 @@ const fileStorageTest = (fileStorage) => {
|
|
|
70
61
|
expect(sharedUrl.right.expires).toEqual(expect.any(Number));
|
|
71
62
|
}
|
|
72
63
|
}
|
|
73
|
-
const read =
|
|
64
|
+
const read = await fileStorage.read(file.key)();
|
|
74
65
|
const readResponse = E.getOrElse(() => {
|
|
75
66
|
throw new Error('Expected right');
|
|
76
67
|
})(read);
|
|
77
68
|
let data = '';
|
|
78
|
-
|
|
69
|
+
await new Promise((resolve) => {
|
|
79
70
|
readResponse.content.on('data', (chunk) => {
|
|
80
71
|
data += chunk;
|
|
81
72
|
});
|
|
@@ -88,20 +79,20 @@ const fileStorageTest = (fileStorage) => {
|
|
|
88
79
|
throw new Error('failed to deserialise stream contents');
|
|
89
80
|
}
|
|
90
81
|
expect(deserializedData.right).toStrictEqual(fileContent);
|
|
91
|
-
const deleted =
|
|
82
|
+
const deleted = await fileStorage.delete(file.key)();
|
|
92
83
|
expect(deleted).toEqual(E.right(undefined));
|
|
93
|
-
})
|
|
84
|
+
});
|
|
94
85
|
});
|
|
95
86
|
});
|
|
96
87
|
describe('Reading a file', () => {
|
|
97
88
|
describe('when the file does not exist', () => {
|
|
98
|
-
it('should return does not exist error', () =>
|
|
99
|
-
const read =
|
|
89
|
+
it('should return does not exist error', async () => {
|
|
90
|
+
const read = await fileStorage.read(`fail_test-${(0, uuid_1.v4)()}.zip`)();
|
|
100
91
|
if (E.isRight(read)) {
|
|
101
92
|
throw new Error('Expected left');
|
|
102
93
|
}
|
|
103
94
|
expect(read.left).toBeInstanceOf(Error);
|
|
104
|
-
})
|
|
95
|
+
});
|
|
105
96
|
});
|
|
106
97
|
});
|
|
107
98
|
});
|
|
@@ -22,15 +22,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
26
|
exports.NodeFsFileStorage = void 0;
|
|
36
27
|
const fs = __importStar(require("fs/promises"));
|
|
@@ -39,6 +30,7 @@ const TE = __importStar(require("fp-ts/lib/TaskEither"));
|
|
|
39
30
|
const function_1 = require("fp-ts/lib/function");
|
|
40
31
|
const Task_1 = require("../task/Task");
|
|
41
32
|
class NodeFsFileStorage {
|
|
33
|
+
basePath;
|
|
42
34
|
constructor(basePath = '/tmp') {
|
|
43
35
|
this.basePath = basePath;
|
|
44
36
|
}
|
|
@@ -49,23 +41,21 @@ class NodeFsFileStorage {
|
|
|
49
41
|
}
|
|
50
42
|
read(key, name = key) {
|
|
51
43
|
const filePath = `${this.basePath}/${key}`;
|
|
52
|
-
return TE.tryCatch(() =>
|
|
53
|
-
const fileHandle =
|
|
54
|
-
const stat =
|
|
44
|
+
return TE.tryCatch(async () => {
|
|
45
|
+
const fileHandle = await fs.open(filePath, 'r');
|
|
46
|
+
const stat = await fs.stat(filePath);
|
|
55
47
|
const stream = fileHandle.createReadStream();
|
|
56
48
|
const metadata = {
|
|
57
49
|
name,
|
|
58
50
|
size: stat.size,
|
|
59
51
|
};
|
|
60
52
|
return { metadata, key: filePath, content: stream };
|
|
61
|
-
}
|
|
53
|
+
}, (reason) => new Error(String(reason)));
|
|
62
54
|
}
|
|
63
55
|
getSharedUrl(key) {
|
|
64
56
|
const filePath = `${this.basePath}/${key}`;
|
|
65
|
-
return TE.tryCatch(() =>
|
|
66
|
-
|
|
67
|
-
url: path.resolve(filePath),
|
|
68
|
-
});
|
|
57
|
+
return TE.tryCatch(async () => ({
|
|
58
|
+
url: path.resolve(filePath),
|
|
69
59
|
}), (reason) => new Error(String(reason)));
|
|
70
60
|
}
|
|
71
61
|
delete(key) {
|
package/dist/http/Http.js
CHANGED
|
@@ -63,5 +63,5 @@ exports.HttpHeaders = {
|
|
|
63
63
|
exports.serializationFormatToHttpContentType = {
|
|
64
64
|
[Serialization_1.SerializationFormat.Json]: HttpContentType.Json,
|
|
65
65
|
};
|
|
66
|
-
const isMultiPartBody = (body) =>
|
|
66
|
+
const isMultiPartBody = (body) => body?.files !== undefined;
|
|
67
67
|
exports.isMultiPartBody = isMultiPartBody;
|
|
@@ -22,15 +22,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
27
|
};
|
|
@@ -77,35 +68,33 @@ function httpClientTest(httpClient) {
|
|
|
77
68
|
const serializedResponse = (0, function_1.pipe)(E.right(responseCodec.encode(response)), E.map((encodedResponse) => serialization.serialize(encodedResponse)), E.getOrElse(() => (new util_1.TextEncoder().encode('Error serializing value').buffer)));
|
|
78
69
|
httpResponse.end(Buffer.from(serializedResponse));
|
|
79
70
|
}
|
|
80
|
-
function processHttpRequest(requestCodec, responseCodec, httpRequest, httpResponse, process, isMultiPartBody = false) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
[fields, files] = yield form.parse(httpRequest);
|
|
88
|
-
}
|
|
89
|
-
catch (err) {
|
|
90
|
-
console.error(err);
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
const input = {
|
|
94
|
-
fields: flattenFields(fields),
|
|
95
|
-
files: flattenFiles(files),
|
|
96
|
-
};
|
|
97
|
-
const response = (0, function_1.pipe)(requestCodec.decode(input), E.map(process), E.map((result) => new util_1.TextEncoder().encode(JSON.stringify(responseCodec.encode(result))).buffer), E.getOrElse(() => new util_1.TextEncoder().encode('Error serializing value').buffer));
|
|
98
|
-
httpResponse.end(Buffer.from(response));
|
|
71
|
+
async function processHttpRequest(requestCodec, responseCodec, httpRequest, httpResponse, process, isMultiPartBody = false) {
|
|
72
|
+
if (isMultiPartBody) {
|
|
73
|
+
const form = (0, formidable_1.default)({});
|
|
74
|
+
let fields;
|
|
75
|
+
let files;
|
|
76
|
+
try {
|
|
77
|
+
[fields, files] = await form.parse(httpRequest);
|
|
99
78
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
79
|
+
catch (err) {
|
|
80
|
+
console.error(err);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const input = {
|
|
84
|
+
fields: flattenFields(fields),
|
|
85
|
+
files: flattenFiles(files),
|
|
86
|
+
};
|
|
87
|
+
const response = (0, function_1.pipe)(requestCodec.decode(input), E.map(process), E.map((result) => new util_1.TextEncoder().encode(JSON.stringify(responseCodec.encode(result))).buffer), E.getOrElse(() => new util_1.TextEncoder().encode('Error serializing value').buffer));
|
|
88
|
+
httpResponse.end(Buffer.from(response));
|
|
89
|
+
}
|
|
90
|
+
const body = [];
|
|
91
|
+
httpRequest.on('data', (chunk) => {
|
|
92
|
+
body.push(chunk);
|
|
93
|
+
});
|
|
94
|
+
httpRequest.on('end', () => {
|
|
95
|
+
const buffer = Buffer.concat(body);
|
|
96
|
+
const response = (0, function_1.pipe)(serialization.deserialize(buffer), E.chain((encodedRequest) => requestCodec.decode(encodedRequest)), E.map(process), E.map((result) => responseCodec.encode(result)), E.map((encodedResult) => serialization.serialize(encodedResult)), E.getOrElse(() => (new util_1.TextEncoder().encode('Error serializing value').buffer)));
|
|
97
|
+
httpResponse.end(Buffer.from(response));
|
|
109
98
|
});
|
|
110
99
|
}
|
|
111
100
|
const flattenFields = (fields) => {
|
|
@@ -118,7 +107,7 @@ function httpClientTest(httpClient) {
|
|
|
118
107
|
flattenedFields[key] = value.join(',');
|
|
119
108
|
}
|
|
120
109
|
else {
|
|
121
|
-
flattenedFields[key] = value
|
|
110
|
+
flattenedFields[key] = value ?? '';
|
|
122
111
|
}
|
|
123
112
|
});
|
|
124
113
|
return flattenedFields;
|
|
@@ -138,19 +127,15 @@ function httpClientTest(httpClient) {
|
|
|
138
127
|
});
|
|
139
128
|
return flattenedFiles;
|
|
140
129
|
};
|
|
141
|
-
const convertFormidableFileToTrayFile = (file) => {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
});
|
|
151
|
-
};
|
|
152
|
-
const requestListener = (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
153
|
-
var _a;
|
|
130
|
+
const convertFormidableFileToTrayFile = (file) => ({
|
|
131
|
+
key: file.newFilename,
|
|
132
|
+
metadata: {
|
|
133
|
+
name: file.originalFilename ?? '',
|
|
134
|
+
size: file.size,
|
|
135
|
+
},
|
|
136
|
+
content: stream_1.Readable.from(file.filepath),
|
|
137
|
+
});
|
|
138
|
+
const requestListener = async (req, res) => {
|
|
154
139
|
if (req.method === 'GET' && typeof req.headers['error'] === 'string') {
|
|
155
140
|
const errorCode = +req.headers['error'];
|
|
156
141
|
res.writeHead(errorCode, {
|
|
@@ -171,31 +156,31 @@ function httpClientTest(httpClient) {
|
|
|
171
156
|
sendHttpResponse(res, response, testResponseCodec);
|
|
172
157
|
}
|
|
173
158
|
else if (req.method === 'POST' &&
|
|
174
|
-
|
|
159
|
+
req.headers['content-type']?.includes(Http_1.HttpContentType.MultipartRequestBody)) {
|
|
175
160
|
res.writeHead(200, { [Http_1.HttpHeader.ContentType]: Http_1.HttpContentType.Json });
|
|
176
|
-
|
|
161
|
+
await processHttpRequest(testMultiPartBodyTypeCodec, testMultiPartBodyTypeCodec, req, res, (input) => input, true);
|
|
177
162
|
}
|
|
178
163
|
else {
|
|
179
164
|
const customHeader = req.headers['x-custom-header'];
|
|
180
165
|
res.writeHead(200, { [Http_1.HttpHeader.ContentType]: Http_1.HttpContentType.Json });
|
|
181
|
-
|
|
166
|
+
await processHttpRequest(testInputCodec, testResponseCodec, req, res, (input) => ({
|
|
182
167
|
strField: customHeader,
|
|
183
168
|
intField: input.inputField,
|
|
184
169
|
}));
|
|
185
170
|
}
|
|
186
|
-
}
|
|
171
|
+
};
|
|
187
172
|
const host = 'localhost';
|
|
188
173
|
const port = 8000; // TODO: Get random port
|
|
189
174
|
const baseUrl = `http://${host}:${port}`;
|
|
190
175
|
const server = (0, http_1.createServer)(requestListener);
|
|
191
176
|
describe('HttpClient Test', () => {
|
|
192
|
-
beforeAll(() =>
|
|
193
|
-
|
|
177
|
+
beforeAll(async () => {
|
|
178
|
+
await new Promise((resolve) => {
|
|
194
179
|
server.listen(port, host, resolve);
|
|
195
180
|
});
|
|
196
|
-
})
|
|
197
|
-
afterAll(() =>
|
|
198
|
-
|
|
181
|
+
});
|
|
182
|
+
afterAll(async () => {
|
|
183
|
+
await new Promise((resolve, reject) => {
|
|
199
184
|
server.close((error) => {
|
|
200
185
|
if (error) {
|
|
201
186
|
reject(error);
|
|
@@ -205,9 +190,9 @@ function httpClientTest(httpClient) {
|
|
|
205
190
|
}
|
|
206
191
|
});
|
|
207
192
|
});
|
|
208
|
-
})
|
|
209
|
-
test('should send a GET request', () =>
|
|
210
|
-
const response =
|
|
193
|
+
});
|
|
194
|
+
test('should send a GET request', async () => {
|
|
195
|
+
const response = await httpClient.execute(Http_1.HttpMethod.Get, baseUrl, {
|
|
211
196
|
headers: { 'x-custom-header': 'customVal' },
|
|
212
197
|
pathParams: {},
|
|
213
198
|
queryString: {},
|
|
@@ -218,14 +203,14 @@ function httpClientTest(httpClient) {
|
|
|
218
203
|
intField: 123,
|
|
219
204
|
};
|
|
220
205
|
const result = (0, function_1.pipe)(response, TE.fromEither, TE.chain((httpResponse) => BufferExtensions_1.BufferExtensions.readableToArrayBuffer(httpResponse.body)), TE.match((error) => E.left(error), (buffer) => (0, function_1.pipe)(serialization.deserialize(buffer), E.chain((encoded) => testResponseCodec.decode(encoded)))));
|
|
221
|
-
const resultE =
|
|
206
|
+
const resultE = await result();
|
|
222
207
|
expect(resultE).toStrictEqual(E.right(testValue));
|
|
223
|
-
})
|
|
224
|
-
test('should send a POST request', () =>
|
|
208
|
+
});
|
|
209
|
+
test('should send a POST request', async () => {
|
|
225
210
|
const testInput = {
|
|
226
211
|
inputField: 321,
|
|
227
212
|
};
|
|
228
|
-
const response =
|
|
213
|
+
const response = await (0, function_1.pipe)((0, Task_1.createTaskEitherFromEither)(E.right(testInputCodec.encode(testInput))), TE.map((encoded) => serialization.serialize(encoded)), TE.chain((serializedInput) => httpClient.execute(Http_1.HttpMethod.Post, baseUrl, {
|
|
229
214
|
headers: {
|
|
230
215
|
'x-custom-header': 'customVal',
|
|
231
216
|
},
|
|
@@ -238,20 +223,20 @@ function httpClientTest(httpClient) {
|
|
|
238
223
|
intField: 321,
|
|
239
224
|
};
|
|
240
225
|
const result = (0, function_1.pipe)(response, TE.fromEither, TE.chain((httpResponse) => BufferExtensions_1.BufferExtensions.readableToArrayBuffer(httpResponse.body)), TE.match((error) => E.left(error), (buffer) => (0, function_1.pipe)(serialization.deserialize(buffer), E.chain((encoded) => testResponseCodec.decode(encoded)))));
|
|
241
|
-
const resultE =
|
|
226
|
+
const resultE = await result();
|
|
242
227
|
expect(resultE).toStrictEqual(E.right(testValue));
|
|
243
|
-
})
|
|
244
|
-
test('should send a POST request with multipart body', () =>
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
const file1 =
|
|
228
|
+
});
|
|
229
|
+
test('should send a POST request with multipart body', async () => {
|
|
230
|
+
await fileStorage.delete('file1')();
|
|
231
|
+
await fileStorage.delete('file2')();
|
|
232
|
+
const file1 = await fileStorage.write({
|
|
248
233
|
key: 'file1',
|
|
249
234
|
metadata: {
|
|
250
235
|
name: 'file1',
|
|
251
236
|
},
|
|
252
237
|
content: stream_1.Readable.from('file 1 content'),
|
|
253
238
|
})();
|
|
254
|
-
const file2 =
|
|
239
|
+
const file2 = await fileStorage.write({
|
|
255
240
|
key: 'file2',
|
|
256
241
|
metadata: {
|
|
257
242
|
name: 'file2',
|
|
@@ -286,7 +271,7 @@ function httpClientTest(httpClient) {
|
|
|
286
271
|
},
|
|
287
272
|
},
|
|
288
273
|
};
|
|
289
|
-
const response =
|
|
274
|
+
const response = await httpClient.execute(Http_1.HttpMethod.Post, baseUrl, {
|
|
290
275
|
headers: {
|
|
291
276
|
'x-custom-header': 'customVal',
|
|
292
277
|
'content-type': Http_1.HttpContentType.MultipartRequestBody,
|
|
@@ -296,7 +281,7 @@ function httpClientTest(httpClient) {
|
|
|
296
281
|
body: testInput,
|
|
297
282
|
})();
|
|
298
283
|
const result = (0, function_1.pipe)(response, TE.fromEither, TE.chain((httpResponse) => BufferExtensions_1.BufferExtensions.readableToArrayBuffer(httpResponse.body)), TE.match((error) => E.left(error), (buffer) => (0, function_1.pipe)(serialization.deserialize(buffer), E.chain((encoded) => testMultiPartBodyTypeCodec.decode(encoded)))));
|
|
299
|
-
const resultE =
|
|
284
|
+
const resultE = await result();
|
|
300
285
|
expect(resultE).toEqual(E.right(expect.objectContaining({
|
|
301
286
|
fields: testInput.fields,
|
|
302
287
|
files: expect.objectContaining({
|
|
@@ -314,9 +299,9 @@ function httpClientTest(httpClient) {
|
|
|
314
299
|
}),
|
|
315
300
|
}),
|
|
316
301
|
})));
|
|
317
|
-
})
|
|
318
|
-
test('should parse an internal error response', () =>
|
|
319
|
-
const response =
|
|
302
|
+
});
|
|
303
|
+
test('should parse an internal error response', async () => {
|
|
304
|
+
const response = await httpClient.execute(Http_1.HttpMethod.Get, baseUrl, {
|
|
320
305
|
headers: { error: '500' },
|
|
321
306
|
pathParams: {},
|
|
322
307
|
queryString: {},
|
|
@@ -328,12 +313,12 @@ function httpClientTest(httpClient) {
|
|
|
328
313
|
if (E.isLeft(response)) {
|
|
329
314
|
throw response.left;
|
|
330
315
|
}
|
|
331
|
-
const responseBodyE =
|
|
316
|
+
const responseBodyE = await BufferExtensions_1.BufferExtensions.readableToArrayBuffer(response.right.body)();
|
|
332
317
|
expect(response.right.statusCode).toStrictEqual(500);
|
|
333
318
|
expect(responseBodyE).toStrictEqual(E.right(serialization.serialize(testErrorResponseCodec.encode(testErrorResponse))));
|
|
334
|
-
})
|
|
335
|
-
test('should parse a not found error response', () =>
|
|
336
|
-
const response =
|
|
319
|
+
});
|
|
320
|
+
test('should parse a not found error response', async () => {
|
|
321
|
+
const response = await httpClient.execute(Http_1.HttpMethod.Get, baseUrl, {
|
|
337
322
|
headers: { error: '404' },
|
|
338
323
|
pathParams: {},
|
|
339
324
|
queryString: {},
|
|
@@ -345,10 +330,10 @@ function httpClientTest(httpClient) {
|
|
|
345
330
|
if (E.isLeft(response)) {
|
|
346
331
|
throw response.left;
|
|
347
332
|
}
|
|
348
|
-
const responseBodyE =
|
|
333
|
+
const responseBodyE = await BufferExtensions_1.BufferExtensions.readableToArrayBuffer(response.right.body)();
|
|
349
334
|
expect(response.right.statusCode).toStrictEqual(404);
|
|
350
335
|
expect(responseBodyE).toStrictEqual(E.right(serialization.serialize(testErrorResponseCodec.encode(testErrorResponse))));
|
|
351
|
-
})
|
|
336
|
+
});
|
|
352
337
|
});
|
|
353
338
|
}
|
|
354
339
|
exports.httpClientTest = httpClientTest;
|
package/dist/result/Result.js
CHANGED
|
@@ -26,6 +26,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
exports.ResultInternal = exports.Result = exports.ResultFailureError = void 0;
|
|
27
27
|
const E = __importStar(require("fp-ts/Either"));
|
|
28
28
|
class ResultFailureError extends Error {
|
|
29
|
+
failureCause;
|
|
29
30
|
constructor(failureCause) {
|
|
30
31
|
super(`Result could not be read because it is a failure: ${JSON.stringify(failureCause)}`);
|
|
31
32
|
this.failureCause = failureCause;
|
|
@@ -30,11 +30,9 @@ const function_1 = require("fp-ts/function");
|
|
|
30
30
|
const Serialization_1 = require("./Serialization");
|
|
31
31
|
const Try_1 = require("../try/Try");
|
|
32
32
|
class JsonSerialization {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
this.format = Serialization_1.SerializationFormat.Json;
|
|
37
|
-
}
|
|
33
|
+
textEncoder = new util_1.TextEncoder();
|
|
34
|
+
textDecoder = new util_1.TextDecoder();
|
|
35
|
+
format = Serialization_1.SerializationFormat.Json;
|
|
38
36
|
serialize(value) {
|
|
39
37
|
const json = JSON.stringify(value);
|
|
40
38
|
return this.textEncoder.encode(json).buffer;
|