1717 * File protocol binding
1818 */
1919import { Form , SecurityScheme } from "@node-wot/td-tools" ;
20- import { ProtocolClient , Content , createLoggers } from "@node-wot/core" ;
20+ import { ProtocolClient , Content , createLoggers , ContentSerdes } from "@node-wot/core" ;
2121import { Subscription } from "rxjs/Subscription" ;
2222import fs = require( "fs" ) ;
23- import path = require ( "path" ) ;
23+ import { fileURLToPath } from "node:url" ;
2424
25- const { debug, warn } = createLoggers ( "binding-file" , "file-client" ) ;
26-
27- /**
28- * Used to determine the Content-Type of a file from the extension in its
29- * {@link filePath} if no explicit Content-Type is defined.
30- *
31- * @param filepath The file path the Content-Type is determined for.
32- * @returns An appropriate Content-Type or `application/octet-stream` as a fallback.
33- */
34- function mapFileExtensionToContentType ( filepath : string ) {
35- const fileExtension = path . extname ( filepath ) ;
36- debug ( `FileClient found '${ fileExtension } ' extension` ) ;
37- switch ( fileExtension ) {
38- case ".txt" :
39- case ".log" :
40- case ".ini" :
41- case ".cfg" :
42- return "text/plain" ;
43- case ".json" :
44- return "application/json" ;
45- case ".jsontd" :
46- return "application/td+json" ;
47- case ".jsonld" :
48- return "application/ld+json" ;
49- default :
50- warn ( `FileClient cannot determine media type for path '${ filepath } '` ) ;
51- return "application/octet-stream" ;
52- }
53- }
25+ const { debug } = createLoggers ( "binding-file" , "file-client" ) ;
5426
5527export default class FileClient implements ProtocolClient {
5628 public toString ( ) : string {
5729 return "[FileClient]" ;
5830 }
5931
60- private async readFile ( filepath : string , contentType ?: string ) : Promise < Content > {
61- const resource = fs . createReadStream ( filepath ) ;
62- const resourceContentType = contentType ?? mapFileExtensionToContentType ( filepath ) ;
63- return new Content ( resourceContentType , resource ) ;
32+ private async readFromFile ( uri : string , contentType : string ) {
33+ const filePath = fileURLToPath ( uri ) ;
34+ debug ( `Reading file of Content-Type ${ contentType } from path ${ filePath } .` ) ;
35+
36+ const resource = fs . createReadStream ( filePath ) ;
37+ return new Content ( contentType , resource ) ;
6438 }
6539
6640 public async readResource ( form : Form ) : Promise < Content > {
67- const filepath = new URL ( form . href ) . pathname ;
68- return this . readFile ( filepath , form . contentType ) ;
41+ const formContentType = form . contentType ;
42+ if ( formContentType == null ) {
43+ debug ( `Found no Content-Type for Form, defaulting to ${ ContentSerdes . DEFAULT } ` ) ;
44+ }
45+ const contentType = formContentType ?? ContentSerdes . DEFAULT ;
46+
47+ return this . readFromFile ( form . href , contentType ) ;
6948 }
7049
7150 public async writeResource ( form : Form , content : Content ) : Promise < void > {
72- throw new Error ( "FileClient does not implement write" ) ;
51+ const filePath = fileURLToPath ( form . href ) ;
52+
53+ const writeStream = fs . createWriteStream ( filePath ) ;
54+ const buffer = await content . toBuffer ( ) ;
55+
56+ writeStream . end ( buffer ) ;
7357 }
7458
7559 public async invokeResource ( form : Form , content : Content ) : Promise < Content > {
@@ -84,7 +68,7 @@ export default class FileClient implements ProtocolClient {
8468 * @inheritdoc
8569 */
8670 public async requestThingDescription ( uri : string ) : Promise < Content > {
87- return this . readFile ( uri , "application/td+json" ) ;
71+ return this . readFromFile ( uri , "application/td+json" ) ;
8872 }
8973
9074 public async subscribeResource (
0 commit comments