nupp.io.files

Portable filesystem access accepts native paths on native hosts and application-owned paths on browser hosts. Set an application identity before resolving the portable configuration, data, or cache directory.

local files = nupp.io.files
files.setApplicationIdentity("example", "notes")

local data = assert(files.dataPath())
assert(files.write(data:join("notes.txt"), "hello"))

Native programs may also pass ordinary strings or nupp.io.path.Path values. Browser programs refuse raw path text and use the opaque ApplicationPath values returned by configurationPath, dataPath, or cachePath.

Browser application data lives in the Origin Private File System. It remains evictable unless requestPersistentStorage succeeds. Capability flags describe the operations whose native semantics have no browser equivalent.

Submodules

ModuleDescription
nupp.io.files.messages

Module contents

Types

TypeKindDescription
ApplicationPathinterfaceAn opaque portable path rooted in this application's platform storage.
CapabilitiesrecordThe exact filesystem guarantees supplied by the selected provider.
EntryrecordAn immediate child returned by a directory listing.
FileinterfaceAn affine open file, which is itself a reader and a writer over its one cursor.
InforecordMetadata about one filesystem object.
KindtypeThe kind of filesystem object described by metadata or a directory entry.
ModetypeA file open mode: read, write, append, or an updating variant.
OrigintypeThe base used by a file seek.
PathtypeA native path or an opaque application-owned path.
TemporaryOptionsrecordNaming and placement options for a native temporary path.
TemporaryPathinterfaceA native temporary path removed when its owner closes unless persisted.
UserFoldertypeA portable name for a conventional user directory.

Functions

FunctionKindDescription
appendfunctionAppends bytes to a file, creating it when absent.
applicationIdentityfunctionReturns the selected application identity, or nil values before one is set.
cachePathfunctionResolves and creates this application's platform cache directory.
configurationPathfunctionResolves and creates this application's platform configuration directory.
copyfunctionCopies a file over another.
createDirectoryfunctionCreates a directory and all missing parents.
createSymlinkfunctionCreates a symbolic link when the provider supports one.
createTemporaryDirectoryfunctionCreates a native temporary directory owner when the provider supports one.
createTemporaryFilefunctionCreates a native temporary file owner when the provider supports one.
dataPathfunctionResolves and creates this application's platform data directory.
executableDirectoryfunctionReturns the native running executable's directory.
existsfunctionReports whether a path resolves.
globfunctionExpands a native filesystem glob.
infofunctionDescribes the filesystem object at a path.
isDirectoryfunctionReports whether a path resolves to a directory.
isFilefunctionReports whether a path resolves to a file.
isSymlinkfunctionReports whether a path itself is a symbolic link.
linesfunctionOpens a file as a line reader, which takes the file and closes it with itself.
listfunctionLists a directory's immediate children.
openfunctionOpens a file in one of the six standard read, write, append, or update modes.
readfunctionReads an entire file as bytes.
readLinkfunctionReads a symbolic link target without resolving it.
removefunctionRemoves a file, link, or directory.
renamefunctionRenames a path, replacing an existing destination when supported.
requestPersistentStoragefunctionRequests non-evictable browser storage; native providers succeed without work.
setApplicationIdentityfunctionSelects the identity used to resolve configuration, data, and cache roots.
setReadOnlyfunctionSets or clears a path's native read-only attribute.
userFolderfunctionResolves a conventional native user folder.
writefunctionReplaces a file with the supplied bytes.
writeAtomicfunctionAtomically replaces a file when the provider supports it.

Values

ValueKindDescription
capabilitiesvariableReports the exact guarantees of the selected filesystem provider.
pendingTransfersvariableReports whole-file transfers that have not settled.

Types#

ApplicationPathinterface#

sealed interface ApplicationPath ...

An opaque portable path rooted in this application's platform storage.

Members

NameKindDescription
joinmethodAppends portable path components without allowing an escape from the root.
toStringmethodReturns a display or native-interoperability form that does not retain authority.

joinmethod#

join: function(self, ...: string): ApplicationPath

Appends portable path components without allowing an escape from the root.

Arguments
NameTypeDescription
?self
...string
Returns
TypeDescription
ApplicationPath

toStringmethod#

toString: function(self): string

Returns a display or native-interoperability form that does not retain authority.

