How to serve file to a user?

So currently I’m trying to do it like this:

import {storage} from "uxp";

export const exportFile = async () => {
    try {
        const [file] = await storage.localFileSystem.getFileForSaving({types: ["ext"]})

        console.log(file)

        await file.write("Some data");
    } catch (e) {
        // console.warn(e)
    }
}

I get nothing - file selection window does not open, console.log() does not happen.
Although breakpoint on const [file] = ... gets triggered, but after that - nothing.

What am I doing wrong? Documentation is pretty much useless at that point

OK, so uncommented console.warn() and the error is:

TypeError: Invalid attempt to destructure non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.

What does that mean?

So here’s the exact copy of the example from the docs

const [file] = await fs.getFileForSaving({ types = [ "txt" ]});
if (!file) {
    // no file selected, or the user didn't want to overwrite one they did select
    return;
}
await file.write("It was a dark and stormy night");

I noticed the { types = [ "txt" ]} part and changed it right away to {types: ["txt"]} (because that = is total BS). Then tried to remove it completely, but had same error.
Apparently the issue was [file] = ... part :man_facepalming: It has to be just file = ... without any destructuring. But still I have another issue now:

import {storage} from "uxp";

export const exportFile = async () => {
    try {
        const file = await storage.localFileSystem.getFileForSaving({types: ["ext"]})

        console.log(file)

        await file.write("Some data");
    } catch (e) {
        console.warn(e)
    }
}

On the console.warn(e) part I get:

TypeError: e.lastIndexOf is not a function

What’s happening there? :frowning:

Not quite sure why the docs suggest using array structuring there in the first place, but since getFileForSaving can return either a File or null, the first error comes from the potential null value.
[foo] = bar essentially means foo = bar[0] but if bar is not iterable you’ll get that first error.

Yep, the docs still need updates, they’re aware of that though.

Does your code jump straight to the catch block or does the file still get logged?

Straight to catch() - no log and no dialog to choose a file

try const [file] = await storage.localFileSystem.getFileForSaving("filename.ext",{types: ["ext"]})

1 Like

Adding file name as first parameter worked perfectly. Thank you
Still no need to de-structure though. Next comment by Peter explains it’s not needed if single file is allowed to be selected

Wonder though if it’s not going to change at some point. Very difficult to develop when docs don’t match at all with what actually needs to be done

It also just makes no sense to destructure there, so I’m sure the code will remain fine.
Even if a function would have return type File | File[] it would be better to first assign it to a variable and then check for its type like const file = Array.isArray(fileOrFiles) ? fileOrFiles[0] : fileOrFiles
Just blindly destructuring is just asking for problems :smiley: