@useairfoil/connector-kit 0.6.0 → 0.7.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 (182) hide show
  1. package/LICENSE.txt +201 -0
  2. package/METRICS.md +38 -42
  3. package/README.md +111 -444
  4. package/dist/annotations-vzSzXtr-.d.mts +34 -0
  5. package/dist/arrow-flight-DDQ0ktx9.mjs +251 -0
  6. package/dist/arrow-flight-DDQ0ktx9.mjs.map +1 -0
  7. package/dist/auth/index.d.mts +2 -0
  8. package/dist/{auth-DvU_CZ7C.js → auth/index.mjs} +6 -8
  9. package/dist/auth/index.mjs.map +1 -0
  10. package/dist/connector-app/index.d.mts +2 -0
  11. package/dist/connector-app/index.mjs +2 -0
  12. package/dist/connector-app-C6_dZnhE.mjs +256 -0
  13. package/dist/connector-app-C6_dZnhE.mjs.map +1 -0
  14. package/dist/{constants-D113Ut1x.js → constants-v3UX-hf6.mjs} +5 -5
  15. package/dist/constants-v3UX-hf6.mjs.map +1 -0
  16. package/dist/demo/index.d.mts +2 -0
  17. package/dist/demo/index.mjs +2 -0
  18. package/dist/demo-DqTJ7TWI.mjs +204 -0
  19. package/dist/demo-DqTJ7TWI.mjs.map +1 -0
  20. package/dist/errors/index.d.mts +2 -0
  21. package/dist/errors/index.mjs +2 -0
  22. package/dist/{errors-DHWylqRZ.js → errors-pT0YVJU5.mjs} +2 -3
  23. package/dist/errors-pT0YVJU5.mjs.map +1 -0
  24. package/dist/iceberg/index.d.mts +3 -0
  25. package/dist/iceberg/index.mjs +3 -0
  26. package/dist/iceberg-Cj2PwlNm.mjs +30 -0
  27. package/dist/iceberg-Cj2PwlNm.mjs.map +1 -0
  28. package/dist/index-BTAbexBp.d.mts +55 -0
  29. package/dist/{index-DXa26Ry5.d.ts → index-BX8G7d41.d.mts} +1 -2
  30. package/dist/{index-VpHaZXZw.d.ts → index-Byr8NTdG.d.mts} +11 -13
  31. package/dist/index-CV6V6fyx.d.mts +79 -0
  32. package/dist/{index-C5Ma7V7t.d.ts → index-CZKx2Yce.d.mts} +72 -37
  33. package/dist/{index-DYpEMJf-.d.ts → index-CgvFomO6.d.mts} +6 -7
  34. package/dist/{index-bfjH7Yb0.d.ts → index-DeTwIUKl.d.mts} +9 -10
  35. package/dist/{index-DKoRwyFn.d.ts → index-DkVNO6ks.d.mts} +2 -5
  36. package/dist/{index-BKw7jA2a.d.ts → index-dHS59EZl.d.mts} +10 -8
  37. package/dist/{index-CR9HJDdr.d.ts → index-eFuoMZZ3.d.mts} +18 -20
  38. package/dist/{index-ZSuiZX5H.d.ts → index-fHIJJoRe.d.mts} +25 -30
  39. package/dist/index-uFa2wwYo.d.mts +27 -0
  40. package/dist/index.d.mts +16 -0
  41. package/dist/index.mjs +45 -0
  42. package/dist/index.mjs.map +1 -0
  43. package/dist/ingestion/index.d.mts +2 -0
  44. package/dist/ingestion/index.mjs +2 -0
  45. package/dist/ingestion-DoCUwm5N.mjs +275 -0
  46. package/dist/ingestion-DoCUwm5N.mjs.map +1 -0
  47. package/dist/ingestor/index.d.mts +3 -0
  48. package/dist/ingestor/index.mjs +4 -0
  49. package/dist/ingestor-DjCEzBzZ.mjs +26 -0
  50. package/dist/ingestor-DjCEzBzZ.mjs.map +1 -0
  51. package/dist/instrumented-Bq1WX2L5.mjs +29 -0
  52. package/dist/instrumented-Bq1WX2L5.mjs.map +1 -0
  53. package/dist/manifest/index.d.mts +2 -0
  54. package/dist/manifest/{index.js → index.mjs} +2 -4
  55. package/dist/{manifest-P7kBnch9.js → manifest-CABeIhAG.mjs} +14 -19
  56. package/dist/manifest-CABeIhAG.mjs.map +1 -0
  57. package/dist/{telemetry-j_nxwYfh.js → metrics-C901IIYZ.mjs} +172 -26
  58. package/dist/metrics-C901IIYZ.mjs.map +1 -0
  59. package/dist/{metrics-C4V1pm6v.d.ts → metrics-DoJ0WeKu.d.mts} +18 -13
  60. package/dist/metrics.d.mts +2 -0
  61. package/dist/metrics.mjs +2 -0
  62. package/dist/{chunk-Bp6m_JJh.js → rolldown-runtime-D7D4PA-g.mjs} +4 -4
  63. package/dist/runtime-config/index.d.mts +2 -0
  64. package/dist/runtime-config/index.mjs +3 -0
  65. package/dist/runtime-config-Bn8Fivt1.mjs +100 -0
  66. package/dist/runtime-config-Bn8Fivt1.mjs.map +1 -0
  67. package/dist/server-D1TTN0_D.mjs +144 -0
  68. package/dist/server-D1TTN0_D.mjs.map +1 -0
  69. package/dist/service-BRoy_EId.d.mts +27 -0
  70. package/dist/service-jWxxfEht.mjs +7 -0
  71. package/dist/service-jWxxfEht.mjs.map +1 -0
  72. package/dist/state-store/index.d.mts +2 -0
  73. package/dist/state-store/index.mjs +2 -0
  74. package/dist/{state-store-BdYulQOY.js → state-store-DhSrKVEH.mjs} +15 -22
  75. package/dist/state-store-DhSrKVEH.mjs.map +1 -0
  76. package/dist/status/{index.d.ts → index.d.mts} +1 -4
  77. package/dist/status/{index.js → index.mjs} +2 -6
  78. package/dist/{status-BTTd7AUR.js → status-4h6Oxh-O.mjs} +14 -16
  79. package/dist/status-4h6Oxh-O.mjs.map +1 -0
  80. package/dist/table-CxM09xf7.mjs +307 -0
  81. package/dist/table-CxM09xf7.mjs.map +1 -0
  82. package/dist/types-NtSv6gwl.d.mts +220 -0
  83. package/dist/webhook/index.d.mts +3 -0
  84. package/dist/webhook/index.mjs +12 -0
  85. package/dist/webhook/index.mjs.map +1 -0
  86. package/package.json +72 -58
  87. package/src/catalog/retry.ts +25 -0
  88. package/src/catalog/table.ts +237 -0
  89. package/src/connector-app/create-table.ts +47 -0
  90. package/src/connector-app/demo.ts +47 -0
  91. package/src/connector-app/index.ts +3 -0
  92. package/src/connector-app/setup.ts +69 -0
  93. package/src/connector-app/start.ts +1 -1
  94. package/src/core/builder.ts +15 -23
  95. package/src/core/index.ts +11 -1
  96. package/src/core/types.ts +114 -39
  97. package/src/demo/definition.ts +68 -0
  98. package/src/demo/generate.ts +167 -0
  99. package/src/demo/index.ts +3 -0
  100. package/src/demo/run.ts +172 -0
  101. package/src/iceberg/annotations.ts +49 -0
  102. package/src/iceberg/error.ts +9 -0
  103. package/src/iceberg/index.ts +3 -0
  104. package/src/iceberg/table.ts +461 -0
  105. package/src/index.ts +3 -1
  106. package/src/ingestion/engine.ts +240 -60
  107. package/src/ingestor/arrow-flight.ts +141 -0
  108. package/src/ingestor/arrow.ts +248 -0
  109. package/src/ingestor/console.ts +13 -0
  110. package/src/ingestor/index.ts +13 -0
  111. package/src/ingestor/instrumented.ts +61 -0
  112. package/src/ingestor/service.ts +30 -0
  113. package/src/manifest/config.ts +3 -3
  114. package/src/metrics.ts +66 -20
  115. package/src/runtime-config/config.ts +11 -8
  116. package/src/runtime-config/constants.ts +3 -2
  117. package/src/runtime-config/index.ts +2 -7
  118. package/src/runtime-config/layer.ts +1 -1
  119. package/src/runtime-config/table-bindings.ts +50 -136
  120. package/src/state-store/layer-key-value-store.ts +8 -3
  121. package/src/state-store/layer-memory.ts +1 -1
  122. package/src/state-store/layer-sql.ts +4 -4
  123. package/src/state-store/schema.ts +2 -2
  124. package/src/state-store/state.ts +14 -2
  125. package/src/status/route.ts +2 -2
  126. package/src/telemetry.ts +20 -28
  127. package/src/webhook/server.ts +39 -40
  128. package/dist/auth/index.d.ts +0 -2
  129. package/dist/auth/index.js +0 -3
  130. package/dist/auth-DvU_CZ7C.js.map +0 -1
  131. package/dist/connector-app/index.d.ts +0 -14
  132. package/dist/connector-app/index.js +0 -12
  133. package/dist/connector-app-BljHd0Pe.js +0 -64
  134. package/dist/connector-app-BljHd0Pe.js.map +0 -1
  135. package/dist/constants-D113Ut1x.js.map +0 -1
  136. package/dist/errors/index.d.ts +0 -2
  137. package/dist/errors/index.js +0 -3
  138. package/dist/errors-DHWylqRZ.js.map +0 -1
  139. package/dist/index-BA8ASHKr.d.ts +0 -31
  140. package/dist/index.d.ts +0 -14
  141. package/dist/index.js +0 -60
  142. package/dist/index.js.map +0 -1
  143. package/dist/ingestion/index.d.ts +0 -6
  144. package/dist/ingestion/index.js +0 -11
  145. package/dist/ingestion-QBGKrFr9.js +0 -200
  146. package/dist/ingestion-QBGKrFr9.js.map +0 -1
  147. package/dist/manifest/index.d.ts +0 -2
  148. package/dist/manifest-P7kBnch9.js.map +0 -1
  149. package/dist/metrics-inkCAxKq.js +0 -136
  150. package/dist/metrics-inkCAxKq.js.map +0 -1
  151. package/dist/metrics.d.ts +0 -4
  152. package/dist/metrics.js +0 -5
  153. package/dist/publisher/index.d.ts +0 -6
  154. package/dist/publisher/index.js +0 -8
  155. package/dist/publisher-BdWJOfer.js +0 -138
  156. package/dist/publisher-BdWJOfer.js.map +0 -1
  157. package/dist/runtime-config/index.d.ts +0 -4
  158. package/dist/runtime-config/index.js +0 -5
  159. package/dist/runtime-config-IbyCVpei.js +0 -60
  160. package/dist/runtime-config-IbyCVpei.js.map +0 -1
  161. package/dist/server-D-eLX3yN.js +0 -183
  162. package/dist/server-D-eLX3yN.js.map +0 -1
  163. package/dist/service-CUjGhe-7.d.ts +0 -32
  164. package/dist/service-DiP-XETo.js +0 -8
  165. package/dist/service-DiP-XETo.js.map +0 -1
  166. package/dist/state-store/index.d.ts +0 -3
  167. package/dist/state-store/index.js +0 -5
  168. package/dist/state-store-BdYulQOY.js.map +0 -1
  169. package/dist/status-BTTd7AUR.js.map +0 -1
  170. package/dist/table-bindings-Dp1DhTeS.js +0 -106
  171. package/dist/table-bindings-Dp1DhTeS.js.map +0 -1
  172. package/dist/telemetry-j_nxwYfh.js.map +0 -1
  173. package/dist/types-jVD5Ys43.d.ts +0 -174
  174. package/dist/webhook/index.d.ts +0 -7
  175. package/dist/webhook/index.js +0 -9
  176. package/dist/webhook-MhFcLW-o.js +0 -13
  177. package/dist/webhook-MhFcLW-o.js.map +0 -1
  178. package/src/publisher/console.ts +0 -18
  179. package/src/publisher/index.ts +0 -7
  180. package/src/publisher/instrumented.ts +0 -75
  181. package/src/publisher/service.ts +0 -37
  182. package/src/publisher/wings.ts +0 -204
