[v3] Built-in service standardisation and enhancement #4050
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
Requires #4045
TODO: update docs
NOTE: this is a synthetic set of commits on top of
v3-alpha
to facilitate reviews and discussion. The new implementation is built on top of #4045. Clonefbbdev/wails:v3-alpha-feature/service-api
for local testing.This PR drafts some changes meant to standardise and enhance the API of built-in services (fileserver, kvstore, log, sqlite), partly along the lines of the discussions that took place on Discord here and here.
The new API is mostly compatible with the existing one, but has some minor breaking changes.
All services now adhere to the following conventions:
Service
for consistent JS imports (fileserver and sqlite used this convention already).New()
function initialises the service with a sane default configuration (breaking).NewWithConfig(config *Config)
allows consumers to provide a custom initial configuration.Service.Configure(config *Config)
allows late configuration and dynamic reconfiguration.Service.Configure
is never exposed to the frontend, because it could allow arbitrary accesses to the filesystem.fileserver
nil
config => no root specified) responds to all requests with 503 Service Unavailable.kvstore
nil
config => no filename specified) provides an in-memory store.Load
andSave
methods have no effect.Service.Load()
replaces the current content of the store with those of the associated file.Service.Save()
writes the current content of the store to the associated file.Service.Clear()
empties the store.On-disk stores are always loaded at startup and saved at shutdown. A clarifying comment has been added to the
AutoSave
option.What if one wishes to load from disk, but then keep in-memory only or write to another file? There you go:
Notice how
Service.Configure
changes the configuration but does not alter the state otherwise, i.e. all data is kept, no automatic loads or saves are performed.log
nil
) writes toapplication.DefaultLogger(slog.LevelInfo)
log.Level
publishes Debug/Info/Warning/Error constants to JSService.Log(ctx context.Context, level Level, message string, args ...any)
logs with dynamic level. When called from JS, it receives the binding call context that links to the source window. Custom handlers may access this value.Service.DebugContext
,Service.InfoContext
etc., matching theslog
API, accept a context; they are exported to js asDebug
,Info
etc and receive the binding call context.The logger implements the
slog.Leveler
interface to provide dynamic level configuration to custom handlers. See doc comment of theService.Level
method for an example.sqlite
nil
) creates an in-memory database.Service.Configure
method changes the configuration but does not close or reopen the DB.Service.Open()
opens (if closed) or reopens the DB, applying the latest configuration.Service.Close()
closes the DB if open; has no effect if closed.Service.Select(...)
renamed toService.Query(...)
for consistency withsql.DB
.Service.ExecContext(...)
andService.QueryContext(...)
accept a context for cancellation support. These are exported to JS asExec
andQuery
, hence cancellation is always supported from JS.Service.Prepare(query string)
(cancelable versionService.PrepareContext
) creates prepared statements.Normally statements must be closed manually, but they are closed automatically upon calling
Service.Close()
. Unlike regularsql.Stmt
s, theirClose
method is idempotent.Advanced binding generator features are used to bring prepared statements to the JS side!
Type of change
How Has This Been Tested?
Ran the services example and verified everything's working fine.
Test Configuration
Checklist:
website/src/pages/changelog.mdx
with details of this PR