@checkcourt/sdk 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -210,6 +210,7 @@ with the matching builder; each throws when the answer would break CheckCourt's
210
210
  | `booking_plan.action` | `ext.date`, `ext.courts` (and the day as subject) | `ui.doc([...])`, shown in a dialog after a click; `ui.hidden()` closes it |
211
211
  | `sidebar.action` | nothing extra | `ui.doc([...])`, shown in a dialog after a click; `ui.hidden()` closes it |
212
212
  | `member.settings.section` | nothing extra | `ui.doc([...])`, a card on the member's own settings page |
213
+ | `nav.page` | nothing extra | `ui.doc([...])` (or an iframe), the content of the app's own page |
213
214
 
214
215
  ```ts
215
216
  if (ext.kind === "render" && ext.point === "court.annotation" && ext.date && ext.courts) {
@@ -227,6 +228,24 @@ if (ext.kind === "render" && ext.point === "court.annotation" && ext.date && ext
227
228
  manifest and may set an `icon` from `APP_ACTION_ICONS`. In every declarative document,
228
229
  CheckCourt places content first, then the buttons, then the links of each level.
229
230
 
231
+ `nav.page` gives your app an entry in the main navigation and a full page of its own at
232
+ `/apps/<installation id>/<index>`. It needs a `label` (at most 24 characters, also the page
233
+ title) and an `icon` from `APP_ACTION_ICONS`, may be declarative or an iframe, and appears at
234
+ most once per manifest. A club installation's entry is shown to every member of the club, a
235
+ member installation's entry only to that member:
236
+
237
+ ```ts
238
+ defineManifest({
239
+ installTargets: ["tenant"],
240
+ extensions: [{ point: "nav.page", kind: "declarative", url: "https://app.example.de/ext/page", label: "Trainingsplan", icon: "calendar" }],
241
+ dataProcessing: { categories: ["Trainingsdaten"], purpose: "Zeigt den Trainingsplan", storageLocation: "EU", avvRequired: false },
242
+ });
243
+
244
+ if (ext.point === "nav.page") {
245
+ return Response.json(ui.doc([ui.heading("Diese Woche"), ui.text("Dienstag 18 Uhr: Jugendtraining")]));
246
+ }
247
+ ```
248
+
230
249
  ### OAuth with PKCE (member apps)
231
250
 
232
251
  ```ts
@@ -53,6 +53,7 @@ export interface PointCapabilities {
53
53
  "booking.hint": Record<string, never>;
54
54
  "booking_plan.action": BookingPlanCapabilities;
55
55
  "sidebar.action": Record<string, never>;
56
+ "nav.page": Record<string, never>;
56
57
  }
