@notionhq/custom-blocks-host 0.3.8 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +143 -225
  3. package/THIRD_PARTY_LICENSES.md +9 -0
  4. package/dist/autoBindProperties.d.ts +5 -2
  5. package/dist/autoBindProperties.d.ts.map +1 -1
  6. package/dist/autoBindProperties.js +5 -2
  7. package/dist/browser.js +1 -1
  8. package/dist/compatibility/addMetadataReadSchemasForProtocol3To4.d.ts +1215 -0
  9. package/dist/compatibility/addMetadataReadSchemasForProtocol3To4.d.ts.map +1 -0
  10. package/dist/compatibility/addMetadataReadSchemasForProtocol3To4.js +27 -0
  11. package/dist/compatibility/normalizeHostToSandboxMessage.d.ts +8 -0
  12. package/dist/compatibility/normalizeHostToSandboxMessage.d.ts.map +1 -0
  13. package/dist/compatibility/normalizeHostToSandboxMessage.js +39 -0
  14. package/dist/compatibility/normalizePageResultsForProtocol3To5.d.ts +11 -0
  15. package/dist/compatibility/normalizePageResultsForProtocol3To5.d.ts.map +1 -0
  16. package/dist/compatibility/normalizePageResultsForProtocol3To5.js +18 -0
  17. package/dist/compatibility/normalizePageResultsForProtocol6.d.ts +9 -0
  18. package/dist/compatibility/normalizePageResultsForProtocol6.d.ts.map +1 -0
  19. package/dist/compatibility/normalizePageResultsForProtocol6.js +18 -0
  20. package/dist/compatibility/normalizeSandboxToHostMessage.d.ts +1091 -0
  21. package/dist/compatibility/normalizeSandboxToHostMessage.d.ts.map +1 -0
  22. package/dist/compatibility/normalizeSandboxToHostMessage.js +9 -0
  23. package/dist/compatibility/pageForProtocol3To5.d.ts +159 -0
  24. package/dist/compatibility/pageForProtocol3To5.d.ts.map +1 -0
  25. package/dist/{lifecycle/legacyPage.js → compatibility/pageForProtocol3To5.js} +50 -9
  26. package/dist/compatibility/pageResult.d.ts +11 -0
  27. package/dist/compatibility/pageResult.d.ts.map +1 -0
  28. package/dist/compatibility/pageWithNullTextFallbackProperties.d.ts +9 -0
  29. package/dist/compatibility/pageWithNullTextFallbackProperties.d.ts.map +1 -0
  30. package/dist/compatibility/pageWithNullTextFallbackProperties.js +46 -0
  31. package/dist/createCustomBlockHost.d.ts +18 -19
  32. package/dist/createCustomBlockHost.d.ts.map +1 -1
  33. package/dist/createCustomBlockHost.js +103 -38
  34. package/dist/index.d.ts +2 -19
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +1 -2
  37. package/dist/{localBlockUrl.d.ts → isAllowedLocalPreviewUrl.d.ts} +2 -2
  38. package/dist/isAllowedLocalPreviewUrl.d.ts.map +1 -0
  39. package/dist/{localBlockUrl.js → isAllowedLocalPreviewUrl.js} +3 -7
  40. package/dist/lifecycle/initErrors.d.ts +1 -0
  41. package/dist/lifecycle/initErrors.d.ts.map +1 -1
  42. package/dist/lifecycle/initErrors.js +7 -0
  43. package/dist/lifecycle/initializationController.d.ts +6 -4
  44. package/dist/lifecycle/initializationController.d.ts.map +1 -1
  45. package/dist/lifecycle/initializationController.js +24 -15
  46. package/dist/lifecycle/resolveManifest.d.ts +13 -0
  47. package/dist/lifecycle/resolveManifest.d.ts.map +1 -0
  48. package/dist/lifecycle/resolveManifest.js +21 -0
  49. package/dist/lifecycle/types.d.ts +1637 -17
  50. package/dist/lifecycle/types.d.ts.map +1 -1
  51. package/dist/lifecycle/types.js +18 -0
  52. package/dist/messages/sandboxMessageRouter.d.ts.map +1 -1
  53. package/dist/messages/sandboxMessageRouter.js +2 -2
  54. package/dist/protocol/dataSources/dataSourcePage.d.ts +3 -4
  55. package/dist/protocol/dataSources/dataSourcePage.js +2 -3
  56. package/dist/protocol/index.d.ts +1 -0
  57. package/dist/protocol/index.js +1 -0
  58. package/dist/protocol/isLocalBlockServerUrl.d.ts +2 -0
  59. package/dist/protocol/isLocalBlockServerUrl.js +9 -0
  60. package/dist/protocol/messages/connect.d.ts +2 -2
  61. package/dist/protocol/messages/connect.js +2 -2
  62. package/dist/protocol/messages/createPageResult.d.ts +2 -2
  63. package/dist/protocol/messages/createPageResult.js +3 -3
  64. package/dist/protocol/messages/getPage.d.ts +2 -2
  65. package/dist/protocol/messages/getPage.js +3 -3
  66. package/dist/protocol/messages/hostToSandbox.d.ts +3 -3
  67. package/dist/protocol/messages/hostToSandbox.js +10 -10
  68. package/dist/protocol/messages/init.d.ts +1 -1
  69. package/dist/protocol/messages/queryDataSourceResult.d.ts +3 -3
  70. package/dist/protocol/messages/queryDataSourceResult.js +6 -3
  71. package/dist/protocol/messages/updatePageResult.d.ts +2 -2
  72. package/dist/protocol/messages/updatePageResult.js +3 -3
  73. package/dist/protocol/pages/page.d.ts +2 -2
  74. package/dist/protocol/pages/page.js +1 -1
  75. package/dist/protocol/protocolVersion.d.ts +3 -2
  76. package/dist/protocol/protocolVersion.js +4 -2
  77. package/dist/protocol.d.ts +9 -0
  78. package/dist/protocol.d.ts.map +1 -0
  79. package/dist/protocol.js +8 -0
  80. package/docs/bridge/changelog.md +67 -0
  81. package/docs/bridge/protocol.md +182 -0
  82. package/docs/bridge/versioning.md +38 -0
  83. package/docs/compatibility.md +68 -0
  84. package/docs/handlers.md +199 -0
  85. package/docs/lifecycle.md +117 -0
  86. package/package.json +11 -3
  87. package/src/autoBindProperties.ts +5 -2
  88. package/src/compatibility/addMetadataReadSchemasForProtocol3To4.ts +36 -0
  89. package/src/compatibility/normalizeHostToSandboxMessage.ts +54 -0
  90. package/src/compatibility/normalizePageResultsForProtocol3To5.ts +28 -0
  91. package/src/compatibility/normalizePageResultsForProtocol6.ts +23 -0
  92. package/src/compatibility/normalizeSandboxToHostMessage.ts +10 -0
  93. package/src/{lifecycle/legacyPage.ts → compatibility/pageForProtocol3To5.ts} +52 -11
  94. package/src/compatibility/pageResult.ts +18 -0
  95. package/src/compatibility/pageWithNullTextFallbackProperties.ts +53 -0
  96. package/src/createCustomBlockHost.ts +152 -62
  97. package/src/index.ts +4 -51
  98. package/src/{localBlockUrl.ts → isAllowedLocalPreviewUrl.ts} +4 -7
  99. package/src/lifecycle/initErrors.ts +9 -0
  100. package/src/lifecycle/initializationController.ts +34 -19
  101. package/src/lifecycle/resolveManifest.ts +31 -0
  102. package/src/lifecycle/types.ts +84 -16
  103. package/src/messages/sandboxMessageRouter.ts +2 -2
  104. package/src/protocol.ts +8 -0
  105. package/dist/lifecycle/legacyPage.d.ts +0 -70
  106. package/dist/lifecycle/legacyPage.d.ts.map +0 -1
  107. package/dist/lifecycle/loadCustomBlockManifest.d.ts +0 -16
  108. package/dist/lifecycle/loadCustomBlockManifest.d.ts.map +0 -1
  109. package/dist/lifecycle/loadCustomBlockManifest.js +0 -65
  110. package/dist/lifecycle/manifestOptions.d.ts +0 -17
  111. package/dist/lifecycle/manifestOptions.d.ts.map +0 -1
  112. package/dist/lifecycle/normalizeHostToSandboxMessage.d.ts +0 -6
  113. package/dist/lifecycle/normalizeHostToSandboxMessage.d.ts.map +0 -1
  114. package/dist/lifecycle/normalizeHostToSandboxMessage.js +0 -16
  115. package/dist/lifecycle/normalizePage.d.ts +0 -7
  116. package/dist/lifecycle/normalizePage.d.ts.map +0 -1
  117. package/dist/lifecycle/normalizePage.js +0 -22
  118. package/dist/localBlockUrl.d.ts.map +0 -1
  119. package/src/lifecycle/loadCustomBlockManifest.ts +0 -89
  120. package/src/lifecycle/manifestOptions.ts +0 -19
  121. package/src/lifecycle/normalizeHostToSandboxMessage.ts +0 -29
  122. package/src/lifecycle/normalizePage.ts +0 -35
  123. /package/dist/{lifecycle/manifestOptions.js → compatibility/pageResult.js} +0 -0
