Framework
Unreleased
v5.4.0
API: resources
- Implement
getFiles()
,extractFile(path, dest)
,readFile(path)
, andreadBinaryFile(path)
functions via theresources
module for reading the files embedded in theresources.neu
resources bundle. These functions works only if the framework loaded resources from the resource bundle -- they will throwNE_RS_APIRQRF
if the framework loaded resources from the resources directory.
API: window
- Implement
minimize()
,unminimize()
, andisMinimized()
functions to minimize and restore the native app window.
Improvements/bugfixes
- Fix issues with the
clipboard.writeImage()
function on Windows. - Fix the unwanted delay with the
window.exitProcessOnClose
configuration option on Windows. - Fix a bug with the
window.isFullScreen()
function on GNU/Linux-based platforms. - Fix duplicate virtual PID issues with the
os.spawnProcess()
function.
v5.3.0
Configuration: window transparency on Windows
Window transparency support was added on the Windows version of the Neutralinojs framework. This can be activated with modes.window.transparent
configuration property or --window-transparent
command-line option. Unlike in other platforms, Windows native window becomes borderless (window controls will be hidden) with the activation of the transparent mode.
API: os
- Add the
temp
key for the supported directory list of theos.getPath(pathKey)
function.
API: filesystem
- Add the
filesystem.getAbsolutePath(path)
function to let developers get a full path string from a relative path string. - Add the
filesystem.getRelativePath(path, ?base)
function to get a relative path from a path and a base path. - Add the
filesystem.getPathParts(path)
to parse and get path segments like filename, extension, root path, etc.
Improvements/bugfixes
- Fix Unicode issues in the Windows version with filesystem, storage, and general modules.
- Fix standard output/error data display issues on Windows
v5.2.0
Configuration: Configless framework initialization
Now, developers can load the Neutralinojs framework without creating a neutralino.config.json
file. Now, there is no mandatory configuration properties since Neutralinojs set reasonable defaults. Developers can launch the framework using the following methods without a configuration file:
# Loading a remote URL
./framework-bin --url=https://neutralino.js.org/docs
# Launches a local static web app
./framework-bin --url="/resources/" --window-title="My web app" --enable-server
Configuration
- New internal CLI arguments added:
--single-page-serve
,--enable-native-api
and--document-root=<string>
Core: Static server SPA (Single Page App) serving
Earlier, Neutralinojs app developers had to use hash routing with their frontend-library-based apps since the internal static server didn't offer an inbuilt URL rewrite logic for SPAs (Single Page Apps). Now, they can use the singlePageServe: true
option in the app configuration file to activate SPA routing. If this setting is on, the static server will serve the main index.html
file when it receives directory requests that possibly send HTTP 404
status.
For example, the /invoices
path serves the main index.html
file if there is no directory named invoices
which holds an index.html
file.
API: window
- Improve the behaviour of the
window.show()
function on Windows. Now, this function flashes the window if it's already in foreground and activates the window properly if it's minimized.
Improvements/bugfixes
- Fix path issues with the
defaultPath
option in system file dialogs on Windows.
v5.1.0
Configuration: window transparency
Neutralinojs offers the inbuilt borderless mode and draggable region API to create custom window frames using HTML and CSS. Earlier, Neutralinojs used a default opaque color (usually white) for the window and webview layer, so app developers couldn't make custom CSS-styled window frames transparent or implement custom window frame shapes (i.e., rounded edges). Now, it offers the window.transparent
boolean flag to activate window transparency.
If the transparency mode is on, the Neutralinojs window and webview use an alpha color layer and become transparent, so developers can use the rgba
CSS color function on body
background to handle the transparency level of the app.
The transparency mode can be activated using the --window-transparent=<bool>
internal command-line option too.
Note: This feature is not implemented for the Windows operating system yet.
API: clipboard
- Implement
clipboard.readImage()
andclipboard.writeImage(image)
functions to work with clipboard image data. - Expose the
clipboard.clear()
function to clear system clipboard. - Expose the
clipboard.getFormat()
function to check the system clipboard data format. This function returnstext
,image
, andunknown
enum values based on existing data on the clipboard.
v5.0.0
API: Reading, writing with standard streams
- Implement
app.readProcessInput(readAll=false)
for reading string data from the standard input stream. This function can read a single line or multiple lines at once. - Implement
app.writeProcessOutput
andapp.writeProcessError
for sending string data to standard output and error streams accordingly.
API: filesystem
- Enable default recursive behavior in the
filesystem.createDirectory
function. - Add
filesystem.copy
,filesystem.move
, andfilesystem.remove
functions. - Add
{recursive}
options object tofilesystem.readDirectory(path, options)
activate recursive directory listing.
API: os
- Accept stdin with the background mode of the
os.execCommand
function.
Core: security
- Now, all app clients and extensions require a valid connect token (A part of the
NL_TOKEN
) to connect to the Neutralinojs framework WebSocket server to receive app events. - The framework now sends the access token, connect token, port, and extension identifier to extension processes via the standard input, so other processes can't read them by scanning the process list.
- The WebSocket client connection origin is checked during the HTTP/WS handshake to make sure that only local clients connect with a specific Neutralinojs app that runs on window, browser, or Chrome mode. Any URL origin is allowed for the cloud mode.
- The above security enhancements fix two security advisories on GitHub.
Global variables
- Now the
NL_ARCH
global variable returns the same value thatcomputer.getArch
returns.
Deprecations
- Removed
filesystem.removeFile
,filesystem.removeDirectory
,filesystem.copyFile
, andfilesystem.moveFile
functions. - Extensions won't receive
--nl-port
,--nl-token
, and--nl-extension-id
as command-line arguments. Now the framework sends these via stdin as a JSON string.
v4.15.0
Configuration: custom user agent string
Developers sometimes use the user agent string to indentify the client in server-side and client-side source codes. Now, Neutralinojs lets app developers extend the default user agent string with a custom string via the window.extendUserAgentWith
configuration property and the --window-extend-user-agent-with=<string>
command-line option, as shown in the following example:
"window": {
// ---
"extendUserAgentWith": "MyAppClient"
}
The above configuration extends the user agent string:
console.log(navigator.userAgent) // <Default UA> MyAppClient
Configuration: custom configuration files
The Neutralinojs framework typically loads the application configuration content from the neutralino.config.json
file, but sometimes app developers need to use a custom configuration filename during development (i.e., For separating production and development environments). Now, you can use the --config-file=<filename>
internal command-line parameter to use a custom app configuration, as shown in the following example:
./myapp-linux_x64 --load-dir-res --config-file=neutralino-dev.config.json
v4.14.1
DevOps
- Use Windows 2019 server and macOS 11 (Big Sur) to compile framework release artifacts.
- Set minimum supported macOS version via
MACOSX_DEPLOYMENT_TARGET=10.7
v4.14.0
Filesystem API
- Introduce the
filesystem.getWatchers
function to get all created watchers. - Add binary file reading support for the
filesystem.updateOpenedFile(id, action, data)
function. This function implementsreadBinary
andreadAllBinary
actions anddataBinary
output action in theopenedFile
global event. - Return the existing watcher identifier from
filesystem.createWatcher
if there is an existing active watcher for the given path.
OS API
- Add a way to set current working directory for process creation functions:
os.execCommand(command, options)
now supportscwd
via the options object andos.spawnProcess(command, cwd)
accepts currently working directory via the second string parameter.
Improvements/bugfixes
- Fix Unicode charactor issues in the tray menu on Windows.
- Avoid including null bytes to file reader events initiated by the
filesystem.openFile
function. - Discard
window
method executions on non-window modes.
DevOps
- Update external GitHub Action packages to their latest versions.
- Fix issues of the failing test cases
v4.13.0
Core: persistent window state
Now the framework stores the primary window state in a temporary file (JSON formatted) and loads during the startup process.
This feature stores and sets the window position (x, y coordinates), size (width and height), and maximized status. This feature is enabled by default in all platforms, but app developers can turn it off by using false
for the window.useSavedState
configuration attribute or --window-use-saved-state
internal CLI argument.
Also, the window state loading status is available via the NL_WSAVSTLOADED
global variable. The framework sets true
for this boolean variable if the window state was loaded from the saved configuration.
Improvements/bugfixes
- Fix several issues in the webview Windows code (i.e., Wait for the window close event, window style fixes, etc.).
v4.12.0
API: window
- Add
window.center
to center the application window programmatically.
Core: configuration
- Setting the initial window position via
modes.window.x
andmodes.window.y
integer config props. - Centering the window at startup via
modes.window.center
boolean config props. - Add config overrides for the startup window position:
--window-center=<true|false>
,--window-x=<int>
and--window-y=<int>
Core: webview
- Statically link the Webview2 loader library on Windows, so app developers can package their apps without including the
WebView2Loader.dll
file.
Improvements/bugfixes
- Added Unicode characters support for Neutralinojs Windows.
v4.11.0
API: File watchers
In some scenarios, Neutralinojs app developers need to implement file watchers in their apps. Earlier, Neutralinojs API didn't offer a native file watcher API and developers had to use less-performant workarounds, such as making recursive filesystem.readDirectory
calls. The new file watchers API lets you create native, cross-platform, event-based file watchers for filesystem paths with the following functions:
filesystem.createWatcher(path)
: Creates a new file watcher for a given path and returns the watcher identifier.filesystem.removeWatcher(watcherId)
: Removes a files watcher based on a file watcher identifier.
Whenever a filesystem change occurs, file watcher instances dispatch the watchFile
event with the following data:
id
: Watcher identifieraction
: Filesystem change:add
,delete
,modified
, andmoved
dir
: Directory pathfilename
: Modified file
Improvements/bugfixes
- Fix the initial window flashing and hidden window state issues on Windows.
- Fix data corruption in binary file appending.
- Apply dark/light themes based on system preferences on Windows.
v4.10.0
DevOps
- Generate official macOS
arm64
(For Apple M1 and higher devices) and universal binaries with the GitHub workflow.
Improvements/bugfixes
- Add a JSON schema definition for the
neutralino.config.json
file. - Fix source code compilation issues on macOS
arm64
systems.
ESM/NPM support
Neutralinojs typically stores the client library implementation in a separate file (neutralino.js
). This approach makes Neutralinojs app development
process easier with a globally exposed JavaScript object, Neutralino
. But, modern web developers use ES modules and they usually like to fetch dependencies from NPM. So, now, developers can load the __neutralino_globals.js
internal script (i.e., <script src="__neutralino_globals.js"></script>
) to load only globals. Then, they can use the client library implementation via neutralino.mjs
with the neu CLI or from @neutralinojs/lib
with a Node package manager.
v4.9.0
API: Custom methods
Neutralinojs offers the extensions API to write custom backend code with any programming language, but extensions come with the following drawbacks that affect apps in several scenarios:
- Extensions use a shared WebSocket for communication, so using direct C++ references (i.e., the window handler) is impossible within extensions.
- The developer is responsible for packaging their extension binaries.
- A C++-based extension is not fast as native C++-based code due to the WebSockets-based IPC.
Alternatively, a developer can download the framework C++ code, modify it, and re-compile it. But, the developer may face issues while synching upstream code modifications. So, Neutralinojs offers a separate namespace, a function template, inbuilt helper functions (i.e., to get the window handler, validation, etc.), and a developer guide to add custom APIs to the Neutralinojs framework without updating the framework core.
Example:
let res = await Neutralino.custom.fetch('https://neutralino.js.org');
If developers make a custom API that others can use, we motivate them to contribute to the Neutralinojs framework by adding it to the main codebase.
Example:
let res = await Neutralino.net.fetch('https://neutralino.js.org');
If the developer adds a new custom method to the framework, the client library will automatically export it to the Neutralino.custom
namespace by using the NL_CMETHODS
internal global variable. The Neutralino.custom.getMethods
function returns an array of custom methods similar to NL_CMETHODS
.
API: File streams
The current Neutralinojs API offers non-stream-based (Promise-based but synchronous-like) functions for working with files. For example, the filesystem.readFile
function reads the file content and retrieves data synchronously even though the WebSocket communication mechanism supports asynchronous patterns. However, the synchronous API lets developers work with files in a simple way, but they face the following issues in some scenarios:
- Reading large files is not performance-friendly (The whole file content gets loaded into the memory).
- Unable to work with dynamic file objects (i.e., Device files).
- File descriptors are not persistent within the app lifecycle as they get destroyed after native API calls.
To solve this issue, we offer an event-based file stream API with the following functions/events:
Functions
filesystem.openFile
: Creates a file stream by openning a file.filesystem.updateOpenedFile
: Triggers a fileread
/readAll
event or sets the file cursor.filesystem.getOpenedFileInfo
: Returns (awaited) information about the file stream (Props:id
,eof
,pos
, andlastRead
)
Events
openedFile
: Occurs per each file read event and whenever the file stream reachesEOF
.
v4.8.0
API: os.getEnvs
os.getEnv
returns a value for a given environment variable key. Developers had to use alternative methods to retrieve a list of all environment variables with values. The os.getEnvs
returns all environment variables as a JavaScript object similar to Node's process.env
.
API: filesystem
- Added
pos
andsize
options forreadFile
andreadBinaryFile
methods to set the file cursor position and buffer size respectively.
API: storage.getKeys
Added the storage.getKeys
function to get an array of Neutralinojs storage keys. Now, developers don't need to write their own functions to retrieve storage keys with the filesystem API.