Arguments
NameTypeDescription
?self
Returns
TypeDescription
string

Capabilitiesrecord#

record Capabilities ...

The exact filesystem guarantees supplied by the selected provider.

Members

NameKindDescription
availablefieldWhether filesystem access is available at all.
arbitraryPathsfieldWhether ordinary native paths are accepted.
symbolicLinksfieldWhether symbolic links can be queried and created.
readOnlyAttributesfieldWhether read-only attributes can be changed.
globfieldWhether filesystem globbing is supported.
renamefieldWhether paths can be renamed.
atomicWritefieldWhether atomic replacement writes are supported.
temporaryPathsfieldWhether temporary path owners can be created.
concurrentOpenHandlesfieldWhether a
currentDirectoryfieldWhether a process working directory exists.
userFoldersfieldWhether conventional user folders can be resolved.
executableDirectoryfieldWhether the running executable's directory can be resolved.
persistentStorageRequestfieldWhether persistent browser storage can be requested.

availablefield#

available: boolean

Whether filesystem access is available at all.

arbitraryPathsfield#

arbitraryPaths: boolean

Whether ordinary native paths are accepted.

readOnlyAttributesfield#

readOnlyAttributes: boolean

Whether read-only attributes can be changed.

globfield#

glob: boolean

Whether filesystem globbing is supported.

renamefield#

rename: boolean

Whether paths can be renamed.

atomicWritefield#

atomicWrite: boolean

Whether atomic replacement writes are supported.

temporaryPathsfield#

temporaryPaths: boolean

Whether temporary path owners can be created.

concurrentOpenHandlesfield#

concurrentOpenHandles: boolean

Whether a

currentDirectoryfield#

Whether a process working directory exists.

userFoldersfield#

userFolders: boolean

Whether conventional user folders can be resolved.

executableDirectoryfield#

Whether the running executable's directory can be resolved.

persistentStorageRequestfield#

persistentStorageRequest: boolean

Whether persistent browser storage can be requested.

Entryrecord#

record Entry ...

An immediate child returned by a directory listing.

Members

NameKindDescription
namefieldThe child's name relative to the listed directory.
kindfieldThe child's kind without following a symbolic link.

namefield#

name: string

The child's name relative to the listed directory.

kindfield#

kind: Kind

The child's kind without following a symbolic link.

Fileinterface#

interface File is io.Reader, io.Writer ...

An affine open file, which is itself a reader and a writer over its one cursor.

Members

NameKindDescription
sizemethodReturns the file's byte length without moving its cursor.
seekmethodMoves the cursor relative to an origin and returns its new position.
positionmethodReturns the shared cursor position.
flushmethodPublishes buffered file writes, and reports a write that failed to land.
isReleasedmethodReports whether the file has already been closed.
closemethodCloses the file and spends its ownership.

sizemethod#

size: function(borrows self: File): (integer?, io.Error?)

Returns the file's byte length without moving its cursor.

Arguments
NameTypeDescription
borrows selfFile
Returns
TypeDescription
integer?
io.Error?

seekmethod#

seek: function(exclusive self: File, offset: integer?, origin: messages.Origin?): (integer?, io.Error?)

Moves the cursor relative to an origin and returns its new position.

Arguments
NameTypeDescription
exclusive selfFile
offsetinteger?
originmessages.Origin?
Returns
TypeDescription
integer?
io.Error?

positionmethod#

position: function(exclusive self: File): (integer?, io.Error?)

Returns the shared cursor position.

Arguments
NameTypeDescription
exclusive selfFile
Returns
TypeDescription
integer?
io.Error?

flushmethod#

flush: function(borrows self: File): (boolean, string?)

Publishes buffered file writes, and reports a write that failed to land.

Arguments
NameTypeDescription
borrows selfFile
Returns
TypeDescription
boolean
string?

isReleasedmethod#

isReleased: function(borrows self: File): boolean

Reports whether the file has already been closed.

Arguments
NameTypeDescription
borrows selfFile
Returns
TypeDescription
boolean

closemethod#

close: @nosuspend function(takes self: File): nil

Closes the file and spends its ownership. Repeated calls are safe.

Arguments
NameTypeDescription
takes selfFile
Returns
TypeDescription
nil

Inforecord#

record Info ...

Metadata about one filesystem object.

Members

