@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
@@ -0,0 +1,377 @@
1
+ import { customBlockCheckboxFilterOperatorSchema, customBlockContainsFilterOperatorSchema, customBlockDateFilterOperatorSchema, customBlockNumberFilterOperatorSchema, customBlockOptionFilterOperatorSchema, customBlockTextFilterOperatorSchema, } from "../../protocol/messages/queryDataSource.js";
2
+ import * as v from "valibot";
3
+ const DEFAULT_DATA_SOURCE_QUERY_LIMIT = 20;
4
+ const MAX_DATA_SOURCE_QUERY_LIMIT = 999;
5
+ const MAX_DATA_SOURCE_QUERY_FILTER_CHILDREN = 25;
6
+ export function resolveDataSourceQuery(args) {
7
+ const { dataSources, key, options, warn } = args;
8
+ if (options !== undefined && !isPlainRecord(options)) {
9
+ return {
10
+ status: "error",
11
+ error: "Data source query options must be an object.",
12
+ };
13
+ }
14
+ if (options !== undefined &&
15
+ Object.keys(options).some(key => !["limit", "filter"].includes(key))) {
16
+ return {
17
+ status: "error",
18
+ error: "Data source query options contain unsupported fields.",
19
+ };
20
+ }
21
+ const dataSource = dataSources.find(entry => entry.key === key);
22
+ if (dataSource === undefined) {
23
+ return {
24
+ status: "error",
25
+ error: `Unknown data source key "${key}". Known keys: [${dataSources.map(entry => entry.key).join(", ")}].`,
26
+ };
27
+ }
28
+ if (dataSource.collectionPointer === undefined) {
29
+ return {
30
+ status: "error",
31
+ error: `Data source "${key}" has not been mapped to a database yet.`,
32
+ };
33
+ }
34
+ const limit = resolveDataSourceQueryLimit(options?.limit, warn);
35
+ if (limit.status === "error") {
36
+ return limit;
37
+ }
38
+ const filter = resolveFilter(options?.filter, dataSource);
39
+ if (filter.status === "error") {
40
+ return filter;
41
+ }
42
+ const identity = stableJsonStringify({
43
+ dataSourceId: dataSource.collectionPointer.id,
44
+ limit: limit.limit,
45
+ filter: filter.filter ?? null,
46
+ });
47
+ return {
48
+ status: "ok",
49
+ dataSource,
50
+ query: {
51
+ dataSourceId: dataSource.collectionPointer.id,
52
+ limit: limit.limit,
53
+ filter: filter.filter,
54
+ identity,
55
+ },
56
+ };
57
+ }
58
+ function resolveDataSourceQueryLimit(limit, warn = console.warn) {
59
+ if (limit === undefined) {
60
+ return { status: "ok", limit: DEFAULT_DATA_SOURCE_QUERY_LIMIT };
61
+ }
62
+ if (typeof limit !== "number" ||
63
+ !Number.isFinite(limit) ||
64
+ !Number.isInteger(limit) ||
65
+ limit < 1) {
66
+ return {
67
+ status: "error",
68
+ error: `Data source query limit must be a positive integer between 1 and ${MAX_DATA_SOURCE_QUERY_LIMIT}.`,
69
+ };
70
+ }
71
+ if (limit > MAX_DATA_SOURCE_QUERY_LIMIT) {
72
+ warn?.(`Data source query limit ${limit} exceeds the maximum of ${MAX_DATA_SOURCE_QUERY_LIMIT}; clamping to ${MAX_DATA_SOURCE_QUERY_LIMIT}.`);
73
+ return { status: "ok", limit: MAX_DATA_SOURCE_QUERY_LIMIT };
74
+ }
75
+ return { status: "ok", limit };
76
+ }
77
+ export function getDataSourceQueryOptionsIdentity(options) {
78
+ try {
79
+ return stableJsonStringify(options ?? {});
80
+ }
81
+ catch {
82
+ return "invalid-data-source-query-options";
83
+ }
84
+ }
85
+ function stableJsonStringify(value) {
86
+ return JSON.stringify(normalizeJsonValue(value));
87
+ }
88
+ function resolveFilter(filter, dataSource) {
89
+ if (filter === undefined) {
90
+ return { status: "ok" };
91
+ }
92
+ if (!isPlainRecord(filter)) {
93
+ return {
94
+ status: "error",
95
+ error: "Data source query filter must be an object.",
96
+ };
97
+ }
98
+ if ("and" in filter) {
99
+ if (Object.keys(filter).length !== 1 || !Array.isArray(filter.and)) {
100
+ return {
101
+ status: "error",
102
+ error: 'Data source query filter "and" must be an array.',
103
+ };
104
+ }
105
+ if (filter.and.length > MAX_DATA_SOURCE_QUERY_FILTER_CHILDREN) {
106
+ return {
107
+ status: "error",
108
+ error: `Data source query filter "and" may contain at most ${MAX_DATA_SOURCE_QUERY_FILTER_CHILDREN} children.`,
109
+ };
110
+ }
111
+ const and = [];
112
+ for (const child of filter.and) {
113
+ const resolved = resolvePropertyFilter(child, dataSource);
114
+ if (resolved.status === "error") {
115
+ return resolved;
116
+ }
117
+ and.push(resolved.filter);
118
+ }
119
+ return { status: "ok", filter: { and } };
120
+ }
121
+ return resolvePropertyFilter(filter, dataSource);
122
+ }
123
+ function resolvePropertyFilter(filter, dataSource) {
124
+ if (!isPlainRecord(filter)) {
125
+ return {
126
+ status: "error",
127
+ error: "Data source query property filter must be an object.",
128
+ };
129
+ }
130
+ const property = resolvePropertyAddress(filter, dataSource);
131
+ if (property.status === "error") {
132
+ return property;
133
+ }
134
+ const branchKeys = Object.keys(filter).filter(key => key !== "key" && key !== "propertyId");
135
+ if (branchKeys.length !== 1) {
136
+ return {
137
+ status: "error",
138
+ error: "Data source query property filter must contain exactly one property branch.",
139
+ };
140
+ }
141
+ const branch = branchKeys[0];
142
+ const value = filter[branch];
143
+ if (!isPlainRecord(value) || Object.keys(value).length !== 1) {
144
+ return invalidOperator(branch);
145
+ }
146
+ if (property.propertyType !== branch) {
147
+ return {
148
+ status: "error",
149
+ error: `Data source query filter branch "${branch}" does not match property type "${property.propertyType}".`,
150
+ };
151
+ }
152
+ switch (branch) {
153
+ case "title": {
154
+ const parsed = v.safeParse(customBlockTextFilterOperatorSchema, value);
155
+ return parsed.success
156
+ ? {
157
+ status: "ok",
158
+ filter: { propertyId: property.propertyId, title: parsed.output },
159
+ }
160
+ : invalidOperator(branch);
161
+ }
162
+ case "rich_text": {
163
+ const parsed = v.safeParse(customBlockTextFilterOperatorSchema, value);
164
+ return parsed.success
165
+ ? {
166
+ status: "ok",
167
+ filter: {
168
+ propertyId: property.propertyId,
169
+ rich_text: parsed.output,
170
+ },
171
+ }
172
+ : invalidOperator(branch);
173
+ }
174
+ case "url":
175
+ case "email":
176
+ case "phone_number": {
177
+ const parsed = v.safeParse(customBlockTextFilterOperatorSchema, value);
178
+ if (!parsed.success) {
179
+ return invalidOperator(branch);
180
+ }
181
+ if (branch === "url") {
182
+ return {
183
+ status: "ok",
184
+ filter: { propertyId: property.propertyId, url: parsed.output },
185
+ };
186
+ }
187
+ if (branch === "email") {
188
+ return {
189
+ status: "ok",
190
+ filter: { propertyId: property.propertyId, email: parsed.output },
191
+ };
192
+ }
193
+ return {
194
+ status: "ok",
195
+ filter: {
196
+ propertyId: property.propertyId,
197
+ phone_number: parsed.output,
198
+ },
199
+ };
200
+ }
201
+ case "number": {
202
+ const parsed = v.safeParse(customBlockNumberFilterOperatorSchema, value);
203
+ if (parsed.success &&
204
+ Object.values(parsed.output).every(entry => typeof entry !== "number" || Number.isFinite(entry))) {
205
+ return {
206
+ status: "ok",
207
+ filter: { propertyId: property.propertyId, number: parsed.output },
208
+ };
209
+ }
210
+ return invalidOperator(branch);
211
+ }
212
+ case "checkbox": {
213
+ const parsed = v.safeParse(customBlockCheckboxFilterOperatorSchema, value);
214
+ return parsed.success
215
+ ? {
216
+ status: "ok",
217
+ filter: {
218
+ propertyId: property.propertyId,
219
+ checkbox: parsed.output,
220
+ },
221
+ }
222
+ : invalidOperator(branch);
223
+ }
224
+ case "select": {
225
+ const parsed = v.safeParse(customBlockOptionFilterOperatorSchema, value);
226
+ return parsed.success
227
+ ? {
228
+ status: "ok",
229
+ filter: { propertyId: property.propertyId, select: parsed.output },
230
+ }
231
+ : invalidOperator(branch);
232
+ }
233
+ case "multi_select": {
234
+ const parsed = v.safeParse(customBlockContainsFilterOperatorSchema, value);
235
+ return parsed.success
236
+ ? {
237
+ status: "ok",
238
+ filter: {
239
+ propertyId: property.propertyId,
240
+ multi_select: parsed.output,
241
+ },
242
+ }
243
+ : invalidOperator(branch);
244
+ }
245
+ case "status": {
246
+ const parsed = v.safeParse(customBlockOptionFilterOperatorSchema, value);
247
+ return parsed.success
248
+ ? {
249
+ status: "ok",
250
+ filter: { propertyId: property.propertyId, status: parsed.output },
251
+ }
252
+ : invalidOperator(branch);
253
+ }
254
+ case "date": {
255
+ const parsed = v.safeParse(customBlockDateFilterOperatorSchema, value);
256
+ if (parsed.success &&
257
+ Object.values(parsed.output).every(entry => entry === true || isValidIsoDate(entry))) {
258
+ return {
259
+ status: "ok",
260
+ filter: { propertyId: property.propertyId, date: parsed.output },
261
+ };
262
+ }
263
+ return invalidOperator(branch);
264
+ }
265
+ default:
266
+ return {
267
+ status: "error",
268
+ error: `Data source query filter branch "${branch}" is not supported.`,
269
+ };
270
+ }
271
+ }
272
+ function resolvePropertyAddress(value, dataSource) {
273
+ const hasKey = "key" in value;
274
+ const hasPropertyId = "propertyId" in value;
275
+ if (hasKey === hasPropertyId) {
276
+ return {
277
+ status: "error",
278
+ error: "Data source query filters must use exactly one of key or propertyId.",
279
+ };
280
+ }
281
+ let propertyId;
282
+ if (hasKey) {
283
+ if (typeof value.key !== "string") {
284
+ return {
285
+ status: "error",
286
+ error: "Data source query property key must be a string.",
287
+ };
288
+ }
289
+ if (!(value.key in dataSource.propertyIdsByKey)) {
290
+ return {
291
+ status: "error",
292
+ error: `Unknown property key "${value.key}" for data source "${dataSource.key}".`,
293
+ };
294
+ }
295
+ const resolvedPropertyId = dataSource.propertyIdsByKey[value.key];
296
+ if (resolvedPropertyId === undefined) {
297
+ return {
298
+ status: "error",
299
+ error: `Property key "${value.key}" for data source "${dataSource.key}" is not bound.`,
300
+ };
301
+ }
302
+ propertyId = resolvedPropertyId;
303
+ }
304
+ else {
305
+ if (typeof value.propertyId !== "string") {
306
+ return {
307
+ status: "error",
308
+ error: "Data source query propertyId must be a string.",
309
+ };
310
+ }
311
+ propertyId = value.propertyId;
312
+ }
313
+ const propertySchema = dataSource.propertySchemasById[propertyId];
314
+ if (propertySchema === undefined) {
315
+ return {
316
+ status: "error",
317
+ error: `Unknown property ID "${propertyId}" for data source "${dataSource.key}".`,
318
+ };
319
+ }
320
+ return {
321
+ status: "ok",
322
+ propertyId,
323
+ propertyType: propertySchema.type,
324
+ };
325
+ }
326
+ function invalidOperator(branch) {
327
+ return {
328
+ status: "error",
329
+ error: `Data source query filter branch "${branch}" has an invalid operator or value.`,
330
+ };
331
+ }
332
+ function normalizeJsonValue(value) {
333
+ if (value === null ||
334
+ typeof value === "string" ||
335
+ typeof value === "boolean") {
336
+ return value;
337
+ }
338
+ if (typeof value === "number") {
339
+ if (!Number.isFinite(value)) {
340
+ throw new Error("Data source query values must be finite JSON numbers.");
341
+ }
342
+ return value;
343
+ }
344
+ if (Array.isArray(value)) {
345
+ return value.map(entry => normalizeJsonValue(entry));
346
+ }
347
+ if (isPlainRecord(value)) {
348
+ const normalized = {};
349
+ for (const key of Object.keys(value).sort()) {
350
+ const child = value[key];
351
+ if (child !== undefined) {
352
+ normalized[key] = normalizeJsonValue(child);
353
+ }
354
+ }
355
+ return normalized;
356
+ }
357
+ throw new Error("Data source query values must be JSON-compatible.");
358
+ }
359
+ function isPlainRecord(value) {
360
+ return (typeof value === "object" &&
361
+ value !== null &&
362
+ !Array.isArray(value) &&
363
+ (Object.getPrototypeOf(value) === Object.prototype ||
364
+ Object.getPrototypeOf(value) === null));
365
+ }
366
+ function isValidIsoDate(value) {
367
+ if (typeof value !== "string") {
368
+ return false;
369
+ }
370
+ const dateOnly = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
371
+ if (dateOnly !== null) {
372
+ const [, year, month, day] = dateOnly;
373
+ const date = new Date(Date.UTC(Number(year), Number(month) - 1, Number(day)));
374
+ return date.toISOString().slice(0, 10) === value;
375
+ }
376
+ return (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d{1,3})?)?(?:Z|[+-]\d{2}:\d{2})$/.test(value) && Number.isFinite(Date.parse(value)));
377
+ }
@@ -29,15 +29,16 @@ export type InitializedHostState = {
29
29
  dataSourceState: Record<string, DataSourceQueryState>;
30
30
  };