@@ -0,0 +1,36 @@
1
+ import { NOTION_BUILTIN_PROPERTY_SCHEMAS } from "@notionhq/custom-blocks-protocol/dataSources/propertySchema.js"
2
+ import type { HostToSandboxMessage } from "@notionhq/custom-blocks-protocol/messages/hostToSandbox.js"
3
+
4
+ /**
5
+ * Protocols 3–4 derive metadata read schemas from host bindings. Restore those
6
+ * schemas only in outgoing copies so host query validation keeps the actual schema.
7
+ *
8
+ * Delete when MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION >= 5.
9
+ */
10
+ export function addMetadataReadSchemasForProtocol3To4(
11
+ message: Extract<
12
+ HostToSandboxMessage,
13
+ { type: "init"; status: "success" } | { type: "dataSourcesChanged" }
14
+ >,
15
+ ) {
16
+ return {
17
+ ...message,
18
+ dataSources: {
19
+ bindings: Object.fromEntries(
20
+ Object.entries(message.dataSources.bindings).map(([key, binding]) => [
21
+ key,
22
+ {
23
+ ...binding,
24
+ collectionSchema: {
25
+ ...binding.collectionSchema,
26
+ propertiesById: {
27
+ ...binding.collectionSchema?.propertiesById,
28
+ ...NOTION_BUILTIN_PROPERTY_SCHEMAS,
29
+ },
30
+ },
31
+ },
32
+ ]),
33
+ ),
34
+ },
35
+ }
36
+ }
@@ -0,0 +1,54 @@
1
+ import type {
2
+ HostToSandboxMessage,
3
+ HostToSandboxMessageWithProtocol3To5Compatibility,
4
+ } from "@notionhq/custom-blocks-protocol/messages/hostToSandbox.js"
5
+ import {
6
+ TEXT_FALLBACK_PROPERTY_PROTOCOL_VERSION,
7
+ UNIFIED_PAGE_PROTOCOL_VERSION,
8
+ } from "@notionhq/custom-blocks-protocol/protocolVersion.js"
9
+ import { addMetadataReadSchemasForProtocol3To4 } from "./addMetadataReadSchemasForProtocol3To4.js"
10
+ import { normalizePageResultsForProtocol3To5 } from "./normalizePageResultsForProtocol3To5.js"
11
+ import { normalizePageResultsForProtocol6 } from "./normalizePageResultsForProtocol6.js"
12
+
13
+ /**
14
+ * Encodes current host messages for the sandbox's declared protocol. Handlers use
15
+ * current shapes. Each target adapter starts from that shape to avoid data loss.
16
+ * Unchanged messages and error results retain their original payloads.
17
+ */
18
+ export function normalizeHostToSandboxMessage(
19
+ message: HostToSandboxMessage,
20
+ bridgeProtocolVersion: number,
21
+ ): HostToSandboxMessageWithProtocol3To5Compatibility {
22
+ // Accepted compatibility gap (2026-10-31): leave unavailable containing-page
23
+ // context in init/pageChanged unchanged for early protocol 5 SDKs. Protocol 5
24
+ // shipped in SDK 0.2.16 on 2026-09-30. SDK 0.2.17 added unavailable context on
25
+ // 2026-10-02 without a protocol bump. SDK 0.2.16 cannot decode that context.
26
+ // Preserve normal contexts and later protocol 5 support. Affected blocks must
27
+ // upgrade their SDK rather than adding SDK-version-based translation here.
28
+ if (
29
+ (message.type === "init" && message.status === "success") ||
30
+ message.type === "dataSourcesChanged"
31
+ ) {
32
+ return bridgeProtocolVersion < 5
33
+ ? addMetadataReadSchemasForProtocol3To4(message)
34
+ : message
35
+ }
36
+ if (
37
+ message.type !== "queryDataSourceResult" &&
38
+ message.type !== "getPageResult" &&
39
+ message.type !== "createPageResult" &&
40
+ message.type !== "updatePageResult"
41
+ ) {
42
+ return message
43
+ }
44
+ if (message.status === "error") {
45
+ return message
46
+ }
47
+ if (bridgeProtocolVersion < UNIFIED_PAGE_PROTOCOL_VERSION) {
48
+ return normalizePageResultsForProtocol3To5(message)
49
+ }
50
+ if (bridgeProtocolVersion < TEXT_FALLBACK_PROPERTY_PROTOCOL_VERSION) {
51
+ return normalizePageResultsForProtocol6(message)
52
+ }
53
+ return message
54
+ }
@@ -0,0 +1,28 @@
1
+ import type { HostToSandboxMessageWithProtocol3To5Compatibility } from "@notionhq/custom-blocks-protocol/messages/hostToSandbox.js"
2
+ import {
3
+ toPageForProtocol3To5,
4
+ toQueryPageForProtocol3To5,
5
+ } from "./pageForProtocol3To5.js"
6
+ import type { SuccessfulPageResult } from "./pageResult.js"
7
+ import { toPageWithNullTextFallbackProperties } from "./pageWithNullTextFallbackProperties.js"
8
+
9
+ /**
10
+ * Encodes current pages for protocols 3–5. Query values are flat and ID-keyed.
11
+ * Page operations omit unsupported property objects and use ID-keyed properties.
12
+ * Convert directly from current pages so query text fallbacks remain available.
13
+ *
14
+ * Delete when MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION >= 6.
15
+ */
16
+ export function normalizePageResultsForProtocol3To5(
17
+ message: SuccessfulPageResult,
18
+ ): HostToSandboxMessageWithProtocol3To5Compatibility {
19
+ if (message.type === "queryDataSourceResult") {
20
+ return { ...message, items: message.items.map(toQueryPageForProtocol3To5) }
21
+ }
22
+ return {
23
+ ...message,
24
+ page: toPageForProtocol3To5(
25
+ toPageWithNullTextFallbackProperties(message.page),
26
+ ),
27
+ }
28
+ }
@@ -0,0 +1,23 @@
1
+ import type { HostToSandboxMessage } from "@notionhq/custom-blocks-protocol/messages/hostToSandbox.js"
2
+ import type { SuccessfulPageResult } from "./pageResult.js"
3
+ import { toPageWithNullTextFallbackProperties } from "./pageWithNullTextFallbackProperties.js"
4
+
5
+ /**
6
+ * Encodes protocol 6 pages, whose receivers require null for text fallback properties.
7
+ *
8
+ * Delete when MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION >= 7.
9
+ */
10
+ export function normalizePageResultsForProtocol6(
11
+ message: SuccessfulPageResult,
12
+ ): HostToSandboxMessage {
13
+ if (message.type === "queryDataSourceResult") {
14
+ return {
15
+ ...message,
16
+ items: message.items.map(toPageWithNullTextFallbackProperties),
17
+ }
18
+ }
19
+ return {
20
+ ...message,
21
+ page: toPageWithNullTextFallbackProperties(message.page),
22
+ }
23
+ }
@@ -0,0 +1,10 @@
1
+ import { sandboxToHostMessageSchema } from "@notionhq/custom-blocks-protocol/messages/sandboxToHost.js"
2
+ import * as v from "valibot"
3
+
4
+ /**
5
+ * Validates sandbox wire messages before handler dispatch. Supported requests
6
+ * currently share one schema, so parsing produces the current handler shape.
7
+ */
8
+ export function normalizeSandboxToHostMessage(payload: unknown) {
9
+ return v.safeParse(sandboxToHostMessageSchema, payload)
10
+ }
@@ -1,6 +1,6 @@
1
1
  import type { NotionDataSourceValue } from "@notionhq/custom-blocks-protocol/dataSources/dataSourceValue.js"
