@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 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
- initialState: {
51
- theme,
52
- contrastMode,
53
- blockId,
54
- parent,
55
- page,
56
- currentUser,
57
- manifest,
58
- dataSources: { bindings },
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
- - `onManifest` provides the selected manifest as soon as it is available after `connect`, before
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
- `initialState.dataSources` may also be a function of the successful `connect` message. This lets a
161
- host derive bindings from the sandbox-provided manifest.
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 also accepts
165
- `noConnectTimeoutMs` and `noInitResultTimeoutMs`; both default to five seconds.
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 { type NotionContrastMode } from "./protocol/contrast.js";
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, CustomBlockHostInitialState } from "./lifecycle/types.js";
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 minimum. Higher
15
- * values retire older SDKs; lower values cannot enable protocol versions the runtime no longer
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,EAEN,KAAK,kBAAkB,EACvB,MAAM,8CAA8C,CAAA;AAErD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AACjF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAA;AAmBvF,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,2BAA2B,EAC3B,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,YAAY,EAAE,2BAA2B,CAAA;IACzC,QAAQ,EAAE,uBAAuB,CAAA;IACjC;;;OAGG;IACH,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;CAC1E,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,CA4ZvB"}
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, initialState, handlers, onManifest, onInitialized, onFailure, onLog, sandboxOrigin, minBridgeProtocolVersion: configuredMinBridgeProtocolVersion, noConnectTimeoutMs, noInitResultTimeoutMs, } = options;
17
- // Callers can retire older SDKs, but cannot restore support for protocols the runtime no longer
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 theme = initialState.theme;
22
- let contrastMode = initialState.contrastMode ?? DEFAULT_CONTRAST_MODE;
23
- let parent = initialState.parent;
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
- * Sends any pending host state changes to the sandbox. It is possible for these to change
137
- * between when the host sends `init` and when the sandbox responds with `initResult`. The host
138
- * does not send pending state changes until the sandbox responds.
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
- if (pendingThemeChange) {
142
- pendingThemeChange = false;
143
- sendInitializedMessage({ type: "themeChanged", theme });
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
- if (pendingContrastModeChange) {
146
- pendingContrastModeChange = false;
147
- sendInitializedMessage({ type: "contrastModeChanged", contrastMode });
140
+ const changes = pendingState;
141
+ pendingState = {};
142
+ if (changes.theme !== undefined) {
143
+ sendInitializedMessage({ type: "themeChanged", theme: changes.theme });
148
144
  }
149
- if (pendingParentChange) {
150
- pendingParentChange = false;
151
- sendInitializedMessage({ type: "parentChanged", parent });
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 (pendingPageChange) {
154
- pendingPageChange = false;
155
- sendInitializedMessage({ type: "pageChanged", page });
154
+ if (changes.page !== undefined) {
155
+ sendInitializedMessage({ type: "pageChanged", page: changes.page });
156
156
  }
157
- if (pendingDataSourcesChange !== undefined) {
158
- const nextDataSources = pendingDataSourcesChange;
159
- pendingDataSourcesChange = undefined;
157
+ if (changes.dataSources !== undefined) {
160
158
  sendInitializedMessage({
161
159
  type: "dataSourcesChanged",
162
- dataSources: nextDataSources,
160
+ dataSources: changes.dataSources,
163
161
  });
164
162
  }
165
- if (pendingCurrentUserChange) {
166
- pendingCurrentUserChange = false;
167
- sendInitializedMessage({ type: "currentUserChanged", currentUser });
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
- blockId: initialState.blockId,
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
- if (sandboxBridgeProtocolVersion <
182
- BRIDGE_PROTOCOL_VERSION_INTRODUCING_UNAVAILABLE_PAGE &&
183
- page.type === "unavailable") {
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
- onManifest?.(manifest);
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(nextTheme) {
262
- theme = nextTheme;
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(nextContrastMode) {
273
- contrastMode = nextContrastMode;
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(nextParent) {
287
- parent = nextParent;
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(nextPage) {
298
- page = nextPage;
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 === "waitingForInitResult" ||
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
- if (initializationController.status !== "initialized") {
308
- if (initializationController.status === "waitingForInitResult") {
309
- pendingPageChange = true;
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(nextDataSources) {
281
+ setDataSources(dataSources) {
317
282
  if (initializationController.hasConnectedSandbox &&
318
283
  manifest !== undefined &&
319
- getBindingErrorCode(manifest, nextDataSources) !== undefined) {
284
+ getBindingErrorCode(manifest, dataSources) !== undefined) {
320
285
  emit("warn", {
321
286
  message: "Ignored invalid data source bindings update",
322
- payload: nextDataSources,
287
+ payload: dataSources,
323
288
  });
324
289
  return;
325
290
  }
326
- dataSources = nextDataSources;
327
- activeDataSources = nextDataSources;
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, CustomBlockHostInitialDataSources, CustomBlockHostInitialState, } from "./lifecycle/types.js";
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
@@ -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,EAAE,sBAAsB,EAAE,MAAM,8DAA8D,CAAA;AAC1G,YAAY,EAAE,aAAa,EAAE,MAAM,qDAAqD,CAAA;AACxF,YAAY,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAA;AAChG,YAAY,EACX,uBAAuB,EACvB,0BAA0B,EAC1B,kBAAkB,GAClB,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,iCAAiC,EACjC,2BAA2B,GAC3B,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
+ {"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,CA+I1B"}
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, CustomBlockHostDataSourcesPayload, InitStatus } from "./types.js";
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
- blockId: NotionBlockId;
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":"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"}
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"}