57
58
  export interface PointSubject {
58
59
  "app.settings": {
@@ -83,6 +84,7 @@ export interface PointSubject {
83
84
  id: string;
84
85
  };
85
86
  "sidebar.action": null;
87
+ "nav.page": null;
86
88
  }
87
89
  interface ContextClaimsOf<P extends ExtensionPoint> {
88
90
  iss: typeof CONTEXT_ISSUER;
@@ -56,6 +56,10 @@ export declare const EXTENSION_POINTS: {
56
56
  readonly targets: readonly ["tenant", "user"];
57
57
  readonly kinds: readonly ["declarative"];
58
58
  };
59
+ readonly "nav.page": {
60
+ readonly targets: readonly ["tenant", "user"];
61
+ readonly kinds: readonly ["declarative", "iframe"];
62
+ };
59
63
  };
60
64
  export type ExtensionPoint = keyof typeof EXTENSION_POINTS;
61
65
  /** Scope the installation needs (in `tenantScopes` or `userScopes`) before the point hands it a subject id. */
@@ -72,13 +76,14 @@ export declare const EXTENSION_POINT_SCOPE: {
72
76
  readonly "booking.hint": "bookings:read";
73
77
  readonly "booking_plan.action": "courts:read";
74
78
  readonly "sidebar.action": null;
79
+ readonly "nav.page": null;
75
80
  };
76
81
  /** Buttons CheckCourt draws from the manifest alone, before the app is ever called. */
77
82
  export declare const STATIC_ACTION_POINTS: readonly ["booking_plan.action", "sidebar.action"];
78
83
  export type StaticActionPoint = (typeof STATIC_ACTION_POINTS)[number];
79
84
  /** Longest `label` of a static action. */
80
85
  export declare const STATIC_ACTION_LABEL_MAX = 24;
81
- /** lucide icon names a static action may use as `icon`. */
86
+ /** lucide icon names a static action or `nav.page` may use as `icon`. */
82
87
  export declare const APP_ACTION_ICONS: readonly ["bell", "calendar", "calendar-check", "camera", "chart-column", "circle-help", "clipboard-list", "clock", "cloud-rain", "door-open", "file-text", "flag", "heart-pulse", "info", "key-round", "lightbulb", "link", "list-checks", "lock-open", "map-pin", "megaphone", "message-square", "receipt", "send", "sparkles", "star", "sun", "thermometer", "ticket", "triangle-alert", "trophy", "user-round", "users", "wallet", "wrench"];
83
88
  export type AppActionIcon = (typeof APP_ACTION_ICONS)[number];
84
89
  /** Every scope an app may request. Role, app, webhook, key, billing and AVV management are reserved for people. */
@@ -93,6 +98,10 @@ type ExtensionOf<P extends ExtensionPoint> = {
93
98
  /** Button text, 1 to 24 characters (`STATIC_ACTION_LABEL_MAX`). */
94
99
  label: string;
95
100
  icon?: AppActionIcon;
101
+ } : P extends "nav.page" ? {
102
+ /** Navigation entry and page title, 1 to 24 characters (`STATIC_ACTION_LABEL_MAX`). */
103
+ label: string;
104
+ icon: AppActionIcon;
96
105
  } : P extends "booking.action" ? {
97
106
  label: string;
98
107
  icon?: never;
@@ -105,7 +114,7 @@ type ExtensionOf<P extends ExtensionPoint> = {
105
114
  });
106
115
  /**
107
116
  * One entry of `extensions`; `kind`, `label` and `icon` are checked per point at compile time.
108
- * Every point may appear once, except `booking.action`.
117
+ * Every point may appear once, except `booking.action`; an app has at most one `nav.page`.
109
118
  */
110
119
  export type ManifestExtension = {
111
120
  [P in ExtensionPoint]: ExtensionOf<P>;
package/dist/manifest.js CHANGED
@@ -16,6 +16,7 @@ export const EXTENSION_POINTS = {
16
16
  "booking.hint": { targets: ["tenant"], kinds: ["declarative"] },
17
17
  "booking_plan.action": { targets: ["tenant"], kinds: ["declarative"] },
18
18
  "sidebar.action": { targets: ["tenant", "user"], kinds: ["declarative"] },
19
+ "nav.page": { targets: ["tenant", "user"], kinds: ["declarative", "iframe"] },
19
20
  };
20
21
  /** Scope the installation needs (in `tenantScopes` or `userScopes`) before the point hands it a subject id. */
21
22
  export const EXTENSION_POINT_SCOPE = {
@@ -31,12 +32,13 @@ export const EXTENSION_POINT_SCOPE = {
31
32
  "booking.hint": "bookings:read",
32
33
  "booking_plan.action": "courts:read",
33
34
  "sidebar.action": null,
35
+ "nav.page": null,
34
36
  };
35
37
  /** Buttons CheckCourt draws from the manifest alone, before the app is ever called. */
36
38
  export const STATIC_ACTION_POINTS = ["booking_plan.action", "sidebar.action"];
37
39
  /** Longest `label` of a static action. */
38
40
  export const STATIC_ACTION_LABEL_MAX = 24;
39
- /** lucide icon names a static action may use as `icon`. */
41
+ /** lucide icon names a static action or `nav.page` may use as `icon`. */
40
42
  export const APP_ACTION_ICONS = [
41
43
  "bell",
42
44
  "calendar",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkcourt/sdk",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Official TypeScript SDK for the CheckCourt app platform",
5
5
  "private": false,
6
6
  "license": "MIT",