TypeScript SDK
Typed manifest
Write the app manifest in TypeScript, with autocompletion and compile-time checks
defineManifest returns the manifest unchanged. It exists for your editor and the
compiler: scopes, events, extension points and their kinds are suggested and checked.
import { defineManifest } from "@checkcourt/sdk";
export default defineManifest({
installTargets: ["tenant"],
tenantScopes: ["bookings:read", "courts:read"],
events: ["booking.created", "booking.cancelled"],
extensions: [
{ point: "booking.detail.panel", kind: "declarative", url: "https://door.example.com/ext/booking" },
{ point: "booking.action", kind: "declarative", url: "https://door.example.com/ext/open", label: "Tür öffnen" },
{ point: "app.settings", kind: "iframe", url: "https://door.example.com/settings" },
],
settingsSchema: {
type: "object",
properties: {
openMinutesBefore: { type: "number", title: "Minuten vor Spielbeginn", minimum: 0, maximum: 60, default: 10 },
},
},
dataProcessing: {
categories: ["Buchungsdaten"],
purpose: "Öffnet die Platztür zur gebuchten Zeit",
storageLocation: "EU",
avvRequired: true,
},
});You upload JSON. Write the file with a small script, for example:
import { writeFileSync } from "node:fs";
import manifest from "../manifest";
writeFileSync("manifest.json", JSON.stringify(manifest, null, 2) + "\n");What the compiler checks
tenantScopesanduserScopesonly contain scopes apps may request. The scopes reserved for people are an error.eventsonly contains subscribable events.app.*events arrive without a subscription.- Every extension has a valid
point, andkindfits the point:dashboard.widget,booking.action,kiosk.tile,court.annotation,member.list.column,booking.hint,booking_plan.actionandsidebar.actiononly allowdeclarative. booking.action,booking_plan.action,sidebar.actionandnav.pageneed alabel.nav.pageneeds anicon(from@checkcourt/sdk0.8.0).iconis otherwise only accepted onbooking_plan.actionandsidebar.action, and only with one of the allowed icon names.heightis only accepted on iframe entries (from@checkcourt/sdk0.9.0); the range 120 to 2,000 is checked on upload.settingsSchemahas the shape CheckCourt renders as a form (string,number,boolean).shares,reads,emitsandsubscribeshave the shape described in Connections between apps.permissionsentries have akeyand alabel, andrequiresis only accepted onnav.page(from@checkcourt/sdk0.11.0). Whetherrequiresnames a declared key, key format and limits are checked on upload.dataProcessingis complete.
What can only be checked at runtime, CheckCourt checks on upload: whether every event
has its scope, whether points with a subject have the required scope, URLs, lengths,
duplicate points and the rules between installTargets and userLinking. You see the
messages in the developer portal.
Types and constants
| Export | Contents |
|---|---|
Manifest | Type of the whole manifest |
ManifestExtension | One entry in extensions |
SettingsSchema, SettingsProperty | settingsSchema |
AppPermission, MAX_APP_PERMISSIONS, APP_PERMISSION_KEY_PATTERN | permissions |
GrantableScope, GRANTABLE_SCOPES | All scopes apps may request |
SubscribableEventType | All subscribable events |
ExtensionPoint, EXTENSION_POINTS | Points with allowed install targets and kinds |
EXTENSION_POINT_SCOPE | Scope a point with a subject needs |
StaticActionPoint, STATIC_ACTION_POINTS, STATIC_ACTION_LABEL_MAX | booking_plan.action and sidebar.action, label limit 24 (also for nav.page) |
AppActionIcon, APP_ACTION_ICONS | Icon names for static actions and nav.page |
IFRAME_EXTENSION_HEIGHT_MIN, IFRAME_EXTENSION_HEIGHT_MAX | Range of height (120 to 2,000) |
DataProcessing | dataProcessing |
SharedMetadata, ReadMetadata, EmittedEvent, SubscribedEvent, AppEventSchema | Connection fields |
SHARED_OBJECT_TYPES, SHARED_OBJECT_SCOPE, CONNECTION_NAME_PATTERN, MAX_SHARED_VALUE_BYTES | Connection rules |