Help us shape the future of Go! Take the 2026 Go Developer Survey

filestore

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package filestore reads and writes the app's file stores. The runner keeps the files; a store holds only this app's files, and no name can leave it.

The permission list declares each store as a data source named filestore:<name>:

data:
  - source: filestore:invoices
    classes: [internal]

Open returns the store as a Store, which is an fs.FS, so fs.ReadFile and fs.WalkDir work with it. Store.WriteFile and Store.Create write a file, which appears, whole, only when the write succeeds; Store.Mkdir, Store.Remove and Store.Rename change folders and names.

Rules:

  • Open each store once, in OnStart, and share it with the pages through the app's deps package.
  • Names are slash-separated paths inside the store, such as 2026/42.pdf, with no leading slash, no . or .. parts and no control characters, of at most 1024 bytes, each part of at most 255 bytes (E-FILE-001).
  • A file is at most 1 GiB (E-FILE-002).

Read more in the guide docs/guides/file-stores.md and the task docs/tasks/upload-a-file.md, which aicoded explain and the MCP tool howto print as guides/file-stores and tasks/upload-a-file.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is one file store. It is an fs.FS, so it works with fs.ReadFile, fs.WalkDir, fs.Glob and template.ParseFS.

func Open

func Open(ctx context.Context, name string) (*Store, error)

Open returns the store name. Its operations keep the values of ctx but not its cancellation, so a store opened at start-up serves every request. Open fails with E-MAN-011 when aicoded.yaml does not declare filestore:<name>.

Example

Open a store once, in OnStart, and keep it in the app's deps for every page. A store is an fs.FS.

package main

import (
	"context"
	"fmt"
	"io/fs"

	"aicoded.dev/framework/filestore"
)

var invoices *filestore.Store

func main() {
	onStart := func(ctx context.Context) error {
		var err error
		invoices, err = filestore.Open(ctx, "invoices") // filestore:invoices in the permission list
		if err != nil {
			return err
		}
		files := 0
		err = fs.WalkDir(invoices, ".", func(_ string, d fs.DirEntry, err error) error {
			if err == nil && !d.IsDir() {
				files++
			}
			return err
		})
		if err != nil {
			return err
		}
		fmt.Println(files, "invoices")
		return nil
	}
	_ = onStart
}

func (*Store) Create

func (s *Store) Create(name string) (io.WriteCloser, error)

Create starts writing the file name. The file replaces any file of that name when Close succeeds; until then, and after a failed Close, the store is unchanged. Always call Close. The folder of name must exist.

func (*Store) Mkdir

func (s *Store) Mkdir(name string) error

Mkdir creates the folder name and any missing parents.

func (*Store) Open

func (s *Store) Open(name string) (fs.File, error)

Open opens the file or folder name for reading.

func (*Store) ReadDir

func (s *Store) ReadDir(name string) ([]fs.DirEntry, error)

ReadDir returns the folder's entries sorted by name.

func (*Store) ReadFile

func (s *Store) ReadFile(name string) ([]byte, error)

ReadFile returns the whole file.

func (*Store) Remove

func (s *Store) Remove(name string) error

Remove removes the file or empty folder name.

func (*Store) Rename

func (s *Store) Rename(oldName, newName string) error

Rename moves oldName to newName, replacing a file of that name. A folder at newName is never replaced.

func (*Store) Stat

func (s *Store) Stat(name string) (fs.FileInfo, error)

Stat returns the file's information.

func (*Store) WriteFile

func (s *Store) WriteFile(name string, data []byte) error

WriteFile writes data as the file name, replacing any file of that name.

Example

WriteFile stores an uploaded file, here in a form's Process hook, under a name the app chooses. The file appears, whole, only when the write succeeds, and replaces a file of that name. Check the upload's name, size and content first, as the guide guides/forms says.

package main

import (
	"io"

	"aicoded.dev/framework/filestore"
	"aicoded.dev/framework/web/form"
)

var invoices *filestore.Store // the store Open returned in OnStart

func main() {
	process := func(upload *form.FileHeader) error {
		f, err := upload.Open()
		if err != nil {
			return err
		}
		defer f.Close()
		data, err := io.ReadAll(f)
		if err != nil {
			return err
		}
		if err := invoices.Mkdir("2026"); err != nil {
			return err
		}
		return invoices.WriteFile("2026/42.pdf", data)
	}
	_ = process
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL