SNJS is a client-side JavaScript library for Standard Notes that contains shared logic for all Standard Notes clients.
SNJS (Standard Notes JavaScript) is a shared library we use in all Standard Notes clients (desktop, web, and mobile React Native). Its role is essentially to extract any business or data logic from client code, so that clients are mostly responsible for UI-level code, and don’t have to think about encryption and key stretching, or even authentication or storage specifics. Extracting the code into a shared library also prevents us from having to write the same critical code on multiple platforms.
The entry point of SNJS is the SNApplication
class. The application class is a complete unit of application functionality. Theoretically, many instances of an application can be created, each with its own storage namespace and memory state. This can allow clients to support multiple user accounts.
An application must be supplied a custom subclass of DeviceInterface. This allows the library to generalize all behavior a client will need to perform throughout normal client operation, such as saving data to a local database store, saving key/values, and accessing the keychain.
The application interacts with a variety of services and managers to facilitate complete client functionality. While the distinction is not fully technical, a service can be thought of as a class that allows consumers to perform actions on demand, while a manager is responsible for managing and reacting to application state (but also expose on-demand functions). All managers and services live in lib/services
.
On Web platforms SNJS interacts with sncrypto
to perform operations as mentioned in the specification document. This includes operations like key generation and data encryption.
SNJS also interacts with a Standard Notes syncing-server, which is dumb data and sync store that deals with encrypted data, and never learns of client secrets or sensitive information.
npm install snjs
import { SNApplication } from 'snjs';
<script src="snjs.js"></script>
Object.assign(window, SNLibrary);
Note: the below usage examples have not kept up to date with library API changes. It is recommended to examine the source code for these functions for exact usage.
- Initialize an application:
const deviceInterface = new DeviceInterfaceSubclass();
const alertService = new SNAlertServiceSubclass();
const app = new SNApplication(
Environment.Web,
Platform.LinuxWeb,
deviceInterface,
new SNWebCrypto(),
alertService,
);
- Launch the application:
await app.prepareForLaunch({
receiveChallenge: (challenge, orchestrator) => {
}
});
await app.launch();
Once the app is launched, you may perform any app-related functions, including:
app.signIn(
email,
password
).then((response) => {
});
app.register(
email,
password
).then((response) => {
});
app.setPasscode(somePasscode).then(() => {
});
const item = await app.createManagedItem(
ContentType.Note,
{
title: 'Ideas',
text: 'Coming soon.'
}
);
/** Save the item both locally and sync with server */
await app.saveItem(item.uuid);
app.streamItems(
contentType: ContentType.Note,
(notes) => {
reloadUI(notes);
}
);
yarn install --pure-lockfile
yarn start
to start Webpack in development mode (watches changes), oryarn build
to create dist files.
Please make sure you have Docker and Docker Compose installed before running tests.
From the root of the repository, run:
# Starts browser-navigable web page
yarn run start:test-server:dev
# Starts backend servers
yarn run test:e2e:dev-setup
Then choose between the following run options:
-
Run tests in the command line:
yarn run test:e2e:dev
-
Run tests in the browser: Open
http://localhost:9002/packages/snjs/mocha/test.html
.
From the root of the repository, run:
yarn run test:unit
- Almost all functions are asynchronous and return promises. You can read about promises here.
Join the #dev channel in our Slack group for help and discussion.