@bardioc/app-sdk 0.4.11 → 1.0.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 +86 -253
- package/dist/api/graph.d.ts +30 -0
- package/dist/api/graph.js +139 -0
- package/dist/api/os.d.ts +30 -0
- package/dist/api/os.js +48 -0
- package/dist/api/relay.d.ts +7 -0
- package/dist/api/relay.js +16 -0
- package/dist/api/request.d.ts +18 -0
- package/dist/api/request.js +12 -0
- package/dist/client.d.ts +104 -0
- package/dist/client.js +106 -0
- package/dist/contract.d.ts +294 -0
- package/dist/contract.js +150 -0
- package/dist/dev-idb.d.ts +10 -0
- package/dist/dev-idb.js +42 -0
- package/dist/dev-proxy.js +17 -3
- package/dist/dev.d.ts +16 -12
- package/dist/dev.js +101 -119
- package/dist/errors.d.ts +24 -25
- package/dist/errors.js +33 -48
- package/dist/index.d.ts +10 -7
- package/dist/index.js +2 -4
- package/dist/manifest.d.ts +10 -2
- package/dist/manifest.js +28 -24
- package/dist/protocol.d.ts +6 -29
- package/dist/protocol.js +3 -31
- package/dist/react.d.ts +22 -26
- package/dist/react.js +88 -181
- package/dist/serve.d.ts +26 -0
- package/dist/serve.js +64 -0
- package/dist/testing.d.ts +17 -0
- package/dist/testing.js +128 -0
- package/dist/types.d.ts +0 -241
- package/dist/vite.js +3 -0
- package/dist/wire.d.ts +46 -0
- package/dist/wire.js +138 -0
- package/package.json +12 -4
- package/dist/contract-matrix.d.ts +0 -148
- package/dist/contract-matrix.js +0 -150
- package/dist/host-bridge.d.ts +0 -3
- package/dist/host-bridge.js +0 -306
- package/dist/transports/backend-transport.d.ts +0 -24
- package/dist/transports/backend-transport.js +0 -54
- package/dist/transports/graph-transport.d.ts +0 -241
- package/dist/transports/graph-transport.js +0 -616
- package/dist/transports/os-transport.d.ts +0 -190
- package/dist/transports/os-transport.js +0 -444
package/README.md
CHANGED
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
# @bardioc/app-sdk
|
|
2
2
|
|
|
3
|
-
SDK
|
|
3
|
+
SDK for building apps that run inside Bardioc as isolated iframes.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
An app talks to its host only through a typed contract over a `MessagePort`: it calls host
|
|
6
|
+
methods (`ui.*`, `bff.request`, `idb.*`, `apps.*`), receives host calls (`ui.command`) and
|
|
7
|
+
events (`context.changed`), and reads streams (`events.graph`). Every failure is a
|
|
8
|
+
`BardiocError` with a `code`.
|
|
9
9
|
|
|
10
10
|
## Requirements
|
|
11
11
|
|
|
12
12
|
- Node.js `>=20.19.0`
|
|
13
13
|
- TypeScript `>=6.0.0`
|
|
14
|
-
- For React apps,
|
|
15
|
-
|
|
16
|
-
## Install into an existing project
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
pnpm add @bardioc/app-sdk
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Apps can be developed independently outside the Bardioc OS and then tested through a live AppStore development session. That keeps the local development loop fast while still exercising the real host communication path.
|
|
14
|
+
- For React apps, `react` and `react-dom` in the consuming project
|
|
23
15
|
|
|
24
16
|
## Quick start
|
|
25
17
|
|
|
@@ -29,284 +21,135 @@ import { createRoot } from 'react-dom/client';
|
|
|
29
21
|
|
|
30
22
|
function App() {
|
|
31
23
|
const notify = useNotify();
|
|
32
|
-
|
|
33
|
-
function sayHello() {
|
|
34
|
-
notify('Hello from my app', 'success');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return <button onClick={sayHello}>Say hello</button>;
|
|
24
|
+
return <button onClick={() => notify('Hello.', 'success')}>Say hello</button>;
|
|
38
25
|
}
|
|
39
26
|
|
|
40
|
-
const isInsideIframe = globalThis.window.parent !== globalThis.window;
|
|
41
|
-
|
|
42
27
|
createRoot(document.getElementById('root')!).render(
|
|
43
|
-
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
</AppSdkProvider>
|
|
47
|
-
) : (
|
|
48
|
-
<div>Open this app from the Bardioc OS dock to use SDK features.</div>
|
|
49
|
-
)
|
|
28
|
+
<AppSdkProvider>
|
|
29
|
+
<App />
|
|
30
|
+
</AppSdkProvider>
|
|
50
31
|
);
|
|
51
32
|
```
|
|
52
33
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
| Path | Contents |
|
|
56
|
-
| --------------------------- | ------------------------------------------- |
|
|
57
|
-
| `@bardioc/app-sdk` | `createHostBridge`, errors, types, manifest |
|
|
58
|
-
| `@bardioc/app-sdk/react` | `AppSdkProvider`, hooks (`useSdk`, etc.) |
|
|
59
|
-
| `@bardioc/app-sdk/dev` | standalone dev bridge helpers |
|
|
60
|
-
| `@bardioc/app-sdk/types` | Type-only TypeScript exports |
|
|
61
|
-
| `@bardioc/app-sdk/protocol` | `SDK_MSG` constants, wire format types |
|
|
62
|
-
| `@bardioc/app-sdk/vite` | `bardiocApp()` Vite plugin |
|
|
63
|
-
|
|
64
|
-
### Key exports
|
|
65
|
-
|
|
66
|
-
```ts
|
|
67
|
-
// Bridge and types
|
|
68
|
-
import {
|
|
69
|
-
createHostBridge,
|
|
70
|
-
type HostBridge,
|
|
71
|
-
type HostBridgeConfig,
|
|
72
|
-
type GraphNodeRaw,
|
|
73
|
-
type GraphEdgeRaw,
|
|
74
|
-
type UserProfile,
|
|
75
|
-
type OrgStructure,
|
|
76
|
-
} from '@bardioc/app-sdk';
|
|
77
|
-
|
|
78
|
-
// Errors
|
|
79
|
-
import {
|
|
80
|
-
EntityNotFoundError,
|
|
81
|
-
ValidationError,
|
|
82
|
-
PermissionError,
|
|
83
|
-
TimeoutError,
|
|
84
|
-
NetworkError,
|
|
85
|
-
SdkError,
|
|
86
|
-
} from '@bardioc/app-sdk';
|
|
87
|
-
|
|
88
|
-
// React hooks
|
|
89
|
-
import { AppSdkProvider, useSdk, useNotify, useSendToKernel } from '@bardioc/app-sdk/react';
|
|
90
|
-
|
|
91
|
-
// Standalone dev helpers
|
|
92
|
-
import { installDevBridge, isDevStandalone, isInsideIframe } from '@bardioc/app-sdk/dev';
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## Vite plugin
|
|
34
|
+
Without React:
|
|
96
35
|
|
|
97
36
|
```ts
|
|
98
|
-
|
|
99
|
-
import { bardiocApp } from '@bardioc/app-sdk/vite';
|
|
100
|
-
import react from '@vitejs/plugin-react';
|
|
101
|
-
import { defineConfig } from 'vite';
|
|
37
|
+
import { connect } from '@bardioc/app-sdk';
|
|
102
38
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
});
|
|
39
|
+
const bardioc = await connect();
|
|
40
|
+
const profile = await bardioc.os.profile.get();
|
|
106
41
|
```
|
|
107
42
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
### Platform fonts
|
|
111
|
-
|
|
112
|
-
The Bardioc platform guarantees a stable font endpoint wherever an app runs — like `/api/transport`, it is a public contract that will never be renamed or removed. Load it with one line in `index.html` and do **not** bundle font packages into your app:
|
|
43
|
+
## Exports
|
|
113
44
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
45
|
+
| Path | Contents |
|
|
46
|
+
| ---------------------------- | ------------------------------------------------------------- |
|
|
47
|
+
| `@bardioc/app-sdk` | `connect`, `Bardioc`, `BardiocError`, manifest, domain types |
|
|
48
|
+
| `@bardioc/app-sdk/react` | `AppSdkProvider` and hooks |
|
|
49
|
+
| `@bardioc/app-sdk/protocol` | the contract: `APP_METHODS`, `serve`, `acceptApp` — for hosts |
|
|
50
|
+
| `@bardioc/app-sdk/dev` | `installDevHost`, `isDevStandalone`, `isInsideIframe` |
|
|
51
|
+
| `@bardioc/app-sdk/dev-proxy` | `startDevAuthProxy` for dev servers without the Vite plugin |
|
|
52
|
+
| `@bardioc/app-sdk/vite` | `bardiocApp()`, `bardiocDevAuth()` |
|
|
53
|
+
| `@bardioc/app-sdk/testing` | `hostConformance`: the behaviour every host must share |
|
|
117
54
|
|
|
118
|
-
|
|
55
|
+
## API
|
|
119
56
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
New apps scaffolded with `create-bardioc-app` include the `<link>` already.
|
|
124
|
-
|
|
125
|
-
## Standalone Dev Session
|
|
57
|
+
```ts
|
|
58
|
+
const bardioc = await connect();
|
|
126
59
|
|
|
127
|
-
|
|
60
|
+
bardioc.context; // { appId, host: 'os' | 'dev', osConfig }
|
|
61
|
+
bardioc.onContextChange(context => {});
|
|
128
62
|
|
|
129
|
-
|
|
130
|
-
|
|
63
|
+
await bardioc.ui.notify('Saved.', 'success');
|
|
64
|
+
await bardioc.ui.setCommands([{ id: 'save', title: 'Save' }]);
|
|
65
|
+
await bardioc.ui.setMenu([{ label: 'File', items: [{ type: 'command', commandId: 'save' }] }]);
|
|
66
|
+
const off = bardioc.ui.onCommand('save', () => save());
|
|
131
67
|
|
|
132
|
-
|
|
68
|
+
await bardioc.bff.request({ path: '/os/me/profile' }); // any BFF path outside /auth
|
|
69
|
+
await bardioc.graph.query('ogit/_type:ogit/Note', { limit: 10 });
|
|
70
|
+
await bardioc.os.organization.getStructure();
|
|
71
|
+
await bardioc.relay('notes').request({ path: '/items' });
|
|
133
72
|
|
|
134
|
-
|
|
73
|
+
const notes = bardioc.idb('notes');
|
|
74
|
+
await notes.put('n1', { title: 'Hi' });
|
|
75
|
+
await notes.get('n1'); // { key, value, updatedAt } | null
|
|
135
76
|
|
|
136
|
-
|
|
137
|
-
|
|
77
|
+
const end = await bardioc.events.graph({ types: ['ogit/Note'] }, event => {});
|
|
78
|
+
end();
|
|
138
79
|
|
|
139
|
-
|
|
140
|
-
await startDevAuthProxy({ projectDir: process.cwd(), port: 3105 });
|
|
80
|
+
await bardioc.apps.list();
|
|
141
81
|
```
|
|
142
82
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
## React hooks
|
|
83
|
+
Scope: a call without `scopeId` uses the window's instance; `scopeId` makes the scope required;
|
|
84
|
+
`scopePolicy: 'none'` sends none.
|
|
146
85
|
|
|
147
|
-
|
|
148
|
-
- `useNotify()` — fire-and-forget toast
|
|
149
|
-
- `useSendToKernel()` — proxy a whitelisted message to the OS service worker
|
|
86
|
+
### React hooks
|
|
150
87
|
|
|
151
|
-
|
|
88
|
+
`useSdk()`, `useNotify()`, `useCommandMenu(commands, menu)`, `useActiveTab(tab)`,
|
|
89
|
+
`useOsConfig()`, `useGraphEvents({ types }, handler)`.
|
|
152
90
|
|
|
153
|
-
|
|
91
|
+
### Errors
|
|
154
92
|
|
|
155
93
|
```ts
|
|
156
|
-
|
|
94
|
+
import { BardiocError } from '@bardioc/app-sdk';
|
|
157
95
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
await drafts.delete('welcome');
|
|
96
|
+
try {
|
|
97
|
+
await bardioc.graph.get(id);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
if (error instanceof BardiocError && error.code === 'not_found') return null;
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
165
102
|
```
|
|
166
103
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
The bridge provides namespaced transport APIs for graph database and OS operations.
|
|
104
|
+
Codes: `invalid`, `unauthenticated`, `forbidden`, `not_found`, `conflict`, `rate_limited`,
|
|
105
|
+
`unavailable`, `timeout`, `cancelled`, `protocol`, `internal`. HTTP failures carry `status` and the
|
|
106
|
+
response body as `details`.
|
|
172
107
|
|
|
173
|
-
|
|
108
|
+
## Standalone development
|
|
174
109
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
Access the graph database via `bridge.transport.graph.*`:
|
|
110
|
+
1. Set `DEV_SECRET` and `API_BASE_URL` in `.env`.
|
|
111
|
+
2. Install the dev host before rendering, then run `pnpm dev`:
|
|
178
112
|
|
|
179
113
|
```ts
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
// Get single node
|
|
183
|
-
const node = await sdk.transport.graph.get<GraphNodeRaw>('node-id');
|
|
184
|
-
|
|
185
|
-
// Query with Lucene
|
|
186
|
-
const people = await sdk.transport.graph.query<GraphNodeRaw>(
|
|
187
|
-
'ogit/_type:ogit/Person AND ogit/name:John*',
|
|
188
|
-
{ limit: 50, offset: 0, scopeId: 'instance-scope-id' }
|
|
189
|
-
);
|
|
190
|
-
|
|
191
|
-
// Gremlin traversal
|
|
192
|
-
const edges = await sdk.transport.graph.gremlin(rootId, "outE('ogit/relates')");
|
|
193
|
-
|
|
194
|
-
// Create node
|
|
195
|
-
const newNode = await sdk.transport.graph.create('ogit/Person', {
|
|
196
|
-
'ogit/name': 'Jane Doe',
|
|
197
|
-
'ogit/email': 'jane@example.com',
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
// Update node
|
|
201
|
-
await sdk.transport.graph.update('node-id', {
|
|
202
|
-
'ogit/name': 'Updated Name',
|
|
203
|
-
});
|
|
114
|
+
import { installDevHost, isDevStandalone } from '@bardioc/app-sdk/dev';
|
|
204
115
|
|
|
205
|
-
|
|
206
|
-
await sdk.transport.graph.connect(fromId, toId, 'ogit/relates');
|
|
207
|
-
|
|
208
|
-
// Delete node
|
|
209
|
-
await sdk.transport.graph.delete('node-id');
|
|
210
|
-
|
|
211
|
-
// Combined query: Elasticsearch picks the start vertices, Gremlin traverses from them
|
|
212
|
-
const speeches = await sdk.transport.graph.combined(
|
|
213
|
-
'+(ogit\\/_type: "ogit/Politics/AgendaItem")',
|
|
214
|
-
"inE().outV().has('ogit/_type', 'ogit/Politics/Discussion')",
|
|
215
|
-
{ limit: 1000 }
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
// Time series
|
|
219
|
-
const values = await sdk.transport.graph.timeseries.get('ts-id', {
|
|
220
|
-
from: '2026-01-01',
|
|
221
|
-
to: '2026-01-31',
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
// Several series in one request, averaged per timestamp
|
|
225
|
-
const merged = await sdk.transport.graph.timeseries.get('ts-id', {
|
|
226
|
-
from: '2026-01-01',
|
|
227
|
-
to: '2026-01-31',
|
|
228
|
-
withIds: ['ts-id-2', 'ts-id-3'],
|
|
229
|
-
aggregate: 'avg',
|
|
230
|
-
});
|
|
116
|
+
if (isDevStandalone()) installDevHost({ appId: 'my-app' });
|
|
231
117
|
```
|
|
232
118
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
it), and time series entries carry only `timestamp` and `value` (read one ID per request when values
|
|
238
|
-
must stay attributable).
|
|
239
|
-
|
|
240
|
-
All graph request option types accept optional `scopeId` when a request must target a specific scope.
|
|
119
|
+
The dev host answers the same contract as the Bardioc host: BFF calls go through the dev-auth
|
|
120
|
+
proxy (the `bardiocDevAuth` Vite plugin, or `startDevAuthProxy` beside angular and nextjs dev
|
|
121
|
+
servers — pass its origin as `apiBaseUrl`), `idb` lives in this browser's IndexedDB, `ui` calls
|
|
122
|
+
are acknowledged, and `apps` answer `unavailable`.
|
|
241
123
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
Access OS features via `bridge.transport.os.*`:
|
|
124
|
+
## Vite plugin
|
|
245
125
|
|
|
246
126
|
```ts
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const avatar = await sdk.transport.os.profile.getAvatar();
|
|
252
|
-
await sdk.transport.os.profile.setAvatar(imageBlob);
|
|
253
|
-
|
|
254
|
-
// Organization
|
|
255
|
-
const org = await sdk.transport.os.organization.getStructure();
|
|
256
|
-
const unit = await sdk.transport.os.organization.createUnit({
|
|
257
|
-
name: 'Engineering',
|
|
258
|
-
parentId: 'parent-unit-id',
|
|
259
|
-
});
|
|
127
|
+
// vite.config.ts
|
|
128
|
+
import { bardiocApp } from '@bardioc/app-sdk/vite';
|
|
129
|
+
import react from '@vitejs/plugin-react';
|
|
130
|
+
import { defineConfig } from 'vite';
|
|
260
131
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
const app = await sdk.transport.os.applications.get('app-id');
|
|
264
|
-
await sdk.transport.os.applications.upload('app-id', zipBlob);
|
|
265
|
-
await sdk.transport.os.request({
|
|
266
|
-
path: '/custom/endpoint',
|
|
267
|
-
method: 'GET',
|
|
268
|
-
scopeId: 'instance-scope-id',
|
|
132
|
+
export default defineConfig({
|
|
133
|
+
plugins: [react(), bardiocApp({ appName: 'my-app', port: 3005 })],
|
|
269
134
|
});
|
|
270
135
|
```
|
|
271
136
|
|
|
272
|
-
|
|
137
|
+
Handles dev base path, port config, host session proxy routes, platform fonts, and manifest validation on build.
|
|
273
138
|
|
|
274
|
-
|
|
275
|
-
- `os.organization.*` — `getStructure`, `createUnit`, `updateUnit`, `createMember`, `updateMember`, `deleteMember`, `inviteMember`
|
|
276
|
-
- `os.applications.*` — `list`, `get`, `upload`, `download`, `getFiles`, `getFile`, `getConfigurations`
|
|
139
|
+
### Platform fonts
|
|
277
140
|
|
|
278
|
-
|
|
141
|
+
The Bardioc platform guarantees a stable font endpoint wherever an app runs — like `/api/transport`, it is a public contract that will never be renamed or removed. Load it with one line in `index.html` and do **not** bundle font packages into your app:
|
|
279
142
|
|
|
280
|
-
|
|
143
|
+
```html
|
|
144
|
+
<link rel="stylesheet" href="/fonts/bardioc-fonts.css" />
|
|
145
|
+
```
|
|
281
146
|
|
|
282
|
-
|
|
283
|
-
import {
|
|
284
|
-
EntityNotFoundError,
|
|
285
|
-
ValidationError,
|
|
286
|
-
PermissionError,
|
|
287
|
-
TimeoutError,
|
|
288
|
-
NetworkError,
|
|
289
|
-
SdkError,
|
|
290
|
-
} from '@bardioc/app-sdk';
|
|
147
|
+
It provides `Nunito Sans Variable` (normal + italic) and `Geist Mono Variable` as variable fonts (latin subset), matching the `--font-nunito-sans` / `--font-geist-mono` theme variables that `@bardioc/ui` resolves by default.
|
|
291
148
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
} catch (error) {
|
|
295
|
-
if (error instanceof EntityNotFoundError) {
|
|
296
|
-
console.log('Node not found:', error.context.id);
|
|
297
|
-
} else if (error instanceof ValidationError) {
|
|
298
|
-
console.log('Invalid data:', error.context?.field);
|
|
299
|
-
} else if (error instanceof PermissionError) {
|
|
300
|
-
console.log('Missing permission:', error.context.permission);
|
|
301
|
-
} else if (error instanceof TimeoutError) {
|
|
302
|
-
console.log('Request timed out:', error.context.operation);
|
|
303
|
-
} else if (error instanceof NetworkError) {
|
|
304
|
-
console.log('Network error:', error.statusCode, error.message);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
```
|
|
149
|
+
- **Embedded in the OS** the URL resolves same-origin against the host, which serves it with immutable caching — one download shared by the host and every app.
|
|
150
|
+
- **Standalone dev** the `bardiocApp()` plugin serves the same files from assets shipped inside this package (dev server only — they are never added to your bundle). This applies to Vite-based apps; the angular and nextjs templates run their own dev servers, where the link is a harmless 404 standalone and resolves normally embedded in the OS.
|
|
308
151
|
|
|
309
|
-
|
|
152
|
+
New apps scaffolded with `create-bardioc-app` include the `<link>` already.
|
|
310
153
|
|
|
311
154
|
## App manifest
|
|
312
155
|
|
|
@@ -317,19 +160,10 @@ Every app must include `public/app-manifest.json`:
|
|
|
317
160
|
"manifestVersion": 2,
|
|
318
161
|
"id": "my-app",
|
|
319
162
|
"name": "My App",
|
|
320
|
-
"version": "1.0.0"
|
|
321
|
-
"permissions": ["notify", "transport"]
|
|
163
|
+
"version": "1.0.0"
|
|
322
164
|
}
|
|
323
165
|
```
|
|
324
166
|
|
|
325
|
-
Available permissions:
|
|
326
|
-
|
|
327
|
-
- `notify` — Show toast notifications via `bridge.notify()`
|
|
328
|
-
- `storage` — Key-value storage via `bridge.storage.*`
|
|
329
|
-
- `indexdb` — App-scoped IndexedDB via `bridge.idb()`
|
|
330
|
-
- `kernel-proxy` — Message the OS service worker via `bridge.sendToKernel()`
|
|
331
|
-
- `transport` — Access graph and OS APIs via `bridge.transport.*`
|
|
332
|
-
|
|
333
167
|
The Vite plugin validates this automatically and fails the build when the manifest is missing or invalid.
|
|
334
168
|
|
|
335
169
|
### Window
|
|
@@ -342,7 +176,6 @@ Optionally control how the OS frames the app via a `window` block:
|
|
|
342
176
|
"id": "my-app",
|
|
343
177
|
"name": "My App",
|
|
344
178
|
"version": "1.0.0",
|
|
345
|
-
"permissions": ["notify"],
|
|
346
179
|
"window": {
|
|
347
180
|
"size": "md",
|
|
348
181
|
"resizable": true
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { BatchResult, CombinedQueryOptions, DeleteOptions, GetNodeOptions, GraphEdgeRaw, GraphNodeRaw, GremlinOptions, HistoryEntry, HistoryOptions, MutationOptions, QueryOptions, TimeseriesHistory, TimeseriesHistoryOptions, TimeseriesOptions, TimeseriesQueryOptions, TimeseriesValue, TransportScopeOptions } from '../types.js';
|
|
2
|
+
import { type BffRequester } from './request.js';
|
|
3
|
+
/** The Bardioc graph API, called through the host. */
|
|
4
|
+
export declare function graphApi(request: BffRequester): {
|
|
5
|
+
get: <T = GraphNodeRaw>(id: string, options?: GetNodeOptions) => Promise<T>;
|
|
6
|
+
getMany: <T = GraphNodeRaw>(ids: string[], options?: GetNodeOptions) => Promise<(T | undefined)[]>;
|
|
7
|
+
getByXid: <T = GraphNodeRaw>(xid: string, options?: GetNodeOptions) => Promise<T>;
|
|
8
|
+
query: <T = GraphNodeRaw>(lucene: string, options?: QueryOptions) => Promise<T[]>;
|
|
9
|
+
gremlin: <T = unknown>(rootId: string, query: string, options?: GremlinOptions) => Promise<T[]>;
|
|
10
|
+
combined: <T = unknown>(elasticsearchQuery: string, gremlinQuery: string, options?: CombinedQueryOptions) => Promise<T[]>;
|
|
11
|
+
create: <T = GraphNodeRaw>(type: string, data: Record<string, unknown>, options?: MutationOptions) => Promise<T>;
|
|
12
|
+
update: <T = GraphNodeRaw>(id: string, data: Record<string, unknown>, options?: MutationOptions) => Promise<T>;
|
|
13
|
+
delete: (id: string, options?: DeleteOptions) => Promise<void>;
|
|
14
|
+
connect: <T = GraphEdgeRaw>(from: string, to: string, type: string, options?: MutationOptions) => Promise<T>;
|
|
15
|
+
history: (id: string, options?: HistoryOptions) => Promise<HistoryEntry[]>;
|
|
16
|
+
batch: {
|
|
17
|
+
delete: (ids: string[], options?: DeleteOptions) => Promise<BatchResult>;
|
|
18
|
+
};
|
|
19
|
+
timeseries: {
|
|
20
|
+
get: (id: string, options?: TimeseriesOptions) => Promise<TimeseriesValue[]>;
|
|
21
|
+
add: (id: string, values: TimeseriesValue[], options?: TransportScopeOptions) => Promise<void>;
|
|
22
|
+
query: (options: TimeseriesQueryOptions) => Promise<TimeseriesValue[]>;
|
|
23
|
+
history: (id: string, timestamp: number, options?: TimeseriesHistoryOptions) => Promise<TimeseriesHistory>;
|
|
24
|
+
};
|
|
25
|
+
content: {
|
|
26
|
+
set: (id: string, data: Blob, contentType: string, options?: TransportScopeOptions) => Promise<string>;
|
|
27
|
+
get: (id: string, contentId: string, options?: TransportScopeOptions) => Promise<Blob>;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export type GraphApi = ReturnType<typeof graphApi>;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { json, scoped, withQuery } from './request.js';
|
|
2
|
+
const GRAPH = '/bardioc/api/graph/7.4';
|
|
3
|
+
const node = (id, suffix = '') => `${GRAPH}/${encodeURIComponent(id)}${suffix}`;
|
|
4
|
+
const readFields = ({ fields, includeDeleted, listMeta }) => ({
|
|
5
|
+
fields,
|
|
6
|
+
includeDeleted,
|
|
7
|
+
listMeta,
|
|
8
|
+
});
|
|
9
|
+
const mutationQuery = ({ fullResponse, listMeta }) => ({ fullResponse, listMeta });
|
|
10
|
+
/** The Bardioc graph API, called through the host. */
|
|
11
|
+
export function graphApi(request) {
|
|
12
|
+
const get = (id, options = {}) => request({
|
|
13
|
+
path: withQuery(node(id), { ...readFields(options), vid: options.vid }),
|
|
14
|
+
...scoped(options),
|
|
15
|
+
});
|
|
16
|
+
const remove = (id, options = {}) => request({
|
|
17
|
+
path: withQuery(node(id), { hard: options.hard }),
|
|
18
|
+
method: 'DELETE',
|
|
19
|
+
...scoped(options),
|
|
20
|
+
});
|
|
21
|
+
return {
|
|
22
|
+
get,
|
|
23
|
+
getMany: (ids, options = {}) => request({
|
|
24
|
+
path: withQuery(`${GRAPH}/query/ids`, { query: ids.join(','), ...readFields(options) }),
|
|
25
|
+
...scoped(options),
|
|
26
|
+
}),
|
|
27
|
+
getByXid: (xid, options = {}) => request({
|
|
28
|
+
path: withQuery(`${GRAPH}/xid/${encodeURIComponent(xid)}`, readFields(options)),
|
|
29
|
+
...scoped(options),
|
|
30
|
+
}),
|
|
31
|
+
query: (lucene, options = {}) => request({
|
|
32
|
+
path: withQuery(`${GRAPH}/query/vertices`, {
|
|
33
|
+
query: lucene,
|
|
34
|
+
limit: options.limit,
|
|
35
|
+
offset: options.offset,
|
|
36
|
+
order: options.order,
|
|
37
|
+
...readFields(options),
|
|
38
|
+
}),
|
|
39
|
+
...scoped(options),
|
|
40
|
+
}),
|
|
41
|
+
gremlin: (rootId, query, options = {}) => request({
|
|
42
|
+
path: `${GRAPH}/query/gremlin`,
|
|
43
|
+
...json({ root: rootId, query, ...readFields(options) }),
|
|
44
|
+
...scoped(options),
|
|
45
|
+
}),
|
|
46
|
+
combined: (elasticsearchQuery, gremlinQuery, options = {}) => request({
|
|
47
|
+
path: `${GRAPH}/query/combined`,
|
|
48
|
+
...json({
|
|
49
|
+
elasticsearch_query: elasticsearchQuery,
|
|
50
|
+
gremlin_query: gremlinQuery,
|
|
51
|
+
limit: options.limit,
|
|
52
|
+
}),
|
|
53
|
+
...scoped(options),
|
|
54
|
+
}),
|
|
55
|
+
create: (type, data, options = {}) => request({
|
|
56
|
+
path: withQuery(`${GRAPH}/new/${encodeURIComponent(type)}`, mutationQuery(options)),
|
|
57
|
+
...json(data),
|
|
58
|
+
...scoped(options),
|
|
59
|
+
}),
|
|
60
|
+
update: (id, data, options = {}) => request({
|
|
61
|
+
path: withQuery(node(id), mutationQuery(options)),
|
|
62
|
+
...json(data),
|
|
63
|
+
...scoped(options),
|
|
64
|
+
}),
|
|
65
|
+
delete: remove,
|
|
66
|
+
connect: (from, to, type, options = {}) => request({
|
|
67
|
+
path: withQuery(`${GRAPH}/connect`, mutationQuery(options)),
|
|
68
|
+
...json({ fromId: from, toId: to, edgeType: type }),
|
|
69
|
+
...scoped(options),
|
|
70
|
+
}),
|
|
71
|
+
history: (id, options = {}) => request({
|
|
72
|
+
path: withQuery(node(id, '/history'), {
|
|
73
|
+
from: options.from,
|
|
74
|
+
to: options.to,
|
|
75
|
+
limit: options.limit,
|
|
76
|
+
offset: options.offset,
|
|
77
|
+
includeDeleted: options.includeDeleted,
|
|
78
|
+
}),
|
|
79
|
+
...scoped(options),
|
|
80
|
+
}),
|
|
81
|
+
batch: {
|
|
82
|
+
delete: async (ids, options = {}) => {
|
|
83
|
+
const results = await Promise.allSettled(ids.map(id => remove(id, options)));
|
|
84
|
+
const result = { succeeded: [], failed: [] };
|
|
85
|
+
results.forEach((outcome, index) => {
|
|
86
|
+
const id = ids[index];
|
|
87
|
+
if (outcome.status === 'fulfilled')
|
|
88
|
+
result.succeeded.push(id);
|
|
89
|
+
else
|
|
90
|
+
result.failed.push({ id, error: String(outcome.reason?.message ?? outcome.reason) });
|
|
91
|
+
});
|
|
92
|
+
return result;
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
timeseries: {
|
|
96
|
+
get: (id, options = {}) => request({
|
|
97
|
+
path: withQuery(node(id, '/values'), {
|
|
98
|
+
from: options.from,
|
|
99
|
+
to: options.to,
|
|
100
|
+
limit: options.limit,
|
|
101
|
+
order: options.order,
|
|
102
|
+
with: options.withIds?.join(','),
|
|
103
|
+
aggregate: options.aggregate,
|
|
104
|
+
includeDeleted: options.includeDeleted,
|
|
105
|
+
}),
|
|
106
|
+
...scoped(options),
|
|
107
|
+
}),
|
|
108
|
+
add: (id, values, options = {}) => request({ path: node(id, '/values'), ...json({ values }), ...scoped(options) }),
|
|
109
|
+
query: (options) => request({
|
|
110
|
+
path: withQuery(`${GRAPH}/query/values`, {
|
|
111
|
+
ids: options.ids?.join(','),
|
|
112
|
+
from: options.from,
|
|
113
|
+
to: options.to,
|
|
114
|
+
limit: options.limit,
|
|
115
|
+
order: options.order,
|
|
116
|
+
aggregate: options.aggregate,
|
|
117
|
+
}),
|
|
118
|
+
...scoped(options),
|
|
119
|
+
}),
|
|
120
|
+
history: (id, timestamp, options = {}) => request({
|
|
121
|
+
path: withQuery(node(id, '/values/history'), {
|
|
122
|
+
timestamp,
|
|
123
|
+
includeDeleted: options.includeDeleted,
|
|
124
|
+
}),
|
|
125
|
+
...scoped(options),
|
|
126
|
+
}),
|
|
127
|
+
},
|
|
128
|
+
content: {
|
|
129
|
+
set: async (id, data, contentType, options = {}) => (await request({
|
|
130
|
+
path: node(id, '/content'),
|
|
131
|
+
method: 'POST',
|
|
132
|
+
body: data,
|
|
133
|
+
contentType,
|
|
134
|
+
...scoped(options),
|
|
135
|
+
})).contentId,
|
|
136
|
+
get: (id, contentId, options = {}) => request({ path: withQuery(node(id, '/content'), { contentId }), ...scoped(options) }),
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
package/dist/api/os.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Application, Configuration, CreateMemberInput, CreateUnitInput, FileEntry, InstanceList, OrgMember, OrgStructure, OrgUnit, UpdateMemberInput, UpdateUnitInput, UserProfile } from '../types.js';
|
|
2
|
+
import { type BffRequester } from './request.js';
|
|
3
|
+
/** The Bardioc OS API, called through the host. */
|
|
4
|
+
export declare function osApi(request: BffRequester): {
|
|
5
|
+
profile: {
|
|
6
|
+
get: () => Promise<UserProfile>;
|
|
7
|
+
getAvatar: () => Promise<Blob>;
|
|
8
|
+
setAvatar: (image: Blob) => Promise<void>;
|
|
9
|
+
getInstances: () => Promise<InstanceList>;
|
|
10
|
+
};
|
|
11
|
+
organization: {
|
|
12
|
+
getStructure: () => Promise<OrgStructure>;
|
|
13
|
+
createUnit: (data: CreateUnitInput) => Promise<OrgUnit>;
|
|
14
|
+
updateUnit: (id: string, data: UpdateUnitInput) => Promise<OrgUnit>;
|
|
15
|
+
createMember: (data: CreateMemberInput) => Promise<OrgMember>;
|
|
16
|
+
updateMember: (id: string, data: UpdateMemberInput) => Promise<OrgMember>;
|
|
17
|
+
deleteMember: (id: string) => Promise<void>;
|
|
18
|
+
inviteMember: (id: string) => Promise<void>;
|
|
19
|
+
};
|
|
20
|
+
applications: {
|
|
21
|
+
list: () => Promise<Application[]>;
|
|
22
|
+
get: (id: string) => Promise<Application>;
|
|
23
|
+
upload: (id: string, zip: Blob) => Promise<void>;
|
|
24
|
+
download: (id: string) => Promise<Blob>;
|
|
25
|
+
getFiles: (id: string) => Promise<FileEntry[]>;
|
|
26
|
+
getFile: (id: string, path: string) => Promise<string>;
|
|
27
|
+
getConfigurations: (id: string) => Promise<Configuration[]>;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export type OsApi = ReturnType<typeof osApi>;
|