Server API Extension
The Server API extension owns the HTTP server of a Jspreadsheet Server deployment. It exposes the REST routes for every document (data, styles, comments, headers, media and the other worksheet modules) plus history snapshots and image storage, and provides the registration points other extensions use to add their own routes.
Documentation
Install
npm install @jspreadsheet/server-api
Settings
The extension is configured by calling it as a function before the server starts:
| Property | Description |
|---|---|
s3: object |
S3 credentials (key, secret, bucket, region, url). Enables the history (snapshot) routes, the image routes and api.setImage. Without it, those routes return S3 not defined. |
Routes
Registering the extension binds an HTTP server that answers under /api. Requests carry the token in an Authorization: Bearer header and pass through your beforeConnect/beforeLoad/beforeChange hooks. The route shapes are:
| Route | Description |
|---|---|
POST /api/create |
Create a new document (guid, config in the body). |
GET /api/<guid> |
Full document configuration. |
DELETE /api/<guid> |
Destroy the document. |
GET /api/<guid>/<worksheetIndex> |
One worksheet's configuration. |
/api/<guid>/[<worksheetIndex>/]<module> |
Module routes (data, value, comments, style, header, media, ...). When the worksheet index is omitted, worksheet 0 is used. See the REST API reference. |
GET/POST/DELETE /api/<guid>/history[/<version>] |
List, create, restore and delete snapshots (S3 required, owner only). |
GET /api/<guid>/images/<filename> |
Serve an image stored through api.setImage (S3 required). |
Extension registration points
Other extensions add routes through three static methods, normally from inside their license hook (see Extensions):
| Method | Description |
|---|---|
api.setAction(fn) |
Registers global actions: fn(actions) adds handlers served at /api/<name>. |
api.setModule(fn) |
Registers document routes: fn(routers) adds handlers served at /api/<guid>/[<worksheetIndex>/]<name>, executed with the document loaded. |
api.setImage(guid, data) |
Stores an image in the configured S3 bucket and returns its URL. Used, for example, to offload base64 images from setMedia changes. |
Usage Example
The following example configures the API extension with S3 storage and a MongoDB adapter wired through the server options:
const server = require('@jspreadsheet/server');
const adapter = require('@jspreadsheet/server-mongodb');
const api = require('@jspreadsheet/server-api');
// License
const license = {
clientId: '356a192b7913b04c54574d18c28d46e6395428ab',
licenseKey: 'MmIyMDhmYmY4NGI1ZDY1ODAwNThjMGZkOTVkNjg2MmQ1NzZmYTFhOTBmZWI3N2M3ZmQ1N2Q3YjMwNDNhMjRhYmViYmRkNGVjZjZlMmNkNDVhODJhYzg1ZmRiY2E3OTJhYjA1ODQzNTliZGZiMmYwNWM4YmRmMjAyZmUwODA1NmEsZXlKamJHbGxiblJKWkNJNklqTTFObUV4T1RKaU56a3hNMkl3TkdNMU5EVTNOR1F4T0dNeU9HUTBObVUyTXprMU5ESTRZV0lpTENKdVlXMWxJam9pU25Od2NtVmhaSE5vWldWMElpd2laR0YwWlNJNk1UYzBNak0wTWpRd01Dd2laRzl0WVdsdUlqcGJJbXB6YUdWc2JDNXVaWFFpTENKamMySXVZWEJ3SWl3aWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0luVmxMbU52YlM1aWNpSXNJbU5rY0c0dWFXOGlMQ0pwYm5SeVlYTm9aV1YwY3k1amIyMGlMQ0p6Wm1OdlpHVmliM1F1WTI5dElpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5KbGJtUmxjaUlzSW5CaGNuTmxjaUlzSW1sdGNHOXlkR1Z5SWl3aWRtRnNhV1JoZEdsdmJuTWlMQ0pqYjIxdFpXNTBjeUlzSW5ObFlYSmphQ0lzSW1Ob1lYSjBjeUlzSW5CeWFXNTBJaXdpWW1GeUlpd2ljMmhsWlhSeklpd2lZMnh2ZFdRaUxDSnRZWE5ySWl3aWMyaGxaWFJ6SWl3aWMyVnlkbVZ5SWl3aWFXNTBjbUZ6YUdWbGRITWlYWDA9'
}
// Connect API to S3 for history and image upload
api({
s3: {
key: "",
secret: "",
bucket: "",
region: "",
url: "",
},
});
server({
port: 3000,
load: async function(guid, auth, cachedConfiguration) {
return await adapter.load(guid, auth, cachedConfiguration);
},
change: async function(guid, changes, auth, onerror) {
return await adapter.change(guid, changes, auth, onerror);
},
create: async function(guid, config, auth) {
return await adapter.create(guid, config, auth);
},
destroy: async function(guid, auth) {
return await adapter.destroy(guid, auth);
},
replace: async function(guid, config, auth) {
return await adapter.replace(guid, config, auth);
},
error: function(e) {
console.error('Error', e)
},
license: license,
extensions: { api },
});
Client API
The REST routes can be called from any HTTP client. Requests carry the authentication token in an Authorization: Bearer header, and write bodies are form-encoded. See HTTP conventions.
Installation
No additional package is required: the example below uses the standard fetch API available in browsers and Node.js.
Example: Updating Comments
Set comments on worksheet 0 by posting to the comments route, POST /api/<guid>/<worksheetIndex>/comments. The body keys are the cell names; a string value creates a simple note, and bracket-notation arrays create threaded comments (each entry requires comments and date, with optional name, user_id and edited):
// API Server
const baseUrl = "http://localhost:8009/api";
// Your authentication token
const token = "eyJhbGciOiJIUzUxMiIsInR5cCJ9.eyJkb21haW4iOiJsb2NhbGhvc3Q6ODAPQSJ9.Xr2Ir2-zEc_tqV5y6i";
// Spreadsheet Guid
const guid = '79b45919-c751-4e2b-a49a-6c1286e2fc03';
// New comments, keyed by cell name
const body = new URLSearchParams();
body.append('A1', 'first comment');
body.append('B3[0][comments]', 'Something');
body.append('B3[0][date]', new Date().toISOString());
body.append('B3[0][name]', 'Random name');
// Set new comments on worksheet 0
fetch(`${baseUrl}/${guid}/0/comments`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
},
body,
})
.then((response) => response.json())
.then((result) => {
// { message: 'Done', rev: <n> }
console.log(result);
})
.catch((err) => {
console.log(err);
});