2
2
  import type {
3
- LegacyNotionPage,
3
+ NotionPageForProtocol3To5,
4
4
  NotionPagePropertyValue,
5
5
  notionPageDataSchema,
6
6
  } from "@notionhq/custom-blocks-protocol/pages/page.js"
@@ -8,9 +8,17 @@ import type { InferOutput } from "valibot"
8
8
  import { toNotionDateValue } from "../dateValue.js"
9
9
  import { unreachable } from "../utils.js"
10
10
 
11
- export function toLegacyPage(
11
+ /**
12
+ * Converts current page data to the page-operation format used by protocols 3–5.
13
+ * Keys property objects by raw ID and omits null properties. Optional icons,
14
+ * covers, timestamps, and URLs use undefined instead of null in this format.
15
+ * Call after clearing property objects unsupported by these protocols.
16
+ *
17
+ * Delete when MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION >= 6.
18
+ */
19
+ export function toPageForProtocol3To5(
12
20
  page: InferOutput<typeof notionPageDataSchema>,
13
- ): LegacyNotionPage {
21
+ ): NotionPageForProtocol3To5 {
14
22
  return {
15
23
  ...page,
16
24
  properties: Object.fromEntries(
@@ -27,23 +35,44 @@ export function toLegacyPage(
27
35
  }
28
36
  }
29
37
 
30
- export function toLegacyQueryPage(
38
+ /**
39
+ * Converts a current page to a protocol 3–5 query row, keeping its ID and archive
40
+ * flags while flattening typed property objects into raw-ID-keyed values.
41
+ * Copies page creation and edit metadata into the reserved property IDs that
42
+ * these query readers expect.
43
+ *
44
+ * Delete when MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION >= 6.
45
+ */
46
+ export function toQueryPageForProtocol3To5(
31
47
  page: InferOutput<typeof notionPageDataSchema>,
32
48
  ) {
33
49
  const propertiesById: Record<string, NotionDataSourceValue | undefined> = {}
34
50
  for (const property of Object.values(page.properties)) {
35
51
  if (property) {
36
- propertiesById[property.id] = toLegacyProperty(property)
52
+ propertiesById[property.id] = toPropertyValueForProtocol3To5(property)
37
53
  }
38
54
  }
39
55
  return {
40
56
  id: page.id,
41
57
  is_archived: page.is_archived,
42
58
  in_trash: page.in_trash,
43
- propertiesById,
59
+ // Reserved metadata IDs retain their historical meaning even if an actual
60
+ // property uses the same ID. Binding schemas use the same precedence.
61
+ propertiesById: {
62
+ ...propertiesById,
63
+ created_time: toDateTimeValueForProtocol3To5(page.created_time),
64
+ last_edited_time: toDateTimeValueForProtocol3To5(page.last_edited_time),
65
+ created_by: page.created_by ? [page.created_by] : undefined,
66
+ last_edited_by: page.last_edited_by ? [page.last_edited_by] : undefined,
67
+ },
44
68
  }
45
69
  }
46
70
 
71
+ /**
72
+ * Flattens rich-text items to the string used by protocol 3–5 query values.
73
+ *
74
+ * Delete when MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION >= 6.
75
+ */
47
76
  function plainText(items: Record<string, unknown>[]): string {
48
77
  return items
49
78
  .map(item => {
@@ -61,7 +90,13 @@ function plainText(items: Record<string, unknown>[]): string {
61
90
  .join("")
62
91
  }
63
92
 
64
- function timestamp(
93
+ /**
94
+ * Converts a timestamp to the UTC date/time object used by protocol 3–5 queries.
95
+ * Missing or invalid timestamps produce undefined; time is stored to the minute.
96
+ *
97
+ * Delete when MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION >= 6.
98
+ */
99
+ function toDateTimeValueForProtocol3To5(
65
100
  value: string | number | null | undefined,
66
101
  ): NotionDataSourceValue | undefined {
67
102
  if (value === undefined || value === null || value === "") {
@@ -79,7 +114,13 @@ function timestamp(
79
114
  }
80
115
  }
81
116
 
82
- function toLegacyProperty(
117
+ /**
118
+ * Converts a typed page property to the scalar, list, record-reference, or
119
+ * date/time value used by protocol 3–5 query results.
120
+ *
121
+ * Delete when MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION >= 6.
122
+ */
123
+ function toPropertyValueForProtocol3To5(
83
124
  property: NotionPagePropertyValue,
84
125
  ): NotionDataSourceValue | undefined {
85
126
  switch (property.type) {
@@ -134,11 +175,11 @@ function toLegacyProperty(
134
175
  case "place":
135
176
  return ""
136
177
  case "created_time":
137
- return timestamp(property.created_time)
178
+ return toDateTimeValueForProtocol3To5(property.created_time)
138
179
  case "last_edited_time":
139
- return timestamp(property.last_edited_time)
180
+ return toDateTimeValueForProtocol3To5(property.last_edited_time)
140
181
  case "last_visited_time":
141
- return timestamp(property.last_visited_time)
182
+ return toDateTimeValueForProtocol3To5(property.last_visited_time)
142
183
  case "created_by":
143
184
  return property.created_by ? [property.created_by] : undefined
144
185
  case "last_edited_by":
@@ -0,0 +1,18 @@
1
+ import type { HostToSandboxMessage } from "@notionhq/custom-blocks-protocol/messages/hostToSandbox.js"
2
+
3
+ /**
4
+ * Page-bearing responses accepted by the target-protocol adapters. The dispatcher
5
+ * passes errors and unrelated messages through unchanged before calling them.
6
+ * Sharing this subset keeps both adapters limited to successful page conversions.
7
+ */
8
+ export type SuccessfulPageResult = Extract<
9
+ HostToSandboxMessage,
10
+ {
11
+ type:
12
+ | "queryDataSourceResult"
13
+ | "getPageResult"
14
+ | "createPageResult"
15
+ | "updatePageResult"
16
+ status: "success"
17
+ }
18
+ >
@@ -0,0 +1,53 @@
1
+ import type { notionPageDataSchema } from "@notionhq/custom-blocks-protocol/pages/page.js"
2
+ import type { InferOutput } from "valibot"
3
+ import { unreachable } from "../utils.js"
4
+
5
+ /**
6
+ * Shared field conversion for receivers that cannot decode text fallback objects.
7
+ *
8
+ * Delete when MIN_HOST_SUPPORTED_BRIDGE_PROTOCOL_VERSION >= 7.
9
+ */
10
+ export function toPageWithNullTextFallbackProperties(
11
+ page: InferOutput<typeof notionPageDataSchema>,
12
+ ): InferOutput<typeof notionPageDataSchema> {
13
+ return {
14
+ ...page,
15
+ properties: Object.fromEntries(
16
+ Object.entries(page.properties).map(([name, property]) => {
17
+ switch (property?.type) {
18
+ case "unique_id":
19
+ case "button":
20
+ case "formula":
21
+ case "location":
22
+ case "rollup":
23
+ case "verification":
24
+ return [name, null]
25
+ case "title":
26
+ case "rich_text":
27
+ case "number":
28
+ case "url":
29
+ case "email":
30
+ case "phone_number":
31
+ case "checkbox":
32
+ case "select":
33
+ case "status":
34
+ case "multi_select":
35
+ case "date":
36
+ case "people":
37
+ case "relation":
38
+ case "files":
39
+ case "place":
40
+ case "created_time":
41
+ case "last_edited_time":
42
+ case "created_by":
43
+ case "last_edited_by":
44
+ case "last_visited_time":
45
+ case undefined:
46
+ return [name, property]
47
+ default:
48
+ return unreachable(property)
49
+ }
50
+ }),
51
+ ),
52
+ }
53
+ }