@notionhq/custom-blocks 0.1.32 → 0.1.34

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.
Files changed (38) hide show
  1. package/dist/bridge/SandboxBridge.d.ts +4 -1
  2. package/dist/bridge/SandboxBridge.d.ts.map +1 -1
  3. package/dist/bridge/SandboxBridge.js +95 -57
  4. package/dist/bridge/dataSources/query.d.ts +26 -0
  5. package/dist/bridge/dataSources/query.d.ts.map +1 -0
  6. package/dist/bridge/dataSources/query.js +377 -0
  7. package/dist/bridge/hostState.d.ts +4 -3
  8. package/dist/bridge/hostState.d.ts.map +1 -1
  9. package/dist/bridge/hostState.js +7 -3
  10. package/dist/bridge/sandboxClient.d.ts +4 -2
  11. package/dist/bridge/sandboxClient.d.ts.map +1 -1
  12. package/dist/bridge/sandboxClient.js +10 -4
  13. package/dist/protocol/messages/init.d.ts +1 -1
  14. package/dist/protocol/messages/init.d.ts.map +1 -1
  15. package/dist/protocol/messages/initResult.d.ts +8 -1
  16. package/dist/protocol/messages/initResult.d.ts.map +1 -1
  17. package/dist/protocol/messages/queryDataSource.d.ts +955 -0
  18. package/dist/protocol/messages/queryDataSource.d.ts.map +1 -1
  19. package/dist/protocol/messages/queryDataSource.js +100 -0
  20. package/dist/protocol/messages/queryDataSourceResult.d.ts +1 -1
  21. package/dist/protocol/messages/queryDataSourceResult.d.ts.map +1 -1
  22. package/dist/protocol/messages/sandboxToHost.d.ts +349 -0
  23. package/dist/protocol/messages/sandboxToHost.d.ts.map +1 -1
  24. package/dist/react/useDataSource.d.ts.map +1 -1
  25. package/dist/react/useDataSource.js +10 -5
  26. package/dist/types.d.ts +45 -0
  27. package/dist/types.d.ts.map +1 -1
  28. package/dist/version.js +1 -1
  29. package/docs/data-sources.md +39 -3
  30. package/docs/errors.md +16 -0
  31. package/docs/lifecycle.md +74 -20
  32. package/package.json +1 -1
  33. package/src/bridge/SandboxBridge.ts +112 -64
  34. package/src/bridge/dataSources/query.ts +470 -0
  35. package/src/bridge/hostState.ts +11 -3
  36. package/src/bridge/sandboxClient.ts +20 -4
  37. package/src/react/useDataSource.ts +16 -5
  38. package/src/types.ts +47 -0
