From 15805dc8a2dcb1da880daaa68caa6628a46eac63 Mon Sep 17 00:00:00 2001 From: Brett Saviano Date: Tue, 4 Aug 2026 11:39:40 -0400 Subject: [PATCH 1/3] Sync server-side web app files as raw bytes --- src/api/index.ts | 15 +++++---- .../FileSystemProvider/FileSystemProvider.ts | 31 +++++++------------ 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/api/index.ts b/src/api/index.ts index 1ba3aacb..d39d9f58 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -647,9 +647,11 @@ export class AtelierAPI { name: string, scope: vscode.Uri | string, mtime?: number, - storageOnly: boolean = false + storageOnly = false, + forceBinary = false ): Promise> { - let params, headers; + const params: Record = {}; + let headers: any; name = this.transformNameIfCsp(name); if ( this.config.apiVersion >= 4 && @@ -663,13 +665,10 @@ export class AtelierAPI { ) .get("multilineMethodArgs") ) { - params = { format: "udl-multiline" }; - } else { - params = {}; - } - if (storageOnly) { - params["storageOnly"] = "1"; + params.format = "udl-multiline"; } + if (storageOnly) params.storageOnly = "1"; + if (forceBinary) params.binary = "1"; if (mtime && mtime > 0) { headers = { "IF-NONE-MATCH": new Date(mtime).toISOString().replace(/T|Z/g, " ").trim() }; } diff --git a/src/providers/FileSystemProvider/FileSystemProvider.ts b/src/providers/FileSystemProvider/FileSystemProvider.ts index 709d03f4..aeee83ce 100644 --- a/src/providers/FileSystemProvider/FileSystemProvider.ts +++ b/src/providers/FileSystemProvider/FileSystemProvider.ts @@ -1,6 +1,5 @@ import * as path from "path"; import * as vscode from "vscode"; -import { isText } from "istextorbinary"; import { AtelierAPI } from "../../api"; import { fireOtherStudioAction, OtherStudioAction } from "../../commands/studio"; import { isfsConfig, projectContentsFromUri, studioOpenDialogFromURI } from "../../utils/FileProviderUtil"; @@ -541,15 +540,16 @@ export class FileSystemProvider implements vscode.FileSystemProvider { .then( async (entry: File) => { const contentBuffer = Buffer.from(content); - const putContent = isText(uri.path.split("/").pop(), contentBuffer) - ? { - content: new TextDecoder().decode(content).split(/\r?\n/), - enc: false, - } - : { - content: base64EncodeContent(contentBuffer), - enc: true, - }; + const putContent = + !csp // Web app files must always be written as raw bytes + ? { + content: new TextDecoder().decode(content).split(/\r?\n/), + enc: false, + } + : { + content: base64EncodeContent(contentBuffer), + enc: true, + }; if (!csp && ["cls", "mac", "int", "inc"].includes(fileExt)) { const curFile = currentFileFromContent(uri, putContent.enc ? contentBuffer : putContent.content.join("\n")); if (!curFile) { @@ -579,15 +579,6 @@ export class FileSystemProvider implements vscode.FileSystemProvider { update = true; } } - if ( - csp && - !putContent.enc && - putContent.content.length > 1 && - putContent.content[putContent.content.length - 1] == "" - ) { - // Avoid appending a blank line on every save, which would cause a web app file to grow each time - putContent.content.pop(); - } // By the time we get here VS Code's built-in conflict resolution mechanism will already have interacted with the user. // Therefore, it's safe to ignore any conflicts. return api @@ -1075,7 +1066,7 @@ export class FileSystemProvider implements vscode.FileSystemProvider { const fileName = isfsDocumentName(uri, csp); const api = new AtelierAPI(uri); return api - .getDoc(fileName, uri, cachedFile?.mtime) + .getDoc(fileName, uri, cachedFile?.mtime, undefined, csp) // Web app files must always be read as raw bytes .then((data) => data.result) .then( ({ ts, content }) => From 1c76568987cd117992f997cf70cf0a2f1f2a22b1 Mon Sep 17 00:00:00 2001 From: Brett Saviano Date: Tue, 4 Aug 2026 11:42:05 -0400 Subject: [PATCH 2/3] Update FileSystemProvider.ts --- .../FileSystemProvider/FileSystemProvider.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/providers/FileSystemProvider/FileSystemProvider.ts b/src/providers/FileSystemProvider/FileSystemProvider.ts index aeee83ce..30e3b518 100644 --- a/src/providers/FileSystemProvider/FileSystemProvider.ts +++ b/src/providers/FileSystemProvider/FileSystemProvider.ts @@ -540,16 +540,15 @@ export class FileSystemProvider implements vscode.FileSystemProvider { .then( async (entry: File) => { const contentBuffer = Buffer.from(content); - const putContent = - !csp // Web app files must always be written as raw bytes - ? { - content: new TextDecoder().decode(content).split(/\r?\n/), - enc: false, - } - : { - content: base64EncodeContent(contentBuffer), - enc: true, - }; + const putContent = !csp // Web app files must always be written as raw bytes + ? { + content: new TextDecoder().decode(content).split(/\r?\n/), + enc: false, + } + : { + content: base64EncodeContent(contentBuffer), + enc: true, + }; if (!csp && ["cls", "mac", "int", "inc"].includes(fileExt)) { const curFile = currentFileFromContent(uri, putContent.enc ? contentBuffer : putContent.content.join("\n")); if (!curFile) { From 63b6ed85171783b84efc4ef5a51d53f9230693ec Mon Sep 17 00:00:00 2001 From: Brett Saviano Date: Tue, 4 Aug 2026 13:01:55 -0400 Subject: [PATCH 3/3] KC's feedback --- src/api/index.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/api/index.ts b/src/api/index.ts index d39d9f58..2d0763e6 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -651,7 +651,6 @@ export class AtelierAPI { forceBinary = false ): Promise> { const params: Record = {}; - let headers: any; name = this.transformNameIfCsp(name); if ( this.config.apiVersion >= 4 && @@ -669,10 +668,15 @@ export class AtelierAPI { } if (storageOnly) params.storageOnly = "1"; if (forceBinary) params.binary = "1"; - if (mtime && mtime > 0) { - headers = { "IF-NONE-MATCH": new Date(mtime).toISOString().replace(/T|Z/g, " ").trim() }; - } - return this.request(1, "GET", `${this.ns}/doc/${name}`, null, params, headers); + return this.request( + 1, + "GET", + `${this.ns}/doc/${name}`, + null, + params, + // headers + mtime && mtime > 0 ? { "IF-NONE-MATCH": new Date(mtime).toISOString().replace(/T|Z/g, " ").trim() } : undefined + ); } // api v1+