@bardioc/app-sdk 1.0.1 → 1.0.3

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
@@ -136,6 +136,8 @@ export default defineConfig({
136
136
 
137
137
  Handles dev base path, port config, host session proxy routes, platform fonts, and manifest validation on build.
138
138
 
139
+ `vite preview` serves the build on `port + 1000` (`4005` here), not on `port`. Pass `previewPort` to choose another one.
140
+
139
141
  ### Platform fonts
140
142
 
141
143
  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:
@@ -3,14 +3,14 @@ import type { TransportScopeOptions } from '../types.js';
3
3
  export type BffRequester = <T>(request: BffRequest) => Promise<T>;
4
4
  type QueryValue = string | number | boolean | undefined;
5
5
  export declare function withQuery(path: string, params: Record<string, QueryValue>): string;
6
- export declare const json: (body: unknown, method?: BffRequest["method"]) => {
7
- readonly method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
6
+ export declare const json: (body: unknown, method?: BffRequest['method']) => {
7
+ readonly method: "DELETE" | "GET" | "PATCH" | "POST" | "PUT";
8
8
  readonly body: unknown;
9
- readonly contentType: "application/json";
9
+ readonly contentType: 'application/json';
10
10
  };
11
11
  export declare const scoped: ({ scopeId }?: TransportScopeOptions) => {
12
12
  readonly scopeId: string;
13
- readonly scopePolicy: "required";
13
+ readonly scopePolicy: 'required';
14
14
  } | {
15
15
  readonly scopeId?: undefined;
16
16
  readonly scopePolicy?: undefined;
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
  }
@@ -0,0 +1,148 @@
1
+ import type { AppManifestPermission } from './manifest.js';
2
+ export declare const SDK_CONTRACT_MATRIX: {
3
+ readonly SDK_INIT: {
4
+ readonly requestPayload: "{ appId?: string }";
5
+ readonly responsePayload: "SdkInitResponse";
6
+ readonly permission: null;
7
+ readonly expectedHostBehavior: "Handshake the iframe app and return SDK-owned host context.";
8
+ };
9
+ readonly SDK_NOTIFY: {
10
+ readonly requestPayload: "SdkNotifyPayload";
11
+ readonly responsePayload: "{ ok: true }";
12
+ readonly permission: "notify";
13
+ readonly expectedHostBehavior: "Surface a host-level notification and acknowledge delivery.";
14
+ };
15
+ readonly SDK_KERNEL_PROXY: {
16
+ readonly requestPayload: "SdkKernelProxyPayload";
17
+ readonly responsePayload: "KernelProtocol response";
18
+ readonly permission: "kernel-proxy";
19
+ readonly expectedHostBehavior: "Forward only allow-listed kernel messages through the host.";
20
+ };
21
+ readonly SDK_TRANSPORT: {
22
+ readonly requestPayload: "SdkTransportPayload";
23
+ readonly responsePayload: "Upstream transport response payload";
24
+ readonly permission: "transport";
25
+ readonly expectedHostBehavior: "Relay app-scoped transport requests with scope-aware host mediation.";
26
+ };
27
+ readonly SDK_SET_COMMANDS: {
28
+ readonly requestPayload: "SdkSetCommandsPayload";
29
+ readonly responsePayload: "{ ok: true }";
30
+ readonly permission: null;
31
+ readonly expectedHostBehavior: "Store the app command registry for host command invocation.";
32
+ };
33
+ readonly SDK_SET_MENU: {
34
+ readonly requestPayload: "SdkSetMenuPayload";
35
+ readonly responsePayload: "{ ok: true }";
36
+ readonly permission: null;
37
+ readonly expectedHostBehavior: "Store the app menu tree without degrading supported SDK menu kinds.";
38
+ };
39
+ readonly SDK_SET_ACTIVE_TAB: {
40
+ readonly requestPayload: "SdkSetActiveTabPayload";
41
+ readonly responsePayload: "{ ok: true }";
42
+ readonly permission: null;
43
+ readonly expectedHostBehavior: "Persist the app-reported active tab label in host window state.";
44
+ };
45
+ readonly SDK_SHORTCUT_EVENT: {
46
+ readonly requestPayload: "SdkShortcutEventPayload";
47
+ readonly responsePayload: null;
48
+ readonly permission: null;
49
+ readonly expectedHostBehavior: "Route a focused iframe shortcut event through host shortcut handling.";
50
+ };
51
+ readonly SDK_STORAGE_GET: {
52
+ readonly requestPayload: "SdkStorageGetPayload";
53
+ readonly responsePayload: "unknown";
54
+ readonly permission: "storage";
55
+ readonly expectedHostBehavior: "Host-owned storage bridge; currently deferred in bdf.";
56
+ };
57
+ readonly SDK_STORAGE_SET: {
58
+ readonly requestPayload: "SdkStorageSetPayload";
59
+ readonly responsePayload: "void";
60
+ readonly permission: "storage";
61
+ readonly expectedHostBehavior: "Host-owned storage bridge; currently deferred in bdf.";
62
+ };
63
+ readonly SDK_STORAGE_DELETE: {
64
+ readonly requestPayload: "SdkStorageDeletePayload";
65
+ readonly responsePayload: "void";
66
+ readonly permission: "storage";
67
+ readonly expectedHostBehavior: "Host-owned storage bridge; currently deferred in bdf.";
68
+ };
69
+ readonly SDK_STORAGE_KEYS: {
70
+ readonly requestPayload: "{}";
71
+ readonly responsePayload: "string[]";
72
+ readonly permission: "storage";
73
+ readonly expectedHostBehavior: "Host-owned storage bridge; currently deferred in bdf.";
74
+ };
75
+ readonly SDK_IDB_GET: {
76
+ readonly requestPayload: "SdkIdbGetPayload";
77
+ readonly responsePayload: "SdkIdbEntry | null";
78
+ readonly permission: "indexdb";
79
+ readonly expectedHostBehavior: "Perform app-scoped IndexedDB reads in host-owned storage.";
80
+ };
81
+ readonly SDK_IDB_PUT: {
82
+ readonly requestPayload: "SdkIdbPutPayload";
83
+ readonly responsePayload: "void";
84
+ readonly permission: "indexdb";
85
+ readonly expectedHostBehavior: "Perform app-scoped IndexedDB writes in host-owned storage.";
86
+ };
87
+ readonly SDK_IDB_DELETE: {
88
+ readonly requestPayload: "SdkIdbDeletePayload";
89
+ readonly responsePayload: "void";
90
+ readonly permission: "indexdb";
91
+ readonly expectedHostBehavior: "Perform app-scoped IndexedDB deletes in host-owned storage.";
92
+ };
93
+ readonly SDK_IDB_QUERY: {
94
+ readonly requestPayload: "SdkIdbQueryPayload";
95
+ readonly responsePayload: "SdkIdbEntry[]";
96
+ readonly permission: "indexdb";
97
+ readonly expectedHostBehavior: "Perform app-scoped IndexedDB queries in host-owned storage.";
98
+ };
99
+ readonly SDK_LAUNCH_APP: {
100
+ readonly requestPayload: "{ appId: string }";
101
+ readonly responsePayload: "{ windowId: string | null }";
102
+ readonly permission: null;
103
+ readonly expectedHostBehavior: "Launch another registered app through the host shell.";
104
+ };
105
+ readonly SDK_COMMAND_INVOKE: {
106
+ readonly requestPayload: "SdkCommandInvokePayload";
107
+ readonly responsePayload: "{ ok: true }";
108
+ readonly permission: null;
109
+ readonly expectedHostBehavior: "Host-to-app command callback delivery.";
110
+ };
111
+ readonly SDK_EVENT_SUBSCRIBE: {
112
+ readonly requestPayload: "EventSubscribeRequest";
113
+ readonly responsePayload: "EventSubscribeResponse";
114
+ readonly permission: "events";
115
+ readonly expectedHostBehavior: "Open a scoped graph-event SSE stream for the requested OGIT types.";
116
+ };
117
+ readonly SDK_EVENT_UNSUBSCRIBE: {
118
+ readonly requestPayload: "EventUnsubscribeRequest";
119
+ readonly responsePayload: "{ ok: true }";
120
+ readonly permission: "events";
121
+ readonly expectedHostBehavior: "Close the graph-event SSE stream for the given subscription.";
122
+ };
123
+ readonly SDK_GRAPH_EVENT: {
124
+ readonly requestPayload: "GraphEventPushPayload";
125
+ readonly responsePayload: null;
126
+ readonly permission: null;
127
+ readonly expectedHostBehavior: "Host-to-app graph-event push delivery (no ack).";
128
+ };
129
+ readonly SDK_OS_CONFIG_UPDATE: {
130
+ readonly requestPayload: "OsConfig";
131
+ readonly responsePayload: null;
132
+ readonly permission: null;
133
+ readonly expectedHostBehavior: "Host-to-app runtime OS configuration update delivery.";
134
+ };
135
+ readonly SDK_RESPONSE: {
136
+ readonly requestPayload: "SdkResponse";
137
+ readonly responsePayload: null;
138
+ readonly permission: null;
139
+ readonly expectedHostBehavior: "Request/response envelope used by the bridge runtime.";
140
+ };
141
+ readonly SDK_INIT_ACK: {
142
+ readonly requestPayload: "SdkInitResponse";
143
+ readonly responsePayload: null;
144
+ readonly permission: null;
145
+ readonly expectedHostBehavior: "Handshake acknowledgement used by the bridge runtime.";
146
+ };
147
+ };
148
+ export declare function getRequiredPermissionForSdkMessage(messageType: string): AppManifestPermission | null;
@@ -0,0 +1,150 @@
1
+ import { SDK_MSG } from './protocol.js';
2
+ export const SDK_CONTRACT_MATRIX = {
3
+ [SDK_MSG.INIT]: {
4
+ requestPayload: '{ appId?: string }',
5
+ responsePayload: 'SdkInitResponse',
6
+ permission: null,
7
+ expectedHostBehavior: 'Handshake the iframe app and return SDK-owned host context.',
8
+ },
9
+ [SDK_MSG.NOTIFY]: {
10
+ requestPayload: 'SdkNotifyPayload',
11
+ responsePayload: '{ ok: true }',
12
+ permission: 'notify',
13
+ expectedHostBehavior: 'Surface a host-level notification and acknowledge delivery.',
14
+ },
15
+ [SDK_MSG.KERNEL_PROXY]: {
16
+ requestPayload: 'SdkKernelProxyPayload',
17
+ responsePayload: 'KernelProtocol response',
18
+ permission: 'kernel-proxy',
19
+ expectedHostBehavior: 'Forward only allow-listed kernel messages through the host.',
20
+ },
21
+ [SDK_MSG.TRANSPORT]: {
22
+ requestPayload: 'SdkTransportPayload',
23
+ responsePayload: 'Upstream transport response payload',
24
+ permission: 'transport',
25
+ expectedHostBehavior: 'Relay app-scoped transport requests with scope-aware host mediation.',
26
+ },
27
+ [SDK_MSG.SET_COMMANDS]: {
28
+ requestPayload: 'SdkSetCommandsPayload',
29
+ responsePayload: '{ ok: true }',
30
+ permission: null,
31
+ expectedHostBehavior: 'Store the app command registry for host command invocation.',
32
+ },
33
+ [SDK_MSG.SET_MENU]: {
34
+ requestPayload: 'SdkSetMenuPayload',
35
+ responsePayload: '{ ok: true }',
36
+ permission: null,
37
+ expectedHostBehavior: 'Store the app menu tree without degrading supported SDK menu kinds.',
38
+ },
39
+ [SDK_MSG.SET_ACTIVE_TAB]: {
40
+ requestPayload: 'SdkSetActiveTabPayload',
41
+ responsePayload: '{ ok: true }',
42
+ permission: null,
43
+ expectedHostBehavior: 'Persist the app-reported active tab label in host window state.',
44
+ },
45
+ [SDK_MSG.SHORTCUT_EVENT]: {
46
+ requestPayload: 'SdkShortcutEventPayload',
47
+ responsePayload: null,
48
+ permission: null,
49
+ expectedHostBehavior: 'Route a focused iframe shortcut event through host shortcut handling.',
50
+ },
51
+ [SDK_MSG.STORAGE_GET]: {
52
+ requestPayload: 'SdkStorageGetPayload',
53
+ responsePayload: 'unknown',
54
+ permission: 'storage',
55
+ expectedHostBehavior: 'Host-owned storage bridge; currently deferred in bdf.',
56
+ },
57
+ [SDK_MSG.STORAGE_SET]: {
58
+ requestPayload: 'SdkStorageSetPayload',
59
+ responsePayload: 'void',
60
+ permission: 'storage',
61
+ expectedHostBehavior: 'Host-owned storage bridge; currently deferred in bdf.',
62
+ },
63
+ [SDK_MSG.STORAGE_DELETE]: {
64
+ requestPayload: 'SdkStorageDeletePayload',
65
+ responsePayload: 'void',
66
+ permission: 'storage',
67
+ expectedHostBehavior: 'Host-owned storage bridge; currently deferred in bdf.',
68
+ },
69
+ [SDK_MSG.STORAGE_KEYS]: {
70
+ requestPayload: '{}',
71
+ responsePayload: 'string[]',
72
+ permission: 'storage',
73
+ expectedHostBehavior: 'Host-owned storage bridge; currently deferred in bdf.',
74
+ },
75
+ [SDK_MSG.IDB_GET]: {
76
+ requestPayload: 'SdkIdbGetPayload',
77
+ responsePayload: 'SdkIdbEntry | null',
78
+ permission: 'indexdb',
79
+ expectedHostBehavior: 'Perform app-scoped IndexedDB reads in host-owned storage.',
80
+ },
81
+ [SDK_MSG.IDB_PUT]: {
82
+ requestPayload: 'SdkIdbPutPayload',
83
+ responsePayload: 'void',
84
+ permission: 'indexdb',
85
+ expectedHostBehavior: 'Perform app-scoped IndexedDB writes in host-owned storage.',
86
+ },
87
+ [SDK_MSG.IDB_DELETE]: {
88
+ requestPayload: 'SdkIdbDeletePayload',
89
+ responsePayload: 'void',
90
+ permission: 'indexdb',
91
+ expectedHostBehavior: 'Perform app-scoped IndexedDB deletes in host-owned storage.',
92
+ },
93
+ [SDK_MSG.IDB_QUERY]: {
94
+ requestPayload: 'SdkIdbQueryPayload',
95
+ responsePayload: 'SdkIdbEntry[]',
96
+ permission: 'indexdb',
97
+ expectedHostBehavior: 'Perform app-scoped IndexedDB queries in host-owned storage.',
98
+ },
99
+ [SDK_MSG.LAUNCH_APP]: {
100
+ requestPayload: '{ appId: string }',
101
+ responsePayload: '{ windowId: string | null }',
102
+ permission: null,
103
+ expectedHostBehavior: 'Launch another registered app through the host shell.',
104
+ },
105
+ [SDK_MSG.COMMAND_INVOKE]: {
106
+ requestPayload: 'SdkCommandInvokePayload',
107
+ responsePayload: '{ ok: true }',
108
+ permission: null,
109
+ expectedHostBehavior: 'Host-to-app command callback delivery.',
110
+ },
111
+ [SDK_MSG.EVENT_SUBSCRIBE]: {
112
+ requestPayload: 'EventSubscribeRequest',
113
+ responsePayload: 'EventSubscribeResponse',
114
+ permission: 'events',
115
+ expectedHostBehavior: 'Open a scoped graph-event SSE stream for the requested OGIT types.',
116
+ },
117
+ [SDK_MSG.EVENT_UNSUBSCRIBE]: {
118
+ requestPayload: 'EventUnsubscribeRequest',
119
+ responsePayload: '{ ok: true }',
120
+ permission: 'events',
121
+ expectedHostBehavior: 'Close the graph-event SSE stream for the given subscription.',
122
+ },
123
+ [SDK_MSG.GRAPH_EVENT]: {
124
+ requestPayload: 'GraphEventPushPayload',
125
+ responsePayload: null,
126
+ permission: null,
127
+ expectedHostBehavior: 'Host-to-app graph-event push delivery (no ack).',
128
+ },
129
+ [SDK_MSG.OS_CONFIG_UPDATE]: {
130
+ requestPayload: 'OsConfig',
131
+ responsePayload: null,
132
+ permission: null,
133
+ expectedHostBehavior: 'Host-to-app runtime OS configuration update delivery.',
134
+ },
135
+ [SDK_MSG.RESPONSE]: {
136
+ requestPayload: 'SdkResponse',
137
+ responsePayload: null,
138
+ permission: null,
139
+ expectedHostBehavior: 'Request/response envelope used by the bridge runtime.',
140
+ },
141
+ [SDK_MSG.INIT_ACK]: {
142
+ requestPayload: 'SdkInitResponse',
143
+ responsePayload: null,
144
+ permission: null,
145
+ expectedHostBehavior: 'Handshake acknowledgement used by the bridge runtime.',
146
+ },
147
+ };
148
+ export function getRequiredPermissionForSdkMessage(messageType) {
149
+ return SDK_CONTRACT_MATRIX[messageType]?.permission ?? null;
150
+ }
@@ -48,9 +48,9 @@ declare const MenuRoot: z.ZodMiniObject<{
48
48
  declare const Notify: z.ZodMiniObject<{
49
49
  message: z.ZodMiniString<string>;
50
50
  level: z.ZodMiniEnum<{
51
- success: "success";
52
51
  error: "error";
53
52
  info: "info";
53
+ success: "success";
54
54
  warning: "warning";
55
55
  }>;
56
56
  }, z.core.$strict>;
@@ -64,11 +64,11 @@ declare const Shortcut: z.ZodMiniObject<{
64
64
  declare const BffRequest: z.ZodMiniObject<{
65
65
  path: z.ZodMiniString<string>;
66
66
  method: z.ZodMiniOptional<z.ZodMiniEnum<{
67
+ DELETE: "DELETE";
67
68
  GET: "GET";
69
+ PATCH: "PATCH";
68
70
  POST: "POST";
69
71
  PUT: "PUT";
70
- PATCH: "PATCH";
71
- DELETE: "DELETE";
72
72
  }>>;
73
73
  body: z.ZodMiniOptional<z.ZodMiniUnknown>;
74
74
  contentType: z.ZodMiniOptional<z.ZodMiniString<string>>;
@@ -85,14 +85,14 @@ declare const AppRecord: z.ZodMiniObject<{
85
85
  version: z.ZodMiniString<string>;
86
86
  launchUrl: z.ZodMiniString<string>;
87
87
  source: z.ZodMiniEnum<{
88
- uploaded: "uploaded";
89
88
  dev: "dev";
89
+ uploaded: "uploaded";
90
90
  }>;
91
91
  description: z.ZodMiniOptional<z.ZodMiniString<string>>;
92
92
  icon: z.ZodMiniOptional<z.ZodMiniString<string>>;
93
93
  appId: z.ZodMiniOptional<z.ZodMiniString<string>>;
94
- bundleSize: z.ZodMiniOptional<z.ZodMiniNumberFormat>;
95
- fileCount: z.ZodMiniOptional<z.ZodMiniNumberFormat>;
94
+ bundleSize: z.ZodMiniOptional<z.ZodMiniInt>;
95
+ fileCount: z.ZodMiniOptional<z.ZodMiniInt>;
96
96
  }, z.core.$strict>;
97
97
  declare const AppUpload: z.ZodMiniObject<{
98
98
  alias: z.ZodMiniString<string>;
@@ -103,8 +103,8 @@ declare const AppUpload: z.ZodMiniObject<{
103
103
  }, z.core.$strict>>;
104
104
  appId: z.ZodMiniOptional<z.ZodMiniString<string>>;
105
105
  source: z.ZodMiniOptional<z.ZodMiniEnum<{
106
- uploaded: "uploaded";
107
106
  dev: "dev";
107
+ uploaded: "uploaded";
108
108
  }>>;
109
109
  }, z.core.$strict>;
110
110
  export type Command = z.infer<typeof Command>;
@@ -122,18 +122,50 @@ 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;
133
165
  value: T;
134
166
  updatedAt: number;
135
167
  }
136
- export declare const GRAPH_EVENT_TYPES: readonly ["CREATE", "REPLACE", "UPDATE", "CONNECT", "DISCONNECT", "DELETE", "WRITE_TIMESERIES"];
168
+ export declare const GRAPH_EVENT_TYPES: readonly ['CREATE', 'REPLACE', 'UPDATE', 'CONNECT', 'DISCONNECT', 'DELETE', 'WRITE_TIMESERIES'];
137
169
  export interface GraphEvent {
138
170
  id: string;
139
171
  type: (typeof GRAPH_EVENT_TYPES)[number];
@@ -159,9 +191,9 @@ export declare const APP_METHODS: {
159
191
  readonly 'ui.notify': CallMethod<z.ZodMiniObject<{
160
192
  message: z.ZodMiniString<string>;
161
193
  level: z.ZodMiniEnum<{
162
- success: "success";
163
194
  error: "error";
164
195
  info: "info";
196
+ success: "success";
165
197
  warning: "warning";
166
198
  }>;
167
199
  }, z.core.$strict>, void>;
@@ -198,11 +230,11 @@ export declare const APP_METHODS: {
198
230
  readonly 'bff.request': CallMethod<z.ZodMiniObject<{
199
231
  path: z.ZodMiniString<string>;
200
232
  method: z.ZodMiniOptional<z.ZodMiniEnum<{
233
+ DELETE: "DELETE";
201
234
  GET: "GET";
235
+ PATCH: "PATCH";
202
236
  POST: "POST";
203
237
  PUT: "PUT";
204
- PATCH: "PATCH";
205
- DELETE: "DELETE";
206
238
  }>>;
207
239
  body: z.ZodMiniOptional<z.ZodMiniUnknown>;
208
240
  contentType: z.ZodMiniOptional<z.ZodMiniString<string>>;
@@ -232,7 +264,7 @@ export declare const APP_METHODS: {
232
264
  readonly 'idb.query': CallMethod<z.ZodMiniObject<{
233
265
  store: z.ZodMiniString<string>;
234
266
  prefix: z.ZodMiniOptional<z.ZodMiniString<string>>;
235
- limit: z.ZodMiniOptional<z.ZodMiniNumberFormat>;
267
+ limit: z.ZodMiniOptional<z.ZodMiniInt>;
236
268
  }, z.core.$strict>, IdbEntry<unknown>[]>;
237
269
  readonly 'apps.list': CallMethod<z.ZodMiniUndefined, InstalledApp[]>;
238
270
  readonly 'apps.get': CallMethod<z.ZodMiniObject<{
@@ -244,14 +276,14 @@ export declare const APP_METHODS: {
244
276
  version: z.ZodMiniString<string>;
245
277
  launchUrl: z.ZodMiniString<string>;
246
278
  source: z.ZodMiniEnum<{
247
- uploaded: "uploaded";
248
279
  dev: "dev";
280
+ uploaded: "uploaded";
249
281
  }>;
250
282
  description: z.ZodMiniOptional<z.ZodMiniString<string>>;
251
283
  icon: z.ZodMiniOptional<z.ZodMiniString<string>>;
252
284
  appId: z.ZodMiniOptional<z.ZodMiniString<string>>;
253
- bundleSize: z.ZodMiniOptional<z.ZodMiniNumberFormat>;
254
- fileCount: z.ZodMiniOptional<z.ZodMiniNumberFormat>;
285
+ bundleSize: z.ZodMiniOptional<z.ZodMiniInt>;
286
+ fileCount: z.ZodMiniOptional<z.ZodMiniInt>;
255
287
  }, z.core.$strict>, InstalledApp>;
256
288
  readonly 'apps.delete': CallMethod<z.ZodMiniObject<{
257
289
  id: z.ZodMiniString<string>;
@@ -265,8 +297,8 @@ export declare const APP_METHODS: {
265
297
  }, z.core.$strict>>;
266
298
  appId: z.ZodMiniOptional<z.ZodMiniString<string>>;
267
299
  source: z.ZodMiniOptional<z.ZodMiniEnum<{
268
- uploaded: "uploaded";
269
300
  dev: "dev";
301
+ uploaded: "uploaded";
270
302
  }>>;
271
303
  }, z.core.$strict>, UploadResult>;
272
304
  readonly 'apps.launch': CallMethod<z.ZodMiniObject<{
@@ -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 = {
@@ -0,0 +1,24 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ export type ProxyPayload = {
3
+ sessionKey?: string;
4
+ hostUrl?: string;
5
+ scopeId?: string | null;
6
+ scopePolicy?: 'none' | 'optional' | 'required';
7
+ path: string;
8
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
9
+ body?: unknown;
10
+ contentType?: string;
11
+ };
12
+ interface ProxyTransportOptions {
13
+ appId: string;
14
+ hostUrl: string;
15
+ devSessionKey: string;
16
+ }
17
+ interface SendJsonOptions {
18
+ allowOrigin?: string;
19
+ }
20
+ export declare function readJsonBody<T = unknown>(req: IncomingMessage): Promise<T | null>;
21
+ export declare function applyCors(res: ServerResponse, allowOrigin?: string): void;
22
+ export declare function sendJson(res: ServerResponse, status: number, body: unknown, options?: SendJsonOptions): void;
23
+ export declare function forwardDevAuthProxyRequest(payload: ProxyPayload, options: ProxyTransportOptions): Promise<Response>;
24
+ export {};
@@ -0,0 +1,59 @@
1
+ export async function readJsonBody(req) {
2
+ return new Promise(resolveBody => {
3
+ const chunks = [];
4
+ req.on('data', (chunk) => chunks.push(chunk));
5
+ req.on('end', () => {
6
+ const buffer = Buffer.concat(chunks);
7
+ if (buffer.length === 0) {
8
+ resolveBody(null);
9
+ return;
10
+ }
11
+ try {
12
+ resolveBody(JSON.parse(buffer.toString('utf8')));
13
+ }
14
+ catch {
15
+ resolveBody(null);
16
+ }
17
+ });
18
+ req.on('error', () => resolveBody(null));
19
+ });
20
+ }
21
+ export function applyCors(res, allowOrigin) {
22
+ if (!allowOrigin) {
23
+ return;
24
+ }
25
+ res.setHeader('Access-Control-Allow-Origin', allowOrigin);
26
+ res.setHeader('Access-Control-Allow-Methods', 'POST,OPTIONS');
27
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
28
+ }
29
+ export function sendJson(res, status, body, options = {}) {
30
+ applyCors(res, options.allowOrigin);
31
+ res.statusCode = status;
32
+ res.setHeader('Content-Type', 'application/json');
33
+ res.setHeader('Cache-Control', 'no-store');
34
+ res.end(JSON.stringify(body));
35
+ }
36
+ export async function forwardDevAuthProxyRequest(payload, options) {
37
+ const hostUrl = payload.hostUrl ?? options.hostUrl;
38
+ const sessionKey = payload.sessionKey ?? options.devSessionKey;
39
+ if (!hostUrl || !sessionKey) {
40
+ throw new Error('missing_dev_session');
41
+ }
42
+ return fetch(`${hostUrl.replace(/\/$/, '')}/api/transport`, {
43
+ method: 'POST',
44
+ headers: {
45
+ 'Content-Type': 'application/json',
46
+ 'X-Dev-Session-Key': sessionKey,
47
+ },
48
+ body: JSON.stringify({
49
+ appId: options.appId,
50
+ path: payload.path,
51
+ method: payload.method ?? 'GET',
52
+ body: payload.body,
53
+ contentType: payload.contentType,
54
+ scopePolicy: payload.scopePolicy,
55
+ scopeId: payload.scopeId ?? null,
56
+ }),
57
+ cache: 'no-store',
58
+ });
59
+ }
@@ -0,0 +1,34 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ type VitePlugin = {
3
+ name: string;
4
+ apply?: 'serve' | 'build';
5
+ enforce?: 'pre' | 'post';
6
+ configureServer?: (server: ViteDevServerLike) => void;
7
+ transformIndexHtml?: () => Array<{
8
+ tag: string;
9
+ attrs?: Record<string, string>;
10
+ children?: string;
11
+ injectTo?: 'head' | 'body' | 'head-prepend' | 'body-prepend';
12
+ }> | void;
13
+ };
14
+ interface ViteDevServerLike {
15
+ config: {
16
+ root: string;
17
+ envDir?: string;
18
+ mode?: string;
19
+ base: string;
20
+ logger: {
21
+ warn: (message: string) => void;
22
+ info: (message: string) => void;
23
+ };
24
+ };
25
+ middlewares: {
26
+ use: (handler: (req: IncomingMessage, res: ServerResponse, next: (error?: unknown) => void) => void) => void;
27
+ };
28
+ }
29
+ export interface BardiocDevAuthOptions {
30
+ appName: string;
31
+ sessionStorageKey?: string;
32
+ }
33
+ export declare function bardiocDevAuth(options: BardiocDevAuthOptions): VitePlugin;
34
+ export {};