Engine Keys
The key an engine starts with. A public access token on the WASMClient is all most apps need; the rest is for
apps with a sign-in of their own, and for servers.
Functions
resolveEngineKey()
function resolveEngineKey(source): Promise<string>;
The key for an engine start: the given key, the app's own, or one for the access token.
Throws EngineKeyError when there is none, with the service's reason (an unregistered domain, a revoked token, a plan without the native engine).
A key for a token is cached in localStorage (where there is one), per token, page origin and key service. It is
used until a minute before it expires and renewed in the background once less than a quarter of its life, or less
than a day, is left. When the service cannot be reached, a cached key that has not expired is used; a refusal
(an HTTP 4xx) is final. WASMClient calls it on connect.
Parameters
| Parameter | Type | Description |
|---|---|---|
source | EngineKeySource | The key, the app's getKey, or the access token to get one with. |
Returns
Promise<string>
The key.
Example
import { resolveEngineKey } from '@buerli.io/classcad'
// A server that starts a native engine of its own, with a secret access token
const key = await resolveEngineKey({
token: process.env.CLASSCAD_SECRET_TOKEN,
appType: 'native',
client: 'render farm',
})
await startEngine(key)
Classes
EngineKeyError
The error when there is no key for an engine: no token, the key service cannot be reached, or it refused.
WASMClient.connect rejects with it.
Example
import { EngineKeyError, resolveEngineKey } from '@buerli.io/classcad'
// Checks a page's token before the app starts, and says why it fails
try {
await resolveEngineKey({ token: 'ccpk_…' })
} catch (error) {
if (error instanceof EngineKeyError && error.status && error.status < 500) {
showError(`ClassCAD refused the key: ${error.message}`) // e.g. a domain the account has not registered
} else {
showError('The ClassCAD key service cannot be reached')
}
}
Extends
Error
Constructors
Constructor
new EngineKeyError(
message,
status?,
code?
): EngineKeyError;
Parameters
| Parameter | Type | Description |
|---|---|---|
message | string | What went wrong; the key service's own words when it refused. |
status? | number | The HTTP status of the key service's answer, when it answered. |
code? | string | The key service's error code, when it gave one. |
Returns
Overrides
Error.constructor
Properties
| Property | Modifier | Type | Description |
|---|---|---|---|
code? | public | string | The key service's error code, when it gave one. |
status? | public | number | The HTTP status of the key service's answer, when it answered. |
Types
EngineKey
type EngineKey = {
exp: number;
key: string;
};
An engine key, and when it expires.
What a WASMClient's getKey may resolve to: see the examples of WASMClient and requestEngineKey.
Properties
| Property | Type | Description |
|---|---|---|
exp | number | When the key expires, in milliseconds since 1970 (as Date.now()). |
key | string | The key the engine starts with. |
EngineKeySource
type EngineKeySource = {
appType?: "wasm" | "native";
classcadKey?: string;
client?: string;
getKey?: () => Promise<string | EngineKey>;
keyUrl?: string;
token?: string;
};
Where an engine's key comes from: a key, a ClassCAD access token, or a function of the app's own.
The first one given is used, in this order: classcadKey, getKey, token.
Example
import { resolveEngineKey } from '@buerli.io/classcad'
import type { EngineKeySource } from '@buerli.io/classcad'
// A key from a token exchange of one's own (a self-hosted backend), named for the account's records
const source: EngineKeySource = {
token: 'ccpk_…',
keyUrl: 'https://keys.example.com/api/v1/key',
client: 'configurator 2.1',
}
const key = await resolveEngineKey(source)
Properties
| Property | Type | Description |
|---|---|---|
appType? | "wasm" | "native" | The engine the key is for: 'wasm' (default) or 'native'. |
classcadKey? | string | An engine key itself; when given, nothing is fetched. |
client? | string | Who asks, for the account's records. |
getKey? | () => Promise<string | EngineKey> | Or the app supplies keys itself, for example from its own sign-in (POST /key with a Firebase ID token). |
keyUrl? | string | The token exchange, DEFAULT_KEY_URL unless given. |
token? | string | A ClassCAD access token: ccpk_… in web pages, ccsk_… on servers. |
Advanced
Most apps do not need these directly: types they meet through the exports above, and what is there for special cases or for building on buerli itself.
DEFAULT_KEY_URL
const DEFAULT_KEY_URL: "https://europe-west1-classcad-app.cloudfunctions.net/api/v1/key" = 'https://europe-west1-classcad-app.cloudfunctions.net/api/v1/key';
The token exchange of the ClassCAD backend.
requestEngineKey()
function requestEngineKey(source): Promise<EngineKey>;
Asks the token exchange for a key.
Sends source.token to source.keyUrl (default DEFAULT_KEY_URL) every time; resolveEngineKey
caches the key. Throws an EngineKeyError without a token, when the service cannot be reached, and with
its reason when it refuses.
Parameters
| Parameter | Type | Description |
|---|---|---|
source | EngineKeySource | The access token, and optionally keyUrl, appType and client. |
Returns
Promise<EngineKey>
Example
import { requestEngineKey } from '@buerli.io/classcad'
// The app's server: hands its signed-in users engine keys, with the secret token only it knows
export async function engineKeyRoute(request: Request): Promise<Response> {
if (!(await isSignedIn(request))) return new Response('Sign in first', { status: 401 })
const key = await requestEngineKey({ token: process.env.CLASSCAD_SECRET_TOKEN, client: 'my-app server' })
return Response.json(key) // { key, exp }, what a WASMClient's getKey returns
}