31
31
  export type DataSourceQueryState = {
32
+ dataSourceKey: string;
32
33
  /** Latest pages from the host as parsed from the bridge. `propertiesByKey` is derived lazily. */
33
34
  items: NotionDataSourcePageBridge[];
34
35
  isLoading: boolean;
35
36
  hasMore: boolean;
36
37
  error?: CustomBlockQueryDataSourceErrorInfo;
37
- subscriptionId?: string;
38
38
  latestLimit?: number;
39
+ latestQueryIdentity?: string;
39
40
  };
40
- export declare function createEmptyDataSourceQueryState(): DataSourceQueryState;
41
+ export declare function createEmptyDataSourceQueryState(dataSourceKey: string): DataSourceQueryState;
41
42
  /**
42
43
  * Resolved page + schema views for a single data source, keyed by raw property
43
44
  * ID and by user-defined key. Re-derived from `propertyIdsByKey` on every read so
@@ -69,5 +70,5 @@ export type UpdateDataSourcePageFn = (args: {
69
70
  pageId: NotionPageId;
70
71
  pageUpdateArgs: NotionDataSourcePageUpdateArgs;
71
72
  }) => Promise<UpdatePageResult>;
72
- export declare function getDataSourceQueryView(hostState: CustomBlockHostState, key: string, updateDataSourcePage: UpdateDataSourcePageFn): DataSourceQueryView;
73
+ export declare function getDataSourceQueryView(hostState: CustomBlockHostState, key: string, subscriptionId: string, updateDataSourcePage: UpdateDataSourcePageFn): DataSourceQueryView;
73
74
  //# sourceMappingURL=hostState.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hostState.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/hostState.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hostState.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/hostState.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
- export function createEmptyDataSourceQueryState() {
1
+ export function createEmptyDataSourceQueryState(dataSourceKey) {
2
2
  return {
3
+ dataSourceKey,
3
4
  items: [],
4
5
  isLoading: false,
5
6
  hasMore: false,
@@ -13,12 +14,15 @@ const EMPTY_QUERY_VIEW = {
13
14
  isLoading: false,
14
15
  hasMore: false,
15
16
  };
16
- export function getDataSourceQueryView(hostState, key, updateDataSourcePage) {
17
+ export function getDataSourceQueryView(hostState, key, subscriptionId, updateDataSourcePage) {
17
18
  if (hostState.status !== "initialized") {
18
19
  return EMPTY_QUERY_VIEW;
19
20
  }
20
21
  const dataSource = hostState.dataSources.find(entry => entry.key === key);
21
- const queryState = hostState.dataSourceState[key] ?? createEmptyDataSourceQueryState();
22
+ const subscriptionState = hostState.dataSourceState[subscriptionId];
23
+ const queryState = subscriptionState?.dataSourceKey === key
24
+ ? subscriptionState
25
+ : createEmptyDataSourceQueryState(key);
22
26
  if (dataSource === undefined) {
23
27
  return {
24
28
  items: [],
@@ -19,8 +19,10 @@ export declare const customBlockHost: {
19
19
  postResize: (height: number) => void;
20
20
  };
21
21
  export declare const customBlockDataSources: {
22
- query: (key: string, options?: UseDataSourceOptions) => void;
23
- getView: (hostState: CustomBlockHostState, key: string) => DataSourceQueryView;
22
+ createSubscriptionId: () => string;
23
+ query: (subscriptionId: string, key: string, options?: UseDataSourceOptions) => void;
24
+ release: (subscriptionId: string) => void;
25
+ getView: (hostState: CustomBlockHostState, key: string, subscriptionId: string) => DataSourceQueryView;
24
26
  };
25
27
  export declare const messageLog: {
26
28
  getSnapshot: () => readonly MessageLogEntry[];
@@ -1 +1 @@
1
- {"version":3,"file":"sandboxClient.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/sandboxClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAA;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mDAAmD,CAAA;AACpF,OAAO,KAAK,EACX,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,MAAM,aAAa,CAAA;AACpB,OAAO,EACN,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EAExB,MAAM,gBAAgB,CAAA;AACvB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,KAAK,eAAe,EAAiB,MAAM,oBAAoB,CAAA;AAWxE,eAAO,MAAM,eAAe;;kCAKG,kBAAkB;yBAI3B,WAAW,KAAG,OAAO,CAAC,IAAI,CAAC;0BAI1B,MAAM,IAAI;oBAIlB,oBAAoB;IAIlC;;;OAGG;4BACqB,WAAW;;yBAQd,MAAM;CAG3B,CAAA;AAED,eAAO,MAAM,sBAAsB;iBACrB,MAAM,YAAY,oBAAoB;yBAKvC,oBAAoB,OAC1B,MAAM,KACT,mBAAmB;CAKtB,CAAA;AAED,eAAO,MAAM,UAAU;uBACL,SAAS,eAAe,EAAE;0BAIrB,MAAM,IAAI;CAGhC,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,KAAK;IACjB;;OAEG;oBACa,cAAc,KAAG,OAAO,CAAC,gBAAgB,CAAC;IAI1D;;OAEG;kBACW,YAAY,KAAG,OAAO,CAAC,aAAa,CAAC;IAInD;;OAEG;oBACa,cAAc,KAAG,OAAO,CAAC,gBAAgB,CAAC;IAI1D;;OAEG;qBACc,YAAY,KAAG,OAAO,CAAC,gBAAgB,CAAC;CAGzD,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,KAAK;IACjB;;OAEG;mBACY,aAAa,KAAG,OAAO,CAAC,eAAe,CAAC;IAIvD;;OAEG;kBACW,YAAY,KAAG,OAAO,CAAC,aAAa,CAAC;CAGnD,CAAA"}
1
+ {"version":3,"file":"sandboxClient.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/sandboxClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAA;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mDAAmD,CAAA;AACpF,OAAO,KAAK,EACX,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,MAAM,aAAa,CAAA;AACpB,OAAO,EACN,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EAExB,MAAM,gBAAgB,CAAA;AACvB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,KAAK,eAAe,EAAiB,MAAM,oBAAoB,CAAA;AAWxE,eAAO,MAAM,eAAe;;kCAKG,kBAAkB;yBAI3B,WAAW,KAAG,OAAO,CAAC,IAAI,CAAC;0BAI1B,MAAM,IAAI;oBAIlB,oBAAoB;IAIlC;;;OAGG;4BACqB,WAAW;;yBAQd,MAAM;CAG3B,CAAA;AAED,eAAO,MAAM,sBAAsB;;4BAMjB,MAAM,OACjB,MAAM,YACD,oBAAoB;8BAKL,MAAM;yBAKpB,oBAAoB,OAC1B,MAAM,kBACK,MAAM,KACpB,mBAAmB;CAQtB,CAAA;AAED,eAAO,MAAM,UAAU;uBACL,SAAS,eAAe,EAAE;0BAIrB,MAAM,IAAI;CAGhC,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,KAAK;IACjB;;OAEG;oBACa,cAAc,KAAG,OAAO,CAAC,gBAAgB,CAAC;IAI1D;;OAEG;kBACW,YAAY,KAAG,OAAO,CAAC,aAAa,CAAC;IAInD;;OAEG;oBACa,cAAc,KAAG,OAAO,CAAC,gBAAgB,CAAC;IAI1D;;OAEG;qBACc,YAAY,KAAG,OAAO,CAAC,gBAAgB,CAAC;CAGzD,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,KAAK;IACjB;;OAEG;mBACY,aAAa,KAAG,OAAO,CAAC,eAAe,CAAC;IAIvD;;OAEG;kBACW,YAAY,KAAG,OAAO,CAAC,aAAa,CAAC;CAGnD,CAAA"}
@@ -38,11 +38,17 @@ export const customBlockHost = {
38
38
  },
39
39
  };
40
40
  export const customBlockDataSources = {
41
- query: (key, options) => {
42
- getBridge().queryDataSource(key, options);
41
+ createSubscriptionId: () => {
42
+ return getBridge().createDataSourceSubscriptionId();
43
43
  },
44
- getView: (hostState, key) => {
45
- return getDataSourceQueryViewWithBridge(hostState, key, args => getBridge().updateDataSourcePage(args));
44
+ query: (subscriptionId, key, options) => {
45
+ getBridge().queryDataSource(subscriptionId, key, options);
46
+ },
47
+ release: (subscriptionId) => {
48
+ getBridge().releaseDataSourceSubscription(subscriptionId);
49
+ },
50
+ getView: (hostState, key, subscriptionId) => {
51
+ return getDataSourceQueryViewWithBridge(hostState, key, subscriptionId, args => getBridge().updateDataSourcePage(args));
46
52
  },
47
53
  };
48
54
  export const messageLog = {
@@ -2,7 +2,7 @@ import * as v from "valibot";
2
2
  import type { CustomBlockErrorCode, CustomBlockErrorInfo } from "../errors.js";
3
3
  import type { CustomBlockInitResultErrorCode } from "./initResult.js";
4
4
  export declare const customBlockInitErrorCodeSchema: v.StringSchema<undefined>;
5
- export type CustomBlockInitErrorCode = CustomBlockErrorCode<"manifest_unavailable" | "manifest_invalid" | "invalid_protocol_version" | "unsupported_protocol_version" | "context_unavailable" | "current_user_unavailable" | "missing_data_source_binding" | "data_source_unavailable" | "missing_property_binding" | "invalid_property_binding">;
5
+ export type CustomBlockInitErrorCode = CustomBlockErrorCode<"manifest_unavailable" | "manifest_invalid" | "invalid_connect_payload" | "invalid_protocol_version" | "unsupported_protocol_version" | "context_unavailable" | "current_user_unavailable" | "missing_data_source_binding" | "data_source_unavailable" | "missing_property_binding" | "invalid_property_binding">;
6
6
  export type CustomBlockInitErrorInfo = CustomBlockErrorInfo<CustomBlockInitErrorCode>;
7
7
  /**
8
8
  * Every initialization failure visible to block code. This combines errors
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../home/runner/work/custom-blocks/custom-blocks/protocol/src/messages/init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAG5B,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAO9E,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,iBAAiB,CAAA;AAIrE,eAAO,MAAM,8BAA8B,2BAAa,CAAA;AAExD,MAAM,MAAM,wBAAwB,GAAG,oBAAoB,CACxD,sBAAsB,GACtB,kBAAkB,GAClB,0BAA0B,GAC1B,8BAA8B,GAC9B,qBAAqB,GACrB,0BAA0B,GAC1B,6BAA6B,GAC7B,yBAAyB,GACzB,0BAA0B,GAC1B,0BAA0B,CAC5B,CAAA;AAED,MAAM,MAAM,wBAAwB,GACnC,oBAAoB,CAAC,wBAAwB,CAAC,CAAA;AAE/C;;;;GAIG;AACH,MAAM,MAAM,kCAAkC,GAC3C,wBAAwB,GACxB,8BAA8B,GAC9B,oBAAoB,CAAC,eAAe,GAAG,cAAc,CAAC,CAAA;AAEzD,MAAM,MAAM,kCAAkC,GAC7C,oBAAoB,CAAC,kCAAkC,CAAC,CAAA;AAEzD,eAAO,MAAM,8BAA8B;;;;aAIzC,CAAA;AAEF,qBAAa,8BACZ,SAAQ,KACR,YAAW,oBAAoB;gBAEnB,KAAK,EAAE,kCAAkC;IAOrD,IAAI,EAAE,kCAAkC,CAAA;IACxC,WAAW,EAAE,OAAO,CAAA;CACpB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAuB5B,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,iBAAiB,CAAC,CAAA"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../home/runner/work/custom-blocks/custom-blocks/protocol/src/messages/init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAG5B,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAO9E,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,iBAAiB,CAAA;AAIrE,eAAO,MAAM,8BAA8B,2BAAa,CAAA;AAExD,MAAM,MAAM,wBAAwB,GAAG,oBAAoB,CACxD,sBAAsB,GACtB,kBAAkB,GAClB,yBAAyB,GACzB,0BAA0B,GAC1B,8BAA8B,GAC9B,qBAAqB,GACrB,0BAA0B,GAC1B,6BAA6B,GAC7B,yBAAyB,GACzB,0BAA0B,GAC1B,0BAA0B,CAC5B,CAAA;AAED,MAAM,MAAM,wBAAwB,GACnC,oBAAoB,CAAC,wBAAwB,CAAC,CAAA;AAE/C;;;;GAIG;AACH,MAAM,MAAM,kCAAkC,GAC3C,wBAAwB,GACxB,8BAA8B,GAC9B,oBAAoB,CAAC,eAAe,GAAG,cAAc,CAAC,CAAA;AAEzD,MAAM,MAAM,kCAAkC,GAC7C,oBAAoB,CAAC,kCAAkC,CAAC,CAAA;AAEzD,eAAO,MAAM,8BAA8B;;;;aAIzC,CAAA;AAEF,qBAAa,8BACZ,SAAQ,KACR,YAAW,oBAAoB;gBAEnB,KAAK,EAAE,kCAAkC;IAOrD,IAAI,EAAE,kCAAkC,CAAA;IACxC,WAAW,EAAE,OAAO,CAAA;CACpB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAuB5B,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,iBAAiB,CAAC,CAAA"}
@@ -1,7 +1,14 @@
1
1
  import * as v from "valibot";
2
2
  import type { CustomBlockErrorCode, CustomBlockErrorInfo } from "../errors.js";
3
3
  export declare const customBlockInitResultErrorCodeSchema: v.StringSchema<undefined>;
4
- export type CustomBlockInitResultErrorCode = CustomBlockErrorCode<"invalid_init_bindings">;
4
+ export type CustomBlockInitResultErrorCode = CustomBlockErrorCode<
5
+ /**
6
+ * The host-provided bindings defined in `init.dataSources` were rejected by the sandbox because
7
+ * they did not completely match the expected manifest keys.
8
+ */
9
+ "invalid_init_bindings"
10
+ /** The host-provided `init` payload failed to parse. */
11
+ | "invalid_init_payload">;
5
12
  export type CustomBlockInitResultErrorInfo = CustomBlockErrorInfo<CustomBlockInitResultErrorCode>;