@@ -0,0 +1,16 @@
1
+ import { t as index_d_exports } from "./index-BX8G7d41.mjs";
2
+ import { t as ConnectorError } from "./index-DkVNO6ks.mjs";
3
+ import { t as Identified } from "./annotations-vzSzXtr-.mjs";
4
+ import { A as WebhookRouteContext, C as ResourceUpdateOf, D as WebhookAckMode, E as TableSource, O as WebhookHandler, S as ResourceUpdate, T as TableResource, _ as ResourceRequiredField, a as FeedRows, b as ResourceSchema, c as FetchPageResult, d as ResourceDefinition, f as ResourceDelete, g as ResourcePayload, i as Cursor$1, k as WebhookRoute, l as PageFetch, m as ResourceKey, n as ChangesFetch, o as FetchChangesResult, p as ResourceField, r as ConnectorDefinition, s as FetchFeedResult, t as ChangesFeed, u as ResourceBatch, v as ResourceRow, x as ResourceState, y as ResourceRows } from "./types-NtSv6gwl.mjs";
5
+ import { d as Cursor, f as Fetch, l as telemetry_d_exports, p as Resource, t as index_d_exports$1, u as Connector } from "./index-CZKx2Yce.mjs";
6
+ import { t as index_d_exports$2 } from "./index-CV6V6fyx.mjs";
7
+ import { t as index_d_exports$3 } from "./index-BTAbexBp.mjs";
8
+ import { t as index_d_exports$8 } from "./index-CgvFomO6.mjs";
9
+ import { t as index_d_exports$4 } from "./index-DeTwIUKl.mjs";
10
+ import { t as index_d_exports$5 } from "./index-uFa2wwYo.mjs";
11
+ import { t as index_d_exports$7 } from "./index-fHIJJoRe.mjs";
12
+ import { t as index_d_exports$6 } from "./index-eFuoMZZ3.mjs";
13
+ import { h as metrics_d_exports } from "./metrics-DoJ0WeKu.mjs";
14
+ import { t as index_d_exports$9 } from "./index-Byr8NTdG.mjs";
15
+ import { t as index_d_exports$10 } from "./index-dHS59EZl.mjs";
16
+ export { index_d_exports as Auth, type ChangesFeed, type ChangesFetch, Connector, index_d_exports$1 as ConnectorApp, type ConnectorDefinition, ConnectorError, Cursor, type Cursor$1 as CursorTypes, index_d_exports$2 as Demo, type FeedRows, Fetch, type FetchChangesResult, type FetchFeedResult, type FetchPageResult, index_d_exports$3 as Iceberg, type Identified, index_d_exports$4 as Ingestion, index_d_exports$5 as Ingestor, index_d_exports$6 as Manifest, metrics_d_exports as Metrics, type PageFetch, Resource, type ResourceBatch, type ResourceDefinition, type ResourceDelete, type ResourceField, type ResourceKey, type ResourcePayload, type ResourceRequiredField, type ResourceRow, type ResourceRows, type ResourceSchema, type ResourceState, type ResourceUpdate, type ResourceUpdateOf, index_d_exports$7 as RuntimeConfig, index_d_exports$8 as StateStore, index_d_exports$9 as Status, type TableResource, type TableSource, telemetry_d_exports as Telemetry, index_d_exports$10 as Webhook, type WebhookAckMode, type WebhookHandler, type WebhookRoute, type WebhookRouteContext };
package/dist/index.mjs ADDED
@@ -0,0 +1,45 @@
1
+ import { t as ConnectorError } from "./errors-pT0YVJU5.mjs";
2
+ import { t as auth_exports } from "./auth/index.mjs";
3
+ import { t as connector_app_exports } from "./connector-app-C6_dZnhE.mjs";
4
+ import { t as runtime_config_exports } from "./runtime-config-Bn8Fivt1.mjs";
5
+ import { t as demo_exports } from "./demo-DqTJ7TWI.mjs";
6
+ import { o as metrics_exports, w as telemetry_exports } from "./metrics-C901IIYZ.mjs";
7
+ import { t as state_store_exports } from "./state-store-DhSrKVEH.mjs";
8
+ import { t as status_exports } from "./status-4h6Oxh-O.mjs";
9
+ import { t as ingestion_exports } from "./ingestion-DoCUwm5N.mjs";
10
+ import { t as iceberg_exports } from "./iceberg-Cj2PwlNm.mjs";
11
+ import { t as ingestor_exports } from "./ingestor-DjCEzBzZ.mjs";
12
+ import { t as manifest_exports } from "./manifest-CABeIhAG.mjs";
13
+ import { t as webhook_exports } from "./webhook/index.mjs";
14
+ import { DateTime, Effect, Option } from "effect";
15
+ //#region src/core/builder.ts
16
+ const Connector = { define: (definition) => definition };
17
+ const Resource = { entity: (definition) => definition };
18
+ const Fetch = {
19
+ page: (definition) => definition,
20
+ changes: (definition) => definition,
21
+ feed: (definition) => definition
22
+ };
23
+ const decodeFailure = (kind, value) => new ConnectorError({ message: `Invalid ${kind} cursor value: ${String(value)}` });
24
+ const Cursor = {
25
+ string: () => ({
26
+ kind: "string",
27
+ decode: (value) => typeof value === "string" ? Effect.succeed(value) : Effect.fail(decodeFailure("string", value))
28
+ }),
29
+ number: () => ({
30
+ kind: "number",
31
+ decode: (value) => typeof value === "number" && Number.isFinite(value) ? Effect.succeed(value) : Effect.fail(decodeFailure("number", value))
32
+ }),
33
+ isoDateTime: () => ({
34
+ kind: "isoDateTime",
35
+ decode: (value) => {
36
+ if (typeof value !== "string" || Option.isNone(DateTime.make(value))) return Effect.fail(decodeFailure("ISO datetime", value));
37
+ return Effect.succeed(value);
38
+ }
39
+ }),
40
+ nowIsoDateTime: Effect.map(DateTime.now, DateTime.formatIso)
41
+ };
42
+ //#endregion
43
+ export { auth_exports as Auth, Connector, connector_app_exports as ConnectorApp, ConnectorError, Cursor, demo_exports as Demo, Fetch, iceberg_exports as Iceberg, ingestion_exports as Ingestion, ingestor_exports as Ingestor, manifest_exports as Manifest, metrics_exports as Metrics, Resource, runtime_config_exports as RuntimeConfig, state_store_exports as StateStore, status_exports as Status, telemetry_exports as Telemetry, webhook_exports as Webhook };
44
+
45
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/core/builder.ts"],"sourcesContent":["import { DateTime, Effect, Option } from \"effect\";\n\nimport type {\n ChangesFeed,\n ChangesFetch,\n ConnectorDefinition,\n Cursor as CursorType,\n PageFetch,\n ResourceDefinition,\n ResourceRequiredField,\n ResourceSchema,\n} from \"./types\";\n\nimport { ConnectorError } from \"../errors\";\n\nexport const Connector = {\n define: <\n const Resources extends ReadonlyArray<ResourceDefinition>,\n const FeedResources extends ReadonlyArray<Resources[number]> = Resources,\n >(\n definition: ConnectorDefinition<Resources, FeedResources>,\n ) => definition,\n};\n\nexport const Resource = {\n entity: <\n S extends ResourceSchema,\n Payload = never,\n R = never,\n const Name extends string = string,\n const Version extends ResourceRequiredField<S> = ResourceRequiredField<S>,\n >(\n definition: ResourceDefinition<S, Payload, R, Name, Version>,\n ): ResourceDefinition<S, Payload, R, Name, Version> => definition,\n};\n\nexport const Fetch = {\n page: <Row extends object = never, R = never>(definition: PageFetch<Row, R>) => definition,\n changes: <Row extends object = never, R = never>(definition: ChangesFetch<Row, R>) => definition,\n feed: <const Resources extends ReadonlyArray<ResourceDefinition>, R = never>(\n definition: ChangesFeed<Resources, R>,\n ) => definition,\n};\n\nconst decodeFailure = (kind: string, value: unknown) =>\n new ConnectorError({ message: `Invalid ${kind} cursor value: ${String(value)}` });\n\nexport const Cursor = {\n string: (): CursorType.Definition<string> => ({\n kind: \"string\",\n decode: (value) =>\n typeof value === \"string\"\n ? Effect.succeed(value)\n : Effect.fail(decodeFailure(\"string\", value)),\n }),\n\n number: (): CursorType.Definition<number> => ({\n kind: \"number\",\n decode: (value) =>\n typeof value === \"number\" && Number.isFinite(value)\n ? Effect.succeed(value)\n : Effect.fail(decodeFailure(\"number\", value)),\n }),\n\n isoDateTime: (): CursorType.Definition<string> => ({\n kind: \"isoDateTime\",\n decode: (value) => {\n if (typeof value !== \"string\" || Option.isNone(DateTime.make(value))) {\n return Effect.fail(decodeFailure(\"ISO datetime\", value));\n }\n return Effect.succeed(value);\n },\n }),\n\n nowIsoDateTime: Effect.map(DateTime.now, DateTime.formatIso),\n};\n"],"mappings":";;;;;;;;;;;;;;;AAeA,MAAa,YAAY,EACvB,SAIE,eACG,WACP;AAEA,MAAa,WAAW,EACtB,SAOE,eACqD,WACzD;AAEA,MAAa,QAAQ;CACnB,OAA8C,eAAkC;CAChF,UAAiD,eAAqC;CACtF,OACE,eACG;AACP;AAEA,MAAM,iBAAiB,MAAc,UACnC,IAAI,eAAe,EAAE,SAAS,WAAW,KAAK,iBAAiB,OAAO,KAAK,IAAI,CAAC;AAElF,MAAa,SAAS;CACpB,eAA8C;EAC5C,MAAM;EACN,SAAS,UACP,OAAO,UAAU,WACb,OAAO,QAAQ,KAAK,IACpB,OAAO,KAAK,cAAc,UAAU,KAAK,CAAC;CAClD;CAEA,eAA8C;EAC5C,MAAM;EACN,SAAS,UACP,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAC9C,OAAO,QAAQ,KAAK,IACpB,OAAO,KAAK,cAAc,UAAU,KAAK,CAAC;CAClD;CAEA,oBAAmD;EACjD,MAAM;EACN,SAAS,UAAU;GACjB,IAAI,OAAO,UAAU,YAAY,OAAO,OAAO,SAAS,KAAK,KAAK,CAAC,GACjE,OAAO,OAAO,KAAK,cAAc,gBAAgB,KAAK,CAAC;GAEzD,OAAO,OAAO,QAAQ,KAAK;EAC7B;CACF;CAEA,gBAAgB,OAAO,IAAI,SAAS,KAAK,SAAS,SAAS;AAC7D"}
@@ -0,0 +1,2 @@
1
+ import { n as RunOptions, r as run } from "../index-DeTwIUKl.mjs";
2
+ export { type RunOptions, run };
@@ -0,0 +1,2 @@
1
+ import { n as run } from "../ingestion-DoCUwm5N.mjs";
2
+ export { run };
@@ -0,0 +1,275 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
+ import { t as ConnectorError } from "./errors-pT0YVJU5.mjs";
3
+ import { C as annotateError, d as setLastSuccessTimestamp, f as setSyncState, p as setWebhookQueueDepth, v as Attr, x as SpanName } from "./metrics-C901IIYZ.mjs";
4
+ import { t as Ingestor } from "./service-jWxxfEht.mjs";
5
+ import { t as ingestBatch } from "./instrumented-Bq1WX2L5.mjs";
6
+ import { o as StateStore } from "./state-store-DhSrKVEH.mjs";
7
+ import { c as deriveSyncState, l as hasChanges, s as statusRoute, u as normalizeCursor } from "./status-4h6Oxh-O.mjs";
8
+ import { n as router, t as WebhookQueue } from "./server-D1TTN0_D.mjs";
9
+ import { Array, DateTime, Effect, Layer, Order, Queue } from "effect";
10
+ import { HttpRouter, HttpServerResponse } from "effect/http";
11
+ import * as Observability from "effect/observability";
12
+ //#region src/ingestion/engine.ts
13
+ function run(definition, options) {
14
+ return Effect.gen(function* () {
15
+ if (definition.changes) yield* validateFeed(definition, definition.changes);
16
+ const ingestor = yield* Ingestor;
17
+ const connector = selectResources(definition, ingestor.resourceNames);
18
+ const queueLayer = makeWebhookQueueLayer(connector.name);
19
+ const runtimeLayer = options?.webhook ? Layer.mergeAll(queueLayer, makeWebhookServerLayer(connector, options.webhook).pipe(Layer.provide(queueLayer))) : Layer.empty;
20
+ return yield* Effect.gen(function* () {
21
+ const initialCutoff = options?.initialCutoff ?? (yield* DateTime.now.pipe(Effect.map(DateTime.formatIso)));
22
+ yield* Effect.logInfo("Connector started").pipe(Effect.annotateLogs({
23
+ [Attr.connectorName]: connector.name,
24
+ resources: connector.resources.length
25
+ }));
26
+ const sourceRun = runIngestion(connector, initialCutoff);
27
+ const webhookRun = options?.webhook ? runWebhookRuntime(connector, options.webhook.routes) : Effect.void;
28
+ return yield* Effect.all([sourceRun, webhookRun], { concurrency: "unbounded" }).pipe(Effect.asVoid);
29
+ }).pipe(Effect.provide(runtimeLayer));
30
+ });
31
+ }
32
+ const selectResources = (connector, names) => {
33
+ if (names === void 0) return connector;
34
+ const isSelected = (resource) => names.includes(resource.name);
35
+ const { changes, ...rest } = connector;
36
+ const feedResources = changes?.resources.filter(isSelected) ?? [];
37
+ return {
38
+ ...rest,
39
+ resources: connector.resources.filter(isSelected),
40
+ ...changes && feedResources.length > 0 ? { changes: {
41
+ ...changes,
42
+ resources: feedResources
43
+ } } : {}
44
+ };
45
+ };
46
+ const makeWebhookQueueLayer = (connector) => Layer.effect(WebhookQueue)(Effect.gen(function* () {
47
+ const queue = yield* Queue.bounded(1024);
48
+ yield* setWebhookQueueDepth(connector, 0);
49
+ return WebhookQueue.of({ queue });
50
+ }));
51
+ const runWebhookRuntime = (connector, routes) => {
52
+ const hasAfterEnqueue = routes.some((route) => route.ackMode === "after-enqueue");
53
+ return Effect.all([hasAfterEnqueue ? runWebhookQueueConsumer(connector) : Effect.void, Effect.never], { concurrency: "unbounded" }).pipe(Effect.asVoid);
54
+ };
55
+ const runWebhookQueueConsumer = (connector) => Effect.gen(function* () {
56
+ const queue = yield* WebhookQueue;
57
+ while (true) {
58
+ const batch = yield* Queue.take(queue.queue);
59
+ const depth = yield* Queue.size(queue.queue);
60
+ yield* setWebhookQueueDepth(connector.name, depth);
61
+ yield* ingestBatch({
62
+ connector: connector.name,
63
+ resource: batch.resource,
64
+ source: "webhook",
65
+ batch: batch.batch
66
+ });
67
+ }
68
+ });
69
+ const makeWebhookServerLayer = (connector, options) => {
70
+ const healthPath = options.healthPath ?? "/health";
71
+ const metricsPath = options.metricsPath === void 0 ? "/metrics" : options.metricsPath;
72
+ const statusPath = options.statusPath === void 0 ? "/status" : options.statusPath;
73
+ const app = Layer.mergeAll(router(options.routes, {
74
+ connectorName: connector.name,
75
+ resourceNames: connector.resources.map((resource) => resource.name)
76
+ }), HttpRouter.add("GET", healthPath, Effect.succeed(HttpServerResponse.text("ok"))), ...metricsPath === false ? [] : [Observability.PrometheusMetrics.layerHttp({ path: metricsPath })], ...statusPath === false ? [] : [statusRoute(connector, statusPath)]);
77
+ return HttpRouter.serve(app, { disableLogger: options.disableHttpLogger ?? true });
78
+ };
79
+ const runIngestion = (connector, initialCutoff) => Effect.gen(function* () {
80
+ const feed = connector.changes;
81
+ yield* Effect.all([Effect.forEach(connector.resources, (resource) => runResourceSources(connector, resource, initialCutoff), { concurrency: "unbounded" }), feed ? runChangesFeed(connector, feed, initialCutoff) : Effect.void], { concurrency: "unbounded" });
82
+ });
83
+ const bySavedAt = Order.mapInput(Order.String, (state) => state.lastSuccessAt ?? "");
84
+ const validateFeed = (connector, feed) => Effect.forEach(feed.resources, (member, index) => {
85
+ if (feed.resources.findIndex((item) => item.name === member.name) !== index) return Effect.fail(new ConnectorError({ message: `Resource ${member.name} is in the changes feed twice` }));
86
+ const resource = connector.resources.find((item) => item.name === member.name);
87
+ if (!resource) return Effect.fail(new ConnectorError({ message: `Changes feed resource ${member.name} is not a resource of connector ${connector.name}` }));
88
+ if (resource.changes) return Effect.fail(new ConnectorError({ message: `Resource ${member.name} has its own changes and is also in the changes feed` }));
89
+ return Effect.void;
90
+ }).pipe(Effect.andThen(feed.resources.length === 0 ? Effect.fail(new ConnectorError({ message: "The changes feed has no resources" })) : Effect.void));
91
+ const initializeResourceState = (existing, initialCutoff) => ({
92
+ ...existing,
93
+ changes: existing?.changes ?? { cursor: initialCutoff },
94
+ backfill: existing?.backfill ?? {
95
+ cutoff: initialCutoff,
96
+ completed: false
97
+ }
98
+ });
99
+ const getInitializedState = Effect.fnUntraced(function* (resource, initialCutoff) {
100
+ const existing = yield* (yield* StateStore).getResourceState(resource);
101
+ return initializeResourceState(existing, initialCutoff);
102
+ });
103
+ const runResourceSources = (connector, resource, initialCutoff) => {
104
+ const runs = [resource.backfill ? isolateSourceFailure(runBackfill(connector, resource, initialCutoff), connector, resource, "backfill") : Effect.void, resource.changes ? isolateSourceFailure(runChanges(connector, resource, initialCutoff), connector, resource, "changes") : Effect.void];
105
+ return initializeRuntimeStatus(connector, resource, initialCutoff).pipe(Effect.andThen(Effect.all(runs, { concurrency: "unbounded" })), Effect.asVoid, Effect.catch((error) => setSyncState({
106
+ connector: connector.name,
107
+ resource: resource.name
108
+ }, "error").pipe(Effect.andThen(Effect.logError("Connector resource initialization failed", error)), Effect.annotateLogs({
109
+ [Attr.connectorName]: connector.name,
110
+ resource: resource.name
111
+ }), Effect.andThen(Effect.never))));
112
+ };
113
+ const recordResourceError = (connector, resource, source, operation) => (effect) => effect.pipe(Effect.tapError(() => setSyncState({
114
+ connector: connector.name,
115
+ resource: resource.name
116
+ }, "error").pipe(Effect.andThen(StateStore.pipe(Effect.flatMap((store) => store.setResourceError(resource.name, source, operation)))))));
117
+ const isolateSourceFailure = (effect, connector, resource, source) => effect.pipe(Effect.catch((error) => Effect.logError("Connector source parked", error).pipe(Effect.annotateLogs({
118
+ [Attr.connectorName]: connector.name,
119
+ resource: resource.name,
120
+ source
121
+ }), Effect.andThen(Effect.never))));
122
+ const refreshRuntimeStatus = Effect.fnUntraced(function* (connector, resource, initialCutoff) {
123
+ const state = yield* getInitializedState(resource.name, initialCutoff);
124
+ yield* setSyncState({
125
+ connector: connector.name,
126
+ resource: resource.name
127
+ }, deriveSyncState(connector, resource, state));
128
+ return state;
129
+ });
130
+ const initializeRuntimeStatus = Effect.fnUntraced(function* (connector, resource, initialCutoff) {
131
+ const state = yield* getInitializedState(resource.name, initialCutoff);
132
+ yield* setSyncState({
133
+ connector: connector.name,
134
+ resource: resource.name
135
+ }, deriveSyncState(connector, resource, state));
136
+ if (resource.backfill) yield* setLastSuccessTimestamp({
137
+ connector: connector.name,
138
+ resource: resource.name,
139
+ source: "backfill"
140
+ }, state.backfill?.lastSuccessAt);
141
+ if (hasChanges(connector, resource)) yield* setLastSuccessTimestamp({
142
+ connector: connector.name,
143
+ resource: resource.name,
144
+ source: "changes"
145
+ }, state.changes?.lastSuccessAt);
146
+ });
147
+ const runBackfill = Effect.fnUntraced(function* (connector, resource, initialCutoff) {
148
+ if (!resource.backfill) return;
149
+ const store = yield* StateStore;
150
+ let state = yield* getInitializedState(resource.name, initialCutoff);
151
+ if (state.backfill?.completed === true) {
152
+ yield* store.clearResourceError(resource.name, "backfill").pipe(recordResourceError(connector, resource, "backfill", "checkpoint"));
153
+ yield* refreshRuntimeStatus(connector, resource, initialCutoff);
154
+ return;
155
+ }
156
+ while (state.backfill?.completed !== true) {
157
+ const backfill = state.backfill ?? {
158
+ cutoff: initialCutoff,
159
+ completed: false
160
+ };
161
+ const clearsVisibleError = state.lastError?.source === "backfill";
162
+ const page = yield* resource.backfill.fetch({
163
+ pageCursor: backfill.pageCursor,
164
+ cutoff: backfill.cutoff
165
+ }).pipe(recordResourceError(connector, resource, "backfill", "fetch"));
166
+ yield* ingestBatch({
167
+ connector: connector.name,
168
+ resource: resource.name,
169
+ source: "backfill",
170
+ batch: {
171
+ cursor: page.nextPageCursor ?? backfill.cutoff,
172
+ rows: page.rows
173
+ }
174
+ }).pipe(recordResourceError(connector, resource, "backfill", "ingest"));
175
+ const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));
176
+ state = {
177
+ ...state,
178
+ backfill: {
179
+ cutoff: backfill.cutoff,
180
+ pageCursor: page.nextPageCursor,
181
+ completed: !page.hasMore,
182
+ lastSuccessAt
183
+ }
184
+ };
185
+ yield* Effect.withSpan(store.setBackfillState(resource.name, {
186
+ cutoff: normalizeCursor(backfill.cutoff),
187
+ pageCursor: page.nextPageCursor === void 0 ? void 0 : normalizeCursor(page.nextPageCursor),
188
+ completed: !page.hasMore,
189
+ lastSuccessAt
190
+ }).pipe(Effect.andThen(setLastSuccessTimestamp({
191
+ connector: connector.name,
192
+ resource: resource.name,
193
+ source: "backfill"
194
+ }, lastSuccessAt)), Effect.andThen(store.clearResourceError(resource.name, "backfill")), Effect.tapError((error) => annotateError("state_set", error))), SpanName.stateSet, { attributes: { [Attr.stateKey]: resource.name } }).pipe(recordResourceError(connector, resource, "backfill", "checkpoint"));
195
+ if (clearsVisibleError || !page.hasMore) state = yield* refreshRuntimeStatus(connector, resource, initialCutoff);
196
+ }
197
+ });
198
+ const runChanges = Effect.fnUntraced(function* (connector, resource, initialCutoff) {
199
+ if (!resource.changes) return;
200
+ const store = yield* StateStore;
201
+ while (true) {
202
+ const state = yield* getInitializedState(resource.name, initialCutoff);
203
+ const cursor = state.changes?.cursor ?? initialCutoff;
204
+ const clearsVisibleError = state.lastError?.source === "changes";
205
+ const page = yield* resource.changes.fetch({ cursor }).pipe(recordResourceError(connector, resource, "changes", "fetch"));
206
+ yield* ingestBatch({
207
+ connector: connector.name,
208
+ resource: resource.name,
209
+ source: "changes",
210
+ batch: {
211
+ cursor: page.cursor,
212
+ rows: page.rows
213
+ }
214
+ }).pipe(recordResourceError(connector, resource, "changes", "ingest"));
215
+ const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));
216
+ yield* Effect.withSpan(store.setChangesState(resource.name, {
217
+ cursor: normalizeCursor(page.cursor),
218
+ lastSuccessAt
219
+ }).pipe(Effect.andThen(setLastSuccessTimestamp({
220
+ connector: connector.name,
221
+ resource: resource.name,
222
+ source: "changes"
223
+ }, lastSuccessAt)), Effect.andThen(store.clearResourceError(resource.name, "changes")), Effect.tapError((error) => annotateError("state_set", error))), SpanName.stateSet, { attributes: { [Attr.stateKey]: resource.name } }).pipe(recordResourceError(connector, resource, "changes", "checkpoint"));
224
+ if (clearsVisibleError) yield* refreshRuntimeStatus(connector, resource, initialCutoff);
225
+ if (!page.hasMore) yield* Effect.sleep(resource.changes.interval ?? "1 minute");
226
+ }
227
+ });
228
+ const runChangesFeed = (connector, feed, initialCutoff) => Effect.gen(function* () {
229
+ const store = yield* StateStore;
230
+ const members = feed.resources;
231
+ const selected = new Set(members.map((resource) => resource.name));
232
+ const recordFeedError = (operation) => (effect) => effect.pipe(Effect.tapError(() => Effect.forEach(members, (resource) => setSyncState({
233
+ connector: connector.name,
234
+ resource: resource.name
235
+ }, "error").pipe(Effect.andThen(store.setResourceError(resource.name, "changes", operation))), { discard: true })));
236
+ while (true) {
237
+ const states = yield* Effect.forEach(members, (resource) => store.getResourceState(resource.name));
238
+ const saved = states.flatMap((state) => state?.changes ? [state.changes] : []);
239
+ const cursor = Array.isReadonlyArrayNonEmpty(saved) ? Array.min(saved, bySavedAt).cursor : initialCutoff;
240
+ const result = yield* feed.fetch({
241
+ cursor,
242
+ selected
243
+ }).pipe(recordFeedError("fetch"));
244
+ yield* Effect.forEach(members, (resource) => ingestBatch({
245
+ connector: connector.name,
246
+ resource: resource.name,
247
+ source: "changes",
248
+ batch: {
249
+ cursor: result.cursor,
250
+ rows: result.rows[resource.name] ?? []
251
+ }
252
+ }), { discard: true }).pipe(recordFeedError("ingest"));
253
+ const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));
254
+ yield* Effect.forEach(members, (resource) => Effect.withSpan(store.setChangesState(resource.name, {
255
+ cursor: normalizeCursor(result.cursor),
256
+ lastSuccessAt
257
+ }).pipe(Effect.andThen(setLastSuccessTimestamp({
258
+ connector: connector.name,
259
+ resource: resource.name,
260
+ source: "changes"
261
+ }, lastSuccessAt)), Effect.andThen(store.clearResourceError(resource.name, "changes")), Effect.tapError((error) => annotateError("state_set", error))), SpanName.stateSet, { attributes: { [Attr.stateKey]: resource.name } }), { discard: true }).pipe(recordFeedError("checkpoint"));
262
+ yield* Effect.forEach(members, (resource, index) => states[index]?.lastError?.source === "changes" ? refreshRuntimeStatus(connector, resource, initialCutoff) : Effect.void);
263
+ if (!result.hasMore) yield* Effect.sleep(feed.interval ?? "1 minute");
264
+ }
265
+ }).pipe(Effect.catch((error) => Effect.logError("Connector changes feed parked", error).pipe(Effect.annotateLogs({
266
+ [Attr.connectorName]: connector.name,
267
+ resources: feed.resources.map((resource) => resource.name).join(",")
268
+ }), Effect.andThen(Effect.never))));
269
+ //#endregion
270
+ //#region src/ingestion/index.ts
271
+ var ingestion_exports = /* @__PURE__ */ __exportAll({ run: () => run });
272
+ //#endregion
273
+ export { run as n, ingestion_exports as t };
274
+
275
+ //# sourceMappingURL=ingestion-DoCUwm5N.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingestion-DoCUwm5N.mjs","names":["Metrics.setWebhookQueueDepth","Metrics.setSyncState","Metrics.setLastSuccessTimestamp","Arr"],"sources":["../src/ingestion/engine.ts","../src/ingestion/index.ts"],"sourcesContent":["import { Array as Arr, DateTime, Effect, Layer, Order, Queue } from \"effect\";\nimport { HttpRouter, type HttpServer, HttpServerResponse } from \"effect/http\";\nimport * as Observability from \"effect/observability\";\n\nimport type {\n ChangesFeed,\n ConnectorDefinition,\n Cursor,\n ResourceDefinition,\n ResourceState,\n WebhookRoute,\n} from \"../core/types\";\nimport type { StateOperation, StateSource } from \"../state-store/schema\";\n\nimport { ConnectorError } from \"../errors\";\nimport { ingestBatch } from \"../ingestor/instrumented\";\nimport { Ingestor } from \"../ingestor/service\";\nimport * as Metrics from \"../metrics\";\nimport { StateStore } from \"../state-store\";\nimport { deriveSyncState, hasChanges, normalizeCursor } from \"../state-store/state\";\nimport { statusRoute } from \"../status\";\nimport { Attr, SpanName, annotateError } from \"../telemetry\";\nimport { router, WebhookQueue, type QueuedWebhookBatch } from \"../webhook/server\";\n\ntype RunBaseOptions = {\n readonly initialCutoff?: Cursor.Value;\n};\n\nexport type RunOptions = RunBaseOptions & {\n readonly webhook?: {\n readonly routes: ReadonlyArray<WebhookRoute>;\n readonly healthPath?: HttpRouter.PathInput;\n readonly metricsPath?: HttpRouter.PathInput | false;\n readonly statusPath?: HttpRouter.PathInput | false;\n readonly disableHttpLogger?: boolean;\n };\n};\n\ntype RunNoWebhookOptions = RunBaseOptions & {\n readonly webhook?: undefined;\n};\n\ntype RunWebhookOptions = RunOptions & {\n readonly webhook: NonNullable<RunOptions[\"webhook\"]>;\n};\n\n/**\n * Runs all connector ingestion loops. Callers provide the Ingestor and\n * StateStore layers; webhook mode additionally requires an HttpServer layer.\n */\nexport function run<const Resources extends ReadonlyArray<ResourceDefinition>>(\n connector: ConnectorDefinition<Resources>,\n options?: RunNoWebhookOptions,\n): Effect.Effect<void, ConnectorError, StateStore | Ingestor>;\nexport function run<const Resources extends ReadonlyArray<ResourceDefinition>>(\n connector: ConnectorDefinition<Resources>,\n options: RunWebhookOptions,\n): Effect.Effect<void, ConnectorError, StateStore | Ingestor | HttpServer.HttpServer>;\nexport function run(definition: ConnectorDefinition, options?: RunOptions) {\n return Effect.gen(function* () {\n // Check the whole feed, even the resources that don't run.\n if (definition.changes) yield* validateFeed(definition, definition.changes);\n const ingestor = yield* Ingestor;\n const connector = selectResources(definition, ingestor.resourceNames);\n const queueLayer = makeWebhookQueueLayer(connector.name);\n const runtimeLayer = options?.webhook\n ? Layer.mergeAll(\n queueLayer,\n makeWebhookServerLayer(connector, options.webhook).pipe(Layer.provide(queueLayer)),\n )\n : Layer.empty;\n\n return yield* Effect.gen(function* () {\n const initialCutoff =\n options?.initialCutoff ?? (yield* DateTime.now.pipe(Effect.map(DateTime.formatIso)));\n yield* Effect.logInfo(\"Connector started\").pipe(\n Effect.annotateLogs({\n [Attr.connectorName]: connector.name,\n resources: connector.resources.length,\n }),\n );\n\n const sourceRun = runIngestion(connector, initialCutoff);\n const webhookRun = options?.webhook\n ? runWebhookRuntime(connector, options.webhook.routes)\n : Effect.void;\n\n return yield* Effect.all([sourceRun, webhookRun], { concurrency: \"unbounded\" }).pipe(\n Effect.asVoid,\n );\n }).pipe(Effect.provide(runtimeLayer));\n });\n}\n\nconst selectResources = (\n connector: ConnectorDefinition,\n names: ReadonlyArray<string> | undefined,\n): ConnectorDefinition => {\n if (names === undefined) return connector;\n const isSelected = (resource: ResourceDefinition) => names.includes(resource.name);\n const { changes, ...rest } = connector;\n const feedResources = changes?.resources.filter(isSelected) ?? [];\n return {\n ...rest,\n resources: connector.resources.filter(isSelected),\n ...(changes && feedResources.length > 0\n ? { changes: { ...changes, resources: feedResources } }\n : {}),\n };\n};\n\nconst makeWebhookQueueLayer = (connector: string): Layer.Layer<WebhookQueue> =>\n Layer.effect(WebhookQueue)(\n Effect.gen(function* () {\n const queue = yield* Queue.bounded<QueuedWebhookBatch>(1024);\n yield* Metrics.setWebhookQueueDepth(connector, 0);\n return WebhookQueue.of({ queue });\n }),\n );\n\nconst runWebhookRuntime = (connector: ConnectorDefinition, routes: ReadonlyArray<WebhookRoute>) => {\n const hasAfterEnqueue = routes.some((route) => route.ackMode === \"after-enqueue\");\n return Effect.all(\n [hasAfterEnqueue ? runWebhookQueueConsumer(connector) : Effect.void, Effect.never],\n {\n concurrency: \"unbounded\",\n },\n ).pipe(Effect.asVoid);\n};\n\nconst runWebhookQueueConsumer = (connector: ConnectorDefinition) =>\n Effect.gen(function* () {\n const queue = yield* WebhookQueue;\n while (true) {\n const batch = yield* Queue.take(queue.queue);\n const depth = yield* Queue.size(queue.queue);\n yield* Metrics.setWebhookQueueDepth(connector.name, depth);\n yield* ingestBatch({\n connector: connector.name,\n resource: batch.resource,\n source: \"webhook\",\n batch: batch.batch,\n });\n }\n });\n\nconst makeWebhookServerLayer = (\n connector: ConnectorDefinition,\n options: {\n readonly routes: ReadonlyArray<WebhookRoute>;\n readonly healthPath?: HttpRouter.PathInput;\n readonly metricsPath?: HttpRouter.PathInput | false;\n readonly statusPath?: HttpRouter.PathInput | false;\n readonly disableHttpLogger?: boolean;\n },\n): Layer.Layer<never, never, HttpServer.HttpServer> => {\n const healthPath: HttpRouter.PathInput = options.healthPath ?? \"/health\";\n const metricsPath = options.metricsPath === undefined ? \"/metrics\" : options.metricsPath;\n const statusPath = options.statusPath === undefined ? \"/status\" : options.statusPath;\n const app = Layer.mergeAll(\n router(options.routes, {\n connectorName: connector.name,\n resourceNames: connector.resources.map((resource) => resource.name),\n }),\n HttpRouter.add(\"GET\", healthPath, Effect.succeed(HttpServerResponse.text(\"ok\"))),\n ...(metricsPath === false\n ? []\n : [Observability.PrometheusMetrics.layerHttp({ path: metricsPath })]),\n ...(statusPath === false ? [] : [statusRoute(connector, statusPath)]),\n );\n\n return HttpRouter.serve(app, {\n disableLogger: options.disableHttpLogger ?? true,\n });\n};\n\nconst runIngestion = (\n connector: ConnectorDefinition,\n initialCutoff: Cursor.Value,\n): Effect.Effect<void, ConnectorError, StateStore | Ingestor> =>\n Effect.gen(function* () {\n const feed = connector.changes;\n yield* Effect.all(\n [\n Effect.forEach(\n connector.resources,\n (resource) => runResourceSources(connector, resource, initialCutoff),\n { concurrency: \"unbounded\" },\n ),\n feed ? runChangesFeed(connector, feed, initialCutoff) : Effect.void,\n ],\n { concurrency: \"unbounded\" },\n );\n });\n\nconst bySavedAt = Order.mapInput(\n Order.String,\n (state: NonNullable<ResourceState[\"changes\"]>) => state.lastSuccessAt ?? \"\",\n);\n\nconst validateFeed = (connector: ConnectorDefinition, feed: ChangesFeed) =>\n Effect.forEach(feed.resources, (member, index) => {\n if (feed.resources.findIndex((item) => item.name === member.name) !== index) {\n return Effect.fail(\n new ConnectorError({ message: `Resource ${member.name} is in the changes feed twice` }),\n );\n }\n const resource = connector.resources.find((item) => item.name === member.name);\n if (!resource) {\n return Effect.fail(\n new ConnectorError({\n message: `Changes feed resource ${member.name} is not a resource of connector ${connector.name}`,\n }),\n );\n }\n if (resource.changes) {\n return Effect.fail(\n new ConnectorError({\n message: `Resource ${member.name} has its own changes and is also in the changes feed`,\n }),\n );\n }\n return Effect.void;\n }).pipe(\n Effect.andThen(\n feed.resources.length === 0\n ? Effect.fail(new ConnectorError({ message: \"The changes feed has no resources\" }))\n : Effect.void,\n ),\n );\n\nconst initializeResourceState = (\n existing: ResourceState | undefined,\n initialCutoff: Cursor.Value,\n): ResourceState => ({\n ...existing,\n changes: existing?.changes ?? { cursor: initialCutoff },\n backfill: existing?.backfill ?? {\n cutoff: initialCutoff,\n completed: false,\n },\n});\n\nconst getInitializedState = Effect.fnUntraced(function* (\n resource: string,\n initialCutoff: Cursor.Value,\n) {\n const store = yield* StateStore;\n const existing = yield* store.getResourceState(resource);\n return initializeResourceState(existing, initialCutoff);\n});\n\nconst runResourceSources = (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) => {\n const runs = [\n resource.backfill\n ? isolateSourceFailure(\n runBackfill(connector, resource, initialCutoff),\n connector,\n resource,\n \"backfill\",\n )\n : Effect.void,\n resource.changes\n ? isolateSourceFailure(\n runChanges(connector, resource, initialCutoff),\n connector,\n resource,\n \"changes\",\n )\n : Effect.void,\n ];\n\n return initializeRuntimeStatus(connector, resource, initialCutoff).pipe(\n Effect.andThen(Effect.all(runs, { concurrency: \"unbounded\" })),\n Effect.asVoid,\n Effect.catch((error) =>\n Metrics.setSyncState({ connector: connector.name, resource: resource.name }, \"error\").pipe(\n Effect.andThen(Effect.logError(\"Connector resource initialization failed\", error)),\n Effect.annotateLogs({\n [Attr.connectorName]: connector.name,\n resource: resource.name,\n }),\n Effect.andThen(Effect.never),\n ),\n ),\n );\n};\n\nconst recordResourceError =\n (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n source: StateSource,\n operation: StateOperation,\n ) =>\n <A, R>(\n effect: Effect.Effect<A, ConnectorError, R>,\n ): Effect.Effect<A, ConnectorError, R | StateStore> =>\n effect.pipe(\n Effect.tapError(() =>\n Metrics.setSyncState({ connector: connector.name, resource: resource.name }, \"error\").pipe(\n Effect.andThen(\n StateStore.pipe(\n Effect.flatMap((store) => store.setResourceError(resource.name, source, operation)),\n ),\n ),\n ),\n ),\n );\n\nconst isolateSourceFailure = <A, R>(\n effect: Effect.Effect<A, ConnectorError, R>,\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n source: StateSource,\n): Effect.Effect<A, never, R> =>\n // Only typed source errors are isolated. Defects and interruption still stop the runtime.\n effect.pipe(\n Effect.catch((error) =>\n Effect.logError(\"Connector source parked\", error).pipe(\n Effect.annotateLogs({\n [Attr.connectorName]: connector.name,\n resource: resource.name,\n source,\n }),\n Effect.andThen(Effect.never),\n ),\n ),\n );\n\nconst refreshRuntimeStatus = Effect.fnUntraced(function* (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) {\n const state = yield* getInitializedState(resource.name, initialCutoff);\n yield* Metrics.setSyncState(\n { connector: connector.name, resource: resource.name },\n deriveSyncState(connector, resource, state),\n );\n\n return state;\n});\n\nconst initializeRuntimeStatus = Effect.fnUntraced(function* (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) {\n const state = yield* getInitializedState(resource.name, initialCutoff);\n yield* Metrics.setSyncState(\n { connector: connector.name, resource: resource.name },\n deriveSyncState(connector, resource, state),\n );\n\n if (resource.backfill) {\n yield* Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"backfill\" },\n state.backfill?.lastSuccessAt,\n );\n }\n if (hasChanges(connector, resource)) {\n yield* Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"changes\" },\n state.changes?.lastSuccessAt,\n );\n }\n});\n\nconst runBackfill = Effect.fnUntraced(function* (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) {\n if (!resource.backfill) return;\n const store = yield* StateStore;\n let state = yield* getInitializedState(resource.name, initialCutoff);\n\n if (state.backfill?.completed === true) {\n // The checkpoint may have committed before the previous process cleared\n // its error marker. It may also be hidden by a newer changes error.\n yield* store\n .clearResourceError(resource.name, \"backfill\")\n .pipe(recordResourceError(connector, resource, \"backfill\", \"checkpoint\"));\n yield* refreshRuntimeStatus(connector, resource, initialCutoff);\n return;\n }\n\n while (state.backfill?.completed !== true) {\n const backfill = state.backfill ?? { cutoff: initialCutoff, completed: false };\n const clearsVisibleError = state.lastError?.source === \"backfill\";\n const page = yield* resource.backfill\n .fetch({\n pageCursor: backfill.pageCursor,\n cutoff: backfill.cutoff,\n })\n .pipe(recordResourceError(connector, resource, \"backfill\", \"fetch\"));\n\n yield* ingestBatch({\n connector: connector.name,\n resource: resource.name,\n source: \"backfill\",\n batch: {\n cursor: page.nextPageCursor ?? backfill.cutoff,\n rows: page.rows,\n },\n }).pipe(recordResourceError(connector, resource, \"backfill\", \"ingest\"));\n\n const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));\n state = {\n ...state,\n backfill: {\n cutoff: backfill.cutoff,\n pageCursor: page.nextPageCursor,\n completed: !page.hasMore,\n lastSuccessAt,\n },\n };\n\n // Checkpoint only after ingestion succeeds so a crash cannot skip an\n // unacknowledged page; replay therefore remains at-least-once.\n yield* Effect.withSpan(\n store\n .setBackfillState(resource.name, {\n cutoff: normalizeCursor(backfill.cutoff),\n pageCursor:\n page.nextPageCursor === undefined ? undefined : normalizeCursor(page.nextPageCursor),\n completed: !page.hasMore,\n lastSuccessAt,\n })\n .pipe(\n Effect.andThen(\n Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"backfill\" },\n lastSuccessAt,\n ),\n ),\n Effect.andThen(store.clearResourceError(resource.name, \"backfill\")),\n Effect.tapError((error) => annotateError(\"state_set\", error)),\n ),\n SpanName.stateSet,\n { attributes: { [Attr.stateKey]: resource.name } },\n ).pipe(recordResourceError(connector, resource, \"backfill\", \"checkpoint\"));\n\n // Completion or clearing an error can change the resource-wide sync state.\n if (clearsVisibleError || !page.hasMore) {\n state = yield* refreshRuntimeStatus(connector, resource, initialCutoff);\n }\n }\n});\n\nconst runChanges = Effect.fnUntraced(function* (\n connector: ConnectorDefinition,\n resource: ResourceDefinition,\n initialCutoff: Cursor.Value,\n) {\n if (!resource.changes) return;\n const store = yield* StateStore;\n\n while (true) {\n const state = yield* getInitializedState(resource.name, initialCutoff);\n const cursor = state.changes?.cursor ?? initialCutoff;\n const clearsVisibleError = state.lastError?.source === \"changes\";\n const page = yield* resource.changes\n .fetch({ cursor })\n .pipe(recordResourceError(connector, resource, \"changes\", \"fetch\"));\n\n yield* ingestBatch({\n connector: connector.name,\n resource: resource.name,\n source: \"changes\",\n batch: {\n cursor: page.cursor,\n rows: page.rows,\n },\n }).pipe(recordResourceError(connector, resource, \"changes\", \"ingest\"));\n\n const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));\n // Advance the durable cursor only after the engine acknowledges the page.\n yield* Effect.withSpan(\n store\n .setChangesState(resource.name, {\n cursor: normalizeCursor(page.cursor),\n lastSuccessAt,\n })\n .pipe(\n Effect.andThen(\n Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"changes\" },\n lastSuccessAt,\n ),\n ),\n Effect.andThen(store.clearResourceError(resource.name, \"changes\")),\n Effect.tapError((error) => annotateError(\"state_set\", error)),\n ),\n SpanName.stateSet,\n { attributes: { [Attr.stateKey]: resource.name } },\n ).pipe(recordResourceError(connector, resource, \"changes\", \"checkpoint\"));\n\n if (clearsVisibleError) {\n yield* refreshRuntimeStatus(connector, resource, initialCutoff);\n }\n\n if (!page.hasMore) {\n yield* Effect.sleep(resource.changes.interval ?? \"1 minute\");\n }\n }\n});\n\n// Every member resource stores the feed cursor. All rows are ingested before any\n// cursor is written. If a crash stops the writes partway, the next run starts\n// from the oldest cursor.\nconst runChangesFeed = (\n connector: ConnectorDefinition,\n feed: ChangesFeed,\n initialCutoff: Cursor.Value,\n): Effect.Effect<void, never, StateStore | Ingestor> =>\n Effect.gen(function* () {\n const store = yield* StateStore;\n const members = feed.resources;\n const selected = new Set(members.map((resource) => resource.name));\n // Any failure stops the whole feed, so it is an error for every resource in it.\n const recordFeedError =\n (operation: StateOperation) =>\n <A, R>(effect: Effect.Effect<A, ConnectorError, R>) =>\n effect.pipe(\n Effect.tapError(() =>\n Effect.forEach(\n members,\n (resource) =>\n Metrics.setSyncState(\n { connector: connector.name, resource: resource.name },\n \"error\",\n ).pipe(Effect.andThen(store.setResourceError(resource.name, \"changes\", operation))),\n { discard: true },\n ),\n ),\n );\n\n while (true) {\n const states = yield* Effect.forEach(members, (resource) =>\n store.getResourceState(resource.name),\n );\n // A resource that was off has an older cursor. Resume from the oldest, so it\n // gets the changes it missed. The others read some changes again.\n const saved = states.flatMap((state) => (state?.changes ? [state.changes] : []));\n const cursor = Arr.isReadonlyArrayNonEmpty(saved)\n ? Arr.min(saved, bySavedAt).cursor\n : initialCutoff;\n const result = yield* feed.fetch({ cursor, selected }).pipe(recordFeedError(\"fetch\"));\n\n yield* Effect.forEach(\n members,\n (resource) =>\n ingestBatch({\n connector: connector.name,\n resource: resource.name,\n source: \"changes\",\n batch: {\n cursor: result.cursor,\n rows: result.rows[resource.name] ?? [],\n },\n }),\n { discard: true },\n ).pipe(recordFeedError(\"ingest\"));\n\n const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));\n yield* Effect.forEach(\n members,\n (resource) =>\n Effect.withSpan(\n store\n .setChangesState(resource.name, {\n cursor: normalizeCursor(result.cursor),\n lastSuccessAt,\n })\n .pipe(\n Effect.andThen(\n Metrics.setLastSuccessTimestamp(\n { connector: connector.name, resource: resource.name, source: \"changes\" },\n lastSuccessAt,\n ),\n ),\n Effect.andThen(store.clearResourceError(resource.name, \"changes\")),\n Effect.tapError((error) => annotateError(\"state_set\", error)),\n ),\n SpanName.stateSet,\n { attributes: { [Attr.stateKey]: resource.name } },\n ),\n { discard: true },\n ).pipe(recordFeedError(\"checkpoint\"));\n\n yield* Effect.forEach(members, (resource, index) =>\n states[index]?.lastError?.source === \"changes\"\n ? refreshRuntimeStatus(connector, resource, initialCutoff)\n : Effect.void,\n );\n\n if (!result.hasMore) {\n yield* Effect.sleep(feed.interval ?? \"1 minute\");\n }\n }\n }).pipe(\n // Only typed errors park the feed. Defects and interruption still stop the runtime.\n Effect.catch((error) =>\n Effect.logError(\"Connector changes feed parked\", error).pipe(\n Effect.annotateLogs({\n [Attr.connectorName]: connector.name,\n resources: feed.resources.map((resource) => resource.name).join(\",\"),\n }),\n Effect.andThen(Effect.never),\n ),\n ),\n );\n","export { run, type RunOptions } from \"./engine\";\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { a as IngestorService, i as Ingestor, n as IngestResult, r as IngestSource, t as IngestOptions } from "../service-BRoy_EId.mjs";
2
+ import { a as layerConsole, i as layerArrowFlightConfig, n as ArrowFlightIngestorConfig, r as layerArrowFlight } from "../index-uFa2wwYo.mjs";
3
+ export { type ArrowFlightIngestorConfig, type IngestOptions, type IngestResult, type IngestSource, Ingestor, type IngestorService, layerArrowFlight, layerArrowFlightConfig, layerConsole };
@@ -0,0 +1,4 @@
1
+ import { t as Ingestor } from "../service-jWxxfEht.mjs";
2
+ import { n as layerArrowFlightConfig, t as layerArrowFlight } from "../arrow-flight-DDQ0ktx9.mjs";
3
+ import { n as layerConsole } from "../ingestor-DjCEzBzZ.mjs";
4
+ export { Ingestor, layerArrowFlight, layerArrowFlightConfig, layerConsole };
@@ -0,0 +1,26 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
+ import { t as Ingestor } from "./service-jWxxfEht.mjs";
3
+ import { n as layerArrowFlightConfig, t as layerArrowFlight } from "./arrow-flight-DDQ0ktx9.mjs";
4
+ import { Effect, Layer } from "effect";
5
+ //#region src/ingestor/console.ts
6
+ /** Logs batches without sending them over Arrow Flight. */
7
+ const layerConsole = Layer.succeed(Ingestor)({ ingest: ({ resource, source, batch }) => Effect.logInfo(`[ingestor] -> Source: ${source} | Resource: ${resource}`).pipe(Effect.annotateLogs({
8
+ rows: batch.rows.length,
9
+ cursor: batch.cursor,
10
+ source
11
+ }), Effect.as({
12
+ rows: batch.rows.length,
13
+ bytes: 0
14
+ })) });
15
+ //#endregion
16
+ //#region src/ingestor/index.ts
17
+ var ingestor_exports = /* @__PURE__ */ __exportAll({
18
+ Ingestor: () => Ingestor,
19
+ layerArrowFlight: () => layerArrowFlight,
20
+ layerArrowFlightConfig: () => layerArrowFlightConfig,
21
+ layerConsole: () => layerConsole
22
+ });
23
+ //#endregion
24
+ export { layerConsole as n, ingestor_exports as t };
25
+
26
+ //# sourceMappingURL=ingestor-DjCEzBzZ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingestor-DjCEzBzZ.mjs","names":[],"sources":["../src/ingestor/console.ts","../src/ingestor/index.ts"],"sourcesContent":["import { Effect, Layer } from \"effect\";\n\nimport { Ingestor } from \"./service\";\n\n/** Logs batches without sending them over Arrow Flight. */\nexport const layerConsole = Layer.succeed(Ingestor)({\n ingest: ({ resource, source, batch }) =>\n Effect.logInfo(`[ingestor] -> Source: ${source} | Resource: ${resource}`).pipe(\n Effect.annotateLogs({ rows: batch.rows.length, cursor: batch.cursor, source }),\n // Nothing is encoded, so there are no bytes to count.\n Effect.as({ rows: batch.rows.length, bytes: 0 }),\n ),\n});\n","export { layerConsole } from \"./console\";\nexport {\n Ingestor,\n type IngestOptions,\n type IngestorService,\n type IngestResult,\n type IngestSource,\n} from \"./service\";\nexport {\n layerArrowFlight,\n layerArrowFlightConfig,\n type ArrowFlightIngestorConfig,\n} from \"./arrow-flight\";\n"],"mappings":";;;;;;AAKA,MAAa,eAAe,MAAM,QAAQ,QAAQ,CAAC,CAAC,EAClD,SAAS,EAAE,UAAU,QAAQ,YAC3B,OAAO,QAAQ,yBAAyB,OAAO,eAAe,UAAU,CAAC,CAAC,KACxE,OAAO,aAAa;CAAE,MAAM,MAAM,KAAK;CAAQ,QAAQ,MAAM;CAAQ;AAAO,CAAC,GAE7E,OAAO,GAAG;CAAE,MAAM,MAAM,KAAK;CAAQ,OAAO;AAAE,CAAC,CACjD,EACJ,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { S as addCurrentSpanEvent, _ as withResourceAttributes, b as EventName, i as ingestDuration, n as batchSize, r as batches, u as rowsIngested, v as Attr, x as SpanName, y as EventAttr } from "./metrics-C901IIYZ.mjs";
2
+ import { t as Ingestor } from "./service-jWxxfEht.mjs";
3
+ import { Effect, Metric } from "effect";
4
+ //#region src/ingestor/instrumented.ts
5
+ const ingestBatch = Effect.fnUntraced(function* (options) {
6
+ const metricAttributes = withResourceAttributes({
7
+ connector: options.connector ?? "unknown",
8
+ resource: options.resource,
9
+ source: options.source
10
+ });
11
+ const batchOutcome = (outcome) => Metric.withAttributes(batches, {
12
+ ...metricAttributes,
13
+ [Attr.batchOutcome]: outcome
14
+ });
15
+ const ingest = (yield* Ingestor).ingest(options).pipe(Effect.tap(() => Effect.annotateCurrentSpan({ [Attr.ingestionSuccess]: true })), Effect.tapError(() => Effect.annotateCurrentSpan({
16
+ [Attr.ingestionSuccess]: false,
17
+ [Attr.errorPhase]: "ingest"
18
+ })));
19
+ const result = yield* Effect.withSpan(ingest, SpanName.ingest, { kind: "producer" }).pipe(Effect.trackDuration(Metric.withAttributes(ingestDuration, metricAttributes)), Effect.onError(() => Metric.update(batchOutcome("error"), 1)));
20
+ yield* Metric.update(batchOutcome("success"), 1);
21
+ yield* Metric.update(Metric.withAttributes(rowsIngested, metricAttributes), options.batch.rows.length);
22
+ yield* Metric.update(Metric.withAttributes(batchSize, metricAttributes), options.batch.rows.length);
23
+ if (options.batch.cursor !== void 0) yield* addCurrentSpanEvent(EventName.batchCheckpoint, { [EventAttr.batchCursor]: options.batch.cursor });
24
+ return result;
25
+ });
26
+ //#endregion
27
+ export { ingestBatch as t };
28
+
29
+ //# sourceMappingURL=instrumented-Bq1WX2L5.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrumented-Bq1WX2L5.mjs","names":["Metrics.withResourceAttributes","Metrics.batches","Metrics.ingestDuration","Metrics.rowsIngested","Metrics.batchSize"],"sources":["../src/ingestor/instrumented.ts"],"sourcesContent":["import { Effect, Metric } from \"effect\";\n\nimport type { ResourceBatch } from \"../core/types\";\n\nimport * as Metrics from \"../metrics\";\nimport { Attr, EventAttr, EventName, SpanName, addCurrentSpanEvent } from \"../telemetry\";\nimport { Ingestor, type IngestSource } from \"./service\";\n\nexport const ingestBatch = Effect.fnUntraced(function* (options: {\n readonly connector?: string;\n readonly resource: string;\n readonly source: IngestSource;\n readonly batch: ResourceBatch;\n}) {\n const metricAttributes = Metrics.withResourceAttributes({\n connector: options.connector ?? \"unknown\",\n resource: options.resource,\n source: options.source,\n });\n const batchOutcome = (outcome: \"success\" | \"error\") =>\n Metric.withAttributes(Metrics.batches, {\n ...metricAttributes,\n [Attr.batchOutcome]: outcome,\n });\n\n const ingestor = yield* Ingestor;\n\n const ingest = ingestor.ingest(options).pipe(\n Effect.tap(() => Effect.annotateCurrentSpan({ [Attr.ingestionSuccess]: true })),\n Effect.tapError(() =>\n Effect.annotateCurrentSpan({\n [Attr.ingestionSuccess]: false,\n [Attr.errorPhase]: \"ingest\",\n }),\n ),\n );\n\n // onError keeps the failure, so the engine still sees it and skips the checkpoint.\n const result = yield* Effect.withSpan(ingest, SpanName.ingest, { kind: \"producer\" }).pipe(\n Effect.trackDuration(Metric.withAttributes(Metrics.ingestDuration, metricAttributes)),\n Effect.onError(() => Metric.update(batchOutcome(\"error\"), 1)),\n );\n\n yield* Metric.update(batchOutcome(\"success\"), 1);\n yield* Metric.update(\n Metric.withAttributes(Metrics.rowsIngested, metricAttributes),\n options.batch.rows.length,\n );\n yield* Metric.update(\n Metric.withAttributes(Metrics.batchSize, metricAttributes),\n options.batch.rows.length,\n );\n\n if (options.batch.cursor !== undefined) {\n yield* addCurrentSpanEvent(EventName.batchCheckpoint, {\n [EventAttr.batchCursor]: options.batch.cursor,\n });\n }\n\n return result;\n});\n"],"mappings":";;;;AAQA,MAAa,cAAc,OAAO,WAAW,WAAW,SAKrD;CACD,MAAM,mBAAmBA,uBAA+B;EACtD,WAAW,QAAQ,aAAa;EAChC,UAAU,QAAQ;EAClB,QAAQ,QAAQ;CAClB,CAAC;CACD,MAAM,gBAAgB,YACpB,OAAO,eAAeC,SAAiB;EACrC,GAAG;GACF,KAAK,eAAe;CACvB,CAAC;CAIH,MAAM,UAAS,OAFS,SAAA,CAEA,OAAO,OAAO,CAAC,CAAC,KACtC,OAAO,UAAU,OAAO,oBAAoB,GAAG,KAAK,mBAAmB,KAAK,CAAC,CAAC,GAC9E,OAAO,eACL,OAAO,oBAAoB;GACxB,KAAK,mBAAmB;GACxB,KAAK,aAAa;CACrB,CAAC,CACH,CACF;CAGA,MAAM,SAAS,OAAO,OAAO,SAAS,QAAQ,SAAS,QAAQ,EAAE,MAAM,WAAW,CAAC,CAAC,CAAC,KACnF,OAAO,cAAc,OAAO,eAAeC,gBAAwB,gBAAgB,CAAC,GACpF,OAAO,cAAc,OAAO,OAAO,aAAa,OAAO,GAAG,CAAC,CAAC,CAC9D;CAEA,OAAO,OAAO,OAAO,aAAa,SAAS,GAAG,CAAC;CAC/C,OAAO,OAAO,OACZ,OAAO,eAAeC,cAAsB,gBAAgB,GAC5D,QAAQ,MAAM,KAAK,MACrB;CACA,OAAO,OAAO,OACZ,OAAO,eAAeC,WAAmB,gBAAgB,GACzD,QAAQ,MAAM,KAAK,MACrB;CAEA,IAAI,QAAQ,MAAM,WAAW,KAAA,GAC3B,OAAO,oBAAoB,UAAU,iBAAiB,GACnD,UAAU,cAAc,QAAQ,MAAM,OACzC,CAAC;CAGH,OAAO;AACT,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { _ as number, a as configSchema, b as select, c as ConnectorManifest, d as ConfigField, f as ConfigFieldSpec, g as define$1, h as boolean, i as RuntimeConfigDocument, l as ResourceCapability, m as ConnectorConfigDef, n as ConnectorConfigSchema, o as decodeConfig, p as ConfigValuesOf, r as ConnectorConfigValues, s as toRuntimeDocument, u as define, v as optional, x as string, y as secret } from "../index-eFuoMZZ3.mjs";
2
+ export { type ConfigField, type ConfigFieldSpec, type ConfigValuesOf, type ConnectorConfigDef, type ConnectorConfigSchema, type ConnectorConfigValues, type ConnectorManifest, type ResourceCapability, type RuntimeConfigDocument, boolean, configSchema, decodeConfig, define, define$1 as defineConfig, number, optional, secret, select, string, toRuntimeDocument };
@@ -1,4 +1,2 @@
1
- import "../constants-D113Ut1x.js";
2
- import { a as define, c as number, d as select, f as string, i as toRuntimeDocument, l as optional, n as configSchema, o as boolean, r as decodeConfig, s as define$1, u as secret } from "../manifest-P7kBnch9.js";
3
-
4
- export { boolean, configSchema, decodeConfig, define, define$1 as defineConfig, number, optional, secret, select, string, toRuntimeDocument };
1
+ import { a as define, c as number, d as select, f as string, i as toRuntimeDocument, l as optional, n as configSchema, o as boolean, r as decodeConfig, s as define$1, u as secret } from "../manifest-CABeIhAG.mjs";
2
+ export { boolean, configSchema, decodeConfig, define, define$1 as defineConfig, number, optional, secret, select, string, toRuntimeDocument };
@@ -1,20 +1,18 @@
1
- import { t as __export } from "./chunk-Bp6m_JJh.js";
2
- import { r as isPlatformRuntimeKey } from "./constants-D113Ut1x.js";
3
- import { Config, Option, Predicate, Redacted, Schema, SchemaTransformation, Struct } from "effect";
4
-
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
+ import { r as isPlatformRuntimeKey } from "./constants-v3UX-hf6.mjs";
3
+ import { Config, Predicate, Schema, SchemaTransformation, Struct } from "effect";
5
4
  //#region src/manifest/number-schema.ts