NameKindDescription
kindfieldThe object's filesystem kind.
sizefieldIts byte size, or zero for a directory.
modifiedfieldIts modification time in milliseconds since the Unix epoch, the unit nupp.time.wallTime returns in, with whatever...
readOnlyfieldWhether the native platform refuses writes.

kindfield#

kind: Kind

The object's filesystem kind.

sizefield#

size: integer

Its byte size, or zero for a directory.

modifiedfield#

modified: number

Its modification time in milliseconds since the Unix epoch, the unit nupp.time.wallTime returns in, with whatever fraction the platform records.

readOnlyfield#

readOnly: boolean

Whether the native platform refuses writes.

Kindtype#

type Kind = "file" | "directory" | "symlink" | "other"

The kind of filesystem object described by metadata or a directory entry.

Modetype#

type Mode = "r" | "w" | "a" | "r+" | "w+" | "a+"

A file open mode: read, write, append, or an updating variant.

Origintype#

type Origin = "set" | "current" | "end"

The base used by a file seek.

Pathtype#

type Path = string | paths.Path | appPaths.ApplicationPath

A native path or an opaque application-owned path.

TemporaryOptionsrecord#

record TemporaryOptions ...

Naming and placement options for a native temporary path.

Members

NameKindDescription
directoryfieldThe native directory to create the path in.
prefixfieldA separator-free fragment placed before the random portion of the name.
suffixfieldA separator-free fragment placed after the random portion of the name.

directoryfield#

directory: (string | paths.Path)?

The native directory to create the path in.

prefixfield#

prefix: string?

A separator-free fragment placed before the random portion of the name.

suffixfield#

suffix: string?

A separator-free fragment placed after the random portion of the name.

TemporaryPathinterface#

interface TemporaryPath is nupp.Closeable ...

A native temporary path removed when its owner closes unless persisted.

Members

NameKindDescription
toStringmethodReturns the native path text.
pathmethodReturns the created path as a path value.
persistmethodMoves the temporary path to a durable destination.
isReleasedmethodReports whether the temporary owner has been closed or persisted.
closemethodRemoves the temporary path and spends its ownership.

toStringmethod#

toString: function(self: TemporaryPath): string

Returns the native path text.

Arguments
NameTypeDescription
selfTemporaryPath
Returns
TypeDescription
string

pathmethod#

path: function(self: TemporaryPath): paths.Path

Returns the created path as a path value.

Arguments
NameTypeDescription
selfTemporaryPath
Returns
TypeDescription
paths.Path

persistmethod#

persist: function(self: TemporaryPath, destination: any): (boolean, io.Error?)

Moves the temporary path to a durable destination.

Arguments
NameTypeDescription
selfTemporaryPath
destinationany
Returns
TypeDescription
boolean
io.Error?

isReleasedmethod#

isReleased: function(self: TemporaryPath): boolean

Reports whether the temporary owner has been closed or persisted.

Arguments
NameTypeDescription
selfTemporaryPath
Returns
TypeDescription
boolean

closemethod#

close: @nosuspend function(takes self: TemporaryPath): nil

Removes the temporary path and spends its ownership. Repeated calls, and a call after persist, are safe and do nothing.

Arguments
NameTypeDescription
takes selfTemporaryPath
Returns
TypeDescription
nil

UserFoldertype#

type UserFolder = "home" | "documents" | "downloads" | "desktop" | "pictures" | "music" | "videos"

A portable name for a conventional user directory.

Functions#

appendfunction#

function append(path: Path, borrows bytes: string | io.ByteView): boolean, io.Error?

Appends bytes to a file, creating it when absent.

Arguments

NameTypeDescription
pathPath

the file to append to

borrows bytesstring | io.ByteView

the byte string or view to append

Returns

TypeDescription
boolean

whether the bytes were written

io.Error?

a failure reason, when unsuccessful

applicationIdentityfunction#

function applicationIdentity(): string?, string?

Returns the selected application identity, or nil values before one is set.

Returns

TypeDescription
string?

the organization component

string?

the application component

cachePathfunction#

function cachePath(): appPaths.ApplicationPath?, io.Error?

Resolves and creates this application's platform cache directory.

Returns

TypeDescription
appPaths.ApplicationPath?

the cache path, or nil on failure

io.Error?

a failure reason, when unsuccessful

configurationPathfunction#