6
13
  export declare const customBlockInitResultErrorInfoSchema: v.ObjectSchema<{
7
14
  readonly code: v.StringSchema<undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"initResult.d.ts","sourceRoot":"","sources":["../../../../../home/runner/work/custom-blocks/custom-blocks/protocol/src/messages/initResult.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAC5B,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAI9E,eAAO,MAAM,oCAAoC,2BAAa,CAAA;AAE9D,MAAM,MAAM,8BAA8B,GACzC,oBAAoB,CAAC,uBAAuB,CAAC,CAAA;AAE9C,MAAM,MAAM,8BAA8B,GACzC,oBAAoB,CAAC,8BAA8B,CAAC,CAAA;AAErD,eAAO,MAAM,oCAAoC;;;;aAI/C,CAAA;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;IAKlC,0EAA0E;;;;;;;;;;;0BAU1E,CAAA;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,uBAAuB,CAAC,CAAA"}
1
+ {"version":3,"file":"initResult.d.ts","sourceRoot":"","sources":["../../../../../home/runner/work/custom-blocks/custom-blocks/protocol/src/messages/initResult.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAC5B,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAI9E,eAAO,MAAM,oCAAoC,2BAAa,CAAA;AAE9D,MAAM,MAAM,8BAA8B,GAAG,oBAAoB;AAChE;;;GAGG;AACD,uBAAuB;AACzB,wDAAwD;GACtD,sBAAsB,CACxB,CAAA;AAED,MAAM,MAAM,8BAA8B,GACzC,oBAAoB,CAAC,8BAA8B,CAAC,CAAA;AAErD,eAAO,MAAM,oCAAoC;;;;aAI/C,CAAA;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;IAKlC,0EAA0E;;;;;;;;;;;0BAU1E,CAAA;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,uBAAuB,CAAC,CAAA"}