modelfusion 0.53.2 → 0.54.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/README.md +2 -2
- package/browser/convertAudioChunksToBase64.cjs +8 -0
- package/browser/convertAudioChunksToBase64.d.ts +4 -0
- package/browser/convertAudioChunksToBase64.js +4 -0
- package/browser/convertBlobToBase64.cjs +23 -0
- package/browser/convertBlobToBase64.d.ts +1 -0
- package/browser/convertBlobToBase64.js +19 -0
- package/{ui → browser}/index.cjs +5 -0
- package/browser/index.d.ts +6 -0
- package/browser/index.js +6 -0
- package/browser/invokeFlow.cjs +23 -0
- package/browser/invokeFlow.d.ts +8 -0
- package/browser/invokeFlow.js +19 -0
- package/{event-source → browser}/readEventSource.cjs +8 -3
- package/{event-source → browser}/readEventSource.d.ts +3 -1
- package/{event-source → browser}/readEventSource.js +8 -3
- package/{event-source → browser}/readEventSourceStream.cjs +1 -1
- package/{event-source → browser}/readEventSourceStream.js +1 -1
- package/event-source/createEventSourceStream.cjs +7 -3
- package/event-source/createEventSourceStream.js +7 -3
- package/event-source/index.cjs +0 -2
- package/event-source/index.d.ts +0 -2
- package/event-source/index.js +0 -2
- package/index.cjs +0 -1
- package/index.d.ts +0 -1
- package/index.js +0 -1
- package/package.json +13 -4
- package/server/fastify/AssetStorage.cjs +2 -0
- package/server/fastify/AssetStorage.d.ts +17 -0
- package/server/fastify/AssetStorage.js +1 -0
- package/server/fastify/DefaultFlow.cjs +22 -0
- package/server/fastify/DefaultFlow.d.ts +16 -0
- package/server/fastify/DefaultFlow.js +18 -0
- package/server/fastify/FileSystemAssetStorage.cjs +60 -0
- package/server/fastify/FileSystemAssetStorage.d.ts +19 -0
- package/server/fastify/FileSystemAssetStorage.js +56 -0
- package/server/fastify/FileSystemLogger.cjs +48 -0
- package/server/fastify/FileSystemLogger.d.ts +18 -0
- package/server/fastify/FileSystemLogger.js +44 -0
- package/server/fastify/Flow.cjs +2 -0
- package/server/fastify/Flow.d.ts +9 -0
- package/server/fastify/Flow.js +1 -0
- package/server/fastify/FlowRun.cjs +71 -0
- package/server/fastify/FlowRun.d.ts +28 -0
- package/server/fastify/FlowRun.js +67 -0
- package/server/fastify/FlowSchema.cjs +2 -0
- package/server/fastify/FlowSchema.d.ts +5 -0
- package/server/fastify/FlowSchema.js +1 -0
- package/server/fastify/Logger.cjs +2 -0
- package/server/fastify/Logger.d.ts +13 -0
- package/server/fastify/Logger.js +1 -0
- package/server/fastify/PathProvider.cjs +34 -0
- package/server/fastify/PathProvider.d.ts +12 -0
- package/server/fastify/PathProvider.js +30 -0
- package/server/fastify/index.cjs +24 -0
- package/server/fastify/index.d.ts +8 -0
- package/server/fastify/index.js +8 -0
- package/server/fastify/modelFusionFlowPlugin.cjs +102 -0
- package/server/fastify/modelFusionFlowPlugin.d.ts +12 -0
- package/server/fastify/modelFusionFlowPlugin.js +98 -0
- package/ui/index.d.ts +0 -1
- package/ui/index.js +0 -1
- /package/{ui → browser}/MediaSourceAppender.cjs +0 -0
- /package/{ui → browser}/MediaSourceAppender.d.ts +0 -0
- /package/{ui → browser}/MediaSourceAppender.js +0 -0
- /package/{event-source → browser}/readEventSourceStream.d.ts +0 -0
package/README.md
CHANGED
@@ -623,9 +623,9 @@ Create an 19th century painting image for your input.
|
|
623
623
|
|
624
624
|
Record audio with push-to-talk and transcribe it using Whisper, implemented as a Next.js app. The app shows a list of the transcriptions.
|
625
625
|
|
626
|
-
### [Speech Streaming (Vite
|
626
|
+
### [Duplex Speech Streaming (using Vite/React & ModelFusion Server/Fastify)](https://github.com/lgrammel/modelfusion/tree/main/examples/speech-streaming-vite-react-fastify)
|
627
627
|
|
628
|
-
> _Speech Streaming_, _OpenAI_, _Elevenlabs_ _streaming_, _Vite_, _Fastify_
|
628
|
+
> _Speech Streaming_, _OpenAI_, _Elevenlabs_ _streaming_, _Vite_, _Fastify_, _ModelFusion Server_
|
629
629
|
|
630
630
|
Given a prompt, the server returns both a text and a speech stream response.
|
631
631
|
|
@@ -0,0 +1,8 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.convertAudioChunksToBase64 = void 0;
|
4
|
+
const convertBlobToBase64_js_1 = require("./convertBlobToBase64.cjs");
|
5
|
+
function convertAudioChunksToBase64({ audioChunks, mimeType, }) {
|
6
|
+
return (0, convertBlobToBase64_js_1.convertBlobToBase64)(new Blob(audioChunks, { type: mimeType }));
|
7
|
+
}
|
8
|
+
exports.convertAudioChunksToBase64 = convertAudioChunksToBase64;
|
@@ -0,0 +1,23 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.convertBlobToBase64 = void 0;
|
4
|
+
async function convertBlobToBase64(blob) {
|
5
|
+
return new Promise((resolve, reject) => {
|
6
|
+
const reader = new FileReader();
|
7
|
+
reader.onloadend = () => {
|
8
|
+
if (reader.result) {
|
9
|
+
const base64String = btoa(new Uint8Array(reader.result).reduce((data, byte) => data + String.fromCharCode(byte), ""));
|
10
|
+
resolve(base64String);
|
11
|
+
}
|
12
|
+
else {
|
13
|
+
reject(new Error("Failed to read blob."));
|
14
|
+
}
|
15
|
+
};
|
16
|
+
reader.onerror = () => {
|
17
|
+
reader.abort();
|
18
|
+
reject(new DOMException("Problem parsing input blob."));
|
19
|
+
};
|
20
|
+
reader.readAsArrayBuffer(blob);
|
21
|
+
});
|
22
|
+
}
|
23
|
+
exports.convertBlobToBase64 = convertBlobToBase64;
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function convertBlobToBase64(blob: Blob): Promise<string>;
|
@@ -0,0 +1,19 @@
|
|
1
|
+
export async function convertBlobToBase64(blob) {
|
2
|
+
return new Promise((resolve, reject) => {
|
3
|
+
const reader = new FileReader();
|
4
|
+
reader.onloadend = () => {
|
5
|
+
if (reader.result) {
|
6
|
+
const base64String = btoa(new Uint8Array(reader.result).reduce((data, byte) => data + String.fromCharCode(byte), ""));
|
7
|
+
resolve(base64String);
|
8
|
+
}
|
9
|
+
else {
|
10
|
+
reject(new Error("Failed to read blob."));
|
11
|
+
}
|
12
|
+
};
|
13
|
+
reader.onerror = () => {
|
14
|
+
reader.abort();
|
15
|
+
reject(new DOMException("Problem parsing input blob."));
|
16
|
+
};
|
17
|
+
reader.readAsArrayBuffer(blob);
|
18
|
+
});
|
19
|
+
}
|
package/{ui → browser}/index.cjs
RENAMED
@@ -15,3 +15,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
15
15
|
};
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
17
17
|
__exportStar(require("./MediaSourceAppender.cjs"), exports);
|
18
|
+
__exportStar(require("./convertAudioChunksToBase64.cjs"), exports);
|
19
|
+
__exportStar(require("./convertBlobToBase64.cjs"), exports);
|
20
|
+
__exportStar(require("./invokeFlow.cjs"), exports);
|
21
|
+
__exportStar(require("./readEventSource.cjs"), exports);
|
22
|
+
__exportStar(require("./readEventSourceStream.cjs"), exports);
|
package/browser/index.js
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.invokeFlow = void 0;
|
4
|
+
const ZodSchema_1 = require("../core/structure/ZodSchema");
|
5
|
+
const readEventSource_1 = require("./readEventSource");
|
6
|
+
async function invokeFlow({ url, input, schema, onEvent, onStop, }) {
|
7
|
+
const response = await fetch(url, {
|
8
|
+
method: "POST",
|
9
|
+
headers: { "Content-Type": "application/json" },
|
10
|
+
body: JSON.stringify(input),
|
11
|
+
});
|
12
|
+
const eventSourceUrl = (await response.json()).url;
|
13
|
+
(0, readEventSource_1.readEventSource)({
|
14
|
+
url: eventSourceUrl,
|
15
|
+
schema: new ZodSchema_1.ZodSchema(schema.events),
|
16
|
+
isStopEvent(event) {
|
17
|
+
return event.data === "[DONE]";
|
18
|
+
},
|
19
|
+
onEvent,
|
20
|
+
onStop,
|
21
|
+
});
|
22
|
+
}
|
23
|
+
exports.invokeFlow = invokeFlow;
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import { FlowSchema } from "../server/fastify/FlowSchema";
|
2
|
+
export declare function invokeFlow<INPUT, EVENT>({ url, input, schema, onEvent, onStop, }: {
|
3
|
+
url: string;
|
4
|
+
input: INPUT;
|
5
|
+
schema: FlowSchema<INPUT, EVENT>;
|
6
|
+
onEvent: (event: EVENT, eventSource: EventSource) => void;
|
7
|
+
onStop?: (eventSource: EventSource) => void;
|
8
|
+
}): Promise<void>;
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import { ZodSchema } from "../core/structure/ZodSchema";
|
2
|
+
import { readEventSource } from "./readEventSource";
|
3
|
+
export async function invokeFlow({ url, input, schema, onEvent, onStop, }) {
|
4
|
+
const response = await fetch(url, {
|
5
|
+
method: "POST",
|
6
|
+
headers: { "Content-Type": "application/json" },
|
7
|
+
body: JSON.stringify(input),
|
8
|
+
});
|
9
|
+
const eventSourceUrl = (await response.json()).url;
|
10
|
+
readEventSource({
|
11
|
+
url: eventSourceUrl,
|
12
|
+
schema: new ZodSchema(schema.events),
|
13
|
+
isStopEvent(event) {
|
14
|
+
return event.data === "[DONE]";
|
15
|
+
},
|
16
|
+
onEvent,
|
17
|
+
onStop,
|
18
|
+
});
|
19
|
+
}
|
@@ -2,11 +2,16 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.readEventSource = void 0;
|
4
4
|
const parseJSON_js_1 = require("../util/parseJSON.cjs");
|
5
|
-
function readEventSource({ url, schema, onEvent, onError = console.error, }) {
|
5
|
+
function readEventSource({ url, schema, onEvent, onError = console.error, onStop, isStopEvent, }) {
|
6
6
|
const eventSource = new EventSource(url);
|
7
|
-
eventSource.onmessage = (
|
7
|
+
eventSource.onmessage = (event) => {
|
8
8
|
try {
|
9
|
-
|
9
|
+
if (isStopEvent?.(event)) {
|
10
|
+
eventSource.close();
|
11
|
+
onStop?.(eventSource);
|
12
|
+
return;
|
13
|
+
}
|
14
|
+
const parseResult = (0, parseJSON_js_1.safeParseJsonWithSchema)(event.data, schema);
|
10
15
|
if (!parseResult.success) {
|
11
16
|
onError(parseResult.error, eventSource);
|
12
17
|
return;
|
@@ -1,7 +1,9 @@
|
|
1
1
|
import { Schema } from "../core/structure/Schema.js";
|
2
|
-
export declare function readEventSource<T>({ url, schema, onEvent, onError, }: {
|
2
|
+
export declare function readEventSource<T>({ url, schema, onEvent, onError, onStop, isStopEvent, }: {
|
3
3
|
url: string;
|
4
4
|
schema: Schema<T>;
|
5
5
|
onEvent: (event: T, eventSource: EventSource) => void;
|
6
6
|
onError?: (error: unknown, eventSource: EventSource) => void;
|
7
|
+
onStop?: (eventSource: EventSource) => void;
|
8
|
+
isStopEvent?: (event: MessageEvent<unknown>) => boolean;
|
7
9
|
}): void;
|
@@ -1,9 +1,14 @@
|
|
1
1
|
import { safeParseJsonWithSchema } from "../util/parseJSON.js";
|
2
|
-
export function readEventSource({ url, schema, onEvent, onError = console.error, }) {
|
2
|
+
export function readEventSource({ url, schema, onEvent, onError = console.error, onStop, isStopEvent, }) {
|
3
3
|
const eventSource = new EventSource(url);
|
4
|
-
eventSource.onmessage = (
|
4
|
+
eventSource.onmessage = (event) => {
|
5
5
|
try {
|
6
|
-
|
6
|
+
if (isStopEvent?.(event)) {
|
7
|
+
eventSource.close();
|
8
|
+
onStop?.(eventSource);
|
9
|
+
return;
|
10
|
+
}
|
11
|
+
const parseResult = safeParseJsonWithSchema(event.data, schema);
|
7
12
|
if (!parseResult.success) {
|
8
13
|
onError(parseResult.error, eventSource);
|
9
14
|
return;
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.readEventSourceStream = void 0;
|
4
4
|
const parseJSON_js_1 = require("../util/parseJSON.cjs");
|
5
5
|
const AsyncQueue_js_1 = require("../util/AsyncQueue.cjs");
|
6
|
-
const parseEventSourceStream_js_1 = require("
|
6
|
+
const parseEventSourceStream_js_1 = require("../event-source/parseEventSourceStream.cjs");
|
7
7
|
function readEventSourceStream({ stream, schema, errorHandler, }) {
|
8
8
|
const queue = new AsyncQueue_js_1.AsyncQueue();
|
9
9
|
// run async (no await on purpose):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { safeParseJsonWithSchema } from "../util/parseJSON.js";
|
2
2
|
import { AsyncQueue } from "../util/AsyncQueue.js";
|
3
|
-
import { parseEventSourceStream } from "
|
3
|
+
import { parseEventSourceStream } from "../event-source/parseEventSourceStream.js";
|
4
4
|
export function readEventSourceStream({ stream, schema, errorHandler, }) {
|
5
5
|
const queue = new AsyncQueue();
|
6
6
|
// run async (no await on purpose):
|
@@ -5,10 +5,14 @@ const textEncoder = new TextEncoder();
|
|
5
5
|
function createEventSourceStream(events) {
|
6
6
|
return new ReadableStream({
|
7
7
|
async start(controller) {
|
8
|
-
|
9
|
-
|
8
|
+
try {
|
9
|
+
for await (const event of events) {
|
10
|
+
controller.enqueue(textEncoder.encode(`data: ${JSON.stringify(event)}\n\n`));
|
11
|
+
}
|
12
|
+
}
|
13
|
+
finally {
|
14
|
+
controller.close();
|
10
15
|
}
|
11
|
-
controller.close();
|
12
16
|
},
|
13
17
|
});
|
14
18
|
}
|
@@ -2,10 +2,14 @@ const textEncoder = new TextEncoder();
|
|
2
2
|
export function createEventSourceStream(events) {
|
3
3
|
return new ReadableStream({
|
4
4
|
async start(controller) {
|
5
|
-
|
6
|
-
|
5
|
+
try {
|
6
|
+
for await (const event of events) {
|
7
|
+
controller.enqueue(textEncoder.encode(`data: ${JSON.stringify(event)}\n\n`));
|
8
|
+
}
|
9
|
+
}
|
10
|
+
finally {
|
11
|
+
controller.close();
|
7
12
|
}
|
8
|
-
controller.close();
|
9
13
|
},
|
10
14
|
});
|
11
15
|
}
|
package/event-source/index.cjs
CHANGED
@@ -15,5 +15,3 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
15
15
|
};
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
17
17
|
__exportStar(require("./createEventSourceStream.cjs"), exports);
|
18
|
-
__exportStar(require("./readEventSource.cjs"), exports);
|
19
|
-
__exportStar(require("./readEventSourceStream.cjs"), exports);
|
package/event-source/index.d.ts
CHANGED
package/event-source/index.js
CHANGED
package/index.cjs
CHANGED
@@ -25,6 +25,5 @@ __exportStar(require("./observability/index.cjs"), exports);
|
|
25
25
|
__exportStar(require("./retriever/index.cjs"), exports);
|
26
26
|
__exportStar(require("./text-chunk/index.cjs"), exports);
|
27
27
|
__exportStar(require("./tool/index.cjs"), exports);
|
28
|
-
__exportStar(require("./ui/index.cjs"), exports);
|
29
28
|
__exportStar(require("./util/index.cjs"), exports);
|
30
29
|
__exportStar(require("./vector-index/index.cjs"), exports);
|
package/index.d.ts
CHANGED
@@ -9,6 +9,5 @@ export * from "./observability/index.js";
|
|
9
9
|
export * from "./retriever/index.js";
|
10
10
|
export * from "./text-chunk/index.js";
|
11
11
|
export * from "./tool/index.js";
|
12
|
-
export * from "./ui/index.js";
|
13
12
|
export * from "./util/index.js";
|
14
13
|
export * from "./vector-index/index.js";
|
package/index.js
CHANGED
@@ -9,6 +9,5 @@ export * from "./observability/index.js";
|
|
9
9
|
export * from "./retriever/index.js";
|
10
10
|
export * from "./text-chunk/index.js";
|
11
11
|
export * from "./tool/index.js";
|
12
|
-
export * from "./ui/index.js";
|
13
12
|
export * from "./util/index.js";
|
14
13
|
export * from "./vector-index/index.js";
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "modelfusion",
|
3
3
|
"description": "Build multimodal applications, chatbots, and agents with JavaScript and TypeScript.",
|
4
|
-
"version": "0.
|
4
|
+
"version": "0.54.0",
|
5
5
|
"author": "Lars Grammel",
|
6
6
|
"license": "MIT",
|
7
7
|
"keywords": [
|
@@ -38,6 +38,16 @@
|
|
38
38
|
"types": "./index.d.ts",
|
39
39
|
"import": "./index.js",
|
40
40
|
"require": "./index.cjs"
|
41
|
+
},
|
42
|
+
"./browser": {
|
43
|
+
"types": "./browser/index.d.ts",
|
44
|
+
"import": "./browser/index.js",
|
45
|
+
"require": "./browser/index.cjs"
|
46
|
+
},
|
47
|
+
"./fastify-server": {
|
48
|
+
"types": "./server/fastify/index.d.ts",
|
49
|
+
"import": "./server/fastify/index.js",
|
50
|
+
"require": "./server/fastify/index.cjs"
|
41
51
|
}
|
42
52
|
},
|
43
53
|
"scripts": {
|
@@ -62,8 +72,6 @@
|
|
62
72
|
"zod-to-json-schema": "3.21.4"
|
63
73
|
},
|
64
74
|
"devDependencies": {
|
65
|
-
"@tsconfig/recommended": "1.0.3",
|
66
|
-
"@types/deep-equal": "^1.0.2",
|
67
75
|
"@types/node": "18.11.9",
|
68
76
|
"@types/ws": "^8.5.7",
|
69
77
|
"@typescript-eslint/eslint-plugin": "^6.1.0",
|
@@ -71,8 +79,9 @@
|
|
71
79
|
"copyfiles": "2.4.1",
|
72
80
|
"eslint": "^8.45.0",
|
73
81
|
"eslint-config-prettier": "9.0.0",
|
82
|
+
"fastify": "^4.0.0",
|
74
83
|
"husky": "^8.0.3",
|
75
|
-
"lint-staged": "
|
84
|
+
"lint-staged": "15.0.2",
|
76
85
|
"prettier": "3.0.3",
|
77
86
|
"rimraf": "5.0.5",
|
78
87
|
"typescript": "5.2.2",
|
@@ -0,0 +1,17 @@
|
|
1
|
+
/// <reference types="node" />
|
2
|
+
import { FlowRun } from "./FlowRun.js";
|
3
|
+
export type Asset = {
|
4
|
+
data: Buffer;
|
5
|
+
contentType: string;
|
6
|
+
name: string;
|
7
|
+
};
|
8
|
+
export interface AssetStorage {
|
9
|
+
storeAsset(options: {
|
10
|
+
run: FlowRun<unknown>;
|
11
|
+
asset: Asset;
|
12
|
+
}): Promise<void>;
|
13
|
+
readAsset(options: {
|
14
|
+
run: FlowRun<unknown>;
|
15
|
+
assetName: string;
|
16
|
+
}): Promise<Asset | null>;
|
17
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,22 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.DefaultFlow = void 0;
|
4
|
+
class DefaultFlow {
|
5
|
+
constructor({ schema, process, }) {
|
6
|
+
Object.defineProperty(this, "schema", {
|
7
|
+
enumerable: true,
|
8
|
+
configurable: true,
|
9
|
+
writable: true,
|
10
|
+
value: void 0
|
11
|
+
});
|
12
|
+
Object.defineProperty(this, "process", {
|
13
|
+
enumerable: true,
|
14
|
+
configurable: true,
|
15
|
+
writable: true,
|
16
|
+
value: void 0
|
17
|
+
});
|
18
|
+
this.schema = schema;
|
19
|
+
this.process = process;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
exports.DefaultFlow = DefaultFlow;
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { FlowRun } from "./FlowRun.js";
|
2
|
+
import { FlowSchema } from "./FlowSchema.js";
|
3
|
+
export declare class DefaultFlow<INPUT, EVENT> {
|
4
|
+
readonly schema: FlowSchema<INPUT, EVENT>;
|
5
|
+
constructor({ schema, process, }: {
|
6
|
+
schema: FlowSchema<INPUT, EVENT>;
|
7
|
+
process: (options: {
|
8
|
+
input: INPUT;
|
9
|
+
run: FlowRun<EVENT>;
|
10
|
+
}) => Promise<void>;
|
11
|
+
});
|
12
|
+
process: (options: {
|
13
|
+
input: INPUT;
|
14
|
+
run: FlowRun<EVENT>;
|
15
|
+
}) => Promise<void>;
|
16
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
export class DefaultFlow {
|
2
|
+
constructor({ schema, process, }) {
|
3
|
+
Object.defineProperty(this, "schema", {
|
4
|
+
enumerable: true,
|
5
|
+
configurable: true,
|
6
|
+
writable: true,
|
7
|
+
value: void 0
|
8
|
+
});
|
9
|
+
Object.defineProperty(this, "process", {
|
10
|
+
enumerable: true,
|
11
|
+
configurable: true,
|
12
|
+
writable: true,
|
13
|
+
value: void 0
|
14
|
+
});
|
15
|
+
this.schema = schema;
|
16
|
+
this.process = process;
|
17
|
+
}
|
18
|
+
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.FileSystemAssetStorage = void 0;
|
4
|
+
const node_fs_1 = require("node:fs");
|
5
|
+
const node_path_1 = require("node:path");
|
6
|
+
class FileSystemAssetStorage {
|
7
|
+
constructor({ path, logger, }) {
|
8
|
+
Object.defineProperty(this, "path", {
|
9
|
+
enumerable: true,
|
10
|
+
configurable: true,
|
11
|
+
writable: true,
|
12
|
+
value: void 0
|
13
|
+
});
|
14
|
+
Object.defineProperty(this, "logger", {
|
15
|
+
enumerable: true,
|
16
|
+
configurable: true,
|
17
|
+
writable: true,
|
18
|
+
value: void 0
|
19
|
+
});
|
20
|
+
this.path = path;
|
21
|
+
this.logger = logger;
|
22
|
+
}
|
23
|
+
async storeAsset({ run, asset, }) {
|
24
|
+
try {
|
25
|
+
const assetPath = this.path(run);
|
26
|
+
await node_fs_1.promises.mkdir(assetPath, { recursive: true });
|
27
|
+
await node_fs_1.promises.writeFile((0, node_path_1.join)(assetPath, asset.name), asset.data);
|
28
|
+
await node_fs_1.promises.writeFile((0, node_path_1.join)(assetPath, `${asset.name}.meta.json`), JSON.stringify({
|
29
|
+
name: asset.name,
|
30
|
+
contentType: asset.contentType,
|
31
|
+
}));
|
32
|
+
}
|
33
|
+
catch (error) {
|
34
|
+
this.logger.logError({
|
35
|
+
run,
|
36
|
+
message: `Failed to store asset ${asset.name}`,
|
37
|
+
error,
|
38
|
+
});
|
39
|
+
throw error;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
async readAsset(options) {
|
43
|
+
try {
|
44
|
+
const assetPath = this.path(options.run);
|
45
|
+
const data = await node_fs_1.promises.readFile((0, node_path_1.join)(assetPath, options.assetName));
|
46
|
+
const meta = await node_fs_1.promises.readFile((0, node_path_1.join)(assetPath, `${options.assetName}.meta.json`));
|
47
|
+
const { name, contentType } = JSON.parse(meta.toString());
|
48
|
+
return { data, name, contentType };
|
49
|
+
}
|
50
|
+
catch (error) {
|
51
|
+
this.logger.logError({
|
52
|
+
run: options.run,
|
53
|
+
message: `Failed to read asset ${options.assetName}`,
|
54
|
+
error,
|
55
|
+
});
|
56
|
+
throw error;
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
exports.FileSystemAssetStorage = FileSystemAssetStorage;
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import type { Asset, AssetStorage } from "./AssetStorage.js";
|
2
|
+
import { FlowRun } from "./FlowRun.js";
|
3
|
+
import { Logger } from "./Logger.js";
|
4
|
+
export declare class FileSystemAssetStorage implements AssetStorage {
|
5
|
+
private readonly path;
|
6
|
+
private readonly logger;
|
7
|
+
constructor({ path, logger, }: {
|
8
|
+
path: (run: FlowRun<unknown>) => string;
|
9
|
+
logger: Logger;
|
10
|
+
});
|
11
|
+
storeAsset({ run, asset, }: {
|
12
|
+
run: FlowRun<unknown>;
|
13
|
+
asset: Asset;
|
14
|
+
}): Promise<void>;
|
15
|
+
readAsset(options: {
|
16
|
+
run: FlowRun<unknown>;
|
17
|
+
assetName: string;
|
18
|
+
}): Promise<Asset | null>;
|
19
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import { promises as fs } from "node:fs";
|
2
|
+
import { join } from "node:path";
|
3
|
+
export class FileSystemAssetStorage {
|
4
|
+
constructor({ path, logger, }) {
|
5
|
+
Object.defineProperty(this, "path", {
|
6
|
+
enumerable: true,
|
7
|
+
configurable: true,
|
8
|
+
writable: true,
|
9
|
+
value: void 0
|
10
|
+
});
|
11
|
+
Object.defineProperty(this, "logger", {
|
12
|
+
enumerable: true,
|
13
|
+
configurable: true,
|
14
|
+
writable: true,
|
15
|
+
value: void 0
|
16
|
+
});
|
17
|
+
this.path = path;
|
18
|
+
this.logger = logger;
|
19
|
+
}
|
20
|
+
async storeAsset({ run, asset, }) {
|
21
|
+
try {
|
22
|
+
const assetPath = this.path(run);
|
23
|
+
await fs.mkdir(assetPath, { recursive: true });
|
24
|
+
await fs.writeFile(join(assetPath, asset.name), asset.data);
|
25
|
+
await fs.writeFile(join(assetPath, `${asset.name}.meta.json`), JSON.stringify({
|
26
|
+
name: asset.name,
|
27
|
+
contentType: asset.contentType,
|
28
|
+
}));
|
29
|
+
}
|
30
|
+
catch (error) {
|
31
|
+
this.logger.logError({
|
32
|
+
run,
|
33
|
+
message: `Failed to store asset ${asset.name}`,
|
34
|
+
error,
|
35
|
+
});
|
36
|
+
throw error;
|
37
|
+
}
|
38
|
+
}
|
39
|
+
async readAsset(options) {
|
40
|
+
try {
|
41
|
+
const assetPath = this.path(options.run);
|
42
|
+
const data = await fs.readFile(join(assetPath, options.assetName));
|
43
|
+
const meta = await fs.readFile(join(assetPath, `${options.assetName}.meta.json`));
|
44
|
+
const { name, contentType } = JSON.parse(meta.toString());
|
45
|
+
return { data, name, contentType };
|
46
|
+
}
|
47
|
+
catch (error) {
|
48
|
+
this.logger.logError({
|
49
|
+
run: options.run,
|
50
|
+
message: `Failed to read asset ${options.assetName}`,
|
51
|
+
error,
|
52
|
+
});
|
53
|
+
throw error;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.FileSystemLogger = void 0;
|
4
|
+
const node_fs_1 = require("node:fs");
|
5
|
+
const node_path_1 = require("node:path");
|
6
|
+
class FileSystemLogger {
|
7
|
+
constructor({ path }) {
|
8
|
+
Object.defineProperty(this, "logPath", {
|
9
|
+
enumerable: true,
|
10
|
+
configurable: true,
|
11
|
+
writable: true,
|
12
|
+
value: void 0
|
13
|
+
});
|
14
|
+
this.logPath = path;
|
15
|
+
}
|
16
|
+
async logFunctionEvent({ run, event, }) {
|
17
|
+
const timestamp = event.startTimestamp.getTime();
|
18
|
+
try {
|
19
|
+
const logPath = this.logPath(run);
|
20
|
+
await node_fs_1.promises.mkdir(logPath, { recursive: true });
|
21
|
+
await node_fs_1.promises.writeFile((0, node_path_1.join)(logPath, `${timestamp}-${event.callId}-${event.functionId ?? event.functionType}-${event.eventType}.json`), JSON.stringify(event));
|
22
|
+
}
|
23
|
+
catch (error) {
|
24
|
+
this.logError({
|
25
|
+
run,
|
26
|
+
message: `Failed to write function event ${event.callId}`,
|
27
|
+
error,
|
28
|
+
});
|
29
|
+
}
|
30
|
+
}
|
31
|
+
async logError(options) {
|
32
|
+
const timestamp = Date.now();
|
33
|
+
try {
|
34
|
+
const logPath = this.logPath(options.run);
|
35
|
+
return node_fs_1.promises.writeFile((0, node_path_1.join)(logPath, `${timestamp}-error.json`), JSON.stringify({
|
36
|
+
timestamp: new Date(timestamp).toISOString(),
|
37
|
+
runId: options.run.runId,
|
38
|
+
message: options.message,
|
39
|
+
error: options.error,
|
40
|
+
}));
|
41
|
+
}
|
42
|
+
catch (error) {
|
43
|
+
console.error(`Failed to write error log`);
|
44
|
+
console.error(error);
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
exports.FileSystemLogger = FileSystemLogger;
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import { FunctionEvent } from "../../core/FunctionEvent.js";
|
2
|
+
import { FlowRun } from "./FlowRun.js";
|
3
|
+
import { Logger } from "./Logger.js";
|
4
|
+
export declare class FileSystemLogger implements Logger {
|
5
|
+
private readonly logPath;
|
6
|
+
constructor({ path }: {
|
7
|
+
path: (run: FlowRun<unknown>) => string;
|
8
|
+
});
|
9
|
+
logFunctionEvent({ run, event, }: {
|
10
|
+
run: FlowRun<unknown>;
|
11
|
+
event: FunctionEvent;
|
12
|
+
}): Promise<void>;
|
13
|
+
logError(options: {
|
14
|
+
run: FlowRun<unknown>;
|
15
|
+
message: string;
|
16
|
+
error: unknown;
|
17
|
+
}): Promise<void>;
|
18
|
+
}
|