@notionhq/custom-blocks-host 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -78,6 +78,9 @@ const host = createCustomBlockHost({
78
78
  onIgnoredConnect: () => {
79
79
  remountHostAndIframe();
80
80
  },
81
+ onInitializationFailure: (error) => {
82
+ showInitializationError(error);
83
+ },
81
84
  onLog: (direction, payload) => {
82
85
  console.log(direction, payload);
83
86
  },
@@ -90,6 +93,9 @@ replaced, or the document's first `connect` came after the no-connect timeout.
90
93
  Recreate the host and the iframe together so the document runs a fresh
91
94
  handshake against current host state.
92
95
 
96
+ `onInitializationFailure` receives structured errors from failed `init`
97
+ messages, failed `initResult` messages, and initialization timeouts.
98
+
93
99
  `queryDataSource` is required. Other request handlers are optional. Every
94
100
  request handler may return its result synchronously or as a promise. Results
95
101
  use a `status` discriminator: successful results carry their response payload,
@@ -8,7 +8,7 @@ import type { NotionParent } from "./protocol/parent.js";
8
8
  import type { NotionTheme } from "./protocol/theme.js";
9
9
  import type { NotionUser } from "./protocol/users/user.js";
10
10
  import type { ConnectSuccessMessage, CustomBlockHostDataSourcesPayload, CustomBlockHostInitialState } from "./lifecycle/types.js";
11
- import type { CustomBlockHostHandlers, CustomBlockHostLogDirection } from "./messages/types.js";
11
+ import type { CustomBlockHostHandlers, CustomBlockHostInitializationFailure, CustomBlockHostLogDirection } from "./messages/types.js";
12
12
  export type CustomBlockHostOptions = {
13
13
  iframe: HTMLIFrameElement;
14
14
  sandboxOrigin: string;
@@ -19,6 +19,7 @@ export type CustomBlockHostOptions = {
19
19
  handlers: CustomBlockHostHandlers;
20
20
  onConnect?: (message: ConnectSuccessMessage) => void;
21
21
  onInitResult?: (message: InitResultMessage) => void;
22
+ onInitializationFailure?: (error: CustomBlockHostInitializationFailure) => void;
22
23
  /**
23
24
  * A `connect` arrived after this host's initialization settled — the
24
25
  * document was replaced, or its first `connect` came after the host
@@ -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;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AAEjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sDAAsD,CAAA;AAa1F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4DAA4D,CAAA;AAEtG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAA;AAahG,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,qBAAqB,EACrB,iCAAiC,EACjC,2BAA2B,EAC3B,MAAM,sBAAsB,CAAA;AAE7B,OAAO,KAAK,EACX,uBAAuB,EACvB,2BAA2B,EAC3B,MAAM,qBAAqB,CAAA;AAU5B,MAAM,MAAM,sBAAsB,GAAG;IACpC,MAAM,EAAE,iBAAiB,CAAA;IACzB,aAAa,EAAE,MAAM,CAAA;IACrB,wBAAwB,EAAE,MAAM,CAAA;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,YAAY,EAAE,2BAA2B,CAAA;IACzC,QAAQ,EAAE,uBAAuB,CAAA;IACjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAA;IACpD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACnD;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IACpD,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,IAAI,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,CAAA;IAC7C,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;AAMD,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,sBAAsB,GAC7B,qBAAqB,CA+cvB"}
1
+ {"version":3,"file":"createCustomBlockHost.d.ts","sourceRoot":"","sources":["../src/createCustomBlockHost.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,kBAAkB,EACvB,MAAM,8CAA8C,CAAA;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AAEjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sDAAsD,CAAA;AAa1F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4DAA4D,CAAA;AAEtG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAA;AAahG,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,qBAAqB,EACrB,iCAAiC,EACjC,2BAA2B,EAC3B,MAAM,sBAAsB,CAAA;AAE7B,OAAO,KAAK,EACX,uBAAuB,EACvB,oCAAoC,EACpC,2BAA2B,EAC3B,MAAM,qBAAqB,CAAA;AAU5B,MAAM,MAAM,sBAAsB,GAAG;IACpC,MAAM,EAAE,iBAAiB,CAAA;IACzB,aAAa,EAAE,MAAM,CAAA;IACrB,wBAAwB,EAAE,MAAM,CAAA;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,YAAY,EAAE,2BAA2B,CAAA;IACzC,QAAQ,EAAE,uBAAuB,CAAA;IACjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAA;IACpD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACnD,uBAAuB,CAAC,EAAE,CACzB,KAAK,EAAE,oCAAoC,KACvC,IAAI,CAAA;IACT;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IACpD,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,IAAI,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,CAAA;IAC7C,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;AAMD,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,sBAAsB,GAC7B,qBAAqB,CAidvB"}
@@ -13,7 +13,7 @@ const initializationIdentitySchema = v.object({
13
13
  initializationId: v.string(),
14
14
  });
15
15
  export function createCustomBlockHost(options) {
16
- const { iframe, initialState, handlers, onConnect, onInitResult, onIgnoredConnect, onLog, sandboxOrigin, minBridgeProtocolVersion: configuredMinBridgeProtocolVersion, noConnectTimeoutMs, noInitResultTimeoutMs, } = options;
16
+ const { iframe, initialState, handlers, onConnect, onInitResult, onInitializationFailure, onIgnoredConnect, onLog, sandboxOrigin, minBridgeProtocolVersion: configuredMinBridgeProtocolVersion, noConnectTimeoutMs, noInitResultTimeoutMs, } = options;
17
17
  const minBridgeProtocolVersion = Math.max(configuredMinBridgeProtocolVersion ?? CUSTOM_BLOCK_BRIDGE_PROTOCOL_VERSION, CUSTOM_BLOCK_BRIDGE_PROTOCOL_VERSION);
18
18
  let theme = initialState.theme;
19
19
  let contrastMode = initialState.contrastMode ?? DEFAULT_CONTRAST_MODE;
@@ -212,6 +212,7 @@ export function createCustomBlockHost(options) {
212
212
  onConnect,
213
213
  onInitResult,
214
214
  onIgnoredConnect,
215
+ onInitializationFailure,
215
216
  });
216
217
  function onInvalidSandboxMessage(data, issues) {
217
218
  emit("warn", {
@@ -224,10 +225,13 @@ export function createCustomBlockHost(options) {
224
225
  const initializationId = parsedIdentity.success
225
226
  ? parsedIdentity.output.initializationId
226
227
  : undefined;
227
- if (response.incomingType === "connect" &&
228
- initializationId !== undefined &&
229
- initializationController.handleInvalidConnect(initializationId)) {
230
- return;
228
+ if (response.incomingType === "connect") {
229
+ if (initializationController.handleInvalidConnect(initializationId)) {
230
+ if (initializationId === undefined && response.nack !== undefined) {
231
+ post(response.nack);
232
+ }
233
+ return;
234
+ }
231
235
  }
232
236
  if (response.incomingType === "initResult" &&
233
237
  initializationController.handleInvalidInitResult()) {
@@ -259,8 +263,7 @@ export function createCustomBlockHost(options) {
259
263
  if (message.type !== "connect" &&
260
264
  message.type !== "initResult" &&
261
265
  initializationController.status !== "success") {
262
- // The SDK reports resize as soon as it renders, before the
263
- // handshake completes, so an early resize is routine.
266
+ // Ignore all non-handshake messages until initialization succeeds.
264
267
  if (message.type !== "resize") {
265
268
  emit("warn", {
266
269
  message: `Ignored ${message.type} before initialization completed`,
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { type AutoBindableProperty, getAutoBoundPropertyIdsByKey, } from "./autoBindProperties.js";
2
2
  export { type CustomBlockHostHandle, type CustomBlockHostOptions, createCustomBlockHost, } from "./createCustomBlockHost.js";
3
3
  export type { ConnectSuccessMessage, CustomBlockHostDataSourcesPayload, CustomBlockHostInitialDataSources, CustomBlockHostInitialState, } from "./lifecycle/types.js";
4
- export type { CustomBlockHostCreatePageResult, CustomBlockHostGetPageResult, CustomBlockHostGetUserResult, CustomBlockHostHandlers, CustomBlockHostListUsersResult, CustomBlockHostLogDirection, CustomBlockHostUpdatePageResult, } from "./messages/types.js";
4
+ export type { CustomBlockHostCreatePageResult, CustomBlockHostGetPageResult, CustomBlockHostGetUserResult, CustomBlockHostHandlers, CustomBlockHostInitializationFailure, CustomBlockHostListUsersResult, CustomBlockHostLogDirection, CustomBlockHostUpdatePageResult, } from "./messages/types.js";
5
5
  export type { CustomBlockHostQueryDataSourceResult } from "./queries/types.js";
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,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,+BAA+B,EAC/B,4BAA4B,EAC5B,4BAA4B,EAC5B,uBAAuB,EACvB,8BAA8B,EAC9B,2BAA2B,EAC3B,+BAA+B,GAC/B,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,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,+BAA+B,EAC/B,4BAA4B,EAC5B,4BAA4B,EAC5B,uBAAuB,EACvB,oCAAoC,EACpC,8BAA8B,EAC9B,2BAA2B,EAC3B,+BAA+B,GAC/B,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EAAE,oCAAoC,EAAE,MAAM,oBAAoB,CAAA"}
@@ -9,6 +9,7 @@ import type { CustomBlockPage } from "../protocol/pages/page.js";
9
9
  import type { NotionParent } from "../protocol/parent.js";
10
10
  import type { NotionTheme } from "../protocol/theme.js";
11
11
  import type { NotionUser } from "../protocol/users/user.js";
12
+ import type { CustomBlockHostInitializationFailure } from "../messages/types.js";
12
13
  import type { ConnectSuccessMessage, CustomBlockHostDataSourcesPayload, InitStatus } from "./types.js";
13
14
  type InitializationState = {
14
15
  theme: NotionTheme;
@@ -38,13 +39,14 @@ export type InitializationControllerOptions = {
38
39
  onConnect?: (message: ConnectSuccessMessage) => void;
39
40
  onInitResult?: (message: InitResultMessage) => void;
40
41
  onIgnoredConnect?: (message: ConnectMessage) => void;
42
+ onInitializationFailure?: (error: CustomBlockHostInitializationFailure) => void;
41
43
  };
42
44
  export type InitializationController = {
43
45
  readonly status: InitStatus;
44
46
  readonly hasConnectedSandbox: boolean;
45
47
  handleConnect: (message: ConnectMessage) => void;
46
48
  handleInitResult: (message: InitResultMessage) => void;
47
- handleInvalidConnect: (initializationId: string) => boolean;
49
+ handleInvalidConnect: (initializationId?: string) => boolean;
48
50
  handleInvalidInitResult: () => boolean;
49
51
  onIframeLoad: () => void;
50
52
  stop: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"initializationController.d.ts","sourceRoot":"","sources":["../../src/lifecycle/initializationController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAA;AACtF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAA;AACvF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sDAAsD,CAAA;AAC1F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4DAA4D,CAAA;AACtG,OAAO,KAAK,EACX,wBAAwB,EAExB,MAAM,mDAAmD,CAAA;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAA;AAChG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAA;AACrF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAA;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAA;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gDAAgD,CAAA;AAGhF,OAAO,KAAK,EACX,qBAAqB,EACrB,iCAAiC,EACjC,UAAU,EACV,MAAM,YAAY,CAAA;AAKnB,KAAK,mBAAmB,GAAG;IAC1B,KAAK,EAAE,WAAW,CAAA;IAClB,YAAY,EAAE,kBAAkB,CAAA;IAChC,MAAM,EAAE,YAAY,CAAA;IACpB,IAAI,EAAE,eAAe,CAAA;IACrB,WAAW,EAAE,UAAU,CAAA;CACvB,CAAA;AAED,KAAK,yBAAyB,GAC3B;IACA,MAAM,EAAE,SAAS,CAAA;IACjB,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,WAAW,EAAE,iCAAiC,CAAA;CAC7C,GACD;IACA,MAAM,EAAE,OAAO,CAAA;IACf,KAAK,EAAE,wBAAwB,CAAA;CAC9B,CAAA;AAEJ,MAAM,MAAM,+BAA+B,GAAG;IAC7C,OAAO,EAAE,aAAa,CAAA;IACtB,QAAQ,EAAE,MAAM,mBAAmB,CAAA;IACnC,WAAW,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,yBAAyB,CAAA;IAC1E,IAAI,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,CAAA;IAC7C,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,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAA;IACpD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACnD,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;CACpD,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,gBAAgB,EAAE,MAAM,KAAK,OAAO,CAAA;IAC3D,uBAAuB,EAAE,MAAM,OAAO,CAAA;IACtC,YAAY,EAAE,MAAM,IAAI,CAAA;IACxB,IAAI,EAAE,MAAM,IAAI,CAAA;CAChB,CAAA;AAED,wBAAgB,8BAA8B,CAC7C,OAAO,EAAE,+BAA+B,GACtC,wBAAwB,CAyN1B"}
1
+ {"version":3,"file":"initializationController.d.ts","sourceRoot":"","sources":["../../src/lifecycle/initializationController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAA;AACtF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAA;AACvF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sDAAsD,CAAA;AAC1F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4DAA4D,CAAA;AACtG,OAAO,KAAK,EACX,wBAAwB,EAExB,MAAM,mDAAmD,CAAA;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAA;AAChG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAA;AACrF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAA;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAA;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gDAAgD,CAAA;AAChF,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,sBAAsB,CAAA;AAGhF,OAAO,KAAK,EACX,qBAAqB,EACrB,iCAAiC,EACjC,UAAU,EACV,MAAM,YAAY,CAAA;AAKnB,KAAK,mBAAmB,GAAG;IAC1B,KAAK,EAAE,WAAW,CAAA;IAClB,YAAY,EAAE,kBAAkB,CAAA;IAChC,MAAM,EAAE,YAAY,CAAA;IACpB,IAAI,EAAE,eAAe,CAAA;IACrB,WAAW,EAAE,UAAU,CAAA;CACvB,CAAA;AAED,KAAK,yBAAyB,GAC3B;IACA,MAAM,EAAE,SAAS,CAAA;IACjB,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,WAAW,EAAE,iCAAiC,CAAA;CAC7C,GACD;IACA,MAAM,EAAE,OAAO,CAAA;IACf,KAAK,EAAE,wBAAwB,CAAA;CAC9B,CAAA;AAEJ,MAAM,MAAM,+BAA+B,GAAG;IAC7C,OAAO,EAAE,aAAa,CAAA;IACtB,QAAQ,EAAE,MAAM,mBAAmB,CAAA;IACnC,WAAW,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,yBAAyB,CAAA;IAC1E,IAAI,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,CAAA;IAC7C,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,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAA;IACpD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACnD,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IACpD,uBAAuB,CAAC,EAAE,CACzB,KAAK,EAAE,oCAAoC,KACvC,IAAI,CAAA;CACT,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,gBAAgB,CAAC,EAAE,MAAM,KAAK,OAAO,CAAA;IAC5D,uBAAuB,EAAE,MAAM,OAAO,CAAA;IACtC,YAAY,EAAE,MAAM,IAAI,CAAA;IACxB,IAAI,EAAE,MAAM,IAAI,CAAA;CAChB,CAAA;AAED,wBAAgB,8BAA8B,CAC7C,OAAO,EAAE,+BAA+B,GACtC,wBAAwB,CAyO1B"}
@@ -3,7 +3,7 @@ import { isValidBridgeProtocolVersion } from "./protocolVersion.js";
3
3
  const DEFAULT_NO_CONNECT_TIMEOUT_MS = 5000;
4
4
  const DEFAULT_NO_INIT_RESULT_TIMEOUT_MS = 5000;
5
5
  export function createInitializationController(options) {
6
- const { blockId, getState, prepareInit, post, warn, flushPendingHostStateChanges, minBridgeProtocolVersion, noConnectTimeoutMs = DEFAULT_NO_CONNECT_TIMEOUT_MS, noInitResultTimeoutMs = DEFAULT_NO_INIT_RESULT_TIMEOUT_MS, onConnect, onInitResult, onIgnoredConnect, } = options;
6
+ const { blockId, getState, prepareInit, post, warn, flushPendingHostStateChanges, minBridgeProtocolVersion, noConnectTimeoutMs = DEFAULT_NO_CONNECT_TIMEOUT_MS, noInitResultTimeoutMs = DEFAULT_NO_INIT_RESULT_TIMEOUT_MS, onConnect, onInitResult, onIgnoredConnect, onInitializationFailure, } = options;
7
7
  let initStatus = "waitingForConnect";
8
8
  let noConnectTimeoutId;
9
9
  let noInitResultTimeoutId;
@@ -34,6 +34,7 @@ export function createInitializationController(options) {
34
34
  status: "error",
35
35
  error,
36
36
  });
37
+ onInitializationFailure?.(error);
37
38
  }
38
39
  function sendInit(connect) {
39
40
  if (initStatus !== "waitingForConnect") {
@@ -68,10 +69,12 @@ export function createInitializationController(options) {
68
69
  return;
69
70
  }
70
71
  initStatus = "error";
72
+ const error = initErrorForFailureReason("no_init_result");
71
73
  warn({
72
74
  message: "Sandbox did not send initResult",
73
75
  initializationId: connect.initializationId,
74
76
  });
77
+ onInitializationFailure?.(error);
75
78
  }, noInitResultTimeoutMs);
76
79
  return true;
77
80
  }
@@ -118,7 +121,16 @@ export function createInitializationController(options) {
118
121
  if (initStatus !== "waitingForConnect") {
119
122
  return false;
120
123
  }
121
- sendInitError(initializationId, initErrorForFailureReason("invalid_connect_payload"));
124
+ const error = initErrorForFailureReason("invalid_connect_payload");
125
+ if (initializationId === undefined) {
126
+ initStatus = "error";
127
+ clearNoConnectTimeout();
128
+ warn(error);
129
+ onInitializationFailure?.(error);
130
+ }
131
+ else {
132
+ sendInitError(initializationId, error);
133
+ }
122
134
  return true;
123
135
  }
124
136
  function handleInvalidInitResult() {
@@ -127,7 +139,9 @@ export function createInitializationController(options) {
127
139
  }
128
140
  clearNoInitResultTimeout();
129
141
  initStatus = "error";
130
- warn(initErrorForFailureReason("invalid_init_result_payload"));
142
+ const error = initErrorForFailureReason("invalid_init_result_payload");
143
+ warn(error);
144
+ onInitializationFailure?.(error);
131
145
  return true;
132
146
  }
133
147
  function onIframeLoad() {
@@ -142,7 +156,9 @@ export function createInitializationController(options) {
142
156
  return;
143
157
  }
144
158
  initStatus = "error";
145
- warn(initErrorForFailureReason("no_connect"));
159
+ const error = initErrorForFailureReason("no_connect");
160
+ warn(error);
161
+ onInitializationFailure?.(error);
146
162
  }, noConnectTimeoutMs);
147
163
  }
148
164
  function handleInitResult(message) {
@@ -155,10 +171,14 @@ export function createInitializationController(options) {
155
171
  return;
156
172
  }
157
173
  clearNoInitResultTimeout();
158
- initStatus = message.status === "success" ? "success" : "error";
159
- if (initStatus === "success") {
174
+ if (message.status === "success") {
175
+ initStatus = "success";
160
176
  flushPendingHostStateChanges();
161
177
  }
178
+ else {
179
+ initStatus = "error";
180
+ onInitializationFailure?.(message.error);
181
+ }
162
182
  onInitResult?.(message);
163
183
  }
164
184
  function stop() {
@@ -3,6 +3,8 @@ import type { CreatePageMessage } from "../protocol/messages/createPage.js";
3
3
  import type { CreatePageResultMessage, CustomBlockCreatePageErrorInfo } from "../protocol/messages/createPageResult.js";
4
4
  import type { CustomBlockGetPageErrorInfo, GetPageMessage, GetPageResultMessage } from "../protocol/messages/getPage.js";
5
5
  import type { CustomBlockGetUserErrorInfo, GetUserMessage, GetUserResultMessage } from "../protocol/messages/getUser.js";
6
+ import type { CustomBlockInitErrorInfo } from "../protocol/messages/init.js";
7
+ import type { CustomBlockInitResultErrorInfo } from "../protocol/messages/initResult.js";
6
8
  import type { CustomBlockListUsersErrorInfo, ListUsersMessage, ListUsersResultMessage } from "../protocol/messages/listUsers.js";
7
9
  import type { QueryDataSourceMessage } from "../protocol/messages/queryDataSource.js";
8
10
  import type { ResizeMessage } from "../protocol/messages/resize.js";
@@ -24,6 +26,7 @@ export type CustomBlockHostHandlers = {
24
26
  updatePage?: (message: UpdatePageMessage) => MaybePromise<CustomBlockHostUpdatePageResult>;
25
27
  resize?: (message: ResizeMessage) => void;
26
28
  };
29
+ export type CustomBlockHostInitializationFailure = CustomBlockInitErrorInfo | CustomBlockInitResultErrorInfo;
27
30
  export type CustomBlockHostLogDirection = "in" | "out" | "warn";
28
31
  export {};
29
32
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/messages/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oDAAoD,CAAA;AAC9F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAA;AAChG,OAAO,KAAK,EACX,uBAAuB,EACvB,8BAA8B,EAC9B,MAAM,+DAA+D,CAAA;AACtE,OAAO,KAAK,EACX,2BAA2B,EAC3B,cAAc,EACd,oBAAoB,EACpB,MAAM,sDAAsD,CAAA;AAC7D,OAAO,KAAK,EACX,2BAA2B,EAC3B,cAAc,EACd,oBAAoB,EACpB,MAAM,sDAAsD,CAAA;AAC7D,OAAO,KAAK,EACX,6BAA6B,EAC7B,gBAAgB,EAChB,sBAAsB,EACtB,MAAM,wDAAwD,CAAA;AAC/D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8DAA8D,CAAA;AAC1G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qDAAqD,CAAA;AACxF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAA;AAChG,OAAO,KAAK,EACX,8BAA8B,EAC9B,uBAAuB,EACvB,MAAM,+DAA+D,CAAA;AACtE,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,qBAAqB,CAAA;AAE/E,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AAErC,MAAM,MAAM,+BAA+B,GAAG,oBAAoB,CACjE,uBAAuB,EACvB,8BAA8B,CAC9B,CAAA;AAED,MAAM,MAAM,4BAA4B,GAAG,oBAAoB,CAC9D,oBAAoB,EACpB,2BAA2B,CAC3B,CAAA;AAED,MAAM,MAAM,+BAA+B,GAAG,oBAAoB,CACjE,uBAAuB,EACvB,8BAA8B,CAC9B,CAAA;AAED,MAAM,MAAM,4BAA4B,GAAG,oBAAoB,CAC9D,oBAAoB,EACpB,2BAA2B,CAC3B,CAAA;AAED,MAAM,MAAM,8BAA8B,GAAG,oBAAoB,CAChE,sBAAsB,EACtB,6BAA6B,CAC7B,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACrC,eAAe,EAAE,CAChB,OAAO,EAAE,sBAAsB,KAC3B,YAAY,CAAC,oCAAoC,CAAC,CAAA;IACvD,UAAU,CAAC,EAAE,CACZ,OAAO,EAAE,iBAAiB,KACtB,YAAY,CAAC,+BAA+B,CAAC,CAAA;IAClD,OAAO,CAAC,EAAE,CACT,OAAO,EAAE,cAAc,KACnB,YAAY,CAAC,4BAA4B,CAAC,CAAA;IAC/C,OAAO,CAAC,EAAE,CACT,OAAO,EAAE,cAAc,KACnB,YAAY,CAAC,4BAA4B,CAAC,CAAA;IAC/C,SAAS,CAAC,EAAE,CACX,OAAO,EAAE,gBAAgB,KACrB,YAAY,CAAC,8BAA8B,CAAC,CAAA;IACjD,UAAU,CAAC,EAAE,CACZ,OAAO,EAAE,iBAAiB,KACtB,YAAY,CAAC,+BAA+B,CAAC,CAAA;IAClD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAA;CACzC,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/messages/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oDAAoD,CAAA;AAC9F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAA;AAChG,OAAO,KAAK,EACX,uBAAuB,EACvB,8BAA8B,EAC9B,MAAM,+DAA+D,CAAA;AACtE,OAAO,KAAK,EACX,2BAA2B,EAC3B,cAAc,EACd,oBAAoB,EACpB,MAAM,sDAAsD,CAAA;AAC7D,OAAO,KAAK,EACX,2BAA2B,EAC3B,cAAc,EACd,oBAAoB,EACpB,MAAM,sDAAsD,CAAA;AAC7D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mDAAmD,CAAA;AACjG,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,yDAAyD,CAAA;AAC7G,OAAO,KAAK,EACX,6BAA6B,EAC7B,gBAAgB,EAChB,sBAAsB,EACtB,MAAM,wDAAwD,CAAA;AAC/D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8DAA8D,CAAA;AAC1G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qDAAqD,CAAA;AACxF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAA;AAChG,OAAO,KAAK,EACX,8BAA8B,EAC9B,uBAAuB,EACvB,MAAM,+DAA+D,CAAA;AACtE,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,qBAAqB,CAAA;AAE/E,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AAErC,MAAM,MAAM,+BAA+B,GAAG,oBAAoB,CACjE,uBAAuB,EACvB,8BAA8B,CAC9B,CAAA;AAED,MAAM,MAAM,4BAA4B,GAAG,oBAAoB,CAC9D,oBAAoB,EACpB,2BAA2B,CAC3B,CAAA;AAED,MAAM,MAAM,+BAA+B,GAAG,oBAAoB,CACjE,uBAAuB,EACvB,8BAA8B,CAC9B,CAAA;AAED,MAAM,MAAM,4BAA4B,GAAG,oBAAoB,CAC9D,oBAAoB,EACpB,2BAA2B,CAC3B,CAAA;AAED,MAAM,MAAM,8BAA8B,GAAG,oBAAoB,CAChE,sBAAsB,EACtB,6BAA6B,CAC7B,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACrC,eAAe,EAAE,CAChB,OAAO,EAAE,sBAAsB,KAC3B,YAAY,CAAC,oCAAoC,CAAC,CAAA;IACvD,UAAU,CAAC,EAAE,CACZ,OAAO,EAAE,iBAAiB,KACtB,YAAY,CAAC,+BAA+B,CAAC,CAAA;IAClD,OAAO,CAAC,EAAE,CACT,OAAO,EAAE,cAAc,KACnB,YAAY,CAAC,4BAA4B,CAAC,CAAA;IAC/C,OAAO,CAAC,EAAE,CACT,OAAO,EAAE,cAAc,KACnB,YAAY,CAAC,4BAA4B,CAAC,CAAA;IAC/C,SAAS,CAAC,EAAE,CACX,OAAO,EAAE,gBAAgB,KACrB,YAAY,CAAC,8BAA8B,CAAC,CAAA;IACjD,UAAU,CAAC,EAAE,CACZ,OAAO,EAAE,iBAAiB,KACtB,YAAY,CAAC,+BAA+B,CAAC,CAAA;IAClD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAA;CACzC,CAAA;AAED,MAAM,MAAM,oCAAoC,GAC7C,wBAAwB,GACxB,8BAA8B,CAAA;AAEjC,MAAM,MAAM,2BAA2B,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notionhq/custom-blocks-host",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "description": "Reusable host runtime for Notion custom blocks.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -48,6 +48,7 @@ import type {
48
48
  import { getInvalidSandboxMessageResponse } from "./messages/invalidSandboxMessage.js"
49
49
  import type {
50
50
  CustomBlockHostHandlers,
51
+ CustomBlockHostInitializationFailure,
51
52
  CustomBlockHostLogDirection,
52
53
  } from "./messages/types.js"
53
54
  import {
@@ -69,6 +70,9 @@ export type CustomBlockHostOptions = {
69
70
  handlers: CustomBlockHostHandlers
70
71
  onConnect?: (message: ConnectSuccessMessage) => void
71
72
  onInitResult?: (message: InitResultMessage) => void
73
+ onInitializationFailure?: (
74
+ error: CustomBlockHostInitializationFailure,
75
+ ) => void
72
76
  /**
73
77
  * A `connect` arrived after this host's initialization settled — the
74
78
  * document was replaced, or its first `connect` came after the host
@@ -105,6 +109,7 @@ export function createCustomBlockHost(
105
109
  handlers,
106
110
  onConnect,
107
111
  onInitResult,
112
+ onInitializationFailure,
108
113
  onIgnoredConnect,
109
114
  onLog,
110
115
  sandboxOrigin,
@@ -345,6 +350,7 @@ export function createCustomBlockHost(
345
350
  onConnect,
346
351
  onInitResult,
347
352
  onIgnoredConnect,
353
+ onInitializationFailure,
348
354
  })
349
355
 
350
356
  function onInvalidSandboxMessage(
@@ -362,12 +368,13 @@ export function createCustomBlockHost(
362
368
  const initializationId = parsedIdentity.success
363
369
  ? parsedIdentity.output.initializationId
364
370
  : undefined
365
- if (
366
- response.incomingType === "connect" &&
367
- initializationId !== undefined &&
368
- initializationController.handleInvalidConnect(initializationId)
369
- ) {
370
- return
371
+ if (response.incomingType === "connect") {
372
+ if (initializationController.handleInvalidConnect(initializationId)) {
373
+ if (initializationId === undefined && response.nack !== undefined) {
374
+ post(response.nack)
375
+ }
376
+ return
377
+ }
371
378
  }
372
379
  if (
373
380
  response.incomingType === "initResult" &&
@@ -408,8 +415,7 @@ export function createCustomBlockHost(
408
415
  message.type !== "initResult" &&
409
416
  initializationController.status !== "success"
410
417
  ) {
411
- // The SDK reports resize as soon as it renders, before the
412
- // handshake completes, so an early resize is routine.
418
+ // Ignore all non-handshake messages until initialization succeeds.
413
419
  if (message.type !== "resize") {
414
420
  emit("warn", {
415
421
  message: `Ignored ${message.type} before initialization completed`,
package/src/index.ts CHANGED
@@ -18,6 +18,7 @@ export type {
18
18
  CustomBlockHostGetPageResult,
19
19
  CustomBlockHostGetUserResult,
20
20
  CustomBlockHostHandlers,
21
+ CustomBlockHostInitializationFailure,
21
22
  CustomBlockHostListUsersResult,
22
23
  CustomBlockHostLogDirection,
23
24
  CustomBlockHostUpdatePageResult,
@@ -12,6 +12,7 @@ import type { CustomBlockPage } from "@notionhq/custom-blocks-protocol/pages/pag
12
12
  import type { NotionParent } from "@notionhq/custom-blocks-protocol/parent.js"
13
13
  import type { NotionTheme } from "@notionhq/custom-blocks-protocol/theme.js"
14
14
  import type { NotionUser } from "@notionhq/custom-blocks-protocol/users/user.js"
15
+ import type { CustomBlockHostInitializationFailure } from "../messages/types.js"
15
16
  import { initErrorForFailureReason } from "./initErrors.js"
16
17
  import { isValidBridgeProtocolVersion } from "./protocolVersion.js"
17
18
  import type {
@@ -55,6 +56,9 @@ export type InitializationControllerOptions = {
55
56
  onConnect?: (message: ConnectSuccessMessage) => void
56
57
  onInitResult?: (message: InitResultMessage) => void
57
58
  onIgnoredConnect?: (message: ConnectMessage) => void
59
+ onInitializationFailure?: (
60
+ error: CustomBlockHostInitializationFailure,
61
+ ) => void
58
62
  }
59
63
 
60
64
  export type InitializationController = {
@@ -62,7 +66,7 @@ export type InitializationController = {
62
66
  readonly hasConnectedSandbox: boolean
63
67
  handleConnect: (message: ConnectMessage) => void
64
68
  handleInitResult: (message: InitResultMessage) => void
65
- handleInvalidConnect: (initializationId: string) => boolean
69
+ handleInvalidConnect: (initializationId?: string) => boolean
66
70
  handleInvalidInitResult: () => boolean
67
71
  onIframeLoad: () => void
68
72
  stop: () => void
@@ -84,6 +88,7 @@ export function createInitializationController(
84
88
  onConnect,
85
89
  onInitResult,
86
90
  onIgnoredConnect,
91
+ onInitializationFailure,
87
92
  } = options
88
93
 
89
94
  let initStatus: InitStatus = "waitingForConnect"
@@ -122,6 +127,7 @@ export function createInitializationController(
122
127
  status: "error",
123
128
  error,
124
129
  })
130
+ onInitializationFailure?.(error)
125
131
  }
126
132
 
127
133
  function sendInit(connect: ConnectSuccessMessage): boolean {
@@ -157,10 +163,12 @@ export function createInitializationController(
157
163
  return
158
164
  }
159
165
  initStatus = "error"
166
+ const error = initErrorForFailureReason("no_init_result")
160
167
  warn({
161
168
  message: "Sandbox did not send initResult",
162
169
  initializationId: connect.initializationId,
163
170
  })
171
+ onInitializationFailure?.(error)
164
172
  }, noInitResultTimeoutMs)
165
173
  return true
166
174
  }
@@ -212,14 +220,19 @@ export function createInitializationController(
212
220
  }
213
221
  }
214
222
 
215
- function handleInvalidConnect(initializationId: string): boolean {
223
+ function handleInvalidConnect(initializationId?: string): boolean {
216
224
  if (initStatus !== "waitingForConnect") {
217
225
  return false
218
226
  }
219
- sendInitError(
220
- initializationId,
221
- initErrorForFailureReason("invalid_connect_payload"),
222
- )
227
+ const error = initErrorForFailureReason("invalid_connect_payload")
228
+ if (initializationId === undefined) {
229
+ initStatus = "error"
230
+ clearNoConnectTimeout()
231
+ warn(error)
232
+ onInitializationFailure?.(error)
233
+ } else {
234
+ sendInitError(initializationId, error)
235
+ }
223
236
  return true
224
237
  }
225
238
 
@@ -229,7 +242,9 @@ export function createInitializationController(
229
242
  }
230
243
  clearNoInitResultTimeout()
231
244
  initStatus = "error"
232
- warn(initErrorForFailureReason("invalid_init_result_payload"))
245
+ const error = initErrorForFailureReason("invalid_init_result_payload")
246
+ warn(error)
247
+ onInitializationFailure?.(error)
233
248
  return true
234
249
  }
235
250
 
@@ -245,7 +260,9 @@ export function createInitializationController(
245
260
  return
246
261
  }
247
262
  initStatus = "error"
248
- warn(initErrorForFailureReason("no_connect"))
263
+ const error = initErrorForFailureReason("no_connect")
264
+ warn(error)
265
+ onInitializationFailure?.(error)
249
266
  }, noConnectTimeoutMs)
250
267
  }
251
268
 
@@ -261,9 +278,12 @@ export function createInitializationController(
261
278
  return
262
279
  }
263
280
  clearNoInitResultTimeout()
264
- initStatus = message.status === "success" ? "success" : "error"
265
- if (initStatus === "success") {
281
+ if (message.status === "success") {
282
+ initStatus = "success"
266
283
  flushPendingHostStateChanges()
284
+ } else {
285
+ initStatus = "error"
286
+ onInitializationFailure?.(message.error)
267
287
  }
268
288
  onInitResult?.(message)
269
289
  }
@@ -14,6 +14,8 @@ import type {
14
14
  GetUserMessage,
15
15
  GetUserResultMessage,
16
16
  } from "@notionhq/custom-blocks-protocol/messages/getUser.js"
17
+ import type { CustomBlockInitErrorInfo } from "@notionhq/custom-blocks-protocol/messages/init.js"
18
+ import type { CustomBlockInitResultErrorInfo } from "@notionhq/custom-blocks-protocol/messages/initResult.js"
17
19
  import type {
18
20
  CustomBlockListUsersErrorInfo,
19
21
  ListUsersMessage,
@@ -77,4 +79,8 @@ export type CustomBlockHostHandlers = {
77
79
  resize?: (message: ResizeMessage) => void
78
80
  }
79
81
 
82
+ export type CustomBlockHostInitializationFailure =
83
+ | CustomBlockInitErrorInfo
84
+ | CustomBlockInitResultErrorInfo
85
+
80
86
  export type CustomBlockHostLogDirection = "in" | "out" | "warn"