function configurationPath(): appPaths.ApplicationPath?, io.Error?

Resolves and creates this application's platform configuration directory.

Configuration, data and cache are always three distinct directories, so clearing one with a recursive remove never reaches another.

Returns

TypeDescription
appPaths.ApplicationPath?

the configuration path, or nil on failure

io.Error?

a failure reason, when unsuccessful

copyfunction#

function copy(from: Path, to: Path): boolean, io.Error?

Copies a file over another.

Arguments

NameTypeDescription
fromPath

the source file

toPath

the destination file

Returns

TypeDescription
boolean

whether the file was copied

io.Error?

a failure reason, when unsuccessful

createDirectoryfunction#

function createDirectory(path: Path): boolean, io.Error?

Creates a directory and all missing parents.

Arguments

NameTypeDescription
pathPath

the directory to create

Returns

TypeDescription
boolean

whether the directory exists afterward

io.Error?

a failure reason, when unsuccessful

createTemporaryDirectoryfunction#

function createTemporaryDirectory(options: messages.TemporaryOptions?): affine(contracts.TemporaryPath?), io.Error?

Creates a native temporary directory owner when the provider supports one.

Arguments

NameTypeDescription
optionsmessages.TemporaryOptions?

naming and placement options

Returns

TypeDescription
affine(contracts.TemporaryPath?)

the temporary path owner, or nil on failure

io.Error?

a failure reason, when unsuccessful

createTemporaryFilefunction#

function createTemporaryFile(options: messages.TemporaryOptions?): affine(contracts.TemporaryPath?), io.Error?

Creates a native temporary file owner when the provider supports one.

Arguments

NameTypeDescription
optionsmessages.TemporaryOptions?

naming and placement options

Returns

TypeDescription
affine(contracts.TemporaryPath?)

the temporary path owner, or nil on failure

io.Error?

a failure reason, when unsuccessful

dataPathfunction#

function dataPath(): appPaths.ApplicationPath?, io.Error?

Resolves and creates this application's platform data directory.

Returns

TypeDescription
appPaths.ApplicationPath?

the data path, or nil on failure

io.Error?

a failure reason, when unsuccessful

executableDirectoryfunction#

function executableDirectory(): paths.Path?, io.Error?

Returns the native running executable's directory.

Returns

TypeDescription
paths.Path?

the executable directory, or nil when unavailable

io.Error?

a failure reason, when unsuccessful

existsfunction#

function exists(path: Path): boolean

Reports whether a path resolves.

Any failure reads as false, a refused permission or an I/O error as much as a missing name. Ask info when the reason matters.

Arguments

NameTypeDescription
pathPath

the path to inspect

Returns

TypeDescription
boolean

whether it exists

globfunction#

function glob(pattern: string): {paths.Path}?, io.Error?

Expands a native filesystem glob.

Arguments

NameTypeDescription
patternstring

the glob pattern

Returns

TypeDescription
{paths.Path}?

sorted matching paths, or nil on failure

io.Error?

a failure reason, when unsuccessful

infofunction#

function info(path: Path): messages.Info?, io.Error?

Describes the filesystem object at a path.

Arguments

NameTypeDescription
pathPath

the path to inspect

Returns

TypeDescription
messages.Info?

its metadata, or nil on failure

io.Error?

a failure reason, when unsuccessful

isDirectoryfunction#

function isDirectory(path: Path): boolean

Reports whether a path resolves to a directory.

Any failure reads as false; ask info when the reason matters.

Arguments

NameTypeDescription
pathPath

the path to inspect

Returns

TypeDescription
boolean

whether it is a directory

isFilefunction#

function isFile(path: Path): boolean

Reports whether a path resolves to a file.

Any failure reads as false; ask info when the reason matters.

Arguments

NameTypeDescription
pathPath

the path to inspect

Returns

TypeDescription
boolean

whether it is a file

linesfunction#

function lines(path: Path, limit: integer?): affine(io.Lines)?, io.Error?

Opens a file as a line reader, which takes the file and closes it with itself.

A line is read without its terminator, \n or \r\n. A read that fails partway through returns nil and the reason from Lines:read, which is what tells it apart from the end of the file, where the reason is nil.

local log = assert(nupp.io.files.lines("access.log"))
while true do
    local line, reason = log:read()
    if line == nil then
        assert(reason == nil, reason)
        break
    end
    print(line)
