@notionhq/custom-blocks-host 0.2.8 → 0.2.9

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.
@@ -0,0 +1,3308 @@
1
+ // host/src/autoBindProperties.ts
2
+ function getAutoBoundPropertyIdsByKey(args) {
3
+ const { manifestProperties, propertySchemasById } = args;
4
+ const mappings = [];
5
+ for (const [propertyKey, manifestProperty] of Object.entries(
6
+ manifestProperties
7
+ )) {
8
+ const propertyId = getAutoBoundPropertyId({
9
+ propertyKey,
10
+ manifestProperty,
11
+ propertySchemasById
12
+ });
13
+ if (propertyId !== void 0) {
14
+ mappings.push([propertyKey, propertyId]);
15
+ }
16
+ }
17
+ return Object.fromEntries(mappings);
18
+ }
19
+ function getAutoBoundPropertyId(args) {
20
+ const { propertyKey, manifestProperty, propertySchemasById } = args;
21
+ const normalizedManifestName = normalizePropertyDisplayName(
22
+ manifestProperty.name
23
+ );
24
+ const candidates = Object.entries(propertySchemasById).filter(
25
+ ([schemaId, propertySchema]) => propertySchema.type === manifestProperty.type && (schemaId === propertyKey || normalizePropertyDisplayName(propertySchema.name) === normalizedManifestName)
26
+ );
27
+ return candidates.length === 1 ? candidates[0][0] : void 0;
28
+ }
29
+ function normalizePropertyDisplayName(value) {
30
+ return value.trim().toLowerCase();
31
+ }
32
+
33
+ // node_modules/.pnpm/valibot@1.4.2_typescript@7.0.2/node_modules/valibot/dist/index.mjs
34
+ var store$4;
35
+ var DEFAULT_CONFIG = {
36
+ lang: void 0,
37
+ message: void 0,
38
+ abortEarly: void 0,
39
+ abortPipeEarly: void 0
40
+ };
41
+ // @__NO_SIDE_EFFECTS__
42
+ function getGlobalConfig(config$1) {
43
+ if (!config$1 && !store$4) return DEFAULT_CONFIG;
44
+ return {
45
+ lang: config$1?.lang ?? store$4?.lang,
46
+ message: config$1?.message,
47
+ abortEarly: config$1?.abortEarly ?? store$4?.abortEarly,
48
+ abortPipeEarly: config$1?.abortPipeEarly ?? store$4?.abortPipeEarly
49
+ };
50
+ }
51
+ var store$3;
52
+ // @__NO_SIDE_EFFECTS__
53
+ function getGlobalMessage(lang) {
54
+ return store$3?.get(lang);
55
+ }
56
+ var store$2;
57
+ // @__NO_SIDE_EFFECTS__
58
+ function getSchemaMessage(lang) {
59
+ return store$2?.get(lang);
60
+ }
61
+ var store$1;
62
+ // @__NO_SIDE_EFFECTS__
63
+ function getSpecificMessage(reference, lang) {
64
+ return store$1?.get(reference)?.get(lang);
65
+ }
66
+ // @__NO_SIDE_EFFECTS__
67
+ function _stringify(input) {
68
+ const type = typeof input;
69
+ if (type === "string") return `"${input}"`;
70
+ if (type === "number" || type === "bigint" || type === "boolean") return `${input}`;
71
+ if (type === "object" || type === "function") return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? "null";
72
+ return type;
73
+ }
74
+ function _addIssue(context, label, dataset, config$1, other) {
75
+ const input = other && "input" in other ? other.input : dataset.value;
76
+ const expected = other?.expected ?? context.expects ?? null;
77
+ const received = other?.received ?? /* @__PURE__ */ _stringify(input);
78
+ const issue = {
79
+ kind: context.kind,
80
+ type: context.type,
81
+ input,
82
+ expected,
83
+ received,
84
+ message: `Invalid ${label}: ${expected ? `Expected ${expected} but r` : "R"}eceived ${received}`,
85
+ requirement: context.requirement,
86
+ path: other?.path,
87
+ issues: other?.issues,
88
+ lang: config$1.lang,
89
+ abortEarly: config$1.abortEarly,
90
+ abortPipeEarly: config$1.abortPipeEarly
91
+ };
92
+ const isSchema = context.kind === "schema";
93
+ const message$1 = other?.message ?? context.message ?? /* @__PURE__ */ getSpecificMessage(context.reference, issue.lang) ?? (isSchema ? /* @__PURE__ */ getSchemaMessage(issue.lang) : null) ?? config$1.message ?? /* @__PURE__ */ getGlobalMessage(issue.lang);
94
+ if (message$1 !== void 0) issue.message = typeof message$1 === "function" ? message$1(issue) : message$1;
95
+ if (isSchema) dataset.typed = false;
96
+ if (dataset.issues) dataset.issues.push(issue);
97
+ else dataset.issues = [issue];
98
+ }
99
+ var _standardCache = /* @__PURE__ */ new WeakMap();
100
+ // @__NO_SIDE_EFFECTS__
101
+ function _getStandardProps(context) {
102
+ let cached = _standardCache.get(context);
103
+ if (!cached) {
104
+ cached = {
105
+ version: 1,
106
+ vendor: "valibot",
107
+ validate(value$1) {
108
+ return context["~run"]({ value: value$1 }, /* @__PURE__ */ getGlobalConfig());
109
+ }
110
+ };
111
+ _standardCache.set(context, cached);
112
+ }
113
+ return cached;
114
+ }
115
+ // @__NO_SIDE_EFFECTS__
116
+ function _isValidObjectKey(object$1, key) {
117
+ return Object.prototype.hasOwnProperty.call(object$1, key) && key !== "__proto__" && key !== "prototype" && key !== "constructor";
118
+ }
119
+ // @__NO_SIDE_EFFECTS__
120
+ function _joinExpects(values$1, separator) {
121
+ const list = [...new Set(values$1)];
122
+ if (list.length > 1) return `(${list.join(` ${separator} `)})`;
123
+ return list[0] ?? "never";
124
+ }
125
+ var ValiError = class extends Error {
126
+ /**
127
+ * Creates a Valibot error with useful information.
128
+ *
129
+ * @param issues The error issues.
130
+ */
131
+ constructor(issues) {
132
+ super(issues[0].message);
133
+ this.name = "ValiError";
134
+ this.issues = issues;
135
+ }
136
+ };
137
+ // @__NO_SIDE_EFFECTS__
138
+ function brand(name) {
139
+ return {
140
+ kind: "transformation",
141
+ type: "brand",
142
+ reference: brand,
143
+ async: false,
144
+ name,
145
+ "~run"(dataset) {
146
+ return dataset;
147
+ }
148
+ };
149
+ }
150
+ // @__NO_SIDE_EFFECTS__
151
+ function finite(message$1) {
152
+ return {
153
+ kind: "validation",
154
+ type: "finite",
155
+ reference: finite,
156
+ async: false,
157
+ expects: null,
158
+ requirement: Number.isFinite,
159
+ message: message$1,
160
+ "~run"(dataset, config$1) {
161
+ if (dataset.typed && !this.requirement(dataset.value)) _addIssue(this, "finite", dataset, config$1);
162
+ return dataset;
163
+ }
164
+ };
165
+ }
166
+ // @__NO_SIDE_EFFECTS__
167
+ function maxLength(requirement, message$1) {
168
+ return {
169
+ kind: "validation",
170
+ type: "max_length",
171
+ reference: maxLength,
172
+ async: false,
173
+ expects: `<=${requirement}`,
174
+ requirement,
175
+ message: message$1,
176
+ "~run"(dataset, config$1) {
177
+ if (dataset.typed && dataset.value.length > this.requirement) _addIssue(this, "length", dataset, config$1, { received: `${dataset.value.length}` });
178
+ return dataset;
179
+ }
180
+ };
181
+ }
182
+ // @__NO_SIDE_EFFECTS__
183
+ function minLength(requirement, message$1) {
184
+ return {
185
+ kind: "validation",
186
+ type: "min_length",
187
+ reference: minLength,
188
+ async: false,
189
+ expects: `>=${requirement}`,
190
+ requirement,
191
+ message: message$1,
192
+ "~run"(dataset, config$1) {
193
+ if (dataset.typed && dataset.value.length < this.requirement) _addIssue(this, "length", dataset, config$1, { received: `${dataset.value.length}` });
194
+ return dataset;
195
+ }
196
+ };
197
+ }
198
+ // @__NO_SIDE_EFFECTS__
199
+ function minValue(requirement, message$1) {
200
+ return {
201
+ kind: "validation",
202
+ type: "min_value",
203
+ reference: minValue,
204
+ async: false,
205
+ expects: `>=${requirement instanceof Date ? requirement.toJSON() : /* @__PURE__ */ _stringify(requirement)}`,
206
+ requirement,
207
+ message: message$1,
208
+ "~run"(dataset, config$1) {
209
+ if (dataset.typed && !(dataset.value >= this.requirement)) _addIssue(this, "value", dataset, config$1, { received: dataset.value instanceof Date ? dataset.value.toJSON() : /* @__PURE__ */ _stringify(dataset.value) });
210
+ return dataset;
211
+ }
212
+ };
213
+ }
214
+ var ABORT_EARLY_CONFIG = { abortEarly: true };
215
+ // @__NO_SIDE_EFFECTS__
216
+ function getFallback(schema, dataset, config$1) {
217
+ return typeof schema.fallback === "function" ? schema.fallback(dataset, config$1) : schema.fallback;
218
+ }
219
+ // @__NO_SIDE_EFFECTS__
220
+ function getDefault(schema, dataset, config$1) {
221
+ return typeof schema.default === "function" ? schema.default(dataset, config$1) : schema.default;
222
+ }
223
+ // @__NO_SIDE_EFFECTS__
224
+ function array(item, message$1) {
225
+ return {
226
+ kind: "schema",
227
+ type: "array",
228
+ reference: array,
229
+ expects: "Array",
230
+ async: false,
231
+ item,
232
+ message: message$1,
233
+ get "~standard"() {
234
+ return /* @__PURE__ */ _getStandardProps(this);
235
+ },
236
+ "~run"(dataset, config$1) {
237
+ const input = dataset.value;
238
+ if (Array.isArray(input)) {
239
+ dataset.typed = true;
240
+ dataset.value = [];
241
+ for (let key = 0; key < input.length; key++) {
242
+ const value$1 = input[key];
243
+ const itemDataset = this.item["~run"]({ value: value$1 }, config$1);
244
+ if (itemDataset.issues) {
245
+ const pathItem = {
246
+ type: "array",
247
+ origin: "value",
248
+ input,
249
+ key,
250
+ value: value$1
251
+ };
252
+ for (const issue of itemDataset.issues) {
253
+ if (issue.path) issue.path.unshift(pathItem);
254
+ else issue.path = [pathItem];
255
+ dataset.issues?.push(issue);
256
+ }
257
+ if (!dataset.issues) dataset.issues = itemDataset.issues;
258
+ if (config$1.abortEarly) {
259
+ dataset.typed = false;
260
+ break;
261
+ }
262
+ }
263
+ if (!itemDataset.typed) dataset.typed = false;
264
+ dataset.value.push(itemDataset.value);
265
+ }
266
+ } else _addIssue(this, "type", dataset, config$1);
267
+ return dataset;
268
+ }
269
+ };
270
+ }
271
+ // @__NO_SIDE_EFFECTS__
272
+ function boolean(message$1) {
273
+ return {
274
+ kind: "schema",
275
+ type: "boolean",
276
+ reference: boolean,
277
+ expects: "boolean",
278
+ async: false,
279
+ message: message$1,
280
+ get "~standard"() {
281
+ return /* @__PURE__ */ _getStandardProps(this);
282
+ },
283
+ "~run"(dataset, config$1) {
284
+ if (typeof dataset.value === "boolean") dataset.typed = true;
285
+ else _addIssue(this, "type", dataset, config$1);
286
+ return dataset;
287
+ }
288
+ };
289
+ }
290
+ // @__NO_SIDE_EFFECTS__
291
+ function literal(literal_, message$1) {
292
+ return {
293
+ kind: "schema",
294
+ type: "literal",
295
+ reference: literal,
296
+ expects: /* @__PURE__ */ _stringify(literal_),
297
+ async: false,
298
+ literal: literal_,
299
+ message: message$1,
300
+ get "~standard"() {
301
+ return /* @__PURE__ */ _getStandardProps(this);
302
+ },
303
+ "~run"(dataset, config$1) {
304
+ if (dataset.value === this.literal) dataset.typed = true;
305
+ else _addIssue(this, "type", dataset, config$1);
306
+ return dataset;
307
+ }
308
+ };
309
+ }
310
+ // @__NO_SIDE_EFFECTS__
311
+ function nan(message$1) {
312
+ return {
313
+ kind: "schema",
314
+ type: "nan",
315
+ reference: nan,
316
+ expects: "NaN",
317
+ async: false,
318
+ message: message$1,
319
+ get "~standard"() {
320
+ return /* @__PURE__ */ _getStandardProps(this);
321
+ },
322
+ "~run"(dataset, config$1) {
323
+ if (Number.isNaN(dataset.value)) dataset.typed = true;
324
+ else _addIssue(this, "type", dataset, config$1);
325
+ return dataset;
326
+ }
327
+ };
328
+ }
329
+ // @__NO_SIDE_EFFECTS__
330
+ function nullable(wrapped, default_) {
331
+ return {
332
+ kind: "schema",
333
+ type: "nullable",
334
+ reference: nullable,
335
+ expects: `(${wrapped.expects} | null)`,
336
+ async: false,
337
+ wrapped,
338
+ default: default_,
339
+ get "~standard"() {
340
+ return /* @__PURE__ */ _getStandardProps(this);
341
+ },
342
+ "~run"(dataset, config$1) {
343
+ if (dataset.value === null) {
344
+ if (this.default !== void 0) dataset.value = /* @__PURE__ */ getDefault(this, dataset, config$1);
345
+ if (dataset.value === null) {
346
+ dataset.typed = true;
347
+ return dataset;
348
+ }
349
+ }
350
+ return this.wrapped["~run"](dataset, config$1);
351
+ }
352
+ };
353
+ }
354
+ // @__NO_SIDE_EFFECTS__
355
+ function number(message$1) {
356
+ return {
357
+ kind: "schema",
358
+ type: "number",
359
+ reference: number,
360
+ expects: "number",
361
+ async: false,
362
+ message: message$1,
363
+ get "~standard"() {
364
+ return /* @__PURE__ */ _getStandardProps(this);
365
+ },
366
+ "~run"(dataset, config$1) {
367
+ if (typeof dataset.value === "number" && !isNaN(dataset.value)) dataset.typed = true;
368
+ else _addIssue(this, "type", dataset, config$1);
369
+ return dataset;
370
+ }
371
+ };
372
+ }
373
+ // @__NO_SIDE_EFFECTS__
374
+ function object(entries$1, message$1) {
375
+ return {
376
+ kind: "schema",
377
+ type: "object",
378
+ reference: object,
379
+ expects: "Object",
380
+ async: false,
381
+ entries: entries$1,
382
+ message: message$1,
383
+ get "~standard"() {
384
+ return /* @__PURE__ */ _getStandardProps(this);
385
+ },
386
+ "~run"(dataset, config$1) {
387
+ const input = dataset.value;
388
+ if (input && typeof input === "object") {
389
+ dataset.typed = true;
390
+ dataset.value = {};
391
+ for (const key in this.entries) {
392
+ const valueSchema = this.entries[key];
393
+ if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && valueSchema.default !== void 0) {
394
+ const value$1 = key in input ? input[key] : /* @__PURE__ */ getDefault(valueSchema);
395
+ const valueDataset = valueSchema["~run"]({ value: value$1 }, config$1);
396
+ if (valueDataset.issues) {
397
+ const pathItem = {
398
+ type: "object",
399
+ origin: "value",
400
+ input,
401
+ key,
402
+ value: value$1
403
+ };
404
+ for (const issue of valueDataset.issues) {
405
+ if (issue.path) issue.path.unshift(pathItem);
406
+ else issue.path = [pathItem];
407
+ dataset.issues?.push(issue);
408
+ }
409
+ if (!dataset.issues) dataset.issues = valueDataset.issues;
410
+ if (config$1.abortEarly) {
411
+ dataset.typed = false;
412
+ break;
413
+ }
414
+ }
415
+ if (!valueDataset.typed) dataset.typed = false;
416
+ dataset.value[key] = valueDataset.value;
417
+ } else if (valueSchema.fallback !== void 0) dataset.value[key] = /* @__PURE__ */ getFallback(valueSchema);
418
+ else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") {
419
+ _addIssue(this, "key", dataset, config$1, {
420
+ input: void 0,
421
+ expected: `"${key}"`,
422
+ path: [{
423
+ type: "object",
424
+ origin: "key",
425
+ input,
426
+ key,
427
+ value: input[key]
428
+ }]
429
+ });
430
+ if (config$1.abortEarly) break;
431
+ }
432
+ }
433
+ } else _addIssue(this, "type", dataset, config$1);
434
+ return dataset;
435
+ }
436
+ };
437
+ }
438
+ // @__NO_SIDE_EFFECTS__
439
+ function optional(wrapped, default_) {
440
+ return {
441
+ kind: "schema",
442
+ type: "optional",
443
+ reference: optional,
444
+ expects: `(${wrapped.expects} | undefined)`,
445
+ async: false,
446
+ wrapped,
447
+ default: default_,
448
+ get "~standard"() {
449
+ return /* @__PURE__ */ _getStandardProps(this);
450
+ },
451
+ "~run"(dataset, config$1) {
452
+ if (dataset.value === void 0) {
453
+ if (this.default !== void 0) dataset.value = /* @__PURE__ */ getDefault(this, dataset, config$1);
454
+ if (dataset.value === void 0) {
455
+ dataset.typed = true;
456
+ return dataset;
457
+ }
458
+ }
459
+ return this.wrapped["~run"](dataset, config$1);
460
+ }
461
+ };
462
+ }
463
+ // @__NO_SIDE_EFFECTS__
464
+ function picklist(options, message$1) {
465
+ return {
466
+ kind: "schema",
467
+ type: "picklist",
468
+ reference: picklist,
469
+ expects: /* @__PURE__ */ _joinExpects(options.map(_stringify), "|"),
470
+ async: false,
471
+ options,
472
+ message: message$1,
473
+ get "~standard"() {
474
+ return /* @__PURE__ */ _getStandardProps(this);
475
+ },
476
+ "~run"(dataset, config$1) {
477
+ if (this.options.includes(dataset.value)) dataset.typed = true;
478
+ else _addIssue(this, "type", dataset, config$1);
479
+ return dataset;
480
+ }
481
+ };
482
+ }
483
+ // @__NO_SIDE_EFFECTS__
484
+ function record(key, value$1, message$1) {
485
+ return {
486
+ kind: "schema",
487
+ type: "record",
488
+ reference: record,
489
+ expects: "Object",
490
+ async: false,
491
+ key,
492
+ value: value$1,
493
+ message: message$1,
494
+ get "~standard"() {
495
+ return /* @__PURE__ */ _getStandardProps(this);
496
+ },
497
+ "~run"(dataset, config$1) {
498
+ const input = dataset.value;
499
+ if (input && typeof input === "object") {
500
+ dataset.typed = true;
501
+ dataset.value = {};
502
+ for (const entryKey in input) if (/* @__PURE__ */ _isValidObjectKey(input, entryKey)) {
503
+ const entryValue = input[entryKey];
504
+ const keyDataset = this.key["~run"]({ value: entryKey }, config$1);
505
+ if (keyDataset.issues) {
506
+ const pathItem = {
507
+ type: "object",
508
+ origin: "key",
509
+ input,
510
+ key: entryKey,
511
+ value: entryValue
512
+ };
513
+ for (const issue of keyDataset.issues) {
514
+ issue.path = [pathItem];
515
+ dataset.issues?.push(issue);
516
+ }
517
+ if (!dataset.issues) dataset.issues = keyDataset.issues;
518
+ if (config$1.abortEarly) {
519
+ dataset.typed = false;
520
+ break;
521
+ }
522
+ }
523
+ const valueDataset = this.value["~run"]({ value: entryValue }, config$1);
524
+ if (valueDataset.issues) {
525
+ const pathItem = {
526
+ type: "object",
527
+ origin: "value",
528
+ input,
529
+ key: entryKey,
530
+ value: entryValue
531
+ };
532
+ for (const issue of valueDataset.issues) {
533
+ if (issue.path) issue.path.unshift(pathItem);
534
+ else issue.path = [pathItem];
535
+ dataset.issues?.push(issue);
536
+ }
537
+ if (!dataset.issues) dataset.issues = valueDataset.issues;
538
+ if (config$1.abortEarly) {
539
+ dataset.typed = false;
540
+ break;
541
+ }
542
+ }
543
+ if (!keyDataset.typed || !valueDataset.typed) dataset.typed = false;
544
+ if (keyDataset.typed) dataset.value[keyDataset.value] = valueDataset.value;
545
+ }
546
+ } else _addIssue(this, "type", dataset, config$1);
547
+ return dataset;
548
+ }
549
+ };
550
+ }
551
+ // @__NO_SIDE_EFFECTS__
552
+ function strictObject(entries$1, message$1) {
553
+ return {
554
+ kind: "schema",
555
+ type: "strict_object",
556
+ reference: strictObject,
557
+ expects: "Object",
558
+ async: false,
559
+ entries: entries$1,
560
+ message: message$1,
561
+ get "~standard"() {
562
+ return /* @__PURE__ */ _getStandardProps(this);
563
+ },
564
+ "~run"(dataset, config$1) {
565
+ const input = dataset.value;
566
+ if (input && typeof input === "object") {
567
+ dataset.typed = true;
568
+ dataset.value = {};
569
+ for (const key in this.entries) {
570
+ const valueSchema = this.entries[key];
571
+ if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && valueSchema.default !== void 0) {
572
+ const value$1 = key in input ? input[key] : /* @__PURE__ */ getDefault(valueSchema);
573
+ const valueDataset = valueSchema["~run"]({ value: value$1 }, config$1);
574
+ if (valueDataset.issues) {
575
+ const pathItem = {
576
+ type: "object",
577
+ origin: "value",
578
+ input,
579
+ key,
580
+ value: value$1
581
+ };
582
+ for (const issue of valueDataset.issues) {
583
+ if (issue.path) issue.path.unshift(pathItem);
584
+ else issue.path = [pathItem];
585
+ dataset.issues?.push(issue);
586
+ }
587
+ if (!dataset.issues) dataset.issues = valueDataset.issues;
588
+ if (config$1.abortEarly) {
589
+ dataset.typed = false;
590
+ break;
591
+ }
592
+ }
593
+ if (!valueDataset.typed) dataset.typed = false;
594
+ dataset.value[key] = valueDataset.value;
595
+ } else if (valueSchema.fallback !== void 0) dataset.value[key] = /* @__PURE__ */ getFallback(valueSchema);
596
+ else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") {
597
+ _addIssue(this, "key", dataset, config$1, {
598
+ input: void 0,
599
+ expected: `"${key}"`,
600
+ path: [{
601
+ type: "object",
602
+ origin: "key",
603
+ input,
604
+ key,
605
+ value: input[key]
606
+ }]
607
+ });
608
+ if (config$1.abortEarly) break;
609
+ }
610
+ }
611
+ if (!dataset.issues || !config$1.abortEarly) {
612
+ for (const key in input) if (!(key in this.entries)) {
613
+ _addIssue(this, "key", dataset, config$1, {
614
+ input: key,
615
+ expected: "never",
616
+ path: [{
617
+ type: "object",
618
+ origin: "key",
619
+ input,
620
+ key,
621
+ value: input[key]
622
+ }]
623
+ });
624
+ break;
625
+ }
626
+ }
627
+ } else _addIssue(this, "type", dataset, config$1);
628
+ return dataset;
629
+ }
630
+ };
631
+ }
632
+ // @__NO_SIDE_EFFECTS__
633
+ function string(message$1) {
634
+ return {
635
+ kind: "schema",
636
+ type: "string",
637
+ reference: string,
638
+ expects: "string",
639
+ async: false,
640
+ message: message$1,
641
+ get "~standard"() {
642
+ return /* @__PURE__ */ _getStandardProps(this);
643
+ },
644
+ "~run"(dataset, config$1) {
645
+ if (typeof dataset.value === "string") dataset.typed = true;
646
+ else _addIssue(this, "type", dataset, config$1);
647
+ return dataset;
648
+ }
649
+ };
650
+ }
651
+ // @__NO_SIDE_EFFECTS__
652
+ function _subIssues(datasets) {
653
+ let issues;
654
+ if (datasets) for (const dataset of datasets) if (issues) for (const issue of dataset.issues) issues.push(issue);
655
+ else issues = dataset.issues;
656
+ return issues;
657
+ }
658
+ // @__NO_SIDE_EFFECTS__
659
+ function union(options, message$1) {
660
+ return {
661
+ kind: "schema",
662
+ type: "union",
663
+ reference: union,
664
+ expects: /* @__PURE__ */ _joinExpects(options.map((option) => option.expects), "|"),
665
+ async: false,
666
+ options,
667
+ message: message$1,
668
+ get "~standard"() {
669
+ return /* @__PURE__ */ _getStandardProps(this);
670
+ },
671
+ "~run"(dataset, config$1) {
672
+ let validDataset;
673
+ let typedDatasets;
674
+ let untypedDatasets;
675
+ for (const schema of this.options) {
676
+ const optionDataset = schema["~run"]({ value: dataset.value }, config$1);
677
+ if (optionDataset.typed) if (optionDataset.issues) if (typedDatasets) typedDatasets.push(optionDataset);
678
+ else typedDatasets = [optionDataset];
679
+ else {
680
+ validDataset = optionDataset;
681
+ break;
682
+ }
683
+ else if (untypedDatasets) untypedDatasets.push(optionDataset);
684
+ else untypedDatasets = [optionDataset];
685
+ }
686
+ if (validDataset) return validDataset;
687
+ if (typedDatasets) {
688
+ if (typedDatasets.length === 1) return typedDatasets[0];
689
+ _addIssue(this, "type", dataset, config$1, { issues: /* @__PURE__ */ _subIssues(typedDatasets) });
690
+ dataset.typed = true;
691
+ } else if (untypedDatasets?.length === 1) return untypedDatasets[0];
692
+ else _addIssue(this, "type", dataset, config$1, { issues: /* @__PURE__ */ _subIssues(untypedDatasets) });
693
+ return dataset;
694
+ }
695
+ };
696
+ }
697
+ // @__NO_SIDE_EFFECTS__
698
+ function unknown() {
699
+ return {
700
+ kind: "schema",
701
+ type: "unknown",
702
+ reference: unknown,
703
+ expects: "unknown",
704
+ async: false,
705
+ get "~standard"() {
706
+ return /* @__PURE__ */ _getStandardProps(this);
707
+ },
708
+ "~run"(dataset) {
709
+ dataset.typed = true;
710
+ return dataset;
711
+ }
712
+ };
713
+ }
714
+ // @__NO_SIDE_EFFECTS__
715
+ function variant(key, options, message$1) {
716
+ return {
717
+ kind: "schema",
718
+ type: "variant",
719
+ reference: variant,
720
+ expects: "Object",
721
+ async: false,
722
+ key,
723
+ options,
724
+ message: message$1,
725
+ get "~standard"() {
726
+ return /* @__PURE__ */ _getStandardProps(this);
727
+ },
728
+ "~run"(dataset, config$1) {
729
+ const input = dataset.value;
730
+ if (input && typeof input === "object") {
731
+ let outputDataset;
732
+ let maxDiscriminatorPriority = 0;
733
+ let invalidDiscriminatorKey = this.key;
734
+ let expectedDiscriminators = [];
735
+ const parseOptions = (variant$1, allKeys) => {
736
+ for (const schema of variant$1.options) {
737
+ if (schema.type === "variant") parseOptions(schema, new Set(allKeys).add(schema.key));
738
+ else {
739
+ let keysAreValid = true;
740
+ let currentPriority = 0;
741
+ for (const currentKey of allKeys) {
742
+ const discriminatorSchema = schema.entries[currentKey];
743
+ if (currentKey in input ? discriminatorSchema["~run"]({
744
+ typed: false,
745
+ value: input[currentKey]
746
+ }, ABORT_EARLY_CONFIG).issues : discriminatorSchema.type !== "exact_optional" && discriminatorSchema.type !== "optional" && discriminatorSchema.type !== "nullish") {
747
+ keysAreValid = false;
748
+ if (invalidDiscriminatorKey !== currentKey && (maxDiscriminatorPriority < currentPriority || maxDiscriminatorPriority === currentPriority && currentKey in input && !(invalidDiscriminatorKey in input))) {
749
+ maxDiscriminatorPriority = currentPriority;
750
+ invalidDiscriminatorKey = currentKey;
751
+ expectedDiscriminators = [];
752
+ }
753
+ if (invalidDiscriminatorKey === currentKey) expectedDiscriminators.push(schema.entries[currentKey].expects);
754
+ break;
755
+ }
756
+ currentPriority++;
757
+ }
758
+ if (keysAreValid) {
759
+ const optionDataset = schema["~run"]({ value: input }, config$1);
760
+ if (!outputDataset || !outputDataset.typed && optionDataset.typed) outputDataset = optionDataset;
761
+ }
762
+ }
763
+ if (outputDataset && !outputDataset.issues) break;
764
+ }
765
+ };
766
+ parseOptions(this, /* @__PURE__ */ new Set([this.key]));
767
+ if (outputDataset) return outputDataset;
768
+ _addIssue(this, "type", dataset, config$1, {
769
+ input: input[invalidDiscriminatorKey],
770
+ expected: /* @__PURE__ */ _joinExpects(expectedDiscriminators, "|"),
771
+ path: [{
772
+ type: "object",
773
+ origin: "value",
774
+ input,
775
+ key: invalidDiscriminatorKey,
776
+ value: input[invalidDiscriminatorKey]
777
+ }]
778
+ });
779
+ } else _addIssue(this, "type", dataset, config$1);
780
+ return dataset;
781
+ }
782
+ };
783
+ }
784
+ // @__NO_SIDE_EFFECTS__
785
+ function omit(schema, keys) {
786
+ const entries$1 = { ...schema.entries };
787
+ for (const key of keys) delete entries$1[key];
788
+ return {
789
+ ...schema,
790
+ entries: entries$1,
791
+ get "~standard"() {
792
+ return /* @__PURE__ */ _getStandardProps(this);
793
+ }
794
+ };
795
+ }
796
+ function parse(schema, input, config$1) {
797
+ const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig(config$1));
798
+ if (dataset.issues) throw new ValiError(dataset.issues);
799
+ return dataset.value;
800
+ }
801
+ // @__NO_SIDE_EFFECTS__
802
+ function pipe(...pipe$1) {
803
+ return {
804
+ ...pipe$1[0],
805
+ pipe: pipe$1,
806
+ get "~standard"() {
807
+ return /* @__PURE__ */ _getStandardProps(this);
808
+ },
809
+ "~run"(dataset, config$1) {
810
+ for (const item of pipe$1) if (item.kind !== "metadata") {
811
+ if (dataset.issues && (item.kind === "schema" || item.kind === "transformation")) {
812
+ dataset.typed = false;
813
+ break;
814
+ }
815
+ if (!dataset.issues || !config$1.abortEarly && !config$1.abortPipeEarly) dataset = item["~run"](dataset, config$1);
816
+ }
817
+ return dataset;
818
+ }
819
+ };
820
+ }
821
+ // @__NO_SIDE_EFFECTS__
822
+ function safeParse(schema, input, config$1) {
823
+ const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig(config$1));
824
+ return {
825
+ typed: dataset.typed,
826
+ success: !dataset.issues,
827
+ output: dataset.value,
828
+ issues: dataset.issues
829
+ };
830
+ }
831
+
832
+ // protocol/src/ids.ts
833
+ var notionBlockIdSchema = pipe(string(), brand("NotionBlockId"));
834
+ var notionDataSourceIdSchema = pipe(
835
+ string(),
836
+ brand("NotionDataSourceId")
837
+ );
838
+ var notionPageIdSchema = pipe(string(), brand("NotionPageId"));
839
+ var notionAgentIdSchema = pipe(string(), brand("NotionAgentId"));
840
+ var notionSpaceIdSchema = pipe(string(), brand("NotionSpaceId"));
841
+
842
+ // protocol/src/dataSources/propertySchema.ts
843
+ var notionPropertyColorSchema = picklist([
844
+ "default",
845
+ "gray",
846
+ "brown",
847
+ "orange",
848
+ "yellow",
849
+ "green",
850
+ "blue",
851
+ "purple",
852
+ "pink",
853
+ "red",
854
+ "gray_background",
855
+ "brown_background",
856
+ "orange_background",
857
+ "yellow_background",
858
+ "green_background",
859
+ "blue_background",
860
+ "purple_background",
861
+ "pink_background",
862
+ "red_background",
863
+ "default_background"
864
+ ]);
865
+ var notionPropertyOptionSchema = object({
866
+ id: string(),
867
+ name: string(),
868
+ color: optional(notionPropertyColorSchema),
869
+ description: optional(string())
870
+ });
871
+ var notionStatusGroupSchema = object({
872
+ id: string(),
873
+ name: string(),
874
+ color: optional(notionPropertyColorSchema),
875
+ option_ids: array(string())
876
+ });
877
+ var notionDualPropertySchema = object({
878
+ synced_property_id: string(),
879
+ synced_property_name: string()
880
+ });
881
+ var baseProp = object({
882
+ name: string(),
883
+ description: optional(string())
884
+ });
885
+ var NOTION_PROPERTY_TYPES = [
886
+ "title",
887
+ "rich_text",
888
+ "number",
889
+ "checkbox",
890
+ "url",
891
+ "email",
892
+ "phone_number",
893
+ "select",
894
+ "multi_select",
895
+ "status",
896
+ "date",
897
+ "people",
898
+ "files",
899
+ "unique_id",
900
+ "relation",
901
+ "place",
902
+ "formula",
903
+ "rollup",
904
+ "button",
905
+ "verification",
906
+ "last_visited_time",
907
+ "location",
908
+ "created_time",
909
+ "last_edited_time",
910
+ "created_by",
911
+ "last_edited_by"
912
+ ];
913
+ var notionPropertyTypeSchema = picklist(NOTION_PROPERTY_TYPES);
914
+ var CUSTOM_BLOCK_DATA_SOURCE_SORTABLE_PROPERTY_TYPES = [
915
+ "title",
916
+ "rich_text",
917
+ "number",
918
+ "checkbox",
919
+ "url",
920
+ "email",
921
+ "phone_number",
922
+ "date",
923
+ "created_time",
924
+ "last_edited_time"
925
+ ];
926
+ var notionPropertySchemaSchema = variant("type", [
927
+ object({ ...baseProp.entries, type: literal("title") }),
928
+ object({ ...baseProp.entries, type: literal("rich_text") }),
929
+ object({ ...baseProp.entries, type: literal("number") }),
930
+ object({ ...baseProp.entries, type: literal("checkbox") }),
931
+ object({ ...baseProp.entries, type: literal("url") }),
932
+ object({ ...baseProp.entries, type: literal("email") }),
933
+ object({ ...baseProp.entries, type: literal("phone_number") }),
934
+ object({
935
+ ...baseProp.entries,
936
+ type: literal("select"),
937
+ options: array(notionPropertyOptionSchema)
938
+ }),
939
+ object({
940
+ ...baseProp.entries,
941
+ type: literal("multi_select"),
942
+ options: array(notionPropertyOptionSchema)
943
+ }),
944
+ object({
945
+ ...baseProp.entries,
946
+ type: literal("status"),
947
+ options: array(notionPropertyOptionSchema),
948
+ groups: array(notionStatusGroupSchema)
949
+ }),
950
+ object({ ...baseProp.entries, type: literal("date") }),
951
+ object({ ...baseProp.entries, type: literal("people") }),
952
+ object({ ...baseProp.entries, type: literal("files") }),
953
+ object({ ...baseProp.entries, type: literal("unique_id") }),
954
+ object({
955
+ ...baseProp.entries,
956
+ type: literal("relation"),
957
+ data_source_id: optional(string()),
958
+ dual_property: optional(notionDualPropertySchema)
959
+ }),
960
+ object({ ...baseProp.entries, type: literal("place") }),
961
+ object({ ...baseProp.entries, type: literal("formula") }),
962
+ object({ ...baseProp.entries, type: literal("rollup") }),
963
+ // Internal-only types passed through under their bridge-native names.
964
+ object({ ...baseProp.entries, type: literal("button") }),
965
+ object({ ...baseProp.entries, type: literal("verification") }),
966
+ object({ ...baseProp.entries, type: literal("last_visited_time") }),
967
+ object({ ...baseProp.entries, type: literal("location") }),
968
+ // Synthetic built-ins. The host always emits one of each per data source.
969
+ object({ ...baseProp.entries, type: literal("created_time") }),
970
+ object({ ...baseProp.entries, type: literal("last_edited_time") }),
971
+ object({ ...baseProp.entries, type: literal("created_by") }),
972
+ object({ ...baseProp.entries, type: literal("last_edited_by") })
973
+ ]);
974
+ var NOTION_BUILTIN_PROPERTY_SCHEMAS = {
975
+ created_time: { type: "created_time", name: "Created time" },
976
+ last_edited_time: { type: "last_edited_time", name: "Last edited time" },
977
+ created_by: { type: "created_by", name: "Created by" },
978
+ last_edited_by: { type: "last_edited_by", name: "Last edited by" }
979
+ };
980
+
981
+ // protocol/src/dataSources/dataSource.ts
982
+ var collectionPointerValidator = object({
983
+ id: notionDataSourceIdSchema,
984
+ table: string(),
985
+ spaceId: optional(notionSpaceIdSchema)
986
+ });
987
+ var notionCollectionSchemaValidator = object({
988
+ id: optional(notionDataSourceIdSchema),
989
+ /**
990
+ * Describes actual database properties in protocol 5. Protocol 3/4 payloads can also include
991
+ * synthetic metadata for compatibility. Use this map to resolve property bindings. Use this map
992
+ * to validate filter and sort references.
993
+ */
994
+ propertiesById: record(string(), notionPropertySchemaSchema)
995
+ });
996
+ var notionDataSourceSchema = object({
997
+ key: string(),
998
+ collectionPointer: optional(collectionPointerValidator),
999
+ /**
1000
+ * Describes database properties. Use this schema to resolve property bindings. Use this
1001
+ * schema to validate filter and sort references. Undefined when the host does not provide a
1002
+ * database schema.
1003
+ */
1004
+ collectionSchema: optional(notionCollectionSchemaValidator),
1005
+ /**
1006
+ * Maps user-defined property keys to database property IDs. Use this map to resolve a key
1007
+ * such as `name` to its database property ID. A value of `undefined` marks a declared
1008
+ * property without a valid binding. Synthetic metadata does not add entries to this map.
1009
+ */
1010
+ propertyIdsByKey: record(string(), optional(string())),
1011
+ /**
1012
+ * Describes property values in query snapshots. Keys use the same property IDs as a snapshot's
1013
+ * `propertiesById` map.
1014
+ *
1015
+ * Includes four synthetic metadata fields, even when the database schema is unavailable:
1016
+ * `created_time`, `last_edited_time`, `created_by`, and `last_edited_by`. Also includes
1017
+ * database properties when the host provides their schema.
1018
+ *
1019
+ * Use `propertiesById` to read a value. Use this map to read the value's schema. Use
1020
+ * `collectionSchema` to validate filter and sort references.
1021
+ */
1022
+ propertySchemasById: record(string(), notionPropertySchemaSchema)
1023
+ });
1024
+ var notionDataSourceBindingSchema = object({
1025
+ collectionPointer: optional(collectionPointerValidator),
1026
+ /**
1027
+ * Describes database properties. Use this schema to resolve property bindings. Use this
1028
+ * schema to validate filter and sort references. Undefined when the host does not provide a
1029
+ * database schema.
1030
+ */
1031
+ collectionSchema: optional(notionCollectionSchemaValidator),
1032
+ /**
1033
+ * Maps user-defined property keys to database property IDs. Use this map to resolve a key
1034
+ * such as `name` to its database property ID. A value of `undefined` marks a declared
1035
+ * property without a binding. Omitted when the host does not provide property mappings.
1036
+ * Synthetic metadata does not add entries to this map.
1037
+ */
1038
+ propertyIdsByKey: optional(record(string(), optional(string())))
1039
+ });
1040
+ var notionDataSourceBindingsSchema = record(
1041
+ string(),
1042
+ notionDataSourceBindingSchema
1043
+ );
1044
+
1045
+ // protocol/src/manifest.ts
1046
+ var manifestIconSchema = variant("type", [
1047
+ object({
1048
+ type: literal("emoji"),
1049
+ emoji: string()
1050
+ }),
1051
+ object({
1052
+ type: literal("external"),
1053
+ url: string()
1054
+ })
1055
+ ]);
1056
+ var manifestPropertySchema = object({
1057
+ name: string(),
1058
+ description: optional(string()),
1059
+ type: notionPropertyTypeSchema
1060
+ });
1061
+ var manifestDataSourceSchema = object({
1062
+ name: string(),
1063
+ description: optional(string()),
1064
+ icon: optional(manifestIconSchema),
1065
+ properties: optional(record(string(), manifestPropertySchema), {})
1066
+ });
1067
+ var manifestSchema = object({
1068
+ version: literal(1),
1069
+ dataSources: record(string(), manifestDataSourceSchema)
1070
+ });
1071
+
1072
+ // protocol/src/contrast.ts
1073
+ var notionContrastModeSchema = picklist(["standard", "high"]);
1074
+ var DEFAULT_CONTRAST_MODE = "standard";
1075
+
1076
+ // protocol/src/messages/contrastModeChanged.ts
1077
+ var contrastModeChangedMessageSchema = object({
1078
+ type: literal("contrastModeChanged"),
1079
+ contrastMode: notionContrastModeSchema
1080
+ });
1081
+
1082
+ // protocol/src/parent.ts
1083
+ var notionParentSchema = variant("type", [
1084
+ object({ type: literal("page_id"), page_id: notionPageIdSchema }),
1085
+ object({
1086
+ type: literal("data_source_id"),
1087
+ data_source_id: notionDataSourceIdSchema
1088
+ }),
1089
+ object({ type: literal("workspace"), workspace: literal(true) }),
1090
+ object({ type: literal("block_id"), block_id: notionBlockIdSchema }),
1091
+ object({ type: literal("agent_id"), agent_id: notionAgentIdSchema }),
1092
+ object({ type: literal("unavailable") })
1093
+ ]);
1094
+
1095
+ // protocol/src/pages/page.ts
1096
+ var customBlockPageSchema = variant("type", [
1097
+ /** The viewer cannot access the containing page; its ID and parent are not exposed. */
1098
+ object({ type: literal("unavailable") }),
1099
+ /** The viewer can access the containing page; includes its ID and parent location. */
1100
+ object({
1101
+ type: literal("page"),
1102
+ id: notionPageIdSchema,
1103
+ /**
1104
+ * The containing page's own parent. It lets a block distinguish a freestanding page from a
1105
+ * database row without a round trip. Not to be confused with the top-level `parent` runtime
1106
+ * value, which is the custom block's own parent.
1107
+ */
1108
+ parent: notionParentSchema
1109
+ })
1110
+ ]);
1111
+ var notionEmojiIconSchema = object({
1112
+ type: literal("emoji"),
1113
+ emoji: string()
1114
+ });
1115
+ var notionCustomEmojiIconSchema = object({
1116
+ type: literal("custom_emoji"),
1117
+ custom_emoji: object({
1118
+ id: string(),
1119
+ name: optional(string()),
1120
+ url: optional(string())
1121
+ })
1122
+ });
1123
+ var notionExternalFileSchema = object({
1124
+ type: literal("external"),
1125
+ external: object({ url: string() })
1126
+ });
1127
+ var notionHostedFileSchema = object({
1128
+ type: literal("file"),
1129
+ file: object({
1130
+ url: string(),
1131
+ expiry_time: optional(string())
1132
+ })
1133
+ });
1134
+ var notionPageIconSchema = variant("type", [
1135
+ notionEmojiIconSchema,
1136
+ notionCustomEmojiIconSchema,
1137
+ notionExternalFileSchema,
1138
+ notionHostedFileSchema
1139
+ ]);
1140
+ var notionPageCoverSchema = variant("type", [
1141
+ notionExternalFileSchema,
1142
+ notionHostedFileSchema
1143
+ ]);
1144
+ var nullableStringSchema = nullable(string());
1145
+ var notionRichTextItemSchema = record(string(), unknown());
1146
+ var notionSelectOptionInputSchema = union([
1147
+ object({
1148
+ id: string(),
1149
+ name: optional(string()),
1150
+ color: optional(string()),
1151
+ description: optional(nullableStringSchema)
1152
+ }),
1153
+ object({
1154
+ name: string(),
1155
+ id: optional(string()),
1156
+ color: optional(string()),
1157
+ description: optional(nullableStringSchema)
1158
+ })
1159
+ ]);
1160
+ var notionDateInputSchema = object({
1161
+ start: string(),
1162
+ end: optional(nullableStringSchema),
1163
+ time_zone: optional(nullableStringSchema)
1164
+ });
1165
+ var notionUserInputSchema = union([
1166
+ object({
1167
+ object: optional(literal("user")),
1168
+ id: string()
1169
+ }),
1170
+ object({
1171
+ object: literal("group"),
1172
+ id: string(),
1173
+ name: optional(nullableStringSchema)
1174
+ })
1175
+ ]);
1176
+ var notionRelationInputSchema = object({ id: string() });
1177
+ var notionFileInputSchema = union([
1178
+ object({
1179
+ type: literal("external"),
1180
+ name: string(),
1181
+ external: object({ url: string() })
1182
+ }),
1183
+ object({
1184
+ type: literal("file"),
1185
+ name: string(),
1186
+ file: object({
1187
+ url: string(),
1188
+ expiry_time: optional(string())
1189
+ })
1190
+ })
1191
+ ]);
1192
+ var notionPlaceInputSchema = object({
1193
+ lat: number(),
1194
+ lon: number(),
1195
+ name: optional(nullableStringSchema),
1196
+ address: optional(nullableStringSchema),
1197
+ aws_place_id: optional(nullableStringSchema),
1198
+ google_place_id: optional(nullableStringSchema)
1199
+ });
1200
+ var pagePropertyBaseSchema = {
1201
+ id: string()
1202
+ };
1203
+ var notionPagePropertyValueSchema = variant("type", [
1204
+ object({
1205
+ ...pagePropertyBaseSchema,
1206
+ type: literal("title"),
1207
+ title: array(notionRichTextItemSchema)
1208
+ }),
1209
+ object({
1210
+ ...pagePropertyBaseSchema,
1211
+ type: literal("rich_text"),
1212
+ rich_text: array(notionRichTextItemSchema)
1213
+ }),
1214
+ object({
1215
+ ...pagePropertyBaseSchema,
1216
+ type: literal("number"),
1217
+ number: nullable(number())
1218
+ }),
1219
+ object({
1220
+ ...pagePropertyBaseSchema,
1221
+ type: literal("url"),
1222
+ url: nullableStringSchema
1223
+ }),
1224
+ object({
1225
+ ...pagePropertyBaseSchema,
1226
+ type: literal("email"),
1227
+ email: nullableStringSchema
1228
+ }),
1229
+ object({
1230
+ ...pagePropertyBaseSchema,
1231
+ type: literal("phone_number"),
1232
+ phone_number: nullableStringSchema
1233
+ }),
1234
+ object({
1235
+ ...pagePropertyBaseSchema,
1236
+ type: literal("checkbox"),
1237
+ checkbox: boolean()
1238
+ }),
1239
+ object({
1240
+ ...pagePropertyBaseSchema,
1241
+ type: literal("select"),
1242
+ select: nullable(notionSelectOptionInputSchema)
1243
+ }),
1244
+ object({
1245
+ ...pagePropertyBaseSchema,
1246
+ type: literal("status"),
1247
+ status: nullable(notionSelectOptionInputSchema)
1248
+ }),
1249
+ object({
1250
+ ...pagePropertyBaseSchema,
1251
+ type: literal("multi_select"),
1252
+ multi_select: array(notionSelectOptionInputSchema)
1253
+ }),
1254
+ object({
1255
+ ...pagePropertyBaseSchema,
1256
+ type: literal("date"),
1257
+ date: nullable(notionDateInputSchema)
1258
+ }),
1259
+ object({
1260
+ ...pagePropertyBaseSchema,
1261
+ type: literal("people"),
1262
+ people: array(notionUserInputSchema)
1263
+ }),
1264
+ object({
1265
+ ...pagePropertyBaseSchema,
1266
+ type: literal("relation"),
1267
+ has_more: optional(boolean()),
1268
+ relation: array(notionRelationInputSchema)
1269
+ }),
1270
+ object({
1271
+ ...pagePropertyBaseSchema,
1272
+ type: literal("files"),
1273
+ files: array(notionFileInputSchema)
1274
+ }),
1275
+ object({
1276
+ ...pagePropertyBaseSchema,
1277
+ type: literal("place"),
1278
+ place: nullable(notionPlaceInputSchema)
1279
+ })
1280
+ ]);
1281
+ var notionPagePropertyWriteMapSchema = record(
1282
+ string(),
1283
+ notionPagePropertyValueSchema
1284
+ );
1285
+ var notionPageSchema = object({
1286
+ object: literal("page"),
1287
+ id: notionPageIdSchema,
1288
+ parent: notionParentSchema,
1289
+ properties: notionPagePropertyWriteMapSchema,
1290
+ created_time: optional(string()),
1291
+ last_edited_time: optional(string()),
1292
+ icon: optional(notionPageIconSchema),
1293
+ cover: optional(notionPageCoverSchema),
1294
+ url: optional(string()),
1295
+ public_url: optional(string()),
1296
+ /** Whether the page or an ancestor is archived. */
1297
+ is_archived: boolean(),
1298
+ /** Whether the page or an ancestor is in Trash. */
1299
+ in_trash: boolean()
1300
+ });
1301
+
1302
+ // protocol/src/messages/createPageResult.ts
1303
+ var customBlockCreatePageErrorCodeSchema = string();
1304
+ var customBlockCreatePageErrorInfoSchema = object({
1305
+ code: customBlockCreatePageErrorCodeSchema,
1306
+ message: string(),
1307
+ isRetryable: boolean()
1308
+ });
1309
+ var createPageResultMessageSchema = variant("status", [
1310
+ object({
1311
+ type: literal("createPageResult"),
1312
+ requestId: string(),
1313
+ status: literal("success"),
1314
+ /** The newly created page. */
1315
+ page: notionPageSchema
1316
+ }),
1317
+ object({
1318
+ type: literal("createPageResult"),
1319
+ requestId: string(),
1320
+ status: literal("error"),
1321
+ error: customBlockCreatePageErrorInfoSchema
1322
+ })
1323
+ ]);
1324
+
1325
+ // protocol/src/users/user.ts
1326
+ var notionUserIdSchema = pipe(string(), brand("NotionUserId"));
1327
+ var notionUserSchema = object({
1328
+ object: literal("user"),
1329
+ id: notionUserIdSchema,
1330
+ name: optional(string()),
1331
+ avatar_url: nullable(string()),
1332
+ type: literal("person"),
1333
+ person: object({
1334
+ email: string()
1335
+ })
1336
+ });
1337
+ var notionUserListSchema = object({
1338
+ object: literal("list"),
1339
+ results: array(notionUserSchema),
1340
+ next_cursor: nullable(string()),
1341
+ has_more: boolean(),
1342
+ type: literal("user"),
1343
+ user: record(string(), unknown())
1344
+ });
1345
+
1346
+ // protocol/src/messages/currentUserChanged.ts
1347
+ var currentUserChangedMessageSchema = object({
1348
+ type: literal("currentUserChanged"),
1349
+ currentUser: notionUserSchema
1350
+ });
1351
+
1352
+ // protocol/src/messages/dataSourcesChanged.ts
1353
+ var dataSourcesChangedMessageSchema = object({
1354
+ type: literal("dataSourcesChanged"),
1355
+ dataSources: object({
1356
+ bindings: notionDataSourceBindingsSchema
1357
+ })
1358
+ });
1359
+
1360
+ // protocol/src/messages/getPage.ts
1361
+ var customBlockGetPageErrorCodeSchema = string();
1362
+ var customBlockGetPageErrorInfoSchema = object({
1363
+ code: customBlockGetPageErrorCodeSchema,
1364
+ message: string(),
1365
+ isRetryable: boolean()
1366
+ });
1367
+ var getPageMessageSchema = object({
1368
+ type: literal("getPage"),
1369
+ requestId: string(),
1370
+ pageId: notionPageIdSchema
1371
+ });
1372
+ var getPageResultMessageSchema = variant("status", [
1373
+ object({
1374
+ type: literal("getPageResult"),
1375
+ requestId: string(),
1376
+ status: literal("success"),
1377
+ page: notionPageSchema
1378
+ }),
1379
+ object({
1380
+ type: literal("getPageResult"),
1381
+ requestId: string(),
1382
+ status: literal("error"),
1383
+ error: customBlockGetPageErrorInfoSchema
1384
+ })
1385
+ ]);
1386
+
1387
+ // protocol/src/messages/getUser.ts
1388
+ var customBlockGetUserErrorCodeSchema = string();
1389
+ var customBlockGetUserErrorInfoSchema = object({
1390
+ code: customBlockGetUserErrorCodeSchema,
1391
+ message: string(),
1392
+ isRetryable: boolean()
1393
+ });
1394
+ var getUserMessageSchema = object({
1395
+ type: literal("getUser"),
1396
+ requestId: string(),
1397
+ userId: notionUserIdSchema
1398
+ });
1399
+ var getUserResultMessageSchema = variant("status", [
1400
+ object({
1401
+ type: literal("getUserResult"),
1402
+ requestId: string(),
1403
+ status: literal("success"),
1404
+ user: notionUserSchema
1405
+ }),
1406
+ object({
1407
+ type: literal("getUserResult"),
1408
+ requestId: string(),
1409
+ status: literal("error"),
1410
+ error: customBlockGetUserErrorInfoSchema
1411
+ })
1412
+ ]);
1413
+
1414
+ // protocol/src/theme.ts
1415
+ var notionThemeSchema = picklist(["light", "dark"]);
1416
+
1417
+ // protocol/src/messages/init.ts
1418
+ var customBlockInitErrorCodeSchema = string();
1419
+ var customBlockInitErrorInfoSchema = object({
1420
+ code: customBlockInitErrorCodeSchema,
1421
+ message: string(),
1422
+ isRetryable: boolean()
1423
+ });
1424
+ var initMessageSchema = variant("status", [
1425
+ object({
1426
+ type: literal("init"),
1427
+ initializationId: string(),
1428
+ status: literal("success"),
1429
+ theme: notionThemeSchema,
1430
+ contrastMode: notionContrastModeSchema,
1431
+ blockId: notionBlockIdSchema,
1432
+ parent: notionParentSchema,
1433
+ page: customBlockPageSchema,
1434
+ manifest: manifestSchema,
1435
+ dataSources: object({
1436
+ bindings: notionDataSourceBindingsSchema
1437
+ }),
1438
+ currentUser: notionUserSchema
1439
+ }),
1440
+ object({
1441
+ type: literal("init"),
1442
+ initializationId: string(),
1443
+ status: literal("error"),
1444
+ error: customBlockInitErrorInfoSchema
1445
+ })
1446
+ ]);
1447
+
1448
+ // protocol/src/messages/invalidSandboxMessage.ts
1449
+ var invalidSandboxMessageSchema = object({
1450
+ type: literal("invalidSandboxMessage"),
1451
+ /**
1452
+ * A human-readable string intended for sandbox-side logging. It has no structured contract.
1453
+ */
1454
+ reason: string()
1455
+ });
1456
+
1457
+ // protocol/src/messages/listUsers.ts
1458
+ var customBlockListUsersErrorCodeSchema = string();
1459
+ var customBlockListUsersErrorInfoSchema = object({
1460
+ code: customBlockListUsersErrorCodeSchema,
1461
+ message: string(),
1462
+ isRetryable: boolean()
1463
+ });
1464
+ var listUsersMessageSchema = object({
1465
+ type: literal("listUsers"),
1466
+ requestId: string(),
1467
+ startCursor: optional(string()),
1468
+ pageSize: optional(number())
1469
+ });
1470
+ var listUsersResultMessageSchema = variant("status", [
1471
+ object({
1472
+ type: literal("listUsersResult"),
1473
+ requestId: string(),
1474
+ status: literal("success"),
1475
+ list: notionUserListSchema
1476
+ }),
1477
+ object({
1478
+ type: literal("listUsersResult"),
1479
+ requestId: string(),
1480
+ status: literal("error"),
1481
+ error: customBlockListUsersErrorInfoSchema
1482
+ })
1483
+ ]);
1484
+
1485
+ // protocol/src/messages/openPage.ts
1486
+ var openPageModeSchema = picklist(["side_peek", "center_peek"]);
1487
+ var customBlockOpenPageErrorCodeSchema = string();
1488
+ var customBlockOpenPageErrorInfoSchema = object({
1489
+ code: customBlockOpenPageErrorCodeSchema,
1490
+ message: string(),
1491
+ isRetryable: boolean()
1492
+ });
1493
+ var openPageMessageSchema = object({
1494
+ type: literal("openPage"),
1495
+ requestId: string(),
1496
+ pageId: notionPageIdSchema,
1497
+ mode: openPageModeSchema
1498
+ });
1499
+ var openPageResultMessageSchema = variant("status", [
1500
+ object({
1501
+ type: literal("openPageResult"),
1502
+ requestId: string(),
1503
+ status: literal("success"),
1504
+ pageId: notionPageIdSchema
1505
+ }),
1506
+ object({
1507
+ type: literal("openPageResult"),
1508
+ requestId: string(),
1509
+ status: literal("error"),
1510
+ error: customBlockOpenPageErrorInfoSchema
1511
+ })
1512
+ ]);
1513
+
1514
+ // protocol/src/messages/pageChanged.ts
1515
+ var pageChangedMessageSchema = object({
1516
+ type: literal("pageChanged"),
1517
+ page: customBlockPageSchema
1518
+ });
1519
+
1520
+ // protocol/src/messages/parentChanged.ts
1521
+ var parentChangedMessageSchema = object({
1522
+ type: literal("parentChanged"),
1523
+ parent: notionParentSchema
1524
+ });
1525
+
1526
+ // protocol/src/dataSources/dateValue.ts
1527
+ var notionDateReminderSchema = object({
1528
+ unit: picklist(["year", "month", "week", "day"]),
1529
+ value: number(),
1530
+ time: string(),
1531
+ defaultTimeZone: optional(string())
1532
+ });
1533
+ var notionTimeReminderSchema = object({
1534
+ unit: picklist(["hour", "minute"]),
1535
+ value: number()
1536
+ });
1537
+ var notionNoReminderSchema = object({
1538
+ unit: literal("none")
1539
+ });
1540
+ var notionDateTimeReminderSchema = union([
1541
+ notionDateReminderSchema,
1542
+ notionTimeReminderSchema
1543
+ ]);
1544
+ var dateOrNoReminder = optional(
1545
+ union([notionDateReminderSchema, notionNoReminderSchema])
1546
+ );
1547
+ var dateTimeOrNoReminder = optional(
1548
+ union([notionDateTimeReminderSchema, notionNoReminderSchema])
1549
+ );
1550
+ var notionDateSchema = object({
1551
+ type: literal("date"),
1552
+ start_date: string(),
1553
+ reminder: dateOrNoReminder
1554
+ });
1555
+ var notionDateRangeSchema = object({
1556
+ type: literal("daterange"),
1557
+ start_date: string(),
1558
+ end_date: string(),
1559
+ reminder: dateOrNoReminder
1560
+ });
1561
+ var notionDateTimeSchema = object({
1562
+ type: literal("datetime"),
1563
+ start_date: string(),
1564
+ start_time: string(),
1565
+ time_zone: optional(string()),
1566
+ reminder: dateTimeOrNoReminder
1567
+ });
1568
+ var notionDateTimeRangeSchema = object({
1569
+ type: literal("datetimerange"),
1570
+ start_date: string(),
1571
+ start_time: string(),
1572
+ end_date: string(),
1573
+ end_time: string(),
1574
+ time_zone: optional(string()),
1575
+ reminder: dateTimeOrNoReminder
1576
+ });
1577
+ var notionDateValueSchema = variant("type", [
1578
+ notionDateSchema,
1579
+ notionDateRangeSchema,
1580
+ notionDateTimeSchema,
1581
+ notionDateTimeRangeSchema
1582
+ ]);
1583
+
1584
+ // protocol/src/dataSources/recordPointer.ts
1585
+ var notionRecordPointerSchema = object({
1586
+ id: string(),
1587
+ table: string()
1588
+ });
1589
+
1590
+ // protocol/src/dataSources/dataSourceValue.ts
1591
+ var notionDataSourceValueSchema = union([
1592
+ string(),
1593
+ number(),
1594
+ boolean(),
1595
+ notionDateValueSchema,
1596
+ array(string()),
1597
+ array(notionRecordPointerSchema)
1598
+ ]);
1599
+
1600
+ // protocol/src/dataSources/dataSourcePage.ts
1601
+ var notionDataSourcePageBridgeSchema = object({
1602
+ id: notionPageIdSchema,
1603
+ /** Whether the page or an ancestor is archived. */
1604
+ is_archived: boolean(),
1605
+ /** Whether the page or an ancestor is in Trash. */
1606
+ in_trash: boolean(),
1607
+ propertiesById: record(string(), optional(notionDataSourceValueSchema))
1608
+ });
1609
+
1610
+ // protocol/src/messages/queryDataSourceResult.ts
1611
+ var customBlockQueryDataSourceErrorCodeSchema = string();
1612
+ var customBlockQueryDataSourceErrorInfoSchema = object({
1613
+ code: customBlockQueryDataSourceErrorCodeSchema,
1614
+ message: string(),
1615
+ isRetryable: boolean()
1616
+ });
1617
+ var queryDataSourceResultMessageSchema = variant("status", [
1618
+ object({
1619
+ type: literal("queryDataSourceResult"),
1620
+ subscriptionId: string(),
1621
+ status: literal("success"),
1622
+ items: array(notionDataSourcePageBridgeSchema),
1623
+ hasMore: boolean()
1624
+ }),
1625
+ object({
1626
+ type: literal("queryDataSourceResult"),
1627
+ subscriptionId: string(),
1628
+ status: literal("error"),
1629
+ error: customBlockQueryDataSourceErrorInfoSchema
1630
+ })
1631
+ ]);
1632
+
1633
+ // protocol/src/messages/themeChanged.ts
1634
+ var themeChangedMessageSchema = object({
1635
+ type: literal("themeChanged"),
1636
+ theme: notionThemeSchema
1637
+ });
1638
+
1639
+ // protocol/src/messages/updatePageResult.ts
1640
+ var customBlockUpdatePageErrorCodeSchema = string();
1641
+ var customBlockUpdatePageErrorInfoSchema = object({
1642
+ code: customBlockUpdatePageErrorCodeSchema,
1643
+ message: string(),
1644
+ isRetryable: boolean()
1645
+ });
1646
+ var updatePageResultMessageSchema = variant("status", [
1647
+ object({
1648
+ type: literal("updatePageResult"),
1649
+ requestId: string(),
1650
+ status: literal("success"),
1651
+ page: notionPageSchema
1652
+ }),
1653
+ object({
1654
+ type: literal("updatePageResult"),
1655
+ requestId: string(),
1656
+ status: literal("error"),
1657
+ error: customBlockUpdatePageErrorInfoSchema
1658
+ })
1659
+ ]);
1660
+
1661
+ // protocol/src/messages/hostToSandbox.ts
1662
+ var hostToSandboxMessageSchema = variant("type", [
1663
+ initMessageSchema,
1664
+ themeChangedMessageSchema,
1665
+ contrastModeChangedMessageSchema,
1666
+ parentChangedMessageSchema,
1667
+ pageChangedMessageSchema,
1668
+ currentUserChangedMessageSchema,
1669
+ dataSourcesChangedMessageSchema,
1670
+ queryDataSourceResultMessageSchema,
1671
+ createPageResultMessageSchema,
1672
+ getPageResultMessageSchema,
1673
+ getUserResultMessageSchema,
1674
+ listUsersResultMessageSchema,
1675
+ openPageResultMessageSchema,
1676
+ updatePageResultMessageSchema,
1677
+ invalidSandboxMessageSchema
1678
+ ]);
1679
+
1680
+ // protocol/src/protocolVersion.ts
1681
+ var LATEST_BRIDGE_PROTOCOL_VERSION = 5;
1682
+
1683
+ // host/src/lifecycle/initErrors.ts
1684
+ var UNKNOWN_ERROR_MESSAGE = "Unexpected error while initializing custom block.";
1685
+ function initErrorForFailureReason(reason, data = {}) {
1686
+ switch (reason) {
1687
+ case "no_connect":
1688
+ return {
1689
+ code: reason,
1690
+ message: "Sandbox did not send a connect message.",
1691
+ isRetryable: true
1692
+ };
1693
+ case "invalid_connect_payload":
1694
+ return {
1695
+ code: reason,
1696
+ message: "Sandbox sent an invalid connect message.",
1697
+ // The sandbox must be updated to send a valid connect message.
1698
+ isRetryable: false
1699
+ };
1700
+ case "manifest_unavailable":
1701
+ return {
1702
+ code: reason,
1703
+ message: "The custom block manifest is unavailable.",
1704
+ isRetryable: true
1705
+ };
1706
+ case "manifest_invalid":
1707
+ return {
1708
+ code: reason,
1709
+ message: "Sandbox sent an invalid manifest.",
1710
+ // The sandbox must be updated to a valid manifest.
1711
+ isRetryable: false
1712
+ };
1713
+ case "invalid_protocol_version": {
1714
+ const versionText = data.currentBridgeProtocolVersion ? `: ${data.currentBridgeProtocolVersion}` : ".";
1715
+ return {
1716
+ code: reason,
1717
+ message: `Sandbox reported an invalid bridge protocol version ${versionText}`,
1718
+ // The sandbox must be updated to a supported protocol version.
1719
+ isRetryable: false
1720
+ };
1721
+ }
1722
+ case "unsupported_protocol_version": {
1723
+ const currentVersionText = data.currentBridgeProtocolVersion ? `${data.currentBridgeProtocolVersion} ` : "";
1724
+ const minVersionText = data.minBridgeProtocolVersion ? ` Minimum supported version is ${data.minBridgeProtocolVersion}.` : "";
1725
+ return {
1726
+ code: reason,
1727
+ message: `Sandbox bridge protocol version ${currentVersionText}is not supported.${minVersionText}`,
1728
+ // The sandbox must be updated to a supported protocol version.
1729
+ isRetryable: false
1730
+ };
1731
+ }
1732
+ case "init_timeout":
1733
+ return {
1734
+ code: reason,
1735
+ message: "Host dependencies did not finish loading before the timeout.",
1736
+ isRetryable: true
1737
+ };
1738
+ case "context_unavailable":
1739
+ return {
1740
+ code: reason,
1741
+ message: "Host page context is unavailable.",
1742
+ isRetryable: true
1743
+ };
1744
+ case "current_user_unavailable":
1745
+ return {
1746
+ code: reason,
1747
+ message: "Current user is unavailable.",
1748
+ isRetryable: true
1749
+ };
1750
+ case "initial_state_timeout":
1751
+ return {
1752
+ code: reason,
1753
+ message: "Host did not prepare initial state before the timeout.",
1754
+ isRetryable: true
1755
+ };
1756
+ case "missing_data_source_binding":
1757
+ return {
1758
+ code: reason,
1759
+ message: "A required data source is not mapped.",
1760
+ // Host configuration must be changed before this block can initialize.
1761
+ isRetryable: false
1762
+ };
1763
+ case "data_source_unavailable":
1764
+ return {
1765
+ code: reason,
1766
+ message: "A mapped data source is unavailable.",
1767
+ // This error combines some retryable errors (e.g. data source failed to load) with
1768
+ // some non-retryable errors (e.g. data source does not exist or user does not have
1769
+ // access). Fallback to assuming the error is retryable.
1770
+ isRetryable: true
1771
+ };
1772
+ case "missing_property_binding":
1773
+ return {
1774
+ code: reason,
1775
+ message: "A required data source property is not mapped.",
1776
+ // Host configuration must be changed before this block can initialize.
1777
+ isRetryable: false
1778
+ };
1779
+ case "invalid_property_binding":
1780
+ return {
1781
+ code: reason,
1782
+ message: "A mapped data source property is missing or incompatible.",
1783
+ // The bound property's schema must be updated or the binding must be updated to
1784
+ // a property with a compatible schema.
1785
+ isRetryable: false
1786
+ };
1787
+ case "no_init_result":
1788
+ return {
1789
+ code: reason,
1790
+ message: "Sandbox did not acknowledge initialization.",
1791
+ isRetryable: true
1792
+ };
1793
+ case "invalid_init_result_payload":
1794
+ return {
1795
+ code: reason,
1796
+ message: "Sandbox sent an invalid initialization result.",
1797
+ isRetryable: false
1798
+ };
1799
+ case "invalid_init_bindings":
1800
+ return {
1801
+ code: reason,
1802
+ message: "Sandbox rejected the host-provided data source bindings.",
1803
+ isRetryable: false
1804
+ };
1805
+ case "not_in_iframe":
1806
+ return {
1807
+ code: reason,
1808
+ message: "<NotionCustomBlock> only works inside an iframe.",
1809
+ // The block must be embedded in an iframe.
1810
+ isRetryable: false
1811
+ };
1812
+ case "unknown_error":
1813
+ return {
1814
+ code: reason,
1815
+ message: UNKNOWN_ERROR_MESSAGE,
1816
+ // Treat unknown errors as non-retryable.
1817
+ isRetryable: false
1818
+ };
1819
+ default:
1820
+ console.warn(`Unexpected custom block init error: ${reason}`);
1821
+ return {
1822
+ code: reason,
1823
+ message: UNKNOWN_ERROR_MESSAGE,
1824
+ // Treat unknown error codes as non-retryable.
1825
+ isRetryable: false
1826
+ };
1827
+ }
1828
+ }
1829
+
1830
+ // host/src/utils.ts
1831
+ function unreachable(value) {
1832
+ throw new Error(
1833
+ `[custom-blocks-host] Unexpected value encountered: ${JSON.stringify(value)}`
1834
+ );
1835
+ }
1836
+
1837
+ // host/src/lifecycle/protocolVersion.ts
1838
+ function isValidBridgeProtocolVersion(version) {
1839
+ return Number.isFinite(version) && Number.isInteger(version) && version >= 1;
1840
+ }
1841
+
1842
+ // host/src/lifecycle/initializationController.ts
1843
+ var DEFAULT_NO_CONNECT_TIMEOUT_MS = 5e3;
1844
+ var DEFAULT_INITIAL_STATE_TIMEOUT_MS = 5e3;
1845
+ var DEFAULT_NO_INIT_RESULT_TIMEOUT_MS = 5e3;
1846
+ function createInitializationController(options) {
1847
+ const {
1848
+ prepareInit,
1849
+ sendInitMessage,
1850
+ warn,
1851
+ flushPendingHostStateChanges,
1852
+ minBridgeProtocolVersion,
1853
+ noConnectTimeoutMs = DEFAULT_NO_CONNECT_TIMEOUT_MS,
1854
+ initialStateTimeoutMs = DEFAULT_INITIAL_STATE_TIMEOUT_MS,
1855
+ noInitResultTimeoutMs = DEFAULT_NO_INIT_RESULT_TIMEOUT_MS,
1856
+ stopHostWithFailure,
1857
+ onInitResult,
1858
+ onConnectionFailure
1859
+ } = options;
1860
+ let initStatus = "waitingForConnect";
1861
+ let noConnectTimeoutId;
1862
+ let initialStateTimeoutId;
1863
+ let noInitResultTimeoutId;
1864
+ let activeInitializationId;
1865
+ let hasObservedIframeLoad = false;
1866
+ let hasConnectedSandbox = false;
1867
+ function clearNoConnectTimeout() {
1868
+ if (noConnectTimeoutId !== void 0) {
1869
+ window.clearTimeout(noConnectTimeoutId);
1870
+ noConnectTimeoutId = void 0;
1871
+ }
1872
+ }
1873
+ function clearInitialStateTimeout() {
1874
+ if (initialStateTimeoutId !== void 0) {
1875
+ window.clearTimeout(initialStateTimeoutId);
1876
+ initialStateTimeoutId = void 0;
1877
+ }
1878
+ }
1879
+ function clearNoInitResultTimeout() {
1880
+ if (noInitResultTimeoutId !== void 0) {
1881
+ window.clearTimeout(noInitResultTimeoutId);
1882
+ noInitResultTimeoutId = void 0;
1883
+ }
1884
+ }
1885
+ function sendInitError(args) {
1886
+ const { initializationId, error } = args;
1887
+ switch (initStatus) {
1888
+ case "waitingForConnect":
1889
+ case "preparingInit":
1890
+ break;
1891
+ case "waitingForInitResult":
1892
+ case "initialized":
1893
+ case "error":
1894
+ case "stopped":
1895
+ return;
1896
+ default:
1897
+ return unreachable(initStatus);
1898
+ }
1899
+ initStatus = "error";
1900
+ activeInitializationId = initializationId;
1901
+ clearNoConnectTimeout();
1902
+ clearInitialStateTimeout();
1903
+ sendInitMessage({
1904
+ type: "init",
1905
+ initializationId,
1906
+ status: "error",
1907
+ error
1908
+ });
1909
+ onConnectionFailure?.(error);
1910
+ }
1911
+ async function prepareAndSendInit(connect) {
1912
+ if (initStatus !== "waitingForConnect") {
1913
+ return;
1914
+ }
1915
+ initStatus = "preparingInit";
1916
+ activeInitializationId = connect.initializationId;
1917
+ clearNoConnectTimeout();
1918
+ initialStateTimeoutId = window.setTimeout(() => {
1919
+ if (initStatus !== "preparingInit") {
1920
+ return;
1921
+ }
1922
+ const error = initErrorForFailureReason("initial_state_timeout");
1923
+ warn({
1924
+ ...error,
1925
+ initializationId: connect.initializationId
1926
+ });
1927
+ sendInitError({ initializationId: connect.initializationId, error });
1928
+ }, initialStateTimeoutMs);
1929
+ try {
1930
+ const preparation = await prepareInit(connect);
1931
+ if (initStatus !== "preparingInit") {
1932
+ return;
1933
+ }
1934
+ clearInitialStateTimeout();
1935
+ if (preparation.status === "error") {
1936
+ sendInitError({
1937
+ initializationId: connect.initializationId,
1938
+ error: preparation.error
1939
+ });
1940
+ return;
1941
+ }
1942
+ initStatus = "waitingForInitResult";
1943
+ const message = {
1944
+ type: "init",
1945
+ initializationId: connect.initializationId,
1946
+ status: "success",
1947
+ theme: preparation.initialState.theme,
1948
+ contrastMode: preparation.initialState.contrastMode ?? DEFAULT_CONTRAST_MODE,
1949
+ blockId: preparation.initialState.blockId,
1950
+ parent: preparation.initialState.parent,
1951
+ page: preparation.initialState.page,
1952
+ currentUser: preparation.initialState.currentUser,
1953
+ manifest: preparation.initialState.manifest,
1954
+ dataSources: preparation.initialState.dataSources
1955
+ };
1956
+ sendInitMessage(message);
1957
+ noInitResultTimeoutId = window.setTimeout(() => {
1958
+ if (initStatus !== "waitingForInitResult") {
1959
+ return;
1960
+ }
1961
+ initStatus = "error";
1962
+ const error = initErrorForFailureReason("no_init_result");
1963
+ onConnectionFailure?.(error);
1964
+ warn({
1965
+ ...error,
1966
+ initializationId: connect.initializationId
1967
+ });
1968
+ }, noInitResultTimeoutMs);
1969
+ } catch (error) {
1970
+ if (initStatus !== "preparingInit") {
1971
+ return;
1972
+ }
1973
+ warn({
1974
+ message: "Failed to prepare custom block initialization",
1975
+ error
1976
+ });
1977
+ sendInitError({
1978
+ initializationId: connect.initializationId,
1979
+ error: initErrorForFailureReason("unknown_error")
1980
+ });
1981
+ }
1982
+ }
1983
+ function handleConnect(message) {
1984
+ if (initStatus === "stopped") {
1985
+ return;
1986
+ }
1987
+ if (initStatus !== "waitingForConnect") {
1988
+ return;
1989
+ }
1990
+ if (!isValidBridgeProtocolVersion(message.bridgeProtocolVersion)) {
1991
+ const initError = initErrorForFailureReason("invalid_protocol_version", {
1992
+ currentBridgeProtocolVersion: message.bridgeProtocolVersion
1993
+ });
1994
+ sendInitError({
1995
+ initializationId: message.initializationId,
1996
+ error: initError
1997
+ });
1998
+ return;
1999
+ }
2000
+ if (message.bridgeProtocolVersion < minBridgeProtocolVersion) {
2001
+ const initError = initErrorForFailureReason(
2002
+ "unsupported_protocol_version",
2003
+ {
2004
+ currentBridgeProtocolVersion: message.bridgeProtocolVersion,
2005
+ minBridgeProtocolVersion
2006
+ }
2007
+ );
2008
+ sendInitError({
2009
+ initializationId: message.initializationId,
2010
+ error: initError
2011
+ });
2012
+ return;
2013
+ }
2014
+ if (message.status === "error") {
2015
+ sendInitError({
2016
+ initializationId: message.initializationId,
2017
+ error: message.error
2018
+ });
2019
+ return;
2020
+ }
2021
+ hasConnectedSandbox = true;
2022
+ void prepareAndSendInit(message);
2023
+ }
2024
+ function handleInvalidConnect(args) {
2025
+ if (initStatus === "stopped") {
2026
+ return "handled";
2027
+ }
2028
+ if (initStatus !== "waitingForConnect") {
2029
+ return "handled";
2030
+ }
2031
+ const { initializationId, bridgeProtocolVersion } = args;
2032
+ if (initializationId === void 0) {
2033
+ return "nack";
2034
+ }
2035
+ let error = args.error;
2036
+ if (bridgeProtocolVersion !== void 0) {
2037
+ if (!isValidBridgeProtocolVersion(bridgeProtocolVersion)) {
2038
+ error = initErrorForFailureReason("invalid_protocol_version");
2039
+ } else if (bridgeProtocolVersion < minBridgeProtocolVersion) {
2040
+ error = initErrorForFailureReason("unsupported_protocol_version", {
2041
+ currentBridgeProtocolVersion: bridgeProtocolVersion,
2042
+ minBridgeProtocolVersion
2043
+ });
2044
+ }
2045
+ }
2046
+ sendInitError({ initializationId, error });
2047
+ return "handled";
2048
+ }
2049
+ function handleInvalidInitResult(args) {
2050
+ const { initializationId, error } = args;
2051
+ if (initStatus !== "waitingForInitResult" || initializationId === void 0 || initializationId !== activeInitializationId) {
2052
+ return;
2053
+ }
2054
+ clearNoConnectTimeout();
2055
+ clearNoInitResultTimeout();
2056
+ initStatus = "error";
2057
+ warn(error);
2058
+ onConnectionFailure?.(error);
2059
+ }
2060
+ function onIframeLoad() {
2061
+ if (initStatus === "stopped") {
2062
+ return;
2063
+ }
2064
+ if (hasObservedIframeLoad) {
2065
+ stopHostWithFailure({
2066
+ code: "iframe_reloaded",
2067
+ message: "The iframe reloaded. Create a new host and iframe to reconnect.",
2068
+ isRetryable: true
2069
+ });
2070
+ return;
2071
+ }
2072
+ hasObservedIframeLoad = true;
2073
+ clearNoConnectTimeout();
2074
+ if (initStatus !== "waitingForConnect") {
2075
+ return;
2076
+ }
2077
+ noConnectTimeoutId = window.setTimeout(() => {
2078
+ if (initStatus !== "waitingForConnect") {
2079
+ return;
2080
+ }
2081
+ initStatus = "error";
2082
+ const error = initErrorForFailureReason("no_connect");
2083
+ warn(error);
2084
+ onConnectionFailure?.(error);
2085
+ }, noConnectTimeoutMs);
2086
+ }
2087
+ function handleInitResult(message) {
2088
+ if (initStatus !== "waitingForInitResult" || message.initializationId !== activeInitializationId) {
2089
+ warn({
2090
+ message: "Ignored stale or unexpected initResult",
2091
+ payload: message
2092
+ });
2093
+ return;
2094
+ }
2095
+ clearNoInitResultTimeout();
2096
+ initStatus = message.status === "success" ? "initialized" : "error";
2097
+ if (message.status === "success") {
2098
+ flushPendingHostStateChanges();
2099
+ } else {
2100
+ onConnectionFailure?.(message.error);
2101
+ }
2102
+ onInitResult?.(message);
2103
+ }
2104
+ function stop() {
2105
+ initStatus = "stopped";
2106
+ clearNoConnectTimeout();
2107
+ clearInitialStateTimeout();
2108
+ clearNoInitResultTimeout();
2109
+ }
2110
+ return {
2111
+ get status() {
2112
+ return initStatus;
2113
+ },
2114
+ get hasConnectedSandbox() {
2115
+ return hasConnectedSandbox;
2116
+ },
2117
+ handleConnect,
2118
+ handleInitResult,
2119
+ handleInvalidConnect,
2120
+ handleInvalidInitResult,
2121
+ onIframeLoad,
2122
+ stop
2123
+ };
2124
+ }
2125
+
2126
+ // host/src/lifecycle/normalizeHostToSandboxMessage.ts
2127
+ function normalizeHostToSandboxMessage(message, bridgeProtocolVersion) {
2128
+ if (bridgeProtocolVersion >= 5) {
2129
+ return message;
2130
+ }
2131
+ const containsDataSources = message.type === "init" && message.status === "success" || message.type === "dataSourcesChanged";
2132
+ if (!containsDataSources) {
2133
+ return message;
2134
+ }
2135
+ return {
2136
+ ...message,
2137
+ dataSources: {
2138
+ bindings: Object.fromEntries(
2139
+ Object.entries(message.dataSources.bindings).map(([key, binding]) => [
2140
+ key,
2141
+ {
2142
+ ...binding,
2143
+ collectionSchema: {
2144
+ ...binding.collectionSchema,
2145
+ propertiesById: {
2146
+ ...binding.collectionSchema?.propertiesById,
2147
+ ...NOTION_BUILTIN_PROPERTY_SCHEMAS
2148
+ }
2149
+ }
2150
+ }
2151
+ ])
2152
+ )
2153
+ }
2154
+ };
2155
+ }
2156
+
2157
+ // host/src/lifecycle/types.ts
2158
+ var customBlockHostInitialStateSchema = object({
2159
+ theme: notionThemeSchema,
2160
+ /**
2161
+ * Defaults to standard for existing host integrations.
2162
+ * TODO(custom-blocks): Make this required when MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION increases to 4.
2163
+ */
2164
+ contrastMode: optional(notionContrastModeSchema),
2165
+ blockId: notionBlockIdSchema,
2166
+ parent: notionParentSchema,
2167
+ page: customBlockPageSchema,
2168
+ manifest: manifestSchema,
2169
+ dataSources: object({ bindings: notionDataSourceBindingsSchema }),
2170
+ currentUser: notionUserSchema
2171
+ });
2172
+
2173
+ // protocol/src/messages/isInitHandshakeMessage.ts
2174
+ function isInitHandshakeMessage(message) {
2175
+ switch (message.type) {
2176
+ case "connect":
2177
+ case "init":
2178
+ case "initResult":
2179
+ return true;
2180
+ default:
2181
+ return false;
2182
+ }
2183
+ }
2184
+
2185
+ // protocol/src/errors.ts
2186
+ var customBlockErrorInfoSchema = object({
2187
+ code: string(),
2188
+ message: string(),
2189
+ isRetryable: boolean()
2190
+ });
2191
+
2192
+ // protocol/src/messages/connect.ts
2193
+ var connectMessageCommonEntries = {
2194
+ type: literal("connect"),
2195
+ initializationId: string(),
2196
+ /**
2197
+ * The bridge protocol version this sandbox uses to communicate with its host.
2198
+ * Hosts control which versions they support and can support multiple versions
2199
+ * at the same time. Support for older versions is eventually removed, so blocks
2200
+ * may need to update their SDK to continue working.
2201
+ */
2202
+ bridgeProtocolVersion: number(),
2203
+ /**
2204
+ * Semver version of the SDK package that sent this connect message. Should only be used for
2205
+ * analytics purposes. Business logic should compare against `bridgeProtocolVersion` instead.
2206
+ */
2207
+ sdkVersion: string()
2208
+ };
2209
+ var connectMessageSchema = variant("status", [
2210
+ object({
2211
+ status: literal("success"),
2212
+ /**
2213
+ * The data sources and settings the custom block expects. Hosts may omit
2214
+ * this when they already have an authoritative manifest.
2215
+ */
2216
+ manifest: optional(manifestSchema),
2217
+ ...connectMessageCommonEntries
2218
+ }),
2219
+ object({
2220
+ status: literal("error"),
2221
+ error: customBlockErrorInfoSchema,
2222
+ ...connectMessageCommonEntries
2223
+ })
2224
+ ]);
2225
+
2226
+ // protocol/src/messages/createPage.ts
2227
+ var notionCreatePagePositionSchema = variant("type", [
2228
+ object({ type: literal("start") }),
2229
+ object({ type: literal("end") }),
2230
+ object({ type: literal("before"), blockId: notionBlockIdSchema }),
2231
+ object({ type: literal("after"), blockId: notionBlockIdSchema })
2232
+ ]);
2233
+ var createPageParentSchema = variant("type", [
2234
+ object({ type: literal("page_id"), page_id: notionPageIdSchema }),
2235
+ object({
2236
+ type: literal("data_source_id"),
2237
+ data_source_id: notionDataSourceIdSchema
2238
+ })
2239
+ ]);
2240
+ var createPageMessageSchema = object({
2241
+ type: literal("createPage"),
2242
+ requestId: string(),
2243
+ parent: createPageParentSchema,
2244
+ /**
2245
+ * Property values, keyed by raw property IDs from Notion.
2246
+ *
2247
+ * Each value must carry the same raw property ID in its `id` field.
2248
+ * To create a page with manifest-defined property keys, call `pages.create`. The SDK resolves
2249
+ * those keys before it sends this message.
2250
+ */
2251
+ properties: notionPagePropertyWriteMapSchema,
2252
+ position: optional(notionCreatePagePositionSchema)
2253
+ });
2254
+
2255
+ // protocol/src/messages/initResult.ts
2256
+ var customBlockInitResultErrorCodeSchema = string();
2257
+ var customBlockInitResultErrorInfoSchema = object({
2258
+ code: customBlockInitResultErrorCodeSchema,
2259
+ message: string(),
2260
+ isRetryable: boolean()
2261
+ });
2262
+ var initResultMessageSchema = variant("status", [
2263
+ object({
2264
+ type: literal("initResult"),
2265
+ initializationId: string(),
2266
+ status: literal("success"),
2267
+ /** Height of the initial rendered custom-block content, in CSS pixels. */
2268
+ // Older SDKs can omit the height. Current SDKs always send it.
2269
+ // TODO(custom-blocks): Make this required when MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION increases to 4.
2270
+ initialHeight: optional(pipe(number(), finite(), minValue(0)))
2271
+ }),
2272
+ object({
2273
+ type: literal("initResult"),
2274
+ initializationId: string(),
2275
+ status: literal("error"),
2276
+ error: customBlockInitResultErrorInfoSchema
2277
+ })
2278
+ ]);
2279
+
2280
+ // protocol/src/messages/invalidHostMessage.ts
2281
+ var invalidHostMessageSchema = object({
2282
+ type: literal("invalidHostMessage"),
2283
+ /**
2284
+ * A human-readable string intended for sandbox-side logging. It has no structured contract.
2285
+ */
2286
+ reason: string()
2287
+ });
2288
+
2289
+ // protocol/src/messages/queryDataSource.ts
2290
+ var emptyOperatorSchema = union([
2291
+ strictObject({ is_empty: literal(true) }),
2292
+ strictObject({ is_not_empty: literal(true) })
2293
+ ]);
2294
+ var stringOrStringArraySchema = union([string(), array(string())]);
2295
+ var customBlockPersonFilterValueSchema = strictObject({
2296
+ object: picklist(["user", "group"]),
2297
+ id: pipe(string(), minLength(1))
2298
+ });
2299
+ var customBlockPeopleFilterOperatorSchema = union([
2300
+ strictObject({ contains: customBlockPersonFilterValueSchema }),
2301
+ strictObject({ does_not_contain: customBlockPersonFilterValueSchema }),
2302
+ emptyOperatorSchema
2303
+ ]);
2304
+ var customBlockCreatorFilterValueSchema = strictObject({
2305
+ object: literal("user"),
2306
+ id: pipe(string(), minLength(1), maxLength(2e3))
2307
+ });
2308
+ var customBlockCreatedByFilterOperatorSchema = union([
2309
+ strictObject({ contains: customBlockCreatorFilterValueSchema }),
2310
+ strictObject({ does_not_contain: customBlockCreatorFilterValueSchema }),
2311
+ strictObject({ is_empty: literal(true) }),
2312
+ strictObject({ is_not_empty: literal(true) })
2313
+ ]);
2314
+ var customBlockTextFilterOperatorSchema = union([
2315
+ strictObject({ equals: string() }),
2316
+ strictObject({ does_not_equal: string() }),
2317
+ strictObject({ contains: string() }),
2318
+ strictObject({ does_not_contain: string() }),
2319
+ strictObject({ starts_with: string() }),
2320
+ strictObject({ ends_with: string() }),
2321
+ emptyOperatorSchema
2322
+ ]);
2323
+ var customBlockNumberFilterOperatorSchema = union([
2324
+ strictObject({ equals: number() }),
2325
+ strictObject({ does_not_equal: number() }),
2326
+ strictObject({ greater_than: number() }),
2327
+ strictObject({ less_than: number() }),
2328
+ strictObject({ greater_than_or_equal_to: number() }),
2329
+ strictObject({ less_than_or_equal_to: number() }),
2330
+ emptyOperatorSchema
2331
+ ]);
2332
+ var customBlockCheckboxFilterOperatorSchema = union([
2333
+ strictObject({ equals: boolean() }),
2334
+ strictObject({ does_not_equal: boolean() })
2335
+ ]);
2336
+ var customBlockOptionFilterOperatorSchema = union([
2337
+ strictObject({ equals: stringOrStringArraySchema }),
2338
+ strictObject({ does_not_equal: stringOrStringArraySchema }),
2339
+ emptyOperatorSchema
2340
+ ]);
2341
+ var customBlockStatusGroupNameSchema = picklist([
2342
+ "To-do",
2343
+ "In progress",
2344
+ "Complete",
2345
+ "Current",
2346
+ "Future"
2347
+ ]);
2348
+ var customBlockStatusGroupFilterValueSchema = union([
2349
+ customBlockStatusGroupNameSchema,
2350
+ pipe(
2351
+ array(customBlockStatusGroupNameSchema),
2352
+ minLength(1),
2353
+ maxLength(5)
2354
+ )
2355
+ ]);
2356
+ var customBlockStatusGroupFilterOperatorSchema = union([
2357
+ strictObject({ group_equals: customBlockStatusGroupFilterValueSchema }),
2358
+ strictObject({
2359
+ group_does_not_equal: customBlockStatusGroupFilterValueSchema
2360
+ })
2361
+ ]);
2362
+ var customBlockStatusFilterOperatorSchema = union([
2363
+ customBlockOptionFilterOperatorSchema,
2364
+ customBlockStatusGroupFilterOperatorSchema
2365
+ ]);
2366
+ var customBlockContainsFilterOperatorSchema = union([
2367
+ strictObject({ contains: stringOrStringArraySchema }),
2368
+ strictObject({ contains_all: stringOrStringArraySchema }),
2369
+ strictObject({ does_not_contain: stringOrStringArraySchema }),
2370
+ emptyOperatorSchema
2371
+ ]);
2372
+ var dateTargetSchema = picklist(["start_date", "end_date"]);
2373
+ var customBlockRelativeDateValueSchema = picklist([
2374
+ "today",
2375
+ "tomorrow",
2376
+ "yesterday",
2377
+ "one_week_ago",
2378
+ "one_week_from_now",
2379
+ "one_month_ago",
2380
+ "one_month_from_now"
2381
+ ]);
2382
+ var dateComparisonValueSchema = union([
2383
+ customBlockRelativeDateValueSchema,
2384
+ string()
2385
+ ]);
2386
+ var customBlockDateFilterOperatorSchema = union([
2387
+ strictObject({
2388
+ target: optional(dateTargetSchema),
2389
+ equals: dateComparisonValueSchema
2390
+ }),
2391
+ strictObject({
2392
+ target: optional(dateTargetSchema),
2393
+ before: dateComparisonValueSchema
2394
+ }),
2395
+ strictObject({
2396
+ target: optional(dateTargetSchema),
2397
+ after: dateComparisonValueSchema
2398
+ }),
2399
+ strictObject({
2400
+ target: optional(dateTargetSchema),
2401
+ on_or_before: dateComparisonValueSchema
2402
+ }),
2403
+ strictObject({
2404
+ target: optional(dateTargetSchema),
2405
+ on_or_after: dateComparisonValueSchema
2406
+ }),
2407
+ strictObject({
2408
+ target: optional(dateTargetSchema),
2409
+ this_week: strictObject({})
2410
+ }),
2411
+ strictObject({
2412
+ target: optional(dateTargetSchema),
2413
+ past_week: strictObject({})
2414
+ }),
2415
+ strictObject({
2416
+ target: optional(dateTargetSchema),
2417
+ past_month: strictObject({})
2418
+ }),
2419
+ strictObject({
2420
+ target: optional(dateTargetSchema),
2421
+ past_year: strictObject({})
2422
+ }),
2423
+ strictObject({
2424
+ target: optional(dateTargetSchema),
2425
+ next_week: strictObject({})
2426
+ }),
2427
+ strictObject({
2428
+ target: optional(dateTargetSchema),
2429
+ next_month: strictObject({})
2430
+ }),
2431
+ strictObject({
2432
+ target: optional(dateTargetSchema),
2433
+ next_year: strictObject({})
2434
+ }),
2435
+ strictObject({
2436
+ target: optional(dateTargetSchema),
2437
+ is_empty: literal(true)
2438
+ }),
2439
+ strictObject({
2440
+ target: optional(dateTargetSchema),
2441
+ is_not_empty: literal(true)
2442
+ })
2443
+ ]);
2444
+ var resolvedCustomBlockDataSourcePropertyFilterSchema = union([
2445
+ strictObject({
2446
+ propertyId: string(),
2447
+ created_by: customBlockCreatedByFilterOperatorSchema
2448
+ }),
2449
+ strictObject({
2450
+ propertyId: string(),
2451
+ title: customBlockTextFilterOperatorSchema
2452
+ }),
2453
+ strictObject({
2454
+ propertyId: string(),
2455
+ rich_text: customBlockTextFilterOperatorSchema
2456
+ }),
2457
+ strictObject({
2458
+ propertyId: string(),
2459
+ url: customBlockTextFilterOperatorSchema
2460
+ }),
2461
+ strictObject({
2462
+ propertyId: string(),
2463
+ email: customBlockTextFilterOperatorSchema
2464
+ }),
2465
+ strictObject({
2466
+ propertyId: string(),
2467
+ phone_number: customBlockTextFilterOperatorSchema
2468
+ }),
2469
+ strictObject({
2470
+ propertyId: string(),
2471
+ number: customBlockNumberFilterOperatorSchema
2472
+ }),
2473
+ strictObject({
2474
+ propertyId: string(),
2475
+ checkbox: customBlockCheckboxFilterOperatorSchema
2476
+ }),
2477
+ strictObject({
2478
+ propertyId: string(),
2479
+ select: customBlockOptionFilterOperatorSchema
2480
+ }),
2481
+ strictObject({
2482
+ propertyId: string(),
2483
+ multi_select: customBlockContainsFilterOperatorSchema
2484
+ }),
2485
+ strictObject({
2486
+ propertyId: string(),
2487
+ status: customBlockStatusFilterOperatorSchema
2488
+ }),
2489
+ strictObject({
2490
+ propertyId: string(),
2491
+ date: customBlockDateFilterOperatorSchema
2492
+ }),
2493
+ strictObject({
2494
+ propertyId: string(),
2495
+ people: customBlockPeopleFilterOperatorSchema
2496
+ })
2497
+ ]);
2498
+ var resolvedCustomBlockDataSourceFilterSchema = union([
2499
+ resolvedCustomBlockDataSourcePropertyFilterSchema,
2500
+ strictObject({
2501
+ and: array(resolvedCustomBlockDataSourcePropertyFilterSchema)
2502
+ })
2503
+ ]);
2504
+ var CUSTOM_BLOCK_DATA_SOURCE_QUERY_MAX_SORTS = 10;
2505
+ var resolvedCustomBlockDataSourceSortSchema = strictObject({
2506
+ propertyId: string(),
2507
+ direction: picklist(["ascending", "descending"])
2508
+ });
2509
+ var queryDataSourceMessageSchema = object({
2510
+ type: literal("queryDataSource"),
2511
+ /** Stable for the lifetime of this query subscription. */
2512
+ subscriptionId: string(),
2513
+ /** The raw Notion data source ID to read from. */
2514
+ dataSourceId: notionDataSourceIdSchema,
2515
+ /** The number of items to return in each subscription update. */
2516
+ limit: number(),
2517
+ /** A sandbox-resolved property filter. */
2518
+ filter: optional(resolvedCustomBlockDataSourceFilterSchema),
2519
+ /** Sandbox-resolved property sorts, in priority order. */
2520
+ sorts: optional(array(resolvedCustomBlockDataSourceSortSchema))
2521
+ });
2522
+
2523
+ // protocol/src/messages/resize.ts
2524
+ var resizeMessageSchema = object({
2525
+ type: literal("resize"),
2526
+ height: pipe(number(), finite(), minValue(0))
2527
+ });
2528
+
2529
+ // protocol/src/messages/unsubscribeDataSourceQuery.ts
2530
+ var unsubscribeDataSourceQueryMessageSchema = object({
2531
+ type: literal("unsubscribeDataSourceQuery"),
2532
+ /** The subscription to remove from the host. */
2533
+ subscriptionId: string()
2534
+ });
2535
+
2536
+ // protocol/src/messages/updatePage.ts
2537
+ var updatePageMessageSchema = object({
2538
+ type: literal("updatePage"),
2539
+ requestId: string(),
2540
+ pageId: notionPageIdSchema,
2541
+ /**
2542
+ * Property values, keyed by raw property IDs from Notion.
2543
+ *
2544
+ * Each value must carry the same raw property ID in its `id` field.
2545
+ * To update a page with manifest-defined property keys, call `row.update()` on a row returned
2546
+ * by `useDataSource()`. The SDK resolves those keys before it sends this message.
2547
+ */
2548
+ properties: optional(notionPagePropertyWriteMapSchema),
2549
+ icon: optional(notionPageIconSchema),
2550
+ cover: optional(notionPageCoverSchema),
2551
+ archived: optional(boolean())
2552
+ });
2553
+
2554
+ // protocol/src/messages/sandboxToHost.ts
2555
+ var sandboxToHostMessageSchema = variant("type", [
2556
+ connectMessageSchema,
2557
+ initResultMessageSchema,
2558
+ queryDataSourceMessageSchema,
2559
+ unsubscribeDataSourceQueryMessageSchema,
2560
+ createPageMessageSchema,
2561
+ getPageMessageSchema,
2562
+ getUserMessageSchema,
2563
+ listUsersMessageSchema,
2564
+ openPageMessageSchema,
2565
+ updatePageMessageSchema,
2566
+ resizeMessageSchema,
2567
+ invalidHostMessageSchema
2568
+ ]);
2569
+
2570
+ // protocol/src/messages/incomingType.ts
2571
+ function readIncomingType(data) {
2572
+ if (typeof data === "object" && data !== null && "type" in data && typeof data.type === "string") {
2573
+ return data.type;
2574
+ }
2575
+ return void 0;
2576
+ }
2577
+
2578
+ // host/src/messages/invalidSandboxMessage.ts
2579
+ function getInvalidSandboxMessageResponse(data) {
2580
+ const incomingType = readIncomingType(data);
2581
+ if (incomingType === "invalidHostMessage" || incomingType === "invalidSandboxMessage") {
2582
+ return { incomingType };
2583
+ }
2584
+ return {
2585
+ incomingType,
2586
+ nack: {
2587
+ type: "invalidSandboxMessage",
2588
+ reason: nackReasonForInvalidSandboxMessage(incomingType)
2589
+ }
2590
+ };
2591
+ }
2592
+ function nackReasonForInvalidSandboxMessage(incomingType) {
2593
+ if (incomingType !== void 0) {
2594
+ return `Unsupported sandbox message of type "${incomingType}"`;
2595
+ }
2596
+ return "Unsupported sandbox message (no `type` field or non-object payload)";
2597
+ }
2598
+
2599
+ // host/src/messages/sandboxMessageRouter.ts
2600
+ var initializationIdentitySchema = object({
2601
+ initializationId: string()
2602
+ });
2603
+ var bridgeProtocolVersionSchema = object({
2604
+ // NaN is not a valid protocol version. Keep it in this parser so the host can
2605
+ // report `invalid_protocol_version`.
2606
+ bridgeProtocolVersion: union([number(), nan()])
2607
+ });
2608
+ function createSandboxMessageRouter(options) {
2609
+ const {
2610
+ iframe,
2611
+ sandboxOrigin,
2612
+ getInitStatus,
2613
+ emit,
2614
+ sendNack,
2615
+ onInvalidConnect,
2616
+ onInvalidInitResult,
2617
+ onConnect,
2618
+ onInitResult,
2619
+ onQueryDataSource,
2620
+ onUnsubscribeDataSourceQuery,
2621
+ onCreatePage,
2622
+ onGetPage,
2623
+ onOpenPage,
2624
+ onGetUser,
2625
+ onListUsers,
2626
+ onUpdatePage,
2627
+ onResize
2628
+ } = options;
2629
+ function onInvalidSandboxMessage(data, issues) {
2630
+ emit("warn", {
2631
+ message: "Ignored unsupported sandbox message",
2632
+ payload: data,
2633
+ issues
2634
+ });
2635
+ const response = getInvalidSandboxMessageResponse(data);
2636
+ if (response.incomingType === "connect") {
2637
+ const parsedIdentity = safeParse(initializationIdentitySchema, data);
2638
+ const parsedVersion = safeParse(bridgeProtocolVersionSchema, data);
2639
+ const responseType = onInvalidConnect({
2640
+ initializationId: parsedIdentity.success ? parsedIdentity.output.initializationId : void 0,
2641
+ error: initErrorForFailureReason("invalid_connect_payload"),
2642
+ bridgeProtocolVersion: parsedVersion.success ? parsedVersion.output.bridgeProtocolVersion : void 0
2643
+ });
2644
+ if (responseType === "handled") {
2645
+ return;
2646
+ }
2647
+ }
2648
+ if (response.incomingType === "initResult") {
2649
+ const parsedIdentity = safeParse(initializationIdentitySchema, data);
2650
+ onInvalidInitResult({
2651
+ initializationId: parsedIdentity.success ? parsedIdentity.output.initializationId : void 0,
2652
+ error: initErrorForFailureReason("invalid_init_result_payload")
2653
+ });
2654
+ }
2655
+ if (response.nack !== void 0 && getInitStatus() !== "stopped") {
2656
+ sendNack(response.nack);
2657
+ }
2658
+ }
2659
+ return function onMessage(event) {
2660
+ const isExpectedSource = event.source === iframe.contentWindow;
2661
+ const isExpectedOrigin = event.origin === sandboxOrigin;
2662
+ if (!isExpectedSource || !isExpectedOrigin) {
2663
+ return;
2664
+ }
2665
+ const parsed = safeParse(sandboxToHostMessageSchema, event.data);
2666
+ if (!parsed.success) {
2667
+ onInvalidSandboxMessage(event.data, parsed.issues);
2668
+ return;
2669
+ }
2670
+ const message = parsed.output;
2671
+ if (!isInitHandshakeMessage(message) && getInitStatus() !== "initialized") {
2672
+ emit("warn", {
2673
+ message: `Ignored ${message.type} before initialization completed`,
2674
+ payload: message
2675
+ });
2676
+ return;
2677
+ }
2678
+ emit("in", message);
2679
+ switch (message.type) {
2680
+ case "connect":
2681
+ onConnect(message);
2682
+ return;
2683
+ case "initResult":
2684
+ onInitResult(message);
2685
+ return;
2686
+ case "queryDataSource":
2687
+ void onQueryDataSource(message);
2688
+ return;
2689
+ case "unsubscribeDataSourceQuery":
2690
+ onUnsubscribeDataSourceQuery(message);
2691
+ return;
2692
+ case "createPage":
2693
+ void onCreatePage(message);
2694
+ return;
2695
+ case "openPage":
2696
+ void onOpenPage(message);
2697
+ return;
2698
+ case "getPage":
2699
+ void onGetPage(message);
2700
+ return;
2701
+ case "getUser":
2702
+ void onGetUser(message);
2703
+ return;
2704
+ case "listUsers":
2705
+ void onListUsers(message);
2706
+ return;
2707
+ case "updatePage":
2708
+ void onUpdatePage(message);
2709
+ return;
2710
+ case "resize":
2711
+ onResize(message);
2712
+ return;
2713
+ case "invalidHostMessage":
2714
+ return;
2715
+ default:
2716
+ unreachable(message);
2717
+ }
2718
+ };
2719
+ }
2720
+
2721
+ // host/src/protocolVersion.ts
2722
+ var MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION = 3;
2723
+
2724
+ // host/src/queries/querySubscriptions.ts
2725
+ var QuerySubscriptions = class {
2726
+ constructor(onUnsubscribe) {
2727
+ this.onUnsubscribe = onUnsubscribe;
2728
+ }
2729
+ onUnsubscribe;
2730
+ bySubscriptionId = /* @__PURE__ */ new Map();
2731
+ subscribe(message) {
2732
+ this.unsubscribe(message.subscriptionId);
2733
+ const token = {
2734
+ _tag: "QuerySubscriptionToken"
2735
+ };
2736
+ this.bySubscriptionId.set(message.subscriptionId, {
2737
+ message,
2738
+ token,
2739
+ isRefreshing: true,
2740
+ shouldRefreshAgain: false
2741
+ });
2742
+ return token;
2743
+ }
2744
+ isCurrent(subscriptionId, token) {
2745
+ return this.bySubscriptionId.get(subscriptionId)?.token === token;
2746
+ }
2747
+ unsubscribe(subscriptionId) {
2748
+ if (this.bySubscriptionId.delete(subscriptionId)) {
2749
+ this.onUnsubscribe(subscriptionId);
2750
+ }
2751
+ }
2752
+ refresh(dataSourceId) {
2753
+ const refreshes = [];
2754
+ let hasSubscriptions = false;
2755
+ for (const queryState of this.bySubscriptionId.values()) {
2756
+ if (queryState.message.dataSourceId !== dataSourceId) {
2757
+ continue;
2758
+ }
2759
+ hasSubscriptions = true;
2760
+ if (queryState.isRefreshing) {
2761
+ queryState.shouldRefreshAgain = true;
2762
+ continue;
2763
+ }
2764
+ queryState.isRefreshing = true;
2765
+ refreshes.push({
2766
+ message: queryState.message,
2767
+ token: queryState.token
2768
+ });
2769
+ }
2770
+ return hasSubscriptions ? refreshes : void 0;
2771
+ }
2772
+ finish(subscriptionId, token) {
2773
+ const state = this.bySubscriptionId.get(subscriptionId);
2774
+ if (state?.token !== token) {
2775
+ return void 0;
2776
+ }
2777
+ state.isRefreshing = false;
2778
+ if (!state.shouldRefreshAgain) {
2779
+ return void 0;
2780
+ }
2781
+ state.shouldRefreshAgain = false;
2782
+ state.isRefreshing = true;
2783
+ return { message: state.message, token: state.token };
2784
+ }
2785
+ unsubscribeAll() {
2786
+ for (const subscriptionId of this.bySubscriptionId.keys()) {
2787
+ this.unsubscribe(subscriptionId);
2788
+ }
2789
+ }
2790
+ };
2791
+
2792
+ // host/src/queries/validateQueryDataSourceFilter.ts
2793
+ function validateQueryDataSourceFilter(filter, collectionSchema) {
2794
+ if (filter === void 0) {
2795
+ return void 0;
2796
+ }
2797
+ const propertyFilters = "and" in filter ? filter.and : [filter];
2798
+ for (const propertyFilter of propertyFilters) {
2799
+ const error = validatePropertyFilter(propertyFilter, collectionSchema);
2800
+ if (error !== void 0) {
2801
+ return error;
2802
+ }
2803
+ }
2804
+ return void 0;
2805
+ }
2806
+ function validatePropertyFilter(filter, collectionSchema) {
2807
+ if (!Object.hasOwn(collectionSchema.propertiesById, filter.propertyId)) {
2808
+ return {
2809
+ code: "invalid_data_source_query_filter",
2810
+ message: `Data source query filter property ID "${filter.propertyId}" is not defined in the bound data source schema.`,
2811
+ isRetryable: false
2812
+ };
2813
+ }
2814
+ const propertySchema = collectionSchema.propertiesById[filter.propertyId];
2815
+ const branch = Object.keys(filter).find((key) => key !== "propertyId");
2816
+ if (branch !== propertySchema.type) {
2817
+ return {
2818
+ code: "invalid_data_source_query_filter",
2819
+ message: `Data source query filter branch "${branch}" does not match property type "${propertySchema.type}".`,
2820
+ isRetryable: false
2821
+ };
2822
+ }
2823
+ if ("status" in filter && propertySchema.type === "status") {
2824
+ const operator = filter.status;
2825
+ if ("group_equals" in operator || "group_does_not_equal" in operator) {
2826
+ const value = "group_equals" in operator ? operator.group_equals : operator.group_does_not_equal;
2827
+ const names = Array.isArray(value) ? value : [value];
2828
+ const unknownName = names.find(
2829
+ (name) => !propertySchema.groups.some((group) => group.name === name)
2830
+ );
2831
+ return unknownName === void 0 ? void 0 : {
2832
+ code: "invalid_data_source_query_filter",
2833
+ message: `Unknown status group "${unknownName}".`,
2834
+ isRetryable: false
2835
+ };
2836
+ }
2837
+ }
2838
+ const optionFilter = getOptionFilter(filter);
2839
+ if (optionFilter === void 0 || propertySchema.type !== optionFilter.propertyType) {
2840
+ return void 0;
2841
+ }
2842
+ const optionNames = new Set(propertySchema.options.map((option) => option.name));
2843
+ const invalidOptionName = getOptionFilterValues(optionFilter.operator).find(
2844
+ (optionName) => !optionNames.has(optionName)
2845
+ );
2846
+ if (invalidOptionName === void 0) {
2847
+ return void 0;
2848
+ }
2849
+ return {
2850
+ code: "invalid_data_source_query_filter",
2851
+ message: `Data source query filter option "${invalidOptionName}" is not defined for property "${filter.propertyId}".`,
2852
+ isRetryable: false
2853
+ };
2854
+ }
2855
+ function getOptionFilter(filter) {
2856
+ if ("select" in filter) {
2857
+ return { propertyType: "select", operator: filter.select };
2858
+ }
2859
+ if ("multi_select" in filter) {
2860
+ return { propertyType: "multi_select", operator: filter.multi_select };
2861
+ }
2862
+ if ("status" in filter) {
2863
+ const operator = filter.status;
2864
+ return "group_equals" in operator || "group_does_not_equal" in operator ? void 0 : { propertyType: "status", operator };
2865
+ }
2866
+ return void 0;
2867
+ }
2868
+ function getOptionFilterValues(operator) {
2869
+ let value;
2870
+ if ("equals" in operator) {
2871
+ value = operator.equals;
2872
+ } else if ("does_not_equal" in operator) {
2873
+ value = operator.does_not_equal;
2874
+ } else if ("contains" in operator) {
2875
+ value = operator.contains;
2876
+ } else if ("contains_all" in operator) {
2877
+ value = operator.contains_all;
2878
+ } else if ("does_not_contain" in operator) {
2879
+ value = operator.does_not_contain;
2880
+ } else if ("is_empty" in operator || "is_not_empty" in operator) {
2881
+ return [];
2882
+ } else {
2883
+ return unreachable(operator);
2884
+ }
2885
+ return Array.isArray(value) ? value : [value];
2886
+ }
2887
+
2888
+ // host/src/queries/validateQueryDataSourceSorts.ts
2889
+ var supportedDataSourceSortPropertyTypes = new Set(
2890
+ CUSTOM_BLOCK_DATA_SOURCE_SORTABLE_PROPERTY_TYPES
2891
+ );
2892
+ function validateQueryDataSourceSorts(sorts, collectionSchema) {
2893
+ if (sorts === void 0) {
2894
+ return void 0;
2895
+ }
2896
+ if (sorts.length > CUSTOM_BLOCK_DATA_SOURCE_QUERY_MAX_SORTS) {
2897
+ return {
2898
+ code: "invalid_data_source_query_sort",
2899
+ message: `Data source query sorts may contain at most ${CUSTOM_BLOCK_DATA_SOURCE_QUERY_MAX_SORTS} entries.`,
2900
+ isRetryable: false
2901
+ };
2902
+ }
2903
+ const seenPropertyIds = /* @__PURE__ */ new Set();
2904
+ for (const sort of sorts) {
2905
+ if (seenPropertyIds.has(sort.propertyId)) {
2906
+ return {
2907
+ code: "invalid_data_source_query_sort",
2908
+ message: `Data source query sorts cannot contain duplicate property ID "${sort.propertyId}".`,
2909
+ isRetryable: false
2910
+ };
2911
+ }
2912
+ seenPropertyIds.add(sort.propertyId);
2913
+ if (!Object.hasOwn(collectionSchema.propertiesById, sort.propertyId)) {
2914
+ return {
2915
+ code: "invalid_data_source_query_sort",
2916
+ message: `Data source query sort property ID "${sort.propertyId}" is not defined in the bound data source schema.`,
2917
+ isRetryable: false
2918
+ };
2919
+ }
2920
+ const propertySchema = collectionSchema.propertiesById[sort.propertyId];
2921
+ if (!supportedDataSourceSortPropertyTypes.has(propertySchema.type)) {
2922
+ return {
2923
+ code: "invalid_data_source_query_sort",
2924
+ message: `Data source query sorts do not yet support property type "${propertySchema.type}".`,
2925
+ isRetryable: false
2926
+ };
2927
+ }
2928
+ }
2929
+ return void 0;
2930
+ }
2931
+
2932
+ // host/src/createCustomBlockHost.ts
2933
+ var BRIDGE_PROTOCOL_VERSION_INTRODUCING_UNAVAILABLE_PAGE = 5;
2934
+ function createCustomBlockHost(options) {
2935
+ const {
2936
+ iframe,
2937
+ getInitialState,
2938
+ handlers,
2939
+ onManifest,
2940
+ onInitialized,
2941
+ onConnectionFailure,
2942
+ onLog,
2943
+ onQueryUnsubscribed,
2944
+ sandboxOrigin,
2945
+ minBridgeProtocolVersion: configuredMinBridgeProtocolVersion,
2946
+ noConnectTimeoutMs,
2947
+ initialStateTimeoutMs,
2948
+ noInitResultTimeoutMs
2949
+ } = options;
2950
+ const minBridgeProtocolVersion = Math.max(
2951
+ configuredMinBridgeProtocolVersion ?? MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION,
2952
+ MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION
2953
+ );
2954
+ let pendingState = {};
2955
+ let hasPreparedInitialState = false;
2956
+ let manifest;
2957
+ let activeDataSources;
2958
+ let sandboxBridgeProtocolVersion = LATEST_BRIDGE_PROTOCOL_VERSION;
2959
+ const querySubscriptions = new QuerySubscriptions((subscriptionId) => {
2960
+ onQueryUnsubscribed?.(subscriptionId);
2961
+ });
2962
+ function emit(direction, payload) {
2963
+ onLog?.(direction, payload);
2964
+ }
2965
+ function postToSandbox(message) {
2966
+ const status = initializationController.status;
2967
+ switch (status) {
2968
+ case "waitingForConnect":
2969
+ case "preparingInit":
2970
+ case "waitingForInitResult":
2971
+ case "initialized":
2972
+ case "error":
2973
+ break;
2974
+ // A stopped host must not send messages, including pending responses.
2975
+ // Return from the function to skip delivery below.
2976
+ case "stopped":
2977
+ return;
2978
+ default:
2979
+ return unreachable(status);
2980
+ }
2981
+ const sandboxMessage = normalizeHostToSandboxMessage(
2982
+ message,
2983
+ sandboxBridgeProtocolVersion
2984
+ );
2985
+ emit("out", sandboxMessage);
2986
+ iframe.contentWindow?.postMessage(sandboxMessage, sandboxOrigin);
2987
+ }
2988
+ function sendInitMessage(message) {
2989
+ postToSandbox(parse(initMessageSchema, message));
2990
+ }
2991
+ function sendNack(message) {
2992
+ postToSandbox(message);
2993
+ }
2994
+ function sendInitializedMessage(message) {
2995
+ const status = initializationController.status;
2996
+ switch (status) {
2997
+ case "initialized":
2998
+ postToSandbox(parse(hostToSandboxMessageSchema, message));
2999
+ return;
3000
+ // Send state updates and handler results only after initialization succeeds.
3001
+ case "waitingForConnect":
3002
+ case "preparingInit":
3003
+ case "waitingForInitResult":
3004
+ case "error":
3005
+ case "stopped":
3006
+ return;
3007
+ default:
3008
+ unreachable(status);
3009
+ }
3010
+ }
3011
+ async function respondToRequest(message, handler) {
3012
+ if (handler === void 0) {
3013
+ return;
3014
+ }
3015
+ const response = await handler(message);
3016
+ sendInitializedMessage({
3017
+ type: `${message.type}Result`,
3018
+ requestId: message.requestId,
3019
+ ...response
3020
+ });
3021
+ }
3022
+ function postQueryDataSourceResult(args) {
3023
+ const message = args.response.status === "error" ? {
3024
+ type: "queryDataSourceResult",
3025
+ subscriptionId: args.subscriptionId,
3026
+ status: "error",
3027
+ error: args.response.error
3028
+ } : {
3029
+ type: "queryDataSourceResult",
3030
+ subscriptionId: args.subscriptionId,
3031
+ status: "success",
3032
+ items: args.response.items,
3033
+ hasMore: args.response.hasMore
3034
+ };
3035
+ sendInitializedMessage(message);
3036
+ }
3037
+ async function handleQuery(message, token = querySubscriptions.subscribe(message)) {
3038
+ try {
3039
+ const collectionSchema = getCollectionSchema(
3040
+ activeDataSources,
3041
+ message.dataSourceId
3042
+ );
3043
+ const queryError = getQueryValidationError(message, collectionSchema);
3044
+ if (queryError !== void 0) {
3045
+ if (querySubscriptions.isCurrent(message.subscriptionId, token)) {
3046
+ querySubscriptions.unsubscribe(message.subscriptionId);
3047
+ postQueryDataSourceResult({
3048
+ subscriptionId: message.subscriptionId,
3049
+ response: { status: "error", error: queryError }
3050
+ });
3051
+ }
3052
+ return;
3053
+ }
3054
+ const response = await handlers.queryDataSource(message);
3055
+ if (!querySubscriptions.isCurrent(message.subscriptionId, token)) {
3056
+ return;
3057
+ }
3058
+ if (response.status === "error" && !response.error.isRetryable) {
3059
+ querySubscriptions.unsubscribe(message.subscriptionId);
3060
+ }
3061
+ postQueryDataSourceResult({
3062
+ subscriptionId: message.subscriptionId,
3063
+ response
3064
+ });
3065
+ } finally {
3066
+ const refresh = querySubscriptions.finish(message.subscriptionId, token);
3067
+ if (refresh !== void 0) {
3068
+ void handleQuery(refresh.message, refresh.token);
3069
+ }
3070
+ }
3071
+ }
3072
+ function updateHostState(update) {
3073
+ if (initializationController.status === "stopped" || initializationController.status === "error") {
3074
+ return;
3075
+ }
3076
+ Object.assign(pendingState, update);
3077
+ flushPendingHostStateChanges();
3078
+ }
3079
+ function flushPendingHostStateChanges() {
3080
+ if (initializationController.status !== "initialized") {
3081
+ return;
3082
+ }
3083
+ const changes = pendingState;
3084
+ pendingState = {};
3085
+ if (changes.theme !== void 0) {
3086
+ sendInitializedMessage({ type: "themeChanged", theme: changes.theme });
3087
+ }
3088
+ if (changes.contrastMode !== void 0) {
3089
+ sendInitializedMessage({
3090
+ type: "contrastModeChanged",
3091
+ contrastMode: changes.contrastMode
3092
+ });
3093
+ }
3094
+ if (changes.parent !== void 0) {
3095
+ sendInitializedMessage({ type: "parentChanged", parent: changes.parent });
3096
+ }
3097
+ if (changes.page !== void 0) {
3098
+ sendInitializedMessage({ type: "pageChanged", page: changes.page });
3099
+ }
3100
+ if (changes.dataSources !== void 0) {
3101
+ sendInitializedMessage({
3102
+ type: "dataSourcesChanged",
3103
+ dataSources: changes.dataSources
3104
+ });
3105
+ }
3106
+ if (changes.currentUser !== void 0) {
3107
+ sendInitializedMessage({
3108
+ type: "currentUserChanged",
3109
+ currentUser: changes.currentUser
3110
+ });
3111
+ }
3112
+ }
3113
+ const initializationController = createInitializationController({
3114
+ async prepareInit(connect) {
3115
+ sandboxBridgeProtocolVersion = connect.bridgeProtocolVersion;
3116
+ const result = await getInitialState(connect);
3117
+ if (initializationController.status !== "preparingInit") {
3118
+ return result;
3119
+ }
3120
+ return prepareInitialState(result);
3121
+ },
3122
+ sendInitMessage,
3123
+ warn: (payload) => emit("warn", payload),
3124
+ flushPendingHostStateChanges,
3125
+ minBridgeProtocolVersion,
3126
+ noConnectTimeoutMs,
3127
+ initialStateTimeoutMs,
3128
+ noInitResultTimeoutMs,
3129
+ stopHostWithFailure: stopWithFailure,
3130
+ onInitResult(message) {
3131
+ if (message.status === "success" && manifest !== void 0) {
3132
+ onInitialized?.({ manifest, initialHeight: message.initialHeight });
3133
+ }
3134
+ },
3135
+ onConnectionFailure
3136
+ });
3137
+ function prepareInitialState(result) {
3138
+ if (result.status === "error") {
3139
+ return result;
3140
+ }
3141
+ manifest = parse(manifestSchema, result.initialState.manifest);
3142
+ onManifest?.(manifest);
3143
+ const initialStateInput = {
3144
+ ...result.initialState,
3145
+ ...pendingState
3146
+ };
3147
+ pendingState = {};
3148
+ const initialState = {
3149
+ ...parse(
3150
+ omit(customBlockHostInitialStateSchema, ["manifest"]),
3151
+ initialStateInput
3152
+ ),
3153
+ manifest
3154
+ };
3155
+ if (sandboxBridgeProtocolVersion < BRIDGE_PROTOCOL_VERSION_INTRODUCING_UNAVAILABLE_PAGE && initialState.page.type === "unavailable") {
3156
+ return {
3157
+ status: "error",
3158
+ error: initErrorForFailureReason("context_unavailable")
3159
+ };
3160
+ }
3161
+ const bindingErrorCode = getBindingErrorCode(
3162
+ initialState.manifest,
3163
+ initialState.dataSources
3164
+ );
3165
+ if (bindingErrorCode !== void 0) {
3166
+ return {
3167
+ status: "error",
3168
+ error: initErrorForFailureReason(bindingErrorCode)
3169
+ };
3170
+ }
3171
+ activeDataSources = initialState.dataSources;
3172
+ hasPreparedInitialState = true;
3173
+ return { status: "success", initialState };
3174
+ }
3175
+ const onMessage = createSandboxMessageRouter({
3176
+ iframe,
3177
+ sandboxOrigin,
3178
+ getInitStatus: () => initializationController.status,
3179
+ emit,
3180
+ sendNack,
3181
+ onInvalidConnect: initializationController.handleInvalidConnect,
3182
+ onInvalidInitResult: initializationController.handleInvalidInitResult,
3183
+ onConnect: initializationController.handleConnect,
3184
+ onInitResult: initializationController.handleInitResult,
3185
+ onQueryDataSource: handleQuery,
3186
+ onUnsubscribeDataSourceQuery: (message) => querySubscriptions.unsubscribe(message.subscriptionId),
3187
+ onCreatePage: (message) => respondToRequest(message, handlers.createPage),
3188
+ onGetPage: (message) => respondToRequest(message, handlers.getPage),
3189
+ onOpenPage: (message) => respondToRequest(message, handlers.openPage),
3190
+ onGetUser: (message) => respondToRequest(message, handlers.getUser),
3191
+ onListUsers: (message) => respondToRequest(message, handlers.listUsers),
3192
+ onUpdatePage: (message) => respondToRequest(message, handlers.updatePage),
3193
+ onResize: (message) => handlers.resize?.(message)
3194
+ });
3195
+ window.addEventListener("message", onMessage);
3196
+ iframe.addEventListener("load", initializationController.onIframeLoad);
3197
+ function stop() {
3198
+ window.removeEventListener("message", onMessage);
3199
+ iframe.removeEventListener("load", initializationController.onIframeLoad);
3200
+ initializationController.stop();
3201
+ querySubscriptions.unsubscribeAll();
3202
+ }
3203
+ function stopWithFailure(error) {
3204
+ stop();
3205
+ emit("warn", error);
3206
+ onConnectionFailure?.(error);
3207
+ }
3208
+ return {
3209
+ stop,
3210
+ setTheme(theme) {
3211
+ updateHostState({ theme });
3212
+ },
3213
+ setContrastMode(contrastMode) {
3214
+ updateHostState({ contrastMode });
3215
+ },
3216
+ setParent(parent) {
3217
+ updateHostState({ parent });
3218
+ },
3219
+ setPage(page) {
3220
+ if (page.type === "unavailable" && sandboxBridgeProtocolVersion < BRIDGE_PROTOCOL_VERSION_INTRODUCING_UNAVAILABLE_PAGE && (initializationController.status === "preparingInit" && hasPreparedInitialState || initializationController.status === "waitingForInitResult" || initializationController.status === "initialized")) {
3221
+ stopWithFailure(initErrorForFailureReason("context_unavailable"));
3222
+ return;
3223
+ }
3224
+ updateHostState({ page });
3225
+ },
3226
+ setCurrentUser(currentUser) {
3227
+ updateHostState({ currentUser });
3228
+ },
3229
+ setDataSources(dataSources) {
3230
+ const normalizedDataSources = {
3231
+ bindings: parse(
3232
+ notionDataSourceBindingsSchema,
3233
+ dataSources.bindings
3234
+ )
3235
+ };
3236
+ if (initializationController.hasConnectedSandbox && manifest !== void 0 && getBindingErrorCode(manifest, normalizedDataSources) !== void 0) {
3237
+ emit("warn", {
3238
+ message: "Ignored invalid data source bindings update",
3239
+ payload: normalizedDataSources
3240
+ });
3241
+ return;
3242
+ }
3243
+ activeDataSources = normalizedDataSources;
3244
+ updateHostState({ dataSources: normalizedDataSources });
3245
+ },
3246
+ refreshQuery({ dataSourceId }) {
3247
+ if (initializationController.status !== "initialized") {
3248
+ return;
3249
+ }
3250
+ const normalizedDataSourceId = parse(
3251
+ notionDataSourceIdSchema,
3252
+ dataSourceId
3253
+ );
3254
+ const refreshes = querySubscriptions.refresh(normalizedDataSourceId);
3255
+ if (refreshes === void 0) {
3256
+ emit("warn", `No active query exists for data source "${dataSourceId}"`);
3257
+ return;
3258
+ }
3259
+ for (const refresh of refreshes) {
3260
+ void handleQuery(refresh.message, refresh.token);
3261
+ }
3262
+ }
3263
+ };
3264
+ }
3265
+ function getCollectionSchema(dataSources, dataSourceId) {
3266
+ return Object.values(dataSources?.bindings ?? {}).find(
3267
+ (binding) => binding.collectionPointer?.id === dataSourceId
3268
+ )?.collectionSchema;
3269
+ }
3270
+ function getBindingErrorCode(manifest, dataSources) {
3271
+ for (const [dataSourceKey, manifestDataSource] of Object.entries(
3272
+ manifest.dataSources
3273
+ )) {
3274
+ const binding = dataSources.bindings[dataSourceKey];
3275
+ if (binding?.collectionPointer === void 0 || binding.collectionSchema === void 0) {
3276
+ return "missing_data_source_binding";
3277
+ }
3278
+ for (const [propertyKey, manifestProperty] of Object.entries(
3279
+ manifestDataSource.properties ?? {}
3280
+ )) {
3281
+ const propertyId = binding.propertyIdsByKey?.[propertyKey];
3282
+ if (propertyId === void 0) {
3283
+ return "missing_property_binding";
3284
+ }
3285
+ if (binding.collectionSchema.propertiesById[propertyId]?.type !== manifestProperty.type) {
3286
+ return "invalid_property_binding";
3287
+ }
3288
+ }
3289
+ }
3290
+ return void 0;
3291
+ }
3292
+ function getQueryValidationError(message, collectionSchema) {
3293
+ if (collectionSchema === void 0) {
3294
+ if (message.filter === void 0 && (message.sorts?.length ?? 0) === 0) {
3295
+ return void 0;
3296
+ }
3297
+ return {
3298
+ code: "data_source_schema_unavailable",
3299
+ message: "You cannot query this data source with filters or sorts because its schema is unavailable.",
3300
+ isRetryable: false
3301
+ };
3302
+ }
3303
+ return validateQueryDataSourceFilter(message.filter, collectionSchema) ?? validateQueryDataSourceSorts(message.sorts, collectionSchema);
3304
+ }
3305
+ export {
3306
+ createCustomBlockHost,
3307
+ getAutoBoundPropertyIdsByKey
3308
+ };