@bardioc/app-sdk 1.0.0 → 1.0.2
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/dist/client.d.ts +4 -0
- package/dist/client.js +4 -0
- package/dist/contract.d.ts +39 -0
- package/dist/contract.js +6 -0
- package/dist/dev-idb.d.ts +1 -1
- package/dist/dev-idb.js +2 -2
- package/dist/dev.d.ts +2 -6
- package/dist/dev.js +18 -7
- package/dist/index.d.ts +1 -1
- package/dist/protocol.d.ts +1 -1
- package/dist/react.d.ts +3 -1
- package/dist/react.js +11 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -113,7 +113,7 @@ response body as `details`.
|
|
|
113
113
|
```ts
|
|
114
114
|
import { installDevHost, isDevStandalone } from '@bardioc/app-sdk/dev';
|
|
115
115
|
|
|
116
|
-
if (isDevStandalone()) installDevHost(
|
|
116
|
+
if (isDevStandalone()) installDevHost();
|
|
117
117
|
```
|
|
118
118
|
|
|
119
119
|
The dev host answers the same contract as the Bardioc host: BFF calls go through the dev-auth
|
package/dist/client.d.ts
CHANGED
|
@@ -96,6 +96,10 @@ declare function open(port: MessagePort, initial: Context): {
|
|
|
96
96
|
launch: (id: string) => Promise<{
|
|
97
97
|
windowId: string | null;
|
|
98
98
|
}>;
|
|
99
|
+
/** The caller's settings of the developer application `id`, as the host holds them. */
|
|
100
|
+
getConfig: (id: string) => Promise<import("./contract.js").DevAppConfig>;
|
|
101
|
+
/** Replaces them with the edited document; the host applies the answer at once. */
|
|
102
|
+
saveConfig: (id: string, data: Record<string, unknown>) => Promise<import("./contract.js").DevAppConfig>;
|
|
99
103
|
};
|
|
100
104
|
};
|
|
101
105
|
export type Bardioc = ReturnType<typeof open>;
|
package/dist/client.js
CHANGED
|
@@ -92,6 +92,10 @@ function open(port, initial) {
|
|
|
92
92
|
/** The file contents are transferred to the host and unusable here afterwards. */
|
|
93
93
|
upload: (upload) => call('apps.upload', upload, { transfer: upload.files.map(file => file.content) }),
|
|
94
94
|
launch: (id) => call('apps.launch', { id }),
|
|
95
|
+
/** The caller's settings of the developer application `id`, as the host holds them. */
|
|
96
|
+
getConfig: (id) => call('apps.getConfig', { id }),
|
|
97
|
+
/** Replaces them with the edited document; the host applies the answer at once. */
|
|
98
|
+
saveConfig: (id, data) => call('apps.saveConfig', { id, data }),
|
|
95
99
|
},
|
|
96
100
|
};
|
|
97
101
|
}
|
package/dist/contract.d.ts
CHANGED
|
@@ -122,11 +122,43 @@ export interface OsConfig {
|
|
|
122
122
|
windowId: string;
|
|
123
123
|
instanceId: string | null;
|
|
124
124
|
}
|
|
125
|
+
/** A setting's value as the configuration service holds it. */
|
|
126
|
+
export type SettingValue = string | number | boolean | null;
|
|
125
127
|
/** What the host tells an app when it connects, and again whenever it changes. */
|
|
126
128
|
export interface Context {
|
|
127
129
|
appId: string;
|
|
128
130
|
host: 'os' | 'dev';
|
|
129
131
|
osConfig: OsConfig;
|
|
132
|
+
/** The app's own settings, keyed `<group>.<field>` as its manifest declares them. */
|
|
133
|
+
settings?: Record<string, SettingValue>;
|
|
134
|
+
}
|
|
135
|
+
/** One setting as the configuration service renders it: value, flags and declared metadata. */
|
|
136
|
+
export interface Setting {
|
|
137
|
+
value: SettingValue;
|
|
138
|
+
type: string;
|
|
139
|
+
editable: boolean;
|
|
140
|
+
hidden: boolean;
|
|
141
|
+
immutable: boolean;
|
|
142
|
+
declared: boolean;
|
|
143
|
+
origin: string;
|
|
144
|
+
section: string;
|
|
145
|
+
label?: string;
|
|
146
|
+
description?: string;
|
|
147
|
+
unit?: string;
|
|
148
|
+
enum?: SettingValue[];
|
|
149
|
+
min?: number;
|
|
150
|
+
max?: number;
|
|
151
|
+
step?: number;
|
|
152
|
+
order?: number;
|
|
153
|
+
appId?: string;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* A developer's own settings of a developer application: `data` is the document they edit
|
|
157
|
+
* (keys `apps.<id>.<group>.<field>`, group flags under `<group>.__flags`), `settings` its view.
|
|
158
|
+
*/
|
|
159
|
+
export interface DevAppConfig {
|
|
160
|
+
data: Record<string, unknown>;
|
|
161
|
+
settings: Record<string, Setting>;
|
|
130
162
|
}
|
|
131
163
|
export interface IdbEntry<T = unknown> {
|
|
132
164
|
key: string;
|
|
@@ -274,6 +306,13 @@ export declare const APP_METHODS: {
|
|
|
274
306
|
}, z.core.$strict>, {
|
|
275
307
|
windowId: string | null;
|
|
276
308
|
}>;
|
|
309
|
+
readonly 'apps.getConfig': CallMethod<z.ZodMiniObject<{
|
|
310
|
+
id: z.ZodMiniString<string>;
|
|
311
|
+
}, z.core.$strict>, DevAppConfig>;
|
|
312
|
+
readonly 'apps.saveConfig': CallMethod<z.ZodMiniObject<{
|
|
313
|
+
id: z.ZodMiniString<string>;
|
|
314
|
+
data: z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnknown>;
|
|
315
|
+
}, z.core.$strict>, DevAppConfig>;
|
|
277
316
|
};
|
|
278
317
|
/** Methods a host calls on its app. */
|
|
279
318
|
export declare const HOST_METHODS: {
|
package/dist/contract.js
CHANGED
|
@@ -103,6 +103,10 @@ const AppRecord = z.strictObject({
|
|
|
103
103
|
bundleSize: z.optional(count),
|
|
104
104
|
fileCount: z.optional(count),
|
|
105
105
|
});
|
|
106
|
+
const AppConfigSave = z.strictObject({
|
|
107
|
+
id: text,
|
|
108
|
+
data: z.record(z.string(), z.unknown()),
|
|
109
|
+
});
|
|
106
110
|
const AppUpload = z.strictObject({
|
|
107
111
|
alias: text,
|
|
108
112
|
name: text,
|
|
@@ -138,6 +142,8 @@ export const APP_METHODS = {
|
|
|
138
142
|
'apps.delete': call(AppId).returns(),
|
|
139
143
|
'apps.upload': call(AppUpload).returns(120_000),
|
|
140
144
|
'apps.launch': call(AppId).returns(),
|
|
145
|
+
'apps.getConfig': call(AppId).returns(),
|
|
146
|
+
'apps.saveConfig': call(AppConfigSave).returns(),
|
|
141
147
|
};
|
|
142
148
|
/** Methods a host calls on its app. */
|
|
143
149
|
export const HOST_METHODS = {
|
package/dist/dev-idb.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AppMethods, IdbEntry, Params } from './contract.js';
|
|
2
2
|
type In<K extends keyof AppMethods> = Params<AppMethods[K]>;
|
|
3
3
|
/** The host's app storage, kept in this browser's IndexedDB while running standalone. */
|
|
4
|
-
export declare function devIdb(
|
|
4
|
+
export declare function devIdb(): {
|
|
5
5
|
get: ({ store, key }: In<"idb.get">) => Promise<IdbEntry<unknown> | null>;
|
|
6
6
|
put: ({ store, key, value }: In<"idb.put">) => Promise<void>;
|
|
7
7
|
delete: ({ store, key }: In<"idb.delete">) => Promise<void>;
|
package/dist/dev-idb.js
CHANGED
|
@@ -12,11 +12,11 @@ function open(name) {
|
|
|
12
12
|
}
|
|
13
13
|
const toEntry = ({ key, value, updatedAt }) => ({ key, value, updatedAt });
|
|
14
14
|
/** The host's app storage, kept in this browser's IndexedDB while running standalone. */
|
|
15
|
-
export function devIdb(
|
|
15
|
+
export function devIdb() {
|
|
16
16
|
// Opened on first use: most apps never touch their store.
|
|
17
17
|
let db;
|
|
18
18
|
const entries = async (mode) => {
|
|
19
|
-
db ??= open(
|
|
19
|
+
db ??= open('bardioc-dev');
|
|
20
20
|
return (await db).transaction(ENTRIES, mode).objectStore(ENTRIES);
|
|
21
21
|
};
|
|
22
22
|
return {
|
package/dist/dev.d.ts
CHANGED
|
@@ -2,17 +2,13 @@ import { type HostHandlers } from './serve.js';
|
|
|
2
2
|
export declare function isInsideIframe(): boolean;
|
|
3
3
|
export declare function isDevStandalone(): boolean;
|
|
4
4
|
export interface DevHostOptions {
|
|
5
|
-
/** The app's manifest id, handed to the app as `context.appId`. */
|
|
6
|
-
appId: string;
|
|
7
|
-
/** The app's ogit/Auth/Application id, sent as `X-App-ID` on scoped calls; defaults to `appId`. */
|
|
8
|
-
clientId?: string;
|
|
9
5
|
/** Where the dev-auth proxy answers `/rest`. Default: `/rest` on this origin. */
|
|
10
6
|
apiBaseUrl?: string;
|
|
11
7
|
}
|
|
12
8
|
/** The dev host's answers to every app method. */
|
|
13
|
-
export declare function devHandlers({
|
|
9
|
+
export declare function devHandlers({ apiBaseUrl }?: DevHostOptions): HostHandlers;
|
|
14
10
|
/**
|
|
15
11
|
* Stands in for the host while the app runs standalone in development: `connect()` reaches it
|
|
16
12
|
* the way it reaches the host, and BFF calls go through the dev-auth proxy.
|
|
17
13
|
*/
|
|
18
|
-
export declare function installDevHost(options
|
|
14
|
+
export declare function installDevHost(options?: DevHostOptions): () => void;
|
package/dist/dev.js
CHANGED
|
@@ -23,8 +23,8 @@ const unavailable = () => {
|
|
|
23
23
|
throw new BardiocError('unavailable', 'Installed apps live in the Bardioc host');
|
|
24
24
|
};
|
|
25
25
|
/** The dev host's answers to every app method. */
|
|
26
|
-
export function devHandlers({
|
|
27
|
-
const idb = devIdb(
|
|
26
|
+
export function devHandlers({ apiBaseUrl = '/rest' } = {}) {
|
|
27
|
+
const idb = devIdb();
|
|
28
28
|
const request = async ({ path, method = 'GET', body, contentType, scopeId, scopePolicy }, signal) => {
|
|
29
29
|
if (scopePolicy === 'required' && !scopeId) {
|
|
30
30
|
throw new BardiocError('invalid', 'scopeId is required: a dev session has no instance');
|
|
@@ -32,10 +32,9 @@ export function devHandlers({ appId, clientId = appId, apiBaseUrl = '/rest', })
|
|
|
32
32
|
const headers = new Headers({ 'X-Requested-With': 'XMLHttpRequest' });
|
|
33
33
|
if (contentType && body !== undefined)
|
|
34
34
|
headers.set('Content-Type', contentType);
|
|
35
|
-
|
|
35
|
+
// No X-App-ID: a dev app claims no app token and runs on the user's own.
|
|
36
|
+
if (scopeId)
|
|
36
37
|
headers.set('X-Scope-ID', scopeId);
|
|
37
|
-
headers.set('X-App-ID', clientId);
|
|
38
|
-
}
|
|
39
38
|
const encoded = contentType === 'application/json' ? JSON.stringify(body) : body;
|
|
40
39
|
const response = await fetch(`${apiBaseUrl}${path}`, {
|
|
41
40
|
method,
|
|
@@ -58,6 +57,16 @@ export function devHandlers({ appId, clientId = appId, apiBaseUrl = '/rest', })
|
|
|
58
57
|
}
|
|
59
58
|
return () => source.close();
|
|
60
59
|
};
|
|
60
|
+
// The BFF's own answer, so a standalone app tries the settings the host would hold.
|
|
61
|
+
const devConfig = async (id, signal, data) => {
|
|
62
|
+
const layer = (await request({
|
|
63
|
+
path: `/os/dev/config/apps/${encodeURIComponent(id)}`,
|
|
64
|
+
method: data ? 'PUT' : 'GET',
|
|
65
|
+
body: data ? { layer: 'dev', data } : undefined,
|
|
66
|
+
contentType: data ? 'application/json' : undefined,
|
|
67
|
+
}, signal));
|
|
68
|
+
return { data: layer.data ?? {}, settings: layer.settings ?? {} };
|
|
69
|
+
};
|
|
61
70
|
return {
|
|
62
71
|
'ui.notify': () => undefined,
|
|
63
72
|
'ui.setCommands': () => undefined,
|
|
@@ -76,6 +85,8 @@ export function devHandlers({ appId, clientId = appId, apiBaseUrl = '/rest', })
|
|
|
76
85
|
'apps.delete': unavailable,
|
|
77
86
|
'apps.upload': unavailable,
|
|
78
87
|
'apps.launch': unavailable,
|
|
88
|
+
'apps.getConfig': ({ id }, signal) => devConfig(id, signal),
|
|
89
|
+
'apps.saveConfig': ({ id, data }, signal) => devConfig(id, signal, data),
|
|
79
90
|
};
|
|
80
91
|
}
|
|
81
92
|
const DARK = '(prefers-color-scheme: dark)';
|
|
@@ -90,9 +101,9 @@ const osConfig = () => ({
|
|
|
90
101
|
* Stands in for the host while the app runs standalone in development: `connect()` reaches it
|
|
91
102
|
* the way it reaches the host, and BFF calls go through the dev-auth proxy.
|
|
92
103
|
*/
|
|
93
|
-
export function installDevHost(options) {
|
|
104
|
+
export function installDevHost(options = {}) {
|
|
94
105
|
const handlers = devHandlers(options);
|
|
95
|
-
const context = () => ({ appId:
|
|
106
|
+
const context = () => ({ appId: 'dev', host: 'dev', osConfig: osConfig() });
|
|
96
107
|
let connection;
|
|
97
108
|
const stopAccepting = acceptApp({
|
|
98
109
|
source: () => window,
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { connect } from './client.js';
|
|
|
5
5
|
export type { Bardioc } from './client.js';
|
|
6
6
|
export { BardiocError } from './errors.js';
|
|
7
7
|
export type { ErrorCode } from './errors.js';
|
|
8
|
-
export type { AppRecord, AppUpload, BffRequest, Command, Context, GraphEvent, IdbEntry, InstalledApp, MenuItem, MenuRoot, NotifyLevel, OsConfig, Shortcut, UploadResult, } from './contract.js';
|
|
8
|
+
export type { AppRecord, AppUpload, BffRequest, Command, Context, DevAppConfig, GraphEvent, IdbEntry, InstalledApp, MenuItem, MenuRoot, NotifyLevel, OsConfig, Setting, SettingValue, Shortcut, UploadResult, } from './contract.js';
|
|
9
9
|
export { DEFAULT_WINDOW_SIZE, MANIFEST_FILENAME, WINDOW_SIZES, validateManifest, } from './manifest.js';
|
|
10
10
|
export type { AppManifest, AppManifestRole, AppManifestRules, AppManifestWindowConfig, CustomWindowSize, WindowSizePreset, } from './manifest.js';
|
|
11
11
|
export type { Application, BatchResult, CombinedQueryOptions, Configuration, CreateMemberInput, CreateUnitInput, DeleteOptions, FileEntry, GetNodeOptions, GraphEdgeRaw, GraphNodeRaw, GremlinOptions, HistoryEntry, HistoryOptions, InstanceList, MutationOptions, OrgMember, OrgStructure, OrgUnit, QueryOptions, TimeseriesAggregate, TimeseriesHistory, TimeseriesHistoryOptions, TimeseriesOptions, TimeseriesQueryOptions, TimeseriesValue, TransportScopeOptions, UpdateMemberInput, UpdateUnitInput, UserProfile, } from './types.js';
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { APP_METHODS, GRAPH_EVENT_TYPES, HOST_METHODS, PROTOCOL_VERSION, graphEventFilter, } from './contract.js';
|
|
2
|
-
export type { AppMethods, AppRecord, AppUpload, BffRequest, CallMethod, Command, Context, GraphEvent, HostEvents, HostMethods, IdbEntry, InstalledApp, MenuItem, MenuRoot, Method, NotifyLevel, OsConfig, Params, Result, Shortcut, StreamMethod, UploadResult, } from './contract.js';
|
|
2
|
+
export type { AppMethods, AppRecord, AppUpload, BffRequest, CallMethod, Command, Context, DevAppConfig, GraphEvent, HostEvents, HostMethods, IdbEntry, InstalledApp, MenuItem, MenuRoot, Method, NotifyLevel, OsConfig, Params, Result, Setting, SettingValue, Shortcut, StreamMethod, UploadResult, } from './contract.js';
|
|
3
3
|
export { BardiocError } from './errors.js';
|
|
4
4
|
export type { ErrorCode, WireError } from './errors.js';
|
|
5
5
|
export { acceptApp, serve } from './serve.js';
|
package/dist/react.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type DependencyList, type ReactNode } from 'react';
|
|
2
2
|
import { type Bardioc } from './client.js';
|
|
3
|
-
import type { Command, GraphEvent, MenuRoot, NotifyLevel, OsConfig } from './contract.js';
|
|
3
|
+
import type { Command, GraphEvent, MenuRoot, NotifyLevel, OsConfig, SettingValue } from './contract.js';
|
|
4
4
|
export interface AppSdkProviderProps {
|
|
5
5
|
children: ReactNode;
|
|
6
6
|
/** Apply theme, language and size to this document. Default: `true`. */
|
|
@@ -21,6 +21,8 @@ export declare function useCommandMenu(commands: AppCommand[], menu: MenuRoot[]
|
|
|
21
21
|
export declare function useActiveTab(activeTab: string | null): void;
|
|
22
22
|
/** The host's current theme, language and size. */
|
|
23
23
|
export declare function useOsConfig(): OsConfig;
|
|
24
|
+
/** The app's own settings, keyed `<group>.<field>`; follows every change the host pushes. */
|
|
25
|
+
export declare function useSettings(): Record<string, SettingValue>;
|
|
24
26
|
/** Streams graph events of `types` while mounted; `handler` may change without resubscribing. */
|
|
25
27
|
export declare function useGraphEvents({ types }: {
|
|
26
28
|
types: string[];
|
package/dist/react.js
CHANGED
|
@@ -102,6 +102,17 @@ export function useOsConfig() {
|
|
|
102
102
|
}, [bardioc]);
|
|
103
103
|
return osConfig;
|
|
104
104
|
}
|
|
105
|
+
/** The app's own settings, keyed `<group>.<field>`; follows every change the host pushes. */
|
|
106
|
+
export function useSettings() {
|
|
107
|
+
const bardioc = useSdk();
|
|
108
|
+
const [settings, setSettings] = useState(bardioc.context.settings ?? NO_SETTINGS);
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
setSettings(bardioc.context.settings ?? NO_SETTINGS);
|
|
111
|
+
return bardioc.onContextChange(context => setSettings(context.settings ?? NO_SETTINGS));
|
|
112
|
+
}, [bardioc]);
|
|
113
|
+
return settings;
|
|
114
|
+
}
|
|
115
|
+
const NO_SETTINGS = {};
|
|
105
116
|
/** Streams graph events of `types` while mounted; `handler` may change without resubscribing. */
|
|
106
117
|
export function useGraphEvents({ types }, handler, deps = []) {
|
|
107
118
|
const { events } = useSdk();
|