end

Arguments

NameTypeDescription
pathPath

the file to read

limitinteger?

the most bytes one line may hold, or 65536

Returns

TypeDescription
affine(io.Lines)?

the line reader, or nil when the file cannot be opened

io.Error?

a failure reason, when unsuccessful

Raises

TypeCondition
string

when limit is not a positive integer

listfunction#

function list(path: Path): {messages.Entry}?, io.Error?

Lists a directory's immediate children.

Arguments

NameTypeDescription
pathPath

the directory to list

Returns

TypeDescription
{messages.Entry}?

its entries, or nil on failure

io.Error?

a failure reason, when unsuccessful

openfunction#

function open(path: Path, mode: messages.Mode?): affine(contracts.File?), io.Error?

Opens a file in one of the six standard read, write, append, or update modes.

Arguments

NameTypeDescription
pathPath

the native path or browser application path to open

modemessages.Mode?

the access mode, defaulting to read

Returns

TypeDescription
affine(contracts.File?)

the open file owner, or nil on failure

io.Error?

a failure reason, when unsuccessful

readfunction#

function read(path: Path): string?, io.Error?

Reads an entire file as bytes.

Arguments

NameTypeDescription
pathPath

the file to read

Returns

TypeDescription
string?

its bytes, or nil on failure

io.Error?

a failure reason, when unsuccessful

removefunction#

function remove(path: Path, recursive: boolean?): boolean, io.Error?

Removes a file, link, or directory.

Arguments

NameTypeDescription
pathPath

the path to remove

recursiveboolean?

whether to remove a directory's contents

Returns

TypeDescription
boolean

whether the path was removed

io.Error?

a failure reason, when unsuccessful

renamefunction#

function rename(from: Path, to: Path): boolean, io.Error?

Renames a path, replacing an existing destination when supported.

Arguments

NameTypeDescription
fromPath

the source path

toPath

the destination path

Returns

TypeDescription
boolean

whether the path was renamed

io.Error?

a failure reason, when unsuccessful

requestPersistentStoragefunction#

function requestPersistentStorage(): boolean, io.Error?

Requests non-evictable browser storage; native providers succeed without work.

Returns

TypeDescription
boolean

whether persistence is guaranteed

io.Error?

a failure reason, when unsuccessful

setApplicationIdentityfunction#

function setApplicationIdentity(newOrganization: string, newApplication: string): nil

Selects the identity used to resolve configuration, data, and cache roots.

Arguments

NameTypeDescription
newOrganizationstring

the organization component

newApplicationstring

the application component

Returns

TypeDescription
nil

nil after selecting the identity

setReadOnlyfunction#

function setReadOnly(path: Path, readOnly: boolean): boolean, io.Error?

Sets or clears a path's native read-only attribute.

Arguments

NameTypeDescription
pathPath

the path to change

readOnlyboolean

whether writes should be refused

Returns

TypeDescription
boolean

whether the attribute was changed

io.Error?

a failure reason, when unsuccessful

userFolderfunction#

function userFolder(which: messages.UserFolder): paths.Path?, io.Error?

Resolves a conventional native user folder.

Arguments

NameTypeDescription
whichmessages.UserFolder

the folder to resolve

Returns

TypeDescription
paths.Path?

its native path, or nil when unavailable

io.Error?

a failure reason, when unsuccessful

writefunction#

function write(path: Path, borrows bytes: string | io.ByteView): boolean, io.Error?

Replaces a file with the supplied bytes.

Arguments

NameTypeDescription
pathPath

the file to write

borrows bytesstring | io.ByteView

the byte string or view to write

Returns

TypeDescription
boolean

whether the bytes were written

io.Error?

a failure reason, when unsuccessful

writeAtomicfunction#

function writeAtomic(path: Path, borrows bytes: string | io.ByteView): boolean, io.Error?

Atomically replaces a file when the provider supports it.

Arguments

NameTypeDescription
pathPath

the destination file

borrows bytesstring | io.ByteView

the byte string or view to write

Returns

TypeDescription
boolean

whether the file was replaced

io.Error?

a failure reason, when unsuccessful

Values#

capabilitiesvariable#

Reports the exact guarantees of the selected filesystem provider.

pendingTransfersvariable#

Reports whole-file transfers that have not settled.