6
5
  const makeNumberSchema = (constraints) => {
7
6
  if (constraints.integer) return constraints.minimum === void 0 ? Schema.Int : Schema.Int.check(Schema.isGreaterThanOrEqualTo(constraints.minimum));
8
7
  return constraints.minimum === void 0 ? Schema.Finite : Schema.Finite.check(Schema.isGreaterThanOrEqualTo(constraints.minimum));
9
8
  };
10
-
11
9
  //#endregion
12
10
  //#region src/manifest/config.ts
13
11
  const configFieldToConfig = Struct.lambda((field) => field.config);
14
12
  const withDefault = (config, defaultValue) => defaultValue === void 0 ? config : Config.withDefault(config, defaultValue);
15
13
  /** Defines a required non-empty string, optionally with a default. */
16
14
  const string = (options) => ({
17
- config: withDefault(Config.nonEmptyString(options.runtimeKey), options.default),
15
+ config: withDefault(Config.NonEmptyString(options.runtimeKey), options.default),
18
16
  spec: {
19
17
  runtimeKey: options.runtimeKey,
20
18
  type: "string",
@@ -44,7 +42,7 @@ const number = (options) => {
44
42
  };
45
43
  /** Defines a boolean, optionally with a default. */
46
44
  const boolean = (options) => ({
47
- config: withDefault(Config.boolean(options.runtimeKey), options.default),
45
+ config: withDefault(Config.Boolean(options.runtimeKey), options.default),
48
46
  spec: {
49
47
  runtimeKey: options.runtimeKey,
50
48
  type: "boolean",
@@ -56,7 +54,7 @@ const boolean = (options) => ({
56
54
  });
57
55
  /** Defines a string literal choice whose values are preserved in the inferred type. */
58
56
  const select = (options) => ({
59
- config: withDefault(Config.literals(options.values, options.runtimeKey), options.default),
57
+ config: withDefault(Config.Literals(options.values, options.runtimeKey), options.default),
60
58
  spec: {
61
59
  runtimeKey: options.runtimeKey,
62
60
  type: "select",
@@ -102,7 +100,7 @@ const optional = (field) => ({
102
100
  * const formFields = config.spec;
103
101
  * ```
104
102
  */
105
- const define = (fields) => {
103
+ const define$1 = (fields) => {
106
104
  const spec = Object.entries(fields).map(([name, field]) => ({
107
105
  name,
108
106
  ...field.spec
@@ -116,7 +114,6 @@ const define = (fields) => {
116
114
  spec
117
115
  };
118
116
  };
119
-
120
117
  //#endregion
121
118
  //#region src/manifest/manifest.ts
122
119
  /**
@@ -132,8 +129,7 @@ const define = (fields) => {
132
129
  * });
133
130
  * ```
134
131
  */
135
- const define$1 = (manifest) => manifest;
136
-
132
+ const define = (manifest) => manifest;
137
133
  //#endregion
138
134
  //#region src/manifest/schema.ts
139
135
  const numberFromForm = (field) => {
@@ -199,15 +195,14 @@ const toRuntimeDocument = (manifest, values) => {
199
195
  }
200
196
  return document;
201
197
  };
202
-
203
198
  //#endregion
204
199
  //#region src/manifest/index.ts
205
- var manifest_exports = /* @__PURE__ */ __export({
200
+ var manifest_exports = /* @__PURE__ */ __exportAll({
206
201
  boolean: () => boolean,
207
202
  configSchema: () => configSchema,
208
203
  decodeConfig: () => decodeConfig,
209
- define: () => define$1,
210
- defineConfig: () => define,
204
+ define: () => define,
205
+ defineConfig: () => define$1,
211
206
  number: () => number,
212
207
  optional: () => optional,
213
208
  secret: () => secret,
@@ -215,7 +210,7 @@ var manifest_exports = /* @__PURE__ */ __export({
215
210
  string: () => string,
216
211
  toRuntimeDocument: () => toRuntimeDocument
217
212
  });
218
-
219
213
  //#endregion
220
- export { define$1 as a, number as c, select as d, string as f, toRuntimeDocument as i, optional as l, configSchema as n, boolean as o, decodeConfig as r, define as s, manifest_exports as t, secret as u };
221
- //# sourceMappingURL=manifest-P7kBnch9.js.map
214
+ export { define as a, number as c, select as d, string as f, toRuntimeDocument as i, optional as l, configSchema as n, boolean as o, decodeConfig as r, define$1 as s, manifest_exports as t, secret as u };
215
+
216
+ //# sourceMappingURL=manifest-CABeIhAG.mjs.map