bkper 4.24.3 → 4.26.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 +1 -1
- package/lib/agent/extensions/handoff.d.ts.map +1 -1
- package/lib/agent/extensions/handoff.js +2 -0
- package/lib/agent/extensions/handoff.js.map +1 -1
- package/lib/agent/startup-maintenance.d.ts +1 -0
- package/lib/agent/startup-maintenance.d.ts.map +1 -1
- package/lib/agent/startup-maintenance.js +7 -1
- package/lib/agent/startup-maintenance.js.map +1 -1
- package/lib/agent/system-prompt.js +1 -1
- package/lib/commands/apps/git/clone.js +1 -1
- package/lib/commands/apps/git/clone.js.map +1 -1
- package/lib/commands/apps/git/index.d.ts +2 -2
- package/lib/commands/apps/git/index.d.ts.map +1 -1
- package/lib/commands/apps/git/index.js +1 -1
- package/lib/commands/apps/git/index.js.map +1 -1
- package/lib/commands/apps/git/markers.d.ts +2 -2
- package/lib/commands/apps/git/markers.d.ts.map +1 -1
- package/lib/commands/apps/git/markers.js +10 -2
- package/lib/commands/apps/git/markers.js.map +1 -1
- package/lib/commands/apps/git/mode.d.ts +3 -4
- package/lib/commands/apps/git/mode.d.ts.map +1 -1
- package/lib/commands/apps/git/mode.js +24 -28
- package/lib/commands/apps/git/mode.js.map +1 -1
- package/lib/commands/apps/git/push.d.ts +7 -0
- package/lib/commands/apps/git/push.d.ts.map +1 -1
- package/lib/commands/apps/git/push.js +31 -0
- package/lib/commands/apps/git/push.js.map +1 -1
- package/lib/commands/apps/git/types.d.ts +6 -2
- package/lib/commands/apps/git/types.d.ts.map +1 -1
- package/lib/commands/apps/git/types.js.map +1 -1
- package/lib/commands/apps/init.d.ts +3 -1
- package/lib/commands/apps/init.d.ts.map +1 -1
- package/lib/commands/apps/init.js +105 -58
- package/lib/commands/apps/init.js.map +1 -1
- package/lib/commands/apps/register.js +2 -2
- package/lib/commands/apps/register.js.map +1 -1
- package/lib/commands/apps/source-workflow.d.ts.map +1 -1
- package/lib/commands/apps/source-workflow.js +19 -9
- package/lib/commands/apps/source-workflow.js.map +1 -1
- package/lib/dev/miniflare.js +1 -1
- package/lib/dev/miniflare.js.map +1 -1
- package/lib/dev/preflight.js +1 -1
- package/lib/dev/preflight.js.map +1 -1
- package/lib/dev/shared.js +1 -1
- package/lib/dev/shared.js.map +1 -1
- package/lib/docs/apps/app-listing.md +86 -0
- package/lib/docs/apps/architecture.md +188 -0
- package/lib/docs/apps/configuration.md +171 -0
- package/lib/docs/apps/context-menu.md +69 -0
- package/lib/docs/apps/deploying.md +181 -0
- package/lib/docs/apps/development.md +122 -0
- package/lib/docs/apps/event-handlers.md +248 -0
- package/lib/docs/apps/first-app.md +76 -0
- package/lib/docs/apps/overview.md +100 -0
- package/lib/docs/apps/self-hosted.md +63 -0
- package/lib/docs/apps/shared-app-source.md +85 -0
- package/lib/docs/cli/app-management.md +41 -9
- package/lib/docs/index.md +11 -1
- package/lib/docs/sdk/bkper-js.md +5 -0
- package/lib/upgrade/index.d.ts +1 -1
- package/lib/upgrade/index.d.ts.map +1 -1
- package/lib/upgrade/index.js +1 -1
- package/lib/upgrade/index.js.map +1 -1
- package/lib/upgrade/installation.d.ts +4 -0
- package/lib/upgrade/installation.d.ts.map +1 -1
- package/lib/upgrade/installation.js +23 -0
- package/lib/upgrade/installation.js.map +1 -1
- package/package.json +3 -3
- package/lib/docs/apps/app-building.md +0 -1429
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# App Listing
|
|
2
|
+
|
|
3
|
+
All Bkper apps are listed on the Automations Portal at _[app.bkper.com](https://app.bkper.com/) > Automations > Apps_. Each app has its own page with logo, description, and details:
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
App listings are populated from the fields you declare in [`bkper.yaml`](https://bkper.com/docs/build/apps/configuration.md). Sync metadata changes with `bkper app sync`. Deploying code is a separate step.
|
|
8
|
+
|
|
9
|
+
## Listing fields
|
|
10
|
+
|
|
11
|
+
Make sure your `bkper.yaml` has the following fields populated for a complete listing:
|
|
12
|
+
|
|
13
|
+
```yaml
|
|
14
|
+
id: your-app-id
|
|
15
|
+
name: Your App Name
|
|
16
|
+
description: A clear description of what your app does
|
|
17
|
+
|
|
18
|
+
logoUrl: https://your-app.bkper.app/images/logo.svg
|
|
19
|
+
logoUrlDark: https://your-app.bkper.app/images/logo-dark.svg
|
|
20
|
+
|
|
21
|
+
ownerName: Your Name or Organization
|
|
22
|
+
ownerWebsite: https://yourwebsite.com
|
|
23
|
+
|
|
24
|
+
website: https://your-app.bkper.app
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
See [App Configuration](https://bkper.com/docs/build/apps/configuration.md) for the full `bkper.yaml` reference.
|
|
28
|
+
|
|
29
|
+
## Default visibility
|
|
30
|
+
|
|
31
|
+
By default, installation is limited to the users you've declared in `bkper.yaml`:
|
|
32
|
+
|
|
33
|
+
```yaml
|
|
34
|
+
# Specific Bkper usernames
|
|
35
|
+
users: alice bob
|
|
36
|
+
|
|
37
|
+
# Your entire domain
|
|
38
|
+
users: *@yourcompany.com
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Use Bkper usernames for individual access, not email addresses.
|
|
42
|
+
|
|
43
|
+
Your team can install and use the app, but it doesn't appear in the public Bkper app directory for other users.
|
|
44
|
+
|
|
45
|
+
## Publishing to all users
|
|
46
|
+
|
|
47
|
+
To make your app available to all Bkper users, contact us at [support@bkper.com](mailto:support@bkper.com?subject=Publish+Bkper+App). We'll review your app and, once approved, publish it.
|
|
48
|
+
|
|
49
|
+
### What the review involves
|
|
50
|
+
|
|
51
|
+
- **Functionality check** — The app works correctly and handles errors gracefully
|
|
52
|
+
- **Security review** — Event handlers are idempotent and include loop prevention
|
|
53
|
+
- **Listing quality** — The app has a clear name, description, logo, and user-facing documentation
|
|
54
|
+
|
|
55
|
+
### README matters
|
|
56
|
+
|
|
57
|
+
Your app's `README.md` is displayed to end users on the app listing page. Write it for the people who will install and use your app — not for developers.
|
|
58
|
+
|
|
59
|
+
**README should explain:**
|
|
60
|
+
|
|
61
|
+
- What the app does from a user's perspective
|
|
62
|
+
- How to use it (step-by-step for non-technical users)
|
|
63
|
+
- What features are available
|
|
64
|
+
- API access details when the app intentionally exposes `/api/*` routes for users or integrators
|
|
65
|
+
|
|
66
|
+
**API access details should stay concise:**
|
|
67
|
+
|
|
68
|
+
- App base URL for production and preview
|
|
69
|
+
- OpenAPI spec URL at `/openapi.json`
|
|
70
|
+
- One minimal authenticated example, such as a `curl` call with `Authorization: Bearer <token>`
|
|
71
|
+
|
|
72
|
+
**README should NOT contain:**
|
|
73
|
+
|
|
74
|
+
- Tech stack or architecture details
|
|
75
|
+
- Build commands or development setup
|
|
76
|
+
- Project structure or internal file paths
|
|
77
|
+
- Long API references, generated schemas, SDK internals, or route-by-route developer docs
|
|
78
|
+
|
|
79
|
+
Put developer documentation in `AGENTS.md` or internal docs instead. Keep `README.md` focused on the user experience and any integration entry points users need.
|
|
80
|
+
|
|
81
|
+
### Where published apps appear
|
|
82
|
+
|
|
83
|
+
Once published, your app appears in:
|
|
84
|
+
|
|
85
|
+
- **[bkper.com/apps](https://bkper.com/apps)** — The public app directory
|
|
86
|
+
- **Automations Portal** — Inside every Bkper book, users can find and install your app
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# App Architecture
|
|
2
|
+
|
|
3
|
+
Bkper platform apps use one Worker bundle per app and environment. The same Worker serves the browser client, app-defined `/api/*` routes, and Bkper event ingress at `/events`.
|
|
4
|
+
|
|
5
|
+
Treat `/api/*` as the reusable surface for app behavior. The bundled web client is one consumer; scripts, external clients, and agents can call the same routes with bearer authentication.
|
|
6
|
+
|
|
7
|
+
## Structure
|
|
8
|
+
|
|
9
|
+
```txt
|
|
10
|
+
my-app/
|
|
11
|
+
├── client/
|
|
12
|
+
│ ├── index.html
|
|
13
|
+
│ ├── package.json
|
|
14
|
+
│ ├── vite.config.ts
|
|
15
|
+
│ └── src/
|
|
16
|
+
│ ├── api/
|
|
17
|
+
│ ├── app/
|
|
18
|
+
│ ├── auth/
|
|
19
|
+
│ ├── components/
|
|
20
|
+
│ └── services/
|
|
21
|
+
├── server/
|
|
22
|
+
│ ├── package.json
|
|
23
|
+
│ └── src/
|
|
24
|
+
│ ├── api/
|
|
25
|
+
│ ├── events/
|
|
26
|
+
│ ├── services/
|
|
27
|
+
│ └── index.ts
|
|
28
|
+
├── scripts/
|
|
29
|
+
├── bkper.yaml
|
|
30
|
+
├── env.d.ts
|
|
31
|
+
├── package.json
|
|
32
|
+
├── package-lock.json
|
|
33
|
+
└── tsconfig.json
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The root npm workspace orchestrates development, tests, builds, and deployment. The template keeps browser dependencies in `client/` and Worker dependencies in `server/`. Add a shared package only when both sides actually need one.
|
|
37
|
+
|
|
38
|
+
## Client
|
|
39
|
+
|
|
40
|
+
The client uses:
|
|
41
|
+
|
|
42
|
+
- [Lit](https://lit.dev/) for components and rendering.
|
|
43
|
+
- [Web Awesome](https://webawesome.com/) for UI components.
|
|
44
|
+
- [`@bkper/web-design`](https://www.npmjs.com/package/@bkper/web-design) for Bkper design tokens.
|
|
45
|
+
- [Vite](https://vitejs.dev/) for development and production builds, configured in `client/vite.config.ts`.
|
|
46
|
+
|
|
47
|
+
Client code has two data paths:
|
|
48
|
+
|
|
49
|
+
- **Direct Bkper calls** use `bkper-js` for browser-specific behavior.
|
|
50
|
+
- **App API calls** use the generated typed client in `client/src/api/` with `auth.authenticatedFetch()`.
|
|
51
|
+
|
|
52
|
+
### Client authentication
|
|
53
|
+
|
|
54
|
+
The client authenticates users with [`@bkper/web-auth`](https://www.npmjs.com/package/@bkper/web-auth). OAuth is preconfigured on the platform, so there are no client IDs, redirect URIs, or consent screens to configure.
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { Bkper } from 'bkper-js';
|
|
58
|
+
import { BkperAuth } from '@bkper/web-auth';
|
|
59
|
+
|
|
60
|
+
const isLocalDev = ['localhost', '127.0.0.1'].includes(window.location.hostname);
|
|
61
|
+
const auth = new BkperAuth({
|
|
62
|
+
baseUrl: isLocalDev ? window.location.origin : undefined,
|
|
63
|
+
onLoginSuccess: () => initializeApp(),
|
|
64
|
+
onLoginRequired: () => showLoginButton(),
|
|
65
|
+
});
|
|
66
|
+
await auth.init();
|
|
67
|
+
|
|
68
|
+
const bkper = new Bkper({
|
|
69
|
+
oauthTokenProvider: async () => auth.getAccessToken(),
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`@bkper/web-auth` handles login, redirects, and token refresh. The template keeps this behavior behind `client/src/auth/auth-session.ts`.
|
|
74
|
+
|
|
75
|
+
See the [@bkper/web-auth API Reference](https://bkper.com/docs/api/bkper-web-auth.md) for the full SDK documentation.
|
|
76
|
+
|
|
77
|
+
## Server Worker
|
|
78
|
+
|
|
79
|
+
The server runs on [Cloudflare Workers](https://developers.cloudflare.com/workers/) and uses [Hono](https://hono.dev/) with typed OpenAPI routes. It handles:
|
|
80
|
+
|
|
81
|
+
- app API routes under `/api/*`;
|
|
82
|
+
- Bkper event ingress under `/events`;
|
|
83
|
+
- platform services such as KV and secrets through `c.env`;
|
|
84
|
+
- static client assets through the `ASSETS` binding.
|
|
85
|
+
|
|
86
|
+
The Worker entry point composes those concerns while routes delegate business behavior to services:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import { OpenAPIHono } from '@hono/zod-openapi';
|
|
90
|
+
import { registerApiRoutes } from './api/routes.js';
|
|
91
|
+
import { registerEventRoutes } from './events/routes.js';
|
|
92
|
+
import { appContextMiddleware, type AppEnv } from './app-context.js';
|
|
93
|
+
|
|
94
|
+
const app = new OpenAPIHono();
|
|
95
|
+
|
|
96
|
+
app.use('/api/*', appContextMiddleware());
|
|
97
|
+
app.use('/events', appContextMiddleware());
|
|
98
|
+
registerApiRoutes(app);
|
|
99
|
+
registerEventRoutes(app);
|
|
100
|
+
|
|
101
|
+
app.get('*', c => c.env.ASSETS.fetch(c.req.raw));
|
|
102
|
+
|
|
103
|
+
export default app;
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## App API contract
|
|
107
|
+
|
|
108
|
+
The default template publishes versioned routes under `/api/v1/*` and exposes their OpenAPI contract at `/openapi.json`.
|
|
109
|
+
|
|
110
|
+
| Concern | Location |
|
|
111
|
+
| ---------------------------- | ------------------------------------- |
|
|
112
|
+
| OpenAPI metadata | `server/src/api/openapi.ts` |
|
|
113
|
+
| Request and response schemas | `server/src/api/schemas.ts` |
|
|
114
|
+
| Thin route handlers | `server/src/api/routes.ts` |
|
|
115
|
+
| Business behavior | `server/src/services/` |
|
|
116
|
+
| Generated client types | `client/src/api/generated/types.d.ts` |
|
|
117
|
+
| Typed client wrapper | `client/src/api/app-api.ts` |
|
|
118
|
+
| Contract snapshot | `server/test/openapi.snapshot.json` |
|
|
119
|
+
|
|
120
|
+
When changing the API:
|
|
121
|
+
|
|
122
|
+
1. Update schemas, services, routes, and focused unit tests.
|
|
123
|
+
2. Run `npm run api` to regenerate client types.
|
|
124
|
+
3. Review the OpenAPI snapshot when the public contract changes.
|
|
125
|
+
4. Run `npm run check` before release.
|
|
126
|
+
|
|
127
|
+
Keep existing `/api/v1/*` contracts backward compatible. Additive fields and routes can remain in `v1`; breaking changes belong in a new namespace such as `/api/v2/*`.
|
|
128
|
+
|
|
129
|
+
### URLs
|
|
130
|
+
|
|
131
|
+
```txt
|
|
132
|
+
Production API: https://{appId}.bkper.app/api/*
|
|
133
|
+
Preview API: https://{appId}-preview.bkper.app/api/*
|
|
134
|
+
Local API: http://localhost:8787/api/*
|
|
135
|
+
|
|
136
|
+
Production spec: https://{appId}.bkper.app/openapi.json
|
|
137
|
+
Preview spec: https://{appId}-preview.bkper.app/openapi.json
|
|
138
|
+
Local spec: http://localhost:8787/openapi.json
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Example script call:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
TOKEN="$(bkper auth token)"
|
|
145
|
+
|
|
146
|
+
curl \
|
|
147
|
+
-H "Authorization: Bearer ${TOKEN}" \
|
|
148
|
+
"https://my-app.bkper.app/api/v1/books"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Replace `my-app` with the app id from `bkper.yaml`.
|
|
152
|
+
|
|
153
|
+
### Server API authentication
|
|
154
|
+
|
|
155
|
+
Deployed `/api/*` routes require a Bkper OAuth bearer token. The template client uses `authenticatedFetch()` so token attachment and refresh stay inside `@bkper/web-auth`:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
const response = await auth.authenticatedFetch('/api/v1/books');
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Dispatch validates the incoming bearer token and strips the `Authorization` header before the Worker runs. Server code should not read or forward the token.
|
|
162
|
+
|
|
163
|
+
When a route calls Bkper, create the SDK without a token provider:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
import { Bkper } from 'bkper-js';
|
|
167
|
+
|
|
168
|
+
const bkper = new Bkper();
|
|
169
|
+
const books = await bkper.getBooks();
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Platform outbound authentication injects the validated user's OAuth token on Bkper API requests.
|
|
173
|
+
|
|
174
|
+
## Event handlers
|
|
175
|
+
|
|
176
|
+
Platform event deliveries reach `/events` on the same Worker. Event adapters live in `server/src/events/`, while reusable business behavior belongs in `server/src/services/`.
|
|
177
|
+
|
|
178
|
+
Event code uses server-side `new Bkper()` and must not read `bkper-oauth-token`, `bkper-agent-id`, or `Authorization` headers. Dispatch and platform outbound authentication handle the event token and app agent identity.
|
|
179
|
+
|
|
180
|
+
See [Event Handlers](https://bkper.com/docs/build/apps/event-handlers.md) for routing, responses, loop prevention, and event types. Self-hosted handlers process event authentication directly because the platform outbound layer is not involved.
|
|
181
|
+
|
|
182
|
+
## App shapes
|
|
183
|
+
|
|
184
|
+
The platform supports different shapes:
|
|
185
|
+
|
|
186
|
+
- **Full app** — Client UI, `/api/*` backend behavior, and `/events` automation in one Worker. This is the default template.
|
|
187
|
+
- **Event-only app** — Keep `server/` and omit `deployment.client`.
|
|
188
|
+
- **UI-only app** — Keep a minimal Worker for static assets when behavior is truly browser-only. Add `/api/*` when scripts, integrations, or agents should reuse that behavior.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# App Configuration
|
|
2
|
+
|
|
3
|
+
The `bkper.yaml` file is the single configuration file for your Bkper app. It defines the app's identity, access control, menu integration, event handling, and deployment settings.
|
|
4
|
+
|
|
5
|
+
It lives in the root of your project. Use `bkper app sync` to push metadata changes to Bkper, and use `bkper app deploy` to upload built code to the platform.
|
|
6
|
+
|
|
7
|
+
## Minimal example
|
|
8
|
+
|
|
9
|
+
```yaml
|
|
10
|
+
id: my-app
|
|
11
|
+
name: My App
|
|
12
|
+
description: A Bkper app that does something useful
|
|
13
|
+
developers: myuser
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Starter example
|
|
17
|
+
|
|
18
|
+
From the [app template](https://github.com/bkper/bkper-app-template):
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
id: my-app
|
|
22
|
+
name: My App
|
|
23
|
+
description: A Bkper app that does something useful
|
|
24
|
+
|
|
25
|
+
logoUrl: https://my-app.bkper.app/images/logo-light.svg
|
|
26
|
+
logoUrlDark: https://my-app.bkper.app/images/logo-dark.svg
|
|
27
|
+
|
|
28
|
+
website: https://my-app.bkper.app
|
|
29
|
+
ownerName: Bkper
|
|
30
|
+
ownerLogoUrl: https://avatars.githubusercontent.com/u/11943086?v=4
|
|
31
|
+
ownerWebsite: https://bkper.com
|
|
32
|
+
|
|
33
|
+
developers: someuser *@yoursite.com
|
|
34
|
+
users: someuser *@yoursite.com
|
|
35
|
+
|
|
36
|
+
menuUrl: https://my-app.bkper.app?bookId=${book.id}
|
|
37
|
+
menuUrlDev: https://my-app-preview.bkper.app?bookId=${book.id}
|
|
38
|
+
menuOpenMode: SIDEBAR
|
|
39
|
+
|
|
40
|
+
webhookUrl: https://my-app.bkper.app/events
|
|
41
|
+
webhookUrlDev: https://my-app-preview.bkper.app/events
|
|
42
|
+
apiVersion: v5
|
|
43
|
+
events:
|
|
44
|
+
- TRANSACTION_CHECKED
|
|
45
|
+
|
|
46
|
+
deployment:
|
|
47
|
+
server: server/src/index.ts
|
|
48
|
+
client: client
|
|
49
|
+
services:
|
|
50
|
+
- KV
|
|
51
|
+
secrets: []
|
|
52
|
+
compatibility_date: '2026-01-28'
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### App identity
|
|
56
|
+
|
|
57
|
+
| Field | Description |
|
|
58
|
+
| ------------- | --------------------------------------------------------------------------------------------------------- |
|
|
59
|
+
| `id` | Permanent app identifier. Lowercase letters, numbers, and hyphens only. Cannot be changed after creation. |
|
|
60
|
+
| `name` | Display name shown in the Bkper UI. |
|
|
61
|
+
| `description` | Brief description of what the app does. |
|
|
62
|
+
|
|
63
|
+
### Branding
|
|
64
|
+
|
|
65
|
+
| Field | Description |
|
|
66
|
+
| ------------- | ------------------------------------------ |
|
|
67
|
+
| `logoUrl` | App logo for light mode (SVG recommended). |
|
|
68
|
+
| `logoUrlDark` | App logo for dark mode. |
|
|
69
|
+
| `website` | App website or documentation URL. |
|
|
70
|
+
|
|
71
|
+
### Ownership
|
|
72
|
+
|
|
73
|
+
| Field | Description |
|
|
74
|
+
| -------------- | ------------------------------------------------------------ |
|
|
75
|
+
| `ownerName` | Developer or company name. |
|
|
76
|
+
| `ownerLogoUrl` | Owner's logo/avatar URL. |
|
|
77
|
+
| `ownerWebsite` | Owner's website. |
|
|
78
|
+
| `repoUrl` | Source code repository URL. |
|
|
79
|
+
| `repoPrivate` | Whether the repository is private. |
|
|
80
|
+
| `deprecated` | Hides from app listings; existing installs continue working. |
|
|
81
|
+
|
|
82
|
+
### Access control
|
|
83
|
+
|
|
84
|
+
| Field | Description |
|
|
85
|
+
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
86
|
+
| `developers` | Who can update the app and deploy new versions. Accepts comma- or space-separated Bkper usernames and domain wildcards such as `*@yoursite.com`. |
|
|
87
|
+
| `users` | Who can install and use the app. Uses the same format as `developers`; leave empty for public apps. |
|
|
88
|
+
|
|
89
|
+
### Menu integration
|
|
90
|
+
|
|
91
|
+
| Field | Description |
|
|
92
|
+
| -------------- | --------------------------------------------------------------------------- |
|
|
93
|
+
| `menuUrl` | Production menu URL. Supports [variable substitution](#menu-url-variables). |
|
|
94
|
+
| `menuUrlDev` | Development menu URL, typically a preview or local app URL. |
|
|
95
|
+
| `menuText` | Custom menu text (defaults to app name). |
|
|
96
|
+
| `menuOpenMode` | How the app menu opens: `SIDEBAR` (default), `EXPANDED`, or `NEW_TAB`. |
|
|
97
|
+
|
|
98
|
+
See [Context Menu](https://bkper.com/docs/build/apps/context-menu.md) for details on building menu integrations.
|
|
99
|
+
|
|
100
|
+
### Menu URL variables
|
|
101
|
+
|
|
102
|
+
The following variables can be used in `menuUrl` and `menuUrlDev`:
|
|
103
|
+
|
|
104
|
+
| Variable | Description |
|
|
105
|
+
| --------------------------- | ---------------------------------------- |
|
|
106
|
+
| `${book.id}` | Current book ID |
|
|
107
|
+
| `${book.properties.xxx}` | Book property value |
|
|
108
|
+
| `${account.id}` | Selected account ID |
|
|
109
|
+
| `${account.name}` | Selected account name |
|
|
110
|
+
| `${account.properties.xxx}` | Account property value |
|
|
111
|
+
| `${group.id}` | Selected group ID |
|
|
112
|
+
| `${group.name}` | Selected group name |
|
|
113
|
+
| `${group.properties.xxx}` | Group property value |
|
|
114
|
+
| `${transactions.ids}` | Comma-separated selected transaction IDs |
|
|
115
|
+
| `${transactions.query}` | Current search query |
|
|
116
|
+
|
|
117
|
+
### Event handling
|
|
118
|
+
|
|
119
|
+
| Field | Description |
|
|
120
|
+
| --------------- | ----------------------------------------------------------------------------------- |
|
|
121
|
+
| `webhookUrl` | Production webhook URL for receiving events. |
|
|
122
|
+
| `webhookUrlDev` | Development webhook URL (auto-updated by `bkper app dev`). |
|
|
123
|
+
| `apiVersion` | API version for event payloads (currently `v5`). |
|
|
124
|
+
| `events` | List of [event types](https://bkper.com/docs/build/apps/event-handlers.md#event-types) to subscribe to. |
|
|
125
|
+
|
|
126
|
+
See [Event Handlers](https://bkper.com/docs/build/apps/event-handlers.md) for details on handling events.
|
|
127
|
+
|
|
128
|
+
### File patterns
|
|
129
|
+
|
|
130
|
+
| Field | Description |
|
|
131
|
+
| -------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
132
|
+
| `filePatterns` | List of glob patterns (e.g., `*.ofx`, `*.csv`). When a matching file is uploaded, a `FILE_CREATED` event is triggered. |
|
|
133
|
+
|
|
134
|
+
### Properties schema
|
|
135
|
+
|
|
136
|
+
The `propertiesSchema` field defines autocomplete suggestions for custom properties in the Bkper UI, helping users discover the correct property keys and values for your app.
|
|
137
|
+
|
|
138
|
+
Suggested keys must follow the same custom property rules as user-entered keys, including the 30-character maximum after normalization.
|
|
139
|
+
|
|
140
|
+
```yaml
|
|
141
|
+
propertiesSchema:
|
|
142
|
+
book:
|
|
143
|
+
keys:
|
|
144
|
+
- my_app_enabled
|
|
145
|
+
values:
|
|
146
|
+
- 'true'
|
|
147
|
+
- 'false'
|
|
148
|
+
group:
|
|
149
|
+
keys:
|
|
150
|
+
- my_app_category
|
|
151
|
+
account:
|
|
152
|
+
keys:
|
|
153
|
+
- my_app_sync_id
|
|
154
|
+
transaction:
|
|
155
|
+
keys:
|
|
156
|
+
- my_app_reference
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Deployment
|
|
160
|
+
|
|
161
|
+
For apps deployed to the [Bkper Platform](https://bkper.com/docs/build/apps/overview.md):
|
|
162
|
+
|
|
163
|
+
| Field | Description |
|
|
164
|
+
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
165
|
+
| `deployment.server` | TypeScript entry point for the single server Worker. It serves `/api/*`, `/events`, and static assets. |
|
|
166
|
+
| `deployment.client` | Optional Vite/static client root. Built assets are deployed with the same Worker. |
|
|
167
|
+
| `deployment.services` | Platform services to provision. Currently: `KV` (key-value storage). |
|
|
168
|
+
| `deployment.secrets` | Secret names used by the app. Managed via `bkper app secrets`. |
|
|
169
|
+
| `deployment.compatibility_date` | [Cloudflare Workers compatibility date](https://developers.cloudflare.com/workers/configuration/compatibility-dates/). |
|
|
170
|
+
|
|
171
|
+
See [Building & Deploying](https://bkper.com/docs/build/apps/deploying.md) for the full deployment workflow.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Context Menu
|
|
2
|
+
|
|
3
|
+
Apps can add context menu items on the Transactions page **More** menu in your Books. This lets you open dynamically built URLs with reference to the current Book's context — the active query, selected account, date range, and more.
|
|
4
|
+
|
|
5
|
+
## How it works
|
|
6
|
+
|
|
7
|
+
Once you install an App with a menu configuration, a new menu item appears in your Book:
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
When clicked, a popup opens carrying the particular context of that book at that moment:
|
|
12
|
+
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
Configure the menu URL in your [`bkper.yaml`](https://bkper.com/docs/build/apps/configuration.md):
|
|
18
|
+
|
|
19
|
+
```yaml
|
|
20
|
+
menuUrl: https://my-app.bkper.app?bookId=${book.id}&query=${transactions.query}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
When the user clicks the menu item, the URL expressions `${xxxx}` are replaced with contextual information from the Book:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
https://my-app.bkper.app?bookId=abc123&query=account:Sales
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Where `abc123` is the current Book id and `account:Sales` is the current query being executed.
|
|
30
|
+
|
|
31
|
+
### Development URL
|
|
32
|
+
|
|
33
|
+
Use `menuUrlDev` to keep developer testing separate from production. The app template points it to the preview deployment:
|
|
34
|
+
|
|
35
|
+
```yaml
|
|
36
|
+
menuUrl: https://my-app.bkper.app?bookId=${book.id}&query=${transactions.query}
|
|
37
|
+
menuUrlDev: https://my-app-preview.bkper.app?bookId=${book.id}&query=${transactions.query}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
During local development, you can instead point it to the local Worker URL at `http://localhost:8787`. The development URL is used when an app developer clicks the menu item.
|
|
41
|
+
|
|
42
|
+
### Menu open mode
|
|
43
|
+
|
|
44
|
+
Control how the menu opens with `menuOpenMode`:
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
menuOpenMode: SIDEBAR
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
| Mode | Behavior |
|
|
51
|
+
| ---------- | --------------------------------------------------------------------- |
|
|
52
|
+
| `SIDEBAR` | Opens in a narrow side panel (default). |
|
|
53
|
+
| `EXPANDED` | Opens in a wider panel with more room for complex UIs. |
|
|
54
|
+
| `NEW_TAB` | Opens the menu URL in a new browser tab instead of an embedded panel. |
|
|
55
|
+
|
|
56
|
+
### Available expressions
|
|
57
|
+
|
|
58
|
+
The menu URL supports these dynamic expressions:
|
|
59
|
+
|
|
60
|
+
| Expression | Description |
|
|
61
|
+
| ----------------------- | ------------------------- |
|
|
62
|
+
| `${book.id}` | The current Book ID |
|
|
63
|
+
| `${transactions.query}` | The current query string |
|
|
64
|
+
| `${account.id}` | The selected account ID |
|
|
65
|
+
| `${account.name}` | The selected account name |
|
|
66
|
+
| `${group.id}` | The selected group ID |
|
|
67
|
+
| `${group.name}` | The selected group name |
|
|
68
|
+
|
|
69
|
+
For the full list of accepted expressions, see the [Menu URL variables](https://bkper.com/docs/build/apps/configuration.md#menu-url-variables) reference.
|