@notionhq/custom-blocks-host 0.1.31 → 0.2.1
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 +39 -18
- package/dist/createCustomBlockHost.d.ts +8 -10
- package/dist/createCustomBlockHost.d.ts.map +1 -1
- package/dist/createCustomBlockHost.js +94 -150
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/lifecycle/initErrors.d.ts.map +1 -1
- package/dist/lifecycle/initErrors.js +6 -0
- package/dist/lifecycle/initializationController.d.ts +3 -27
- package/dist/lifecycle/initializationController.d.ts.map +1 -1
- package/dist/lifecycle/initializationController.js +89 -46
- package/dist/lifecycle/types.d.ts +13 -7
- package/dist/lifecycle/types.d.ts.map +1 -1
- package/dist/protocol/messages/init.d.ts +1 -1
- package/package.json +1 -1
- package/src/createCustomBlockHost.ts +118 -172
- package/src/index.ts +23 -2
- package/src/lifecycle/initErrors.ts +6 -0
- package/src/lifecycle/initializationController.ts +97 -78
- package/src/lifecycle/types.ts +19 -10
package/README.md
CHANGED
|
@@ -47,16 +47,20 @@ import { createCustomBlockHost } from "@notionhq/custom-blocks-host"
|
|
|
47
47
|
const host = createCustomBlockHost({
|
|
48
48
|
iframe,
|
|
49
49
|
sandboxOrigin: "https://example.com",
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
50
|
+
minBridgeProtocolVersion: 3,
|
|
51
|
+
getInitialState: async () => ({
|
|
52
|
+
status: "success",
|
|
53
|
+
initialState: {
|
|
54
|
+
theme,
|
|
55
|
+
contrastMode,
|
|
56
|
+
blockId,
|
|
57
|
+
parent,
|
|
58
|
+
page,
|
|
59
|
+
currentUser,
|
|
60
|
+
manifest,
|
|
61
|
+
dataSources: { bindings },
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
60
64
|
handlers: {
|
|
61
65
|
queryDataSource: async message => ({
|
|
62
66
|
status: "success",
|
|
@@ -113,7 +117,26 @@ initial page fails initialization with `context_unavailable`. If page context be
|
|
|
113
117
|
after initialization, the host stops and reports the same error instead of sending an unsupported
|
|
114
118
|
`pageChanged` message.
|
|
115
119
|
|
|
116
|
-
|
|
120
|
+
`getInitialState` runs after the sandbox sends `connect`. It returns a promise for the initial state
|
|
121
|
+
result. The host listens immediately and sends `init` only after `getInitialState` resolves. Await
|
|
122
|
+
record and binding loads inside `getInitialState`.
|
|
123
|
+
|
|
124
|
+
`getInitialState` selects the manifest that the host uses. The host uses this manifest even when
|
|
125
|
+
`connect` supplies another. Production hosts can select persisted definitions. Preview hosts can
|
|
126
|
+
select sandbox manifests. A successful result must include a manifest. If no manifest is available,
|
|
127
|
+
return `manifest_unavailable`.
|
|
128
|
+
|
|
129
|
+
`getInitialState` can return `{ status: "error", error }` to stop initialization. The host converts
|
|
130
|
+
a thrown error or rejected promise to `unknown_error`. If preparation exceeds
|
|
131
|
+
`initialStateTimeoutMs`, the host reports `initial_state_timeout` and stops the handshake.
|
|
132
|
+
|
|
133
|
+
`no_connect` means the host did not receive `connect`. `no_init_result` means the sandbox did not
|
|
134
|
+
acknowledge `init`. The SDK waits for the host without its own timeout.
|
|
135
|
+
|
|
136
|
+
The host discards `getInitialState` results after a timeout or stop, including a stop caused by an
|
|
137
|
+
iframe reload.
|
|
138
|
+
|
|
139
|
+
- `onManifest` provides the selected manifest when `getInitialState` resolves successfully, before
|
|
117
140
|
binding validation and `onInitialized`. Use it to configure bindings even when initialization
|
|
118
141
|
cannot yet succeed.
|
|
119
142
|
|
|
@@ -122,9 +145,6 @@ after initialization, the host stops and reports the same error instead of sendi
|
|
|
122
145
|
- `onFailure` reports a handshake failure, timeout, unavailable page context, or iframe reload. It
|
|
123
146
|
can run after initialization succeeds.
|
|
124
147
|
|
|
125
|
-
The host uses the manifest from `connect`, or `initialState.manifest` if `connect` omits it. If
|
|
126
|
-
neither exists, initialization fails with `manifest_unavailable`.
|
|
127
|
-
|
|
128
148
|
`queryDataSource` is required. Other request handlers are optional. Every request handler may return
|
|
129
149
|
its result synchronously or as a promise. Results use a `status` discriminator: successful results
|
|
130
150
|
carry their response payload, while errors carry `{ code, message, isRetryable }`.
|
|
@@ -157,12 +177,13 @@ The runtime validates option names, supported sort types, and the limit of ten u
|
|
|
157
177
|
properties before it invokes the handler. Sorts retain their array order. Extra fields and mixed
|
|
158
178
|
filter types fail protocol validation.
|
|
159
179
|
|
|
160
|
-
|
|
161
|
-
|
|
180
|
+
Derive bindings from the successful `connect` message inside `getInitialState` and return them in
|
|
181
|
+
`initialState.dataSources`.
|
|
162
182
|
|
|
163
183
|
Set `sandboxOrigin` to the iframe's exact origin. The runtime targets outbound messages to that
|
|
164
|
-
origin and accepts inbound messages only from that iframe and origin. The runtime
|
|
165
|
-
`noConnectTimeoutMs` and `noInitResultTimeoutMs`;
|
|
184
|
+
origin and accepts inbound messages only from that iframe and origin. The runtime accepts
|
|
185
|
+
`noConnectTimeoutMs`, `initialStateTimeoutMs`, and `noInitResultTimeoutMs`; all default to five
|
|
186
|
+
seconds.
|
|
166
187
|
|
|
167
188
|
### Initialization and malformed messages
|
|
168
189
|
|
|
@@ -1,29 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { NotionContrastMode } from "./protocol/contrast.js";
|
|
2
2
|
import type { NotionDataSourceId } from "./protocol/ids.js";
|
|
3
3
|
import type { CustomBlockManifest } from "./protocol/manifest.js";
|
|
4
4
|
import type { CustomBlockPage } from "./protocol/pages/page.js";
|
|
5
5
|
import type { NotionParent } from "./protocol/parent.js";
|
|
6
6
|
import type { NotionTheme } from "./protocol/theme.js";
|
|
7
7
|
import type { NotionUser } from "./protocol/users/user.js";
|
|
8
|
-
import type { CustomBlockHostDataSourcesPayload,
|
|
8
|
+
import type { CustomBlockHostDataSourcesPayload, CustomBlockHostGetInitialState } from "./lifecycle/types.js";
|
|
9
9
|
import type { CustomBlockHostFailure, CustomBlockHostHandlers, CustomBlockHostLogDirection } from "./messages/types.js";
|
|
10
10
|
export type CustomBlockHostOptions = {
|
|
11
11
|
iframe: HTMLIFrameElement;
|
|
12
12
|
sandboxOrigin: string;
|
|
13
13
|
/**
|
|
14
|
-
* Minimum sandbox protocol version to accept. Defaults to the host runtime
|
|
15
|
-
* values retire older SDKs; lower values cannot enable
|
|
16
|
-
* supports.
|
|
14
|
+
* Minimum sandbox protocol version to accept. Defaults to the host runtime
|
|
15
|
+
* minimum. Higher values retire older SDKs; lower values cannot enable
|
|
16
|
+
* protocol versions the runtime no longer supports.
|
|
17
17
|
*/
|
|
18
18
|
minBridgeProtocolVersion?: number;
|
|
19
19
|
noConnectTimeoutMs?: number;
|
|
20
20
|
noInitResultTimeoutMs?: number;
|
|
21
|
-
initialState: CustomBlockHostInitialState;
|
|
22
21
|
handlers: CustomBlockHostHandlers;
|
|
23
|
-
/**
|
|
24
|
-
* Called as soon as the `manifest` is available after `connect`, before `onInitialized` and
|
|
25
|
-
* binding validation.
|
|
26
|
-
*/
|
|
22
|
+
/** Called as soon as the `manifest` is available after `connect`, before `onInitialized` and binding validation. */
|
|
27
23
|
onManifest?: (manifest: CustomBlockManifest) => void;
|
|
28
24
|
/** Callback fired when the initialization handshake with the sandbox completed successfully. */
|
|
29
25
|
onInitialized?: (state: {
|
|
@@ -38,6 +34,8 @@ export type CustomBlockHostOptions = {
|
|
|
38
34
|
*/
|
|
39
35
|
onFailure?: (error: CustomBlockHostFailure) => void;
|
|
40
36
|
onLog?: (direction: CustomBlockHostLogDirection, payload: unknown) => void;
|
|
37
|
+
getInitialState: CustomBlockHostGetInitialState;
|
|
38
|
+
initialStateTimeoutMs?: number;
|
|
41
39
|
};
|
|
42
40
|
export type CustomBlockHostHandle = {
|
|
43
41
|
stop: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCustomBlockHost.d.ts","sourceRoot":"","sources":["../src/createCustomBlockHost.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"createCustomBlockHost.d.ts","sourceRoot":"","sources":["../src/createCustomBlockHost.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAA;AAEtF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AACjF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAA;AAcvF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAA;AACrF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAA;AAE9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAA;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gDAAgD,CAAA;AAIhF,OAAO,KAAK,EACX,iCAAiC,EACjC,8BAA8B,EAG9B,MAAM,sBAAsB,CAAA;AAE7B,OAAO,KAAK,EACX,sBAAsB,EACtB,uBAAuB,EACvB,2BAA2B,EAC3B,MAAM,qBAAqB,CAAA;AAe5B,MAAM,MAAM,sBAAsB,GAAG;IACpC,MAAM,EAAE,iBAAiB,CAAA;IACzB,aAAa,EAAE,MAAM,CAAA;IACrB;;;;OAIG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,QAAQ,EAAE,uBAAuB,CAAA;IACjC,oHAAoH;IACpH,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,mBAAmB,KAAK,IAAI,CAAA;IACpD,gGAAgG;IAChG,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE;QACvB,QAAQ,EAAE,mBAAmB,CAAA;QAC7B,aAAa,CAAC,EAAE,MAAM,CAAA;KACtB,KAAK,IAAI,CAAA;IACV;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAA;IACnD,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,2BAA2B,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IAC1E,eAAe,EAAE,8BAA8B,CAAA;IAC/C,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAA;IACtC,eAAe,EAAE,CAAC,YAAY,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAC3D,SAAS,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAA;IACzC,OAAO,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAA;IACxC,cAAc,EAAE,CAAC,WAAW,EAAE,iCAAiC,KAAK,IAAI,CAAA;IACxE,cAAc,EAAE,CAAC,WAAW,EAAE,UAAU,KAAK,IAAI,CAAA;IACjD,YAAY,EAAE,CAAC,IAAI,EAAE;QAAE,YAAY,EAAE,kBAAkB,CAAA;KAAE,KAAK,IAAI,CAAA;CAClE,CAAA;AAyBD,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,sBAAsB,GAC7B,qBAAqB,CA8WvB"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { DEFAULT_CONTRAST_MODE, } from "./protocol/contrast.js";
|
|
2
1
|
import { LATEST_BRIDGE_PROTOCOL_VERSION } from "./protocol/protocolVersion.js";
|
|
3
2
|
import { initErrorForFailureReason } from "./lifecycle/initErrors.js";
|
|
4
3
|
import { createInitializationController } from "./lifecycle/initializationController.js";
|
|
@@ -13,26 +12,16 @@ import { unreachable } from "./utils.js";
|
|
|
13
12
|
// Earlier SDKs cannot represent this context, so the host reports context_unavailable.
|
|
14
13
|
const BRIDGE_PROTOCOL_VERSION_INTRODUCING_UNAVAILABLE_PAGE = 5;
|
|
15
14
|
export function createCustomBlockHost(options) {
|
|
16
|
-
const { iframe,
|
|
17
|
-
// Callers can retire older SDKs, but cannot restore support for protocols
|
|
18
|
-
// implements. Omission uses the runtime minimum.
|
|
15
|
+
const { iframe, getInitialState, handlers, onManifest, onInitialized, onFailure, onLog, sandboxOrigin, minBridgeProtocolVersion: configuredMinBridgeProtocolVersion, noConnectTimeoutMs, initialStateTimeoutMs, noInitResultTimeoutMs, } = options;
|
|
16
|
+
// Callers can retire older SDKs, but cannot restore support for protocols
|
|
17
|
+
// the runtime no longer implements. Omission uses the runtime minimum.
|
|
19
18
|
const minBridgeProtocolVersion = Math.max(configuredMinBridgeProtocolVersion ??
|
|
20
19
|
MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION, MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION);
|
|
21
|
-
let
|
|
22
|
-
let
|
|
23
|
-
let
|
|
24
|
-
let page = initialState.page;
|
|
25
|
-
let dataSources = initialState.dataSources;
|
|
20
|
+
let pendingState = {};
|
|
21
|
+
let hasPreparedInitialState = false;
|
|
22
|
+
let manifest;
|
|
26
23
|
let activeDataSources;
|
|
27
24
|
let sandboxBridgeProtocolVersion = LATEST_BRIDGE_PROTOCOL_VERSION;
|
|
28
|
-
let manifest = initialState.manifest;
|
|
29
|
-
let currentUser = initialState.currentUser;
|
|
30
|
-
let pendingThemeChange = false;
|
|
31
|
-
let pendingContrastModeChange = false;
|
|
32
|
-
let pendingParentChange = false;
|
|
33
|
-
let pendingPageChange = false;
|
|
34
|
-
let pendingDataSourcesChange;
|
|
35
|
-
let pendingCurrentUserChange = false;
|
|
36
25
|
const querySubscriptions = new QuerySubscriptions();
|
|
37
26
|
function emit(direction, payload) {
|
|
38
27
|
onLog?.(direction, payload);
|
|
@@ -41,6 +30,7 @@ export function createCustomBlockHost(options) {
|
|
|
41
30
|
const status = initializationController.status;
|
|
42
31
|
switch (status) {
|
|
43
32
|
case "waitingForConnect":
|
|
33
|
+
case "preparingInit":
|
|
44
34
|
case "waitingForInitResult":
|
|
45
35
|
case "initialized":
|
|
46
36
|
case "error":
|
|
@@ -70,6 +60,7 @@ export function createCustomBlockHost(options) {
|
|
|
70
60
|
return;
|
|
71
61
|
// Send state updates and handler results only after initialization succeeds.
|
|
72
62
|
case "waitingForConnect":
|
|
63
|
+
case "preparingInit":
|
|
73
64
|
case "waitingForInitResult":
|
|
74
65
|
case "error":
|
|
75
66
|
case "stopped":
|
|
@@ -132,88 +123,65 @@ export function createCustomBlockHost(options) {
|
|
|
132
123
|
response,
|
|
133
124
|
});
|
|
134
125
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
126
|
+
function updateHostState(update) {
|
|
127
|
+
if (initializationController.status === "stopped" ||
|
|
128
|
+
initializationController.status === "error") {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
Object.assign(pendingState, update);
|
|
132
|
+
flushPendingHostStateChanges();
|
|
133
|
+
}
|
|
140
134
|
function flushPendingHostStateChanges() {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
135
|
+
// Keep updates queued until the sandbox acknowledges initialization.
|
|
136
|
+
// Updates received before init is sent are included in its payload instead.
|
|
137
|
+
if (initializationController.status !== "initialized") {
|
|
138
|
+
return;
|
|
144
139
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
140
|
+
const changes = pendingState;
|
|
141
|
+
pendingState = {};
|
|
142
|
+
if (changes.theme !== undefined) {
|
|
143
|
+
sendInitializedMessage({ type: "themeChanged", theme: changes.theme });
|
|
148
144
|
}
|
|
149
|
-
if (
|
|
150
|
-
|
|
151
|
-
|
|
145
|
+
if (changes.contrastMode !== undefined) {
|
|
146
|
+
sendInitializedMessage({
|
|
147
|
+
type: "contrastModeChanged",
|
|
148
|
+
contrastMode: changes.contrastMode,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
if (changes.parent !== undefined) {
|
|
152
|
+
sendInitializedMessage({ type: "parentChanged", parent: changes.parent });
|
|
152
153
|
}
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
sendInitializedMessage({ type: "pageChanged", page });
|
|
154
|
+
if (changes.page !== undefined) {
|
|
155
|
+
sendInitializedMessage({ type: "pageChanged", page: changes.page });
|
|
156
156
|
}
|
|
157
|
-
if (
|
|
158
|
-
const nextDataSources = pendingDataSourcesChange;
|
|
159
|
-
pendingDataSourcesChange = undefined;
|
|
157
|
+
if (changes.dataSources !== undefined) {
|
|
160
158
|
sendInitializedMessage({
|
|
161
159
|
type: "dataSourcesChanged",
|
|
162
|
-
dataSources:
|
|
160
|
+
dataSources: changes.dataSources,
|
|
163
161
|
});
|
|
164
162
|
}
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
|
|
163
|
+
if (changes.currentUser !== undefined) {
|
|
164
|
+
sendInitializedMessage({
|
|
165
|
+
type: "currentUserChanged",
|
|
166
|
+
currentUser: changes.currentUser,
|
|
167
|
+
});
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
const initializationController = createInitializationController({
|
|
171
|
-
|
|
172
|
-
getState: () => ({
|
|
173
|
-
theme,
|
|
174
|
-
contrastMode,
|
|
175
|
-
parent,
|
|
176
|
-
page,
|
|
177
|
-
currentUser,
|
|
178
|
-
}),
|
|
179
|
-
prepareInit(connect) {
|
|
171
|
+
async prepareInit(connect) {
|
|
180
172
|
sandboxBridgeProtocolVersion = connect.bridgeProtocolVersion;
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return {
|
|
185
|
-
status: "error",
|
|
186
|
-
error: initErrorForFailureReason("context_unavailable"),
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
manifest = connect.manifest ?? initialState.manifest;
|
|
190
|
-
if (manifest === undefined) {
|
|
191
|
-
return {
|
|
192
|
-
status: "error",
|
|
193
|
-
error: initErrorForFailureReason("manifest_unavailable"),
|
|
194
|
-
};
|
|
173
|
+
const result = await getInitialState(connect);
|
|
174
|
+
if (initializationController.status !== "preparingInit") {
|
|
175
|
+
return result;
|
|
195
176
|
}
|
|
196
|
-
|
|
197
|
-
const resolvedDataSources = typeof dataSources === "function" ? dataSources(connect) : dataSources;
|
|
198
|
-
const bindingErrorCode = getBindingErrorCode(manifest, resolvedDataSources);
|
|
199
|
-
if (bindingErrorCode !== undefined) {
|
|
200
|
-
return {
|
|
201
|
-
status: "error",
|
|
202
|
-
error: initErrorForFailureReason(bindingErrorCode),
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
activeDataSources = resolvedDataSources;
|
|
206
|
-
return {
|
|
207
|
-
status: "success",
|
|
208
|
-
manifest,
|
|
209
|
-
dataSources: resolvedDataSources,
|
|
210
|
-
};
|
|
177
|
+
return prepareInitialState(result);
|
|
211
178
|
},
|
|
212
179
|
sendInitMessage,
|
|
213
180
|
warn: payload => emit("warn", payload),
|
|
214
181
|
flushPendingHostStateChanges,
|
|
215
182
|
minBridgeProtocolVersion,
|
|
216
183
|
noConnectTimeoutMs,
|
|
184
|
+
initialStateTimeoutMs,
|
|
217
185
|
noInitResultTimeoutMs,
|
|
218
186
|
stopHostWithFailure: stopWithFailure,
|
|
219
187
|
onInitResult(message) {
|
|
@@ -223,6 +191,33 @@ export function createCustomBlockHost(options) {
|
|
|
223
191
|
},
|
|
224
192
|
onFailure,
|
|
225
193
|
});
|
|
194
|
+
function prepareInitialState(result) {
|
|
195
|
+
if (result.status === "error") {
|
|
196
|
+
return result;
|
|
197
|
+
}
|
|
198
|
+
manifest = result.initialState.manifest;
|
|
199
|
+
onManifest?.(manifest);
|
|
200
|
+
const initialState = { ...result.initialState, ...pendingState };
|
|
201
|
+
pendingState = {};
|
|
202
|
+
if (sandboxBridgeProtocolVersion <
|
|
203
|
+
BRIDGE_PROTOCOL_VERSION_INTRODUCING_UNAVAILABLE_PAGE &&
|
|
204
|
+
initialState.page.type === "unavailable") {
|
|
205
|
+
return {
|
|
206
|
+
status: "error",
|
|
207
|
+
error: initErrorForFailureReason("context_unavailable"),
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
const bindingErrorCode = getBindingErrorCode(initialState.manifest, initialState.dataSources);
|
|
211
|
+
if (bindingErrorCode !== undefined) {
|
|
212
|
+
return {
|
|
213
|
+
status: "error",
|
|
214
|
+
error: initErrorForFailureReason(bindingErrorCode),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
activeDataSources = initialState.dataSources;
|
|
218
|
+
hasPreparedInitialState = true;
|
|
219
|
+
return { status: "success", initialState };
|
|
220
|
+
}
|
|
226
221
|
const onMessage = createSandboxMessageRouter({
|
|
227
222
|
iframe,
|
|
228
223
|
sandboxOrigin,
|
|
@@ -258,94 +253,43 @@ export function createCustomBlockHost(options) {
|
|
|
258
253
|
}
|
|
259
254
|
return {
|
|
260
255
|
stop,
|
|
261
|
-
setTheme(
|
|
262
|
-
theme
|
|
263
|
-
if (initializationController.status !== "initialized") {
|
|
264
|
-
if (initializationController.status === "waitingForInitResult") {
|
|
265
|
-
pendingThemeChange = true;
|
|
266
|
-
}
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
const message = { type: "themeChanged", theme };
|
|
270
|
-
sendInitializedMessage(message);
|
|
256
|
+
setTheme(theme) {
|
|
257
|
+
updateHostState({ theme });
|
|
271
258
|
},
|
|
272
|
-
setContrastMode(
|
|
273
|
-
contrastMode
|
|
274
|
-
if (initializationController.status !== "initialized") {
|
|
275
|
-
if (initializationController.status === "waitingForInitResult") {
|
|
276
|
-
pendingContrastModeChange = true;
|
|
277
|
-
}
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
const message = {
|
|
281
|
-
type: "contrastModeChanged",
|
|
282
|
-
contrastMode,
|
|
283
|
-
};
|
|
284
|
-
sendInitializedMessage(message);
|
|
259
|
+
setContrastMode(contrastMode) {
|
|
260
|
+
updateHostState({ contrastMode });
|
|
285
261
|
},
|
|
286
|
-
setParent(
|
|
287
|
-
parent
|
|
288
|
-
if (initializationController.status !== "initialized") {
|
|
289
|
-
if (initializationController.status === "waitingForInitResult") {
|
|
290
|
-
pendingParentChange = true;
|
|
291
|
-
}
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
const message = { type: "parentChanged", parent };
|
|
295
|
-
sendInitializedMessage(message);
|
|
262
|
+
setParent(parent) {
|
|
263
|
+
updateHostState({ parent });
|
|
296
264
|
},
|
|
297
|
-
setPage(
|
|
298
|
-
page
|
|
299
|
-
if (nextPage.type === "unavailable" &&
|
|
265
|
+
setPage(page) {
|
|
266
|
+
if (page.type === "unavailable" &&
|
|
300
267
|
sandboxBridgeProtocolVersion <
|
|
301
268
|
BRIDGE_PROTOCOL_VERSION_INTRODUCING_UNAVAILABLE_PAGE &&
|
|
302
|
-
(initializationController.status === "
|
|
269
|
+
((initializationController.status === "preparingInit" &&
|
|
270
|
+
hasPreparedInitialState) ||
|
|
271
|
+
initializationController.status === "waitingForInitResult" ||
|
|
303
272
|
initializationController.status === "initialized")) {
|
|
304
273
|
stopWithFailure(initErrorForFailureReason("context_unavailable"));
|
|
305
274
|
return;
|
|
306
275
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
const message = { type: "pageChanged", page };
|
|
314
|
-
sendInitializedMessage(message);
|
|
276
|
+
updateHostState({ page });
|
|
277
|
+
},
|
|
278
|
+
setCurrentUser(currentUser) {
|
|
279
|
+
updateHostState({ currentUser });
|
|
315
280
|
},
|
|
316
|
-
setDataSources(
|
|
281
|
+
setDataSources(dataSources) {
|
|
317
282
|
if (initializationController.hasConnectedSandbox &&
|
|
318
283
|
manifest !== undefined &&
|
|
319
|
-
getBindingErrorCode(manifest,
|
|
284
|
+
getBindingErrorCode(manifest, dataSources) !== undefined) {
|
|
320
285
|
emit("warn", {
|
|
321
286
|
message: "Ignored invalid data source bindings update",
|
|
322
|
-
payload:
|
|
287
|
+
payload: dataSources,
|
|
323
288
|
});
|
|
324
289
|
return;
|
|
325
290
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
if (initializationController.status !== "initialized") {
|
|
329
|
-
if (initializationController.status === "waitingForInitResult") {
|
|
330
|
-
pendingDataSourcesChange = nextDataSources;
|
|
331
|
-
}
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
const message = {
|
|
335
|
-
type: "dataSourcesChanged",
|
|
336
|
-
dataSources: nextDataSources,
|
|
337
|
-
};
|
|
338
|
-
sendInitializedMessage(message);
|
|
339
|
-
},
|
|
340
|
-
setCurrentUser(nextCurrentUser) {
|
|
341
|
-
currentUser = nextCurrentUser;
|
|
342
|
-
if (initializationController.status !== "initialized") {
|
|
343
|
-
if (initializationController.status === "waitingForInitResult") {
|
|
344
|
-
pendingCurrentUserChange = true;
|
|
345
|
-
}
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
sendInitializedMessage({ type: "currentUserChanged", currentUser });
|
|
291
|
+
activeDataSources = dataSources;
|
|
292
|
+
updateHostState({ dataSources });
|
|
349
293
|
},
|
|
350
294
|
refreshQuery({ dataSourceId }) {
|
|
351
295
|
if (initializationController.status !== "initialized") {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
+
export type { CustomBlockErrorInfo } from "./protocol/errors.js";
|
|
1
2
|
export type { CreatePageMessage } from "./protocol/messages/createPage.js";
|
|
2
3
|
export type { GetPageMessage } from "./protocol/messages/getPage.js";
|
|
3
4
|
export type { GetUserMessage } from "./protocol/messages/getUser.js";
|
|
4
5
|
export type { ListUsersMessage } from "./protocol/messages/listUsers.js";
|
|
5
6
|
export type { OpenPageMessage } from "./protocol/messages/openPage.js";
|
|
6
|
-
export type { QueryDataSourceMessage } from "./protocol/messages/queryDataSource.js";
|
|
7
|
+
export type { CustomBlockCheckboxFilterOperator, CustomBlockContainsFilterOperator, CustomBlockCreatedByFilterOperator, CustomBlockDateFilterOperator, CustomBlockNumberFilterOperator, CustomBlockOptionFilterOperator, CustomBlockPeopleFilterOperator, CustomBlockPersonFilterValue, CustomBlockTextFilterOperator, QueryDataSourceMessage, ResolvedCustomBlockDataSourceFilter, ResolvedCustomBlockDataSourcePropertyFilter, ResolvedCustomBlockDataSourceSort, } from "./protocol/messages/queryDataSource.js";
|
|
7
8
|
export type { ResizeMessage } from "./protocol/messages/resize.js";
|
|
8
9
|
export type { UpdatePageMessage } from "./protocol/messages/updatePage.js";
|
|
9
|
-
export type { NotionPagePropertyValue, NotionPagePropertyWriteMap, NotionRichTextItem, } from "./protocol/pages/page.js";
|
|
10
|
+
export type { NotionDateInput, NotionFileInput, NotionPageCover, NotionPageIcon, NotionPagePropertyValue, NotionPagePropertyWriteMap, NotionRichTextItem, NotionSelectOptionInput, } from "./protocol/pages/page.js";
|
|
10
11
|
export { type AutoBindableProperty, getAutoBoundPropertyIdsByKey, } from "./autoBindProperties.js";
|
|
11
12
|
export { type CustomBlockHostHandle, type CustomBlockHostOptions, createCustomBlockHost, } from "./createCustomBlockHost.js";
|
|
12
|
-
export type { ConnectSuccessMessage, CustomBlockHostDataSourcesPayload,
|
|
13
|
+
export type { ConnectSuccessMessage, CustomBlockHostDataSourcesPayload, CustomBlockHostGetInitialState, CustomBlockHostInitialState, CustomBlockHostInitialStateResult, } from "./lifecycle/types.js";
|
|
13
14
|
export type { CreatePageMessageInput, CustomBlockHostCreatePageResult, CustomBlockHostFailure, CustomBlockHostGetPageResult, CustomBlockHostGetUserResult, CustomBlockHostHandlers, CustomBlockHostListUsersResult, CustomBlockHostLogDirection, CustomBlockHostOpenPageResult, CustomBlockHostUpdatePageResult, GetPageMessageInput, GetUserMessageInput, ListUsersMessageInput, OpenPageMessageInput, QueryDataSourceMessageInput, ResizeMessageInput, UpdatePageMessageInput, } from "./messages/types.js";
|
|
14
15
|
export type { CustomBlockHostQueryDataSourceResult } from "./queries/types.js";
|
|
15
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAA;AAChG,YAAY,EAAE,cAAc,EAAE,MAAM,sDAAsD,CAAA;AAC1F,YAAY,EAAE,cAAc,EAAE,MAAM,sDAAsD,CAAA;AAC1F,YAAY,EAAE,gBAAgB,EAAE,MAAM,wDAAwD,CAAA;AAC9F,YAAY,EAAE,eAAe,EAAE,MAAM,uDAAuD,CAAA;AAC5F,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,oBAAoB,EAAE,MAAM,4CAA4C,CAAA;AACtF,YAAY,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAA;AAChG,YAAY,EAAE,cAAc,EAAE,MAAM,sDAAsD,CAAA;AAC1F,YAAY,EAAE,cAAc,EAAE,MAAM,sDAAsD,CAAA;AAC1F,YAAY,EAAE,gBAAgB,EAAE,MAAM,wDAAwD,CAAA;AAC9F,YAAY,EAAE,eAAe,EAAE,MAAM,uDAAuD,CAAA;AAC5F,YAAY,EACX,iCAAiC,EACjC,iCAAiC,EACjC,kCAAkC,EAClC,6BAA6B,EAC7B,+BAA+B,EAC/B,+BAA+B,EAC/B,+BAA+B,EAC/B,4BAA4B,EAC5B,6BAA6B,EAC7B,sBAAsB,EACtB,mCAAmC,EACnC,2CAA2C,EAC3C,iCAAiC,GACjC,MAAM,8DAA8D,CAAA;AACrE,YAAY,EAAE,aAAa,EAAE,MAAM,qDAAqD,CAAA;AACxF,YAAY,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAA;AAChG,YAAY,EACX,eAAe,EACf,eAAe,EACf,eAAe,EACf,cAAc,EACd,uBAAuB,EACvB,0BAA0B,EAC1B,kBAAkB,EAClB,uBAAuB,GACvB,MAAM,gDAAgD,CAAA;AACvD,OAAO,EACN,KAAK,oBAAoB,EACzB,4BAA4B,GAC5B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACN,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,qBAAqB,GACrB,MAAM,4BAA4B,CAAA;AACnC,YAAY,EACX,qBAAqB,EACrB,iCAAiC,EACjC,8BAA8B,EAC9B,2BAA2B,EAC3B,iCAAiC,GACjC,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EACX,sBAAsB,EACtB,+BAA+B,EAC/B,sBAAsB,EACtB,4BAA4B,EAC5B,4BAA4B,EAC5B,uBAAuB,EACvB,8BAA8B,EAC9B,2BAA2B,EAC3B,6BAA6B,EAC7B,+BAA+B,EAC/B,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,2BAA2B,EAC3B,kBAAkB,EAClB,sBAAsB,GACtB,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EAAE,oCAAoC,EAAE,MAAM,oBAAoB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initErrors.d.ts","sourceRoot":"","sources":["../../src/lifecycle/initErrors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,wBAAwB,EACxB,wBAAwB,EACxB,MAAM,mDAAmD,CAAA;AAK1D;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACxC,MAAM,EAAE,wBAAwB,EAChC,IAAI,GAAE;IACL,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,4BAA4B,CAAC,EAAE,MAAM,CAAA;CAChC,GACJ,wBAAwB,
|
|
1
|
+
{"version":3,"file":"initErrors.d.ts","sourceRoot":"","sources":["../../src/lifecycle/initErrors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,wBAAwB,EACxB,wBAAwB,EACxB,MAAM,mDAAmD,CAAA;AAK1D;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACxC,MAAM,EAAE,wBAAwB,EAChC,IAAI,GAAE;IACL,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,4BAA4B,CAAC,EAAE,MAAM,CAAA;CAChC,GACJ,wBAAwB,CAqJ1B"}
|
|
@@ -77,6 +77,12 @@ export function initErrorForFailureReason(reason, data = {}) {
|
|
|
77
77
|
message: "Current user is unavailable.",
|
|
78
78
|
isRetryable: true,
|
|
79
79
|
};
|
|
80
|
+
case "initial_state_timeout":
|
|
81
|
+
return {
|
|
82
|
+
code: reason,
|
|
83
|
+
message: "Host did not prepare initial state before the timeout.",
|
|
84
|
+
isRetryable: true,
|
|
85
|
+
};
|
|
80
86
|
case "missing_data_source_binding":
|
|
81
87
|
return {
|
|
82
88
|
code: reason,
|
|
@@ -1,39 +1,16 @@
|
|
|
1
|
-
import type { NotionContrastMode } from "../protocol/contrast.js";
|
|
2
|
-
import type { NotionBlockId } from "../protocol/ids.js";
|
|
3
|
-
import type { CustomBlockManifest } from "../protocol/manifest.js";
|
|
4
1
|
import type { ConnectMessage } from "../protocol/messages/connect.js";
|
|
5
2
|
import type { CustomBlockInitErrorInfo, InitMessage } from "../protocol/messages/init.js";
|
|
6
3
|
import type { InitResultMessage } from "../protocol/messages/initResult.js";
|
|
7
|
-
import type { CustomBlockPage } from "../protocol/pages/page.js";
|
|
8
|
-
import type { NotionParent } from "../protocol/parent.js";
|
|
9
|
-
import type { NotionTheme } from "../protocol/theme.js";
|
|
10
|
-
import type { NotionUser } from "../protocol/users/user.js";
|
|
11
4
|
import type { CustomBlockHostFailure } from "../messages/types.js";
|
|
12
|
-
import type { ConnectSuccessMessage,
|
|
13
|
-
type InitializationState = {
|
|
14
|
-
theme: NotionTheme;
|
|
15
|
-
contrastMode: NotionContrastMode;
|
|
16
|
-
parent: NotionParent;
|
|
17
|
-
page: CustomBlockPage;
|
|
18
|
-
currentUser: NotionUser;
|
|
19
|
-
};
|
|
20
|
-
type InitializationPreparation = {
|
|
21
|
-
status: "success";
|
|
22
|
-
manifest: CustomBlockManifest;
|
|
23
|
-
dataSources: CustomBlockHostDataSourcesPayload;
|
|
24
|
-
} | {
|
|
25
|
-
status: "error";
|
|
26
|
-
error: CustomBlockInitErrorInfo;
|
|
27
|
-
};
|
|
5
|
+
import type { ConnectSuccessMessage, CustomBlockHostInitialStateResult, InitStatus } from "./types.js";
|
|
28
6
|
export type InitializationControllerOptions = {
|
|
29
|
-
|
|
30
|
-
getState: () => InitializationState;
|
|
31
|
-
prepareInit: (connect: ConnectSuccessMessage) => InitializationPreparation;
|
|
7
|
+
prepareInit: (connect: ConnectSuccessMessage) => Promise<CustomBlockHostInitialStateResult>;
|
|
32
8
|
sendInitMessage: (message: InitMessage) => void;
|
|
33
9
|
warn: (payload: unknown) => void;
|
|
34
10
|
flushPendingHostStateChanges: () => void;
|
|
35
11
|
minBridgeProtocolVersion: number;
|
|
36
12
|
noConnectTimeoutMs?: number;
|
|
13
|
+
initialStateTimeoutMs?: number;
|
|
37
14
|
noInitResultTimeoutMs?: number;
|
|
38
15
|
stopHostWithFailure: (error: CustomBlockHostFailure) => void;
|
|
39
16
|
onInitResult?: (message: InitResultMessage) => void;
|
|
@@ -57,5 +34,4 @@ export type InitializationController = {
|
|
|
57
34
|
stop: () => void;
|
|
58
35
|
};
|
|
59
36
|
export declare function createInitializationController(options: InitializationControllerOptions): InitializationController;
|
|
60
|
-
export {};
|
|
61
37
|
//# sourceMappingURL=initializationController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initializationController.d.ts","sourceRoot":"","sources":["../../src/lifecycle/initializationController.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"initializationController.d.ts","sourceRoot":"","sources":["../../src/lifecycle/initializationController.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sDAAsD,CAAA;AAC1F,OAAO,KAAK,EACX,wBAAwB,EACxB,WAAW,EACX,MAAM,mDAAmD,CAAA;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAA;AAChG,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAIlE,OAAO,KAAK,EACX,qBAAqB,EACrB,iCAAiC,EACjC,UAAU,EACV,MAAM,YAAY,CAAA;AAMnB,MAAM,MAAM,+BAA+B,GAAG;IAC7C,WAAW,EAAE,CACZ,OAAO,EAAE,qBAAqB,KAC1B,OAAO,CAAC,iCAAiC,CAAC,CAAA;IAC/C,eAAe,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAA;IAC/C,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IAChC,4BAA4B,EAAE,MAAM,IAAI,CAAA;IACxC,wBAAwB,EAAE,MAAM,CAAA;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,mBAAmB,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAA;IAC5D,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACnD,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAA;CACnD,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACtC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;IAC3B,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAA;IACrC,aAAa,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IAChD,gBAAgB,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACtD,oBAAoB,EAAE,CAAC,IAAI,EAAE;QAC5B,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAA;QACpC,KAAK,EAAE,wBAAwB,CAAA;QAC/B,qBAAqB,EAAE,MAAM,GAAG,SAAS,CAAA;KACzC,KAAK,SAAS,GAAG,MAAM,CAAA;IACxB,uBAAuB,EAAE,CAAC,IAAI,EAAE;QAC/B,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAA;QACpC,KAAK,EAAE,wBAAwB,CAAA;KAC/B,KAAK,IAAI,CAAA;IACV,YAAY,EAAE,MAAM,IAAI,CAAA;IACxB,IAAI,EAAE,MAAM,IAAI,CAAA;CAChB,CAAA;AAED,wBAAgB,8BAA8B,CAC7C,OAAO,EAAE,+BAA+B,GACtC,wBAAwB,CAiU1B"}
|