@@ -58,14 +58,17 @@ export declare class SandboxBridge {
58
58
  */
59
59
  setMockState(message: InitMessage): void;
60
60
  completeInitialization(): void;
61
+ private sendInitResultError;
61
62
  private applyInit;
62
63
  /**
63
64
  * Lets the initial application render commit before we acknowledge init. The host keeps the
64
65
  * iframe covered throughout this frame, so it can apply the measured height before first paint.
65
66
  */
66
67
  private scheduleInitResult;
67
- queryDataSource(key: string, options?: UseDataSourceOptions): void;
68
+ createDataSourceSubscriptionId(): string;
69
+ queryDataSource(subscriptionId: string, key: string, options?: UseDataSourceOptions): void;
68
70
  private setDataSourceQueryError;
71
+ releaseDataSourceSubscription(subscriptionId: string): void;
69
72
  postResize(height: number): void;
70
73
  createPage(args: CreatePageArgs): Promise<CreatePageResult>;
71
74
  getPage(pageId: NotionPageId): Promise<GetPageResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"SandboxBridge.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/SandboxBridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SandboxBridge.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/SandboxBridge.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@ import * as v from "valibot";
7
7
  import { unreachable } from "../utils.js";
8
8
  import { CUSTOM_BLOCKS_SDK_VERSION } from "../version.js";
9
9
  import { NOTION_DARK_BACKGROUND_BASE, NOTION_LIGHT_BACKGROUND_BASE, } from "./appearance.js";
10
+ import { resolveDataSourceQuery } from "./dataSources/query.js";
10
11
  import { resolveDataSources } from "./dataSources/resolve.js";
11
12
  import { resolvePropertyWriteMapForDataSource } from "./dataSources/resolveProperty.js";
12
13
  import { createEmptyDataSourceQueryState, } from "./hostState.js";
@@ -53,6 +54,14 @@ export class SandboxBridge {
53
54
  if (!parsed.success) {
54
55
  console.warn("[custom-blocks-sdk] ignoring malformed host message", parsed.issues);
55
56
  const incomingType = readIncomingType(event.data);
57
+ if (!this.hasReceivedInit &&
58
+ incomingType === "init" &&
59
+ this.initializationId !== undefined &&
60
+ readInitializationId(event.data) === this.initializationId) {
61
+ this.hasReceivedInit = true;
62
+ this.sendInitResultError(invalidInitPayloadError(parsed.issues));
63
+ return;
64
+ }
56
65
  // Loop guard: never NACK a NACK. Excludes both directions —
57
66
  // `invalidSandboxMessage` is what the host normally sends, but
58
67
  // a buggy host that echoes our own `invalidHostMessage` back
@@ -161,12 +170,12 @@ export class SandboxBridge {
161
170
  nextBindings,
162
171
  });
163
172
  this.latestDataSourceBindings = nextBindings;
164
- // Drop cached query state for keys that no longer exist in the mapping.
173
+ // Drop cached query state for subscriptions whose key no longer exists.
165
174
  const nextKeys = new Set(dataSources.map(s => s.key));
166
175
  const prunedState = {};
167
- for (const [key, state] of Object.entries(hostState.dataSourceState)) {
168
- if (nextKeys.has(key)) {
169
- prunedState[key] = state;
176
+ for (const [subscriptionId, state] of Object.entries(hostState.dataSourceState)) {
177
+ if (nextKeys.has(state.dataSourceKey)) {
178
+ prunedState[subscriptionId] = state;
170
179
  }
171
180
  }
172
181
  this.hostState = {
@@ -223,11 +232,10 @@ export class SandboxBridge {
223
232
  return;
224
233
  }
225
234
  case "queryDataSourceResult": {
226
- const queryEntry = Object.entries(hostState.dataSourceState).find(([, state]) => state.subscriptionId === message.subscriptionId);
227
- if (queryEntry === undefined) {
235
+ const currentState = hostState.dataSourceState[message.subscriptionId];
236
+ if (currentState === undefined) {
228
237
  return;
229
238
  }
230
- const [key, currentState] = queryEntry;
231
239
  const queryResult = message.status === "error"
232
240
  ? {
233
241
  items: [],
@@ -243,13 +251,14 @@ export class SandboxBridge {
243
251
  ...hostState,
244
252
  dataSourceState: {
245
253
  ...hostState.dataSourceState,
246
- [key]: {
254
+ [message.subscriptionId]: {
255
+ dataSourceKey: currentState.dataSourceKey,
247
256
  items: queryResult.items,
248
257
  isLoading: false,
249
258
  hasMore: queryResult.hasMore,
250
259
  error: queryResult.error,
251
- subscriptionId: message.subscriptionId,
252
260
  latestLimit: currentState.latestLimit,
261
+ latestQueryIdentity: currentState.latestQueryIdentity,
253
262
  },
254
263
  },
255
264
  };
@@ -400,6 +409,24 @@ export class SandboxBridge {
400
409
  this.postToHost(result);
401
410
  this.flushPendingOutboundMessages();
402
411
  }
412
+ sendInitResultError(error) {
413
+ if (this.hasSentInitResult || this.initializationId === undefined) {
414
+ return;
415
+ }
416
+ const result = {
417
+ type: "initResult",
418
+ initializationId: this.initializationId,
419
+ status: "error",
420
+ error,
421
+ };
422
+ this.hasSentInitResult = true;
423
+ this.postToHost(result);
424
+ if (this.rejectInit) {
425
+ this.rejectInit(new CustomBlockInitializationError(error));
426
+ this.resolveInit = undefined;
427
+ this.rejectInit = undefined;
428
+ }
429
+ }
403
430
  applyInit(message, postResult) {
404
431
  if (postResult) {
405
432
  this.isMockState = false;
@@ -429,18 +456,7 @@ export class SandboxBridge {
429
456
  : resolveMockDataSources(this.latestDataSourceBindings);
430
457
  const bindingError = getInitBindingError(message.manifest, dataSources);
431
458
  if (postResult && bindingError !== undefined) {
432
- const result = {
433
- type: "initResult",
434
- initializationId: message.initializationId,
435
- status: "error",
436
- error: bindingError,
437
- };
438
- this.postToHost(result);
439
- if (this.rejectInit) {
440
- this.rejectInit(new CustomBlockInitializationError(bindingError));
441
- this.resolveInit = undefined;
442
- this.rejectInit = undefined;
443
- }
459
+ this.sendInitResultError(bindingError);
444
460
  return;
445
461
  }
446
462
  this.hostState = {
@@ -497,14 +513,20 @@ export class SandboxBridge {
497
513
  requestAnimationFrame(acknowledge);
498
514
  }
499
515
  }
500
- queryDataSource(key, options = {}) {
516
+ createDataSourceSubscriptionId() {
517
+ return `data-source:${globalThis.crypto.randomUUID()}`;
518
+ }
519
+ queryDataSource(subscriptionId, key, options = {}) {
501
520
  if (this.hostState.status !== "initialized") {
502
521
  return;
503
522
  }
504
523
  const dataSource = this.hostState.dataSources.find(entry => entry.key === key);
505
- const currentState = this.hostState.dataSourceState[key] ?? createEmptyDataSourceQueryState();
524
+ const subscriptionState = this.hostState.dataSourceState[subscriptionId];
525
+ const currentState = subscriptionState?.dataSourceKey === key
526
+ ? subscriptionState
527
+ : createEmptyDataSourceQueryState(key);
506
528
  if (dataSource === undefined) {
507
- this.setDataSourceQueryError(key, currentState, {
529
+ this.setDataSourceQueryError(subscriptionId, currentState, {
508
530
  code: "unknown_data_source_key",
509
531
  message: `Unknown data source key "${key}". Known keys: [${this.hostState.dataSources.map(entry => entry.key).join(", ")}].`,
510
532
  isRetryable: false,
@@ -512,32 +534,42 @@ export class SandboxBridge {
512
534
  return;
513
535
  }
514
536
  if (dataSource.collectionPointer === undefined) {
515
- this.setDataSourceQueryError(key, currentState, {
537
+ this.setDataSourceQueryError(subscriptionId, currentState, {
516
538
  code: "unmapped_data_source",
517
539
  message: `Data source "${key}" has not been mapped to a database yet.`,
518
540
  isRetryable: false,
519
541
  });
520
542
  return;
521
543
  }
522
- const limit = resolveDataSourceQueryLimit(options.limit);
523
- const subscriptionId = makeDataSourceSubscriptionId({
544
+ const resolvedQuery = resolveDataSourceQuery({
545
+ dataSources: this.hostState.dataSources,
524
546
  key,
547
+ options,
525
548
  });
549
+ if (resolvedQuery.status === "error") {
550
+ this.setDataSourceQueryError(subscriptionId, currentState, {
551
+ code: "invalid_data_source_query",
552
+ message: resolvedQuery.error,
553
+ isRetryable: false,
554
+ });
555
+ return;
556
+ }
557
+ const query = resolvedQuery.query;
526
558
  if (currentState.isLoading &&
527
- currentState.subscriptionId === subscriptionId &&
528
- currentState.latestLimit === limit) {
559
+ currentState.latestQueryIdentity === query.identity) {
529
560
  return;
530
561
  }
531
562
  this.hostState = {
532
563
  ...this.hostState,
533
564
  dataSourceState: {
534
565
  ...this.hostState.dataSourceState,
535
- [key]: {
566
+ [subscriptionId]: {
536
567
  ...currentState,
568
+ dataSourceKey: key,
537
569
  isLoading: true,
538
570
  error: undefined,
539
- subscriptionId,
540
- latestLimit: limit,
571
+ latestLimit: query.limit,
572
+ latestQueryIdentity: query.identity,
541
573
  },
542
574
  },
543
575
  };
@@ -545,12 +577,13 @@ export class SandboxBridge {
545
577
  const outbound = {
546
578
  type: "queryDataSource",
547
579
  subscriptionId,
548
- dataSourceId: dataSource.collectionPointer.id,
549
- limit,
580
+ dataSourceId: query.dataSourceId,
581
+ limit: query.limit,
582
+ ...(query.filter !== undefined ? { filter: query.filter } : {}),
550
583
  };
551
584
  this.postToHost(outbound);
552
585
  }
553
- setDataSourceQueryError(key, currentState, error) {
586
+ setDataSourceQueryError(subscriptionId, currentState, error) {
554
587
  if (this.hostState.status !== "initialized") {
555
588
  return;
556
589
  }
@@ -558,17 +591,28 @@ export class SandboxBridge {
558
591
  ...this.hostState,
559
592
  dataSourceState: {
560
593
  ...this.hostState.dataSourceState,
561
- [key]: {
594
+ [subscriptionId]: {
562
595
  ...currentState,
563
596
  isLoading: false,
564
597
  error,
565
- subscriptionId: undefined,
566
598
  latestLimit: undefined,
599
+ latestQueryIdentity: undefined,
567
600
  },
568
601
  },
569
602
  };
570
603
  this.notify();
571
604
  }
605
+ releaseDataSourceSubscription(subscriptionId) {
606
+ if (this.hostState.status !== "initialized" ||
607
+ this.hostState.dataSourceState[subscriptionId] === undefined) {
608
+ return;
609
+ }
610
+ const { [subscriptionId]: _, ...dataSourceState } = this.hostState.dataSourceState;
611
+ this.hostState = {
612
+ ...this.hostState,
613
+ dataSourceState,
614
+ };
615
+ }
572
616
  postResize(height) {
573
617
  if (typeof window === "undefined") {
574
618
  return;
@@ -818,27 +862,21 @@ function reuseDataSourcesForUnchangedBindings(args) {
818
862
  return dataSource;
819
863
  });
820
864
  }
821
- // The default number of items to return in a live snapshot response if no limit is provided.
822
- const DEFAULT_DATA_SOURCE_QUERY_LIMIT = 20;
823
- // The maximum number of items to return in a single live snapshot response.
824
- const MAX_DATA_SOURCE_QUERY_LIMIT = 999;
825
- function resolveDataSourceQueryLimit(limit) {
826
- if (limit === undefined) {
827
- return DEFAULT_DATA_SOURCE_QUERY_LIMIT;
828
- }
829
- if (!Number.isFinite(limit) || !Number.isInteger(limit) || limit < 1) {
830
- console.warn(`[custom-blocks-sdk] useDataSource limit must be a positive integer; using ${DEFAULT_DATA_SOURCE_QUERY_LIMIT}.`);
831
- return DEFAULT_DATA_SOURCE_QUERY_LIMIT;
832
- }
833
- if (limit > MAX_DATA_SOURCE_QUERY_LIMIT) {
834
- console.warn(`[custom-blocks-sdk] useDataSource limit is capped at ${MAX_DATA_SOURCE_QUERY_LIMIT}.`);
835
- return MAX_DATA_SOURCE_QUERY_LIMIT;
836
- }
837
- return limit;
865
+ function invalidInitPayloadError(issues) {
866
+ return {
867
+ code: "invalid_init_payload",
868
+ message: formatInvalidHostReason("init", issues),
869
+ isRetryable: false,
870
+ };
838
871
  }
839
- function makeDataSourceSubscriptionId(args) {
840
- const { key } = args;
841
- return `data-source:${encodeURIComponent(key)}`;
872
+ function readInitializationId(data) {
873
+ if (typeof data === "object" &&
874
+ data !== null &&
875
+ "initializationId" in data &&
876
+ typeof data.initializationId === "string") {
877
+ return data.initializationId;
878
+ }
879
+ return undefined;
842
880
  }
843
881
  function getInitBindingError(manifest, dataSources) {
844
882
  for (const [dataSourceKey, manifestDataSource] of Object.entries(manifest.dataSources)) {
@@ -0,0 +1,26 @@
1
+ import type { NotionDataSource } from "../../protocol/dataSources/dataSource.js";
2
+ import type { NotionDataSourceId } from "../../protocol/ids.js";
3
+ import { type ResolvedCustomBlockDataSourceFilter } from "../../protocol/messages/queryDataSource.js";
4
+ import type { UseDataSourceOptions } from "../../types.js";
5
+ export type ResolvedDataSourceQuery = {
6
+ dataSourceId: NotionDataSourceId;
7
+ limit: number;
8
+ filter?: ResolvedCustomBlockDataSourceFilter;
9
+ identity: string;
10
+ };
11
+ export type ResolveDataSourceQueryResult = {
12
+ status: "error";
13
+ error: string;
14
+ } | {
15
+ status: "ok";
16
+ dataSource: NotionDataSource;
17
+ query: ResolvedDataSourceQuery;
18
+ };
19
+ export declare function resolveDataSourceQuery(args: {
20
+ dataSources: NotionDataSource[];
21
+ key: string;
22
+ options?: unknown;
23
+ warn?: (message: string) => void;
24
+ }): ResolveDataSourceQueryResult;
25
+ export declare function getDataSourceQueryOptionsIdentity(options: UseDataSourceOptions | undefined): string;
26
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/dataSources/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4DAA4D,CAAA;AAClG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AACjF,OAAO,EAON,KAAK,mCAAmC,EAExC,MAAM,8DAA8D,CAAA;AAErE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAM1D,MAAM,MAAM,uBAAuB,GAAG;IACrC,YAAY,EAAE,kBAAkB,CAAA;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,mCAAmC,CAAA;IAC5C,QAAQ,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,4BAA4B,GACrC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClC;IACA,MAAM,EAAE,IAAI,CAAA;IACZ,UAAU,EAAE,gBAAgB,CAAA;IAC5B,KAAK,EAAE,uBAAuB,CAAA;CAC7B,CAAA;AAEJ,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC5C,WAAW,EAAE,gBAAgB,EAAE,CAAA;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC,GAAG,4BAA4B,CAuD/B;AA6BD,wBAAgB,iCAAiC,CAChD,OAAO,EAAE,oBAAoB,GAAG,SAAS,GACvC,MAAM,CAMR"}