@useairfoil/connector-kit 0.5.3 → 0.6.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 (85) hide show
  1. package/METRICS.md +16 -14
  2. package/README.md +15 -3
  3. package/dist/auth/index.d.ts +1 -1
  4. package/dist/connector-app/index.d.ts +13 -13
  5. package/dist/connector-app/index.js +9 -8
  6. package/dist/{connector-app-d7Z-SZLQ.js → connector-app-BljHd0Pe.js} +2 -2
  7. package/dist/{connector-app-d7Z-SZLQ.js.map → connector-app-BljHd0Pe.js.map} +1 -1
  8. package/dist/{constants-BRhIX_rz.js → constants-D113Ut1x.js} +7 -2
  9. package/dist/constants-D113Ut1x.js.map +1 -0
  10. package/dist/errors/index.d.ts +1 -1
  11. package/dist/{index-Byr0Lf0C.d.ts → index-BA8ASHKr.d.ts} +12 -6
  12. package/dist/{index-DKWIh6M1.d.ts → index-BKw7jA2a.d.ts} +3 -3
  13. package/dist/{index-DtJX_tic.d.ts → index-C5Ma7V7t.d.ts} +21 -7
  14. package/dist/{index-CBT-JX-T.d.ts → index-CR9HJDdr.d.ts} +1 -1
  15. package/dist/{index-D54ySAKn.d.ts → index-DKoRwyFn.d.ts} +1 -1
  16. package/dist/{index-CTHVudvQ.d.ts → index-DXa26Ry5.d.ts} +1 -1
  17. package/dist/{index-Coh_SkBs.d.ts → index-DYpEMJf-.d.ts} +2 -2
  18. package/dist/{index-Cq2IzY7T.d.ts → index-VpHaZXZw.d.ts} +3 -3
  19. package/dist/index-ZSuiZX5H.d.ts +85 -0
  20. package/dist/{index-J42AZaXU.d.ts → index-bfjH7Yb0.d.ts} +5 -5
  21. package/dist/index.d.ts +13 -13
  22. package/dist/index.js +14 -12
  23. package/dist/index.js.map +1 -1
  24. package/dist/ingestion/index.d.ts +5 -5
  25. package/dist/ingestion/index.js +8 -7
  26. package/dist/{ingestion-BQo4cbGw.js → ingestion-QBGKrFr9.js} +6 -6
  27. package/dist/{ingestion-BQo4cbGw.js.map → ingestion-QBGKrFr9.js.map} +1 -1
  28. package/dist/manifest/index.d.ts +1 -1
  29. package/dist/manifest/index.js +2 -2
  30. package/dist/{manifest-ByE6YPG0.js → manifest-P7kBnch9.js} +2 -2
  31. package/dist/{manifest-ByE6YPG0.js.map → manifest-P7kBnch9.js.map} +1 -1
  32. package/dist/{metrics-CVAk1ALR.d.ts → metrics-C4V1pm6v.d.ts} +15 -9
  33. package/dist/metrics-inkCAxKq.js +136 -0
  34. package/dist/metrics-inkCAxKq.js.map +1 -0
  35. package/dist/metrics.d.ts +4 -4
  36. package/dist/metrics.js +4 -2
  37. package/dist/publisher/index.d.ts +6 -5
  38. package/dist/publisher/index.js +6 -4
  39. package/dist/{publisher-BYT3RLVO.js → publisher-BdWJOfer.js} +14 -7
  40. package/dist/publisher-BdWJOfer.js.map +1 -0
  41. package/dist/runtime-config/index.d.ts +4 -2
  42. package/dist/runtime-config/index.js +4 -3
  43. package/dist/{runtime-config-BpB-d_bF.js → runtime-config-IbyCVpei.js} +17 -8
  44. package/dist/runtime-config-IbyCVpei.js.map +1 -0
  45. package/dist/{server-CXTQ7odl.js → server-D-eLX3yN.js} +24 -24
  46. package/dist/server-D-eLX3yN.js.map +1 -0
  47. package/dist/{service-IE5qaf9x.d.ts → service-CUjGhe-7.d.ts} +3 -3
  48. package/dist/service-DiP-XETo.js +8 -0
  49. package/dist/service-DiP-XETo.js.map +1 -0
  50. package/dist/state-store/index.d.ts +2 -2
  51. package/dist/state-store/index.js +2 -2
  52. package/dist/{state-store-yl6LiTQ0.js → state-store-BdYulQOY.js} +2 -2
  53. package/dist/{state-store-yl6LiTQ0.js.map → state-store-BdYulQOY.js.map} +1 -1
  54. package/dist/status/index.d.ts +4 -4
  55. package/dist/status/index.js +3 -3
  56. package/dist/{status-B-oZBc33.js → status-BTTd7AUR.js} +2 -2
  57. package/dist/{status-B-oZBc33.js.map → status-BTTd7AUR.js.map} +1 -1
  58. package/dist/table-bindings-Dp1DhTeS.js +106 -0
  59. package/dist/table-bindings-Dp1DhTeS.js.map +1 -0
  60. package/dist/{service-DuFiQwid.js → telemetry-j_nxwYfh.js} +18 -8
  61. package/dist/telemetry-j_nxwYfh.js.map +1 -0
  62. package/dist/{types-B35J5YPu.d.ts → types-jVD5Ys43.d.ts} +2 -2
  63. package/dist/webhook/index.d.ts +6 -5
  64. package/dist/webhook/index.js +6 -5
  65. package/dist/{webhook-DI-Afxkg.js → webhook-MhFcLW-o.js} +2 -2
  66. package/dist/{webhook-DI-Afxkg.js.map → webhook-MhFcLW-o.js.map} +1 -1
  67. package/package.json +2 -2
  68. package/src/metrics.ts +67 -21
  69. package/src/publisher/index.ts +1 -1
  70. package/src/publisher/instrumented.ts +23 -16
  71. package/src/publisher/wings.ts +11 -11
  72. package/src/runtime-config/config.ts +16 -0
  73. package/src/runtime-config/constants.ts +3 -0
  74. package/src/runtime-config/error.ts +4 -1
  75. package/src/runtime-config/index.ts +7 -0
  76. package/src/runtime-config/table-bindings.ts +180 -0
  77. package/src/telemetry.ts +15 -0
  78. package/dist/constants-BRhIX_rz.js.map +0 -1
  79. package/dist/index-o1-Z3n7V.d.ts +0 -55
  80. package/dist/metrics-CWPy2Aqc.js +0 -96
  81. package/dist/metrics-CWPy2Aqc.js.map +0 -1
  82. package/dist/publisher-BYT3RLVO.js.map +0 -1
  83. package/dist/runtime-config-BpB-d_bF.js.map +0 -1
  84. package/dist/server-CXTQ7odl.js.map +0 -1
  85. package/dist/service-DuFiQwid.js.map +0 -1
package/METRICS.md CHANGED
@@ -4,18 +4,20 @@ Connector Kit emits standard metrics through Effect metrics. Production runtimes
4
4
 
5
5
  ## Metrics
6
6
 
7
- | Name | Type | Unit | Attributes |
8
- | -------------------------------------------------- | --------------- | --------------- | -------------------------------------------- |
9
- | `airfoil_connector_entities_upserted_total` | counter | mutations | `connector`, `resource`, `source` |
10
- | `airfoil_connector_entities_deleted_total` | counter | mutations | `connector`, `resource`, `source` |
11
- | `airfoil_connector_batches_total` | counter | batches | `connector`, `resource`, `source`, `outcome` |
12
- | `airfoil_connector_batch_size` | histogram | mutations/batch | `connector`, `resource`, `source` |
13
- | `airfoil_connector_publish_duration_ms` | histogram timer | ms | `connector`, `resource`, `source` |
14
- | `airfoil_connector_webhook_requests_total` | counter | requests | `connector`, `path`, `outcome` |
15
- | `airfoil_connector_webhook_queue_depth` | gauge | batches | `connector` |
16
- | `airfoil_connector_sync_state` | gauge | none | `connector`, `resource`, `state` |
17
- | `airfoil_connector_last_success_timestamp_seconds` | gauge | Unix seconds | `connector`, `resource`, `source` |
18
- | `airfoil_connector_api_retries_total` | counter | retries | `connector`, `reason` |
7
+ | OTLP name | Prometheus name | Type | Unit |
8
+ | ------------------------------------------ | ------------------------------------------ | --------------- | ------------ |
9
+ | `airfoil.connector.entity.upserts` | `airfoil_connector_entity_upserts` | counter | `{mutation}` |
10
+ | `airfoil.connector.entity.deletes` | `airfoil_connector_entity_deletes` | counter | `{mutation}` |
11
+ | `airfoil.connector.batches` | `airfoil_connector_batches` | counter | `{batch}` |
12
+ | `airfoil.connector.batch.size` | `airfoil_connector_batch_size` | histogram | `{mutation}` |
13
+ | `airfoil.connector.publish.duration` | `airfoil_connector_publish_duration` | histogram timer | `ms` |
14
+ | `airfoil.connector.webhook.requests` | `airfoil_connector_webhook_requests` | counter | `{request}` |
15
+ | `airfoil.connector.webhook.queue.depth` | `airfoil_connector_webhook_queue_depth` | gauge | `{batch}` |
16
+ | `airfoil.connector.sync.state` | `airfoil_connector_sync_state` | gauge | `1` |
17
+ | `airfoil.connector.last_success.timestamp` | `airfoil_connector_last_success_timestamp` | gauge | `s` |
18
+ | `airfoil.connector.api.retries` | `airfoil_connector_api_retries` | counter | `{retry}` |
19
+
20
+ OTLP attributes use dotted OTel names. Common dimensions are `airfoil.connector.name`, `airfoil.resource.name`, and `airfoil.resource.source`; specialized attributes are `airfoil.batch.outcome`, `airfoil.webhook.path`, `airfoil.webhook.outcome`, `airfoil.connector.sync.state`, and `airfoil.connector.api.retry.reason`. The Prometheus endpoint replaces dots in metric and label names with underscores and does not append `_total`.
19
21
 
20
22
  Batch `source` is `backfill`, `changes`, or `webhook`. Batch `outcome` is `accepted`, `rejected`, or `error`. Webhook `outcome` is `ok`, `read_error`, `invalid_json`, `invalid_payload`, `rejected`, or `handler_error`. Sync `state` is `pending`, `backfilling`, `live`, or `error`.
21
23
 
@@ -26,7 +28,7 @@ Counters are activity since process start, not entity population. Use `increase(
26
28
  The last-success gauge is restored from durable state after restart and is `0` until the source commits its first checkpoint. Calculate source freshness in Prometheus:
27
29
 
28
30
  ```promql
29
- time() - airfoil_connector_last_success_timestamp_seconds
31
+ time() - airfoil_connector_last_success_timestamp
30
32
  ```
31
33
 
32
34
  ## Sync Status
@@ -75,4 +77,4 @@ const schema = Schema.toStandardSchemaV1(Manifest.configSchema(polarManifest));
75
77
  const result = await schema["~standard"].validate(formValues);
76
78
  ```
77
79
 
78
- Poll `GET /status` and decode with `Status.StatusResponseSchema`. Chart ingestion with `increase(airfoil_connector_entities_upserted_total[...])`, alert on `airfoil_connector_sync_state{state="error"} == 1`, and alert on non-`ok` webhook outcomes.
80
+ Poll `GET /status` and decode with `Status.StatusResponseSchema`. Chart ingestion with `increase(airfoil_connector_entity_upserts[...])`, alert on `airfoil_connector_sync_state{airfoil_connector_sync_state="error"} == 1`, and alert on non-`ok` `airfoil_webhook_outcome` values.
package/README.md CHANGED
@@ -159,6 +159,14 @@ Render fields from `manifest.config`: use `field.name` as the form/storage key,
159
159
 
160
160
  Hosted connectors receive the runtime document as a read-only JSON file. `AIRFOIL_CONFIG_PATH` selects the file, and `RuntimeConfig.layerHosted()` adds the file beneath Effect's existing environment provider. The file is required and must contain valid JSON; each connector's Effect Config validates the fields it reads. Local sandboxes use Effect's default environment provider. Platform-owned config such as Wings host, namespace, table names, PostgreSQL settings, ports, and OTEL settings stays outside the manifest and outside the connector JSON.
161
161
 
162
+ Hosted HTTP runtimes use `AIRFOIL_HTTP_PORT` (default `8080`). Wings table routing is one atomic `AIRFOIL_TABLE_BINDINGS` JSON object keyed by connector resource name. `Publisher.layerWingsConfig(connector)` rejects missing or unknown resources and validates every binding before ingestion starts:
163
+
164
+ ```env
165
+ AIRFOIL_TABLE_BINDINGS={"posts":"namespaces/default/tables/posts"}
166
+ ```
167
+
168
+ An object binding may add a typed runtime partition, for example `{"name":"namespaces/default/tables/posts","partition":{"type":"string","value":"tenant-a"}}`. Signed and unsigned 64-bit partition values use decimal strings; byte partitions use base64.
169
+
162
170
  ### Pre-provision Checks
163
171
 
164
172
  The dashboard backend imports each connector package and runs `ConnectorApp.check(...)` after manifest decoding but before persisting secrets or creating database and Kubernetes resources. Validate submitted resource names against `manifest.resources` at the request boundary before calling the typed check API. Replace the backend process provider with the submitted runtime document so unrelated backend environment variables cannot satisfy connector configuration:
@@ -357,17 +365,21 @@ const publisherLayer = Publisher.layerWings({
357
365
  The `tables` map is keyed by resource name. Values can be table names or objects with a table name and optional partition value.
358
366
 
359
367
  ```ts
368
+ import * as Wings from "@useairfoil/wings";
369
+
360
370
  Publisher.layerWings({
361
371
  connector,
362
372
  tables: {
363
373
  posts: {
364
374
  name: "namespaces/default/tables/posts",
365
- partitionValue: "account_123",
375
+ partitionValue: Wings.PartitionValue.string("account_123"),
366
376
  },
367
377
  },
368
378
  });
369
379
  ```
370
380
 
381
+ Hosted entrypoints should use `Publisher.layerWingsConfig(connector)` instead. It loads the exact resource map from `AIRFOIL_TABLE_BINDINGS`, delegates partition decoding and table compatibility to Wings, and applies Connector Kit's manifest-resource validation before ingestion starts.
382
+
371
383
  The Wings publisher resolves table metadata during layer construction, validates resource key/version/partition compatibility, sends upserts with full rows, and sends deletes with key/version-only rows.
372
384
 
373
385
  ## Minimal Example
@@ -440,7 +452,7 @@ Effect.scoped(ConnectorApp.start(connector, { port: 8080 })).pipe(
440
452
 
441
453
  `Telemetry` contains connector-kit span names, span attributes, error annotation helpers, OTLP tracing layers, and OTLP metrics layers. HTTP connector runtimes expose shallow process health at `GET /health`, Prometheus metrics at `GET /metrics`, and durable sync state at `GET /status` by default. Provider, Wings, and PostgreSQL failures do not make `/health` fail.
442
454
 
443
- `/status` includes `lastSuccessAt` for each checkpointed backfill or changes source. Use `time() - airfoil_connector_last_success_timestamp_seconds` to monitor source freshness without interpreting provider cursors.
455
+ `/status` includes `lastSuccessAt` for each checkpointed backfill or changes source. Use `time() - airfoil_connector_last_success_timestamp` to monitor source freshness without interpreting provider cursors. OTLP receives the canonical `airfoil.connector.last_success.timestamp` name; the Prometheus endpoint replaces dots with underscores.
444
456
 
445
457
  Common entry points:
446
458
 
@@ -471,7 +483,7 @@ Telemetry environment variables:
471
483
  | `OTEL_EXPORTER_OTLP_HEADERS` | Connector Kit | Optional comma-separated headers, for example `Authorization=Bearer <token>,X-Axiom-Dataset=<dataset>`. |
472
484
  | `OTEL_SERVICE_NAME` | Effect | Service name resource attribute, for example `producer-shopify`. |
473
485
  | `OTEL_SERVICE_VERSION` | Effect | Optional service version resource attribute. |
474
- | `OTEL_RESOURCE_ATTRIBUTES` | Effect | Optional comma-separated resource attributes, for example `deployment.environment=production,team=data`. |
486
+ | `OTEL_RESOURCE_ATTRIBUTES` | Effect | Operator-owned identity, for example `service.instance.id=instance-1,airfoil.connector.revision=4,airfoil.team.id=team-acme`. |
475
487
 
476
488
  ## Testing
477
489
 
@@ -1,2 +1,2 @@
1
- import { i as makeTokenCache, n as ExpiringToken, r as TokenCache } from "../index-CTHVudvQ.js";
1
+ import { i as makeTokenCache, n as ExpiringToken, r as TokenCache } from "../index-DXa26Ry5.js";
2
2
  export { ExpiringToken, TokenCache, makeTokenCache };
@@ -1,14 +1,14 @@
1
- import "../index-CTHVudvQ.js";
2
- import "../index-D54ySAKn.js";
3
- import "../types-B35J5YPu.js";
4
- import { d as CheckResult, f as ResourceCheckResult, i as start, n as App, p as check, r as StartOptions, u as CheckOptions } from "../index-DtJX_tic.js";
5
- import "../service-IE5qaf9x.js";
6
- import "../index-Coh_SkBs.js";
7
- import "../index-J42AZaXU.js";
8
- import "../index-CBT-JX-T.js";
9
- import "../metrics-CVAk1ALR.js";
10
- import "../index-Byr0Lf0C.js";
11
- import "../index-o1-Z3n7V.js";
12
- import "../index-Cq2IzY7T.js";
13
- import "../index-DKWIh6M1.js";
1
+ import "../index-DXa26Ry5.js";
2
+ import "../index-DKoRwyFn.js";
3
+ import "../types-jVD5Ys43.js";
4
+ import { d as CheckResult, f as ResourceCheckResult, i as start, n as App, p as check, r as StartOptions, u as CheckOptions } from "../index-C5Ma7V7t.js";
5
+ import "../service-CUjGhe-7.js";
6
+ import "../index-DYpEMJf-.js";
7
+ import "../index-bfjH7Yb0.js";
8
+ import "../index-CR9HJDdr.js";
9
+ import "../metrics-C4V1pm6v.js";
10
+ import "../index-ZSuiZX5H.js";
11
+ import "../index-BA8ASHKr.js";
12
+ import "../index-VpHaZXZw.js";
13
+ import "../index-BKw7jA2a.js";
14
14
  export { App, CheckOptions, CheckResult, ResourceCheckResult, StartOptions, check, start };
@@ -1,11 +1,12 @@
1
1
  import "../errors-DHWylqRZ.js";
2
- import { n as start, r as check } from "../connector-app-d7Z-SZLQ.js";
3
- import "../metrics-CWPy2Aqc.js";
4
- import "../constants-BRhIX_rz.js";
5
- import "../service-DuFiQwid.js";
6
- import "../server-CXTQ7odl.js";
7
- import "../state-store-yl6LiTQ0.js";
8
- import "../status-B-oZBc33.js";
9
- import "../ingestion-BQo4cbGw.js";
2
+ import { n as start, r as check } from "../connector-app-BljHd0Pe.js";
3
+ import "../constants-D113Ut1x.js";
4
+ import "../telemetry-j_nxwYfh.js";
5
+ import "../metrics-inkCAxKq.js";
6
+ import "../service-DiP-XETo.js";
7
+ import "../server-D-eLX3yN.js";
8
+ import "../state-store-BdYulQOY.js";
9
+ import "../status-BTTd7AUR.js";
10
+ import "../ingestion-QBGKrFr9.js";
10
11
 
11
12
  export { check, start };
@@ -1,5 +1,5 @@
1
1
  import { t as __export } from "./chunk-Bp6m_JJh.js";
2
- import { n as run } from "./ingestion-BQo4cbGw.js";
2
+ import { n as run } from "./ingestion-QBGKrFr9.js";
3
3
  import { Context, DateTime, Effect, Layer, Tuple } from "effect";
4
4
  import { NodeHttpServer } from "@effect/platform-node";
5
5
  import { HttpRouter } from "effect/unstable/http";
@@ -61,4 +61,4 @@ var connector_app_exports = /* @__PURE__ */ __export({
61
61
 
62
62
  //#endregion
63
63
  export { start as n, check as r, connector_app_exports as t };
64
- //# sourceMappingURL=connector-app-d7Z-SZLQ.js.map
64
+ //# sourceMappingURL=connector-app-BljHd0Pe.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"connector-app-d7Z-SZLQ.js","names":["ok: ResourceCheckResult","runIngestion"],"sources":["../src/connector-app/check.ts","../src/connector-app/start.ts","../src/connector-app/index.ts"],"sourcesContent":["import { Context, Effect, Layer, Tuple } from \"effect\";\n\nimport type { ConnectorDefinition, ResourceDefinition, ResourceName } from \"../core/types\";\n\nexport type ResourceCheckResult =\n | { readonly _tag: \"ok\" }\n | { readonly _tag: \"error\"; readonly message: string };\n\nexport type CheckOptions<Name extends string> = {\n readonly resources: ReadonlyArray<Name>;\n};\n\ntype ResourceCheckResults<Name extends PropertyKey> = {\n readonly [Key in Name]: ResourceCheckResult;\n};\n\nexport type CheckResult<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Name extends ResourceName<Resources> = ResourceName<Resources>,\n> = ResourceCheckResults<Name>;\n\ntype CheckFailure = { readonly message: string };\n\nconst ok: ResourceCheckResult = { _tag: \"ok\" };\n\nconst error = (message: string): ResourceCheckResult => ({ _tag: \"error\", message });\n\nconst fromEntries = <Name extends string>(\n entries: ReadonlyArray<readonly [Name, ResourceCheckResult]>,\n): ResourceCheckResults<Name> => Object.fromEntries(entries) as ResourceCheckResults<Name>;\n\nconst resultsFor = <Name extends string>(names: ReadonlyArray<Name>, result: ResourceCheckResult) =>\n fromEntries(names.map((name) => Tuple.make(name, result)));\n\n/**\n * Builds the connector service from its layer and validates only the selected\n * resources. The layer remains open until every check finishes.\n */\nexport function check<\n Identifier,\n const Resources extends ReadonlyArray<ResourceDefinition>,\n E extends CheckFailure,\n R,\n const Name extends ResourceName<Resources>,\n>(\n service: Context.Key<Identifier, ConnectorDefinition<Resources>>,\n layer: Layer.Layer<Identifier, E, R>,\n options: CheckOptions<Name>,\n): Effect.Effect<CheckResult<Resources, Name>, never, R> {\n if (options.resources.length === 0) {\n return Effect.succeed(fromEntries<Name>([]));\n }\n\n return service.pipe(\n Effect.flatMap((connector) =>\n Effect.forEach(options.resources, (name) => {\n const resource = connector.resources.find((candidate) => candidate.name === name);\n const result = resource\n ? resource.check.pipe(\n Effect.match({\n onFailure: (failure) => error(failure.message),\n onSuccess: () => ok,\n }),\n )\n : Effect.succeed(error(`Unknown connector resource: ${name}`));\n\n return result.pipe(Effect.map((result) => Tuple.make(name, result)));\n }).pipe(Effect.map(fromEntries)),\n ),\n Effect.provide(layer),\n Effect.match({\n onFailure: (failure) => resultsFor(options.resources, error(failure.message)),\n onSuccess: (results) => results,\n }),\n );\n}\n","import { NodeHttpServer } from \"@effect/platform-node\";\nimport { DateTime, Effect } from \"effect\";\nimport { HttpRouter } from \"effect/unstable/http\";\nimport { createServer } from \"node:http\";\n\nimport type { ConnectorDefinition } from \"../core\";\nimport type { Cursor } from \"../core/types\";\n\nimport { run as runIngestion } from \"../ingestion\";\n\nexport type App = ConnectorDefinition;\n\nexport type StartOptions = {\n readonly port: number;\n readonly initialCutoff?: Cursor.Value;\n readonly healthPath?: HttpRouter.PathInput;\n readonly metricsPath?: HttpRouter.PathInput | false;\n readonly statusPath?: HttpRouter.PathInput | false;\n readonly disableHttpLogger?: boolean;\n};\n\nexport const start = (app: App, options: StartOptions) =>\n Effect.gen(function* () {\n const initialCutoff =\n options.initialCutoff ?? (yield* DateTime.now.pipe(Effect.map(DateTime.formatIso)));\n const routes = app.webhooks?.map((route) => route.path) ?? [];\n\n yield* Effect.logInfo(\"webhook server ready\").pipe(\n Effect.annotateLogs({ port: options.port, routes }),\n );\n\n return yield* runIngestion(app, {\n initialCutoff,\n webhook: {\n routes: app.webhooks ?? [],\n healthPath: options.healthPath ?? \"/health\",\n metricsPath: options.metricsPath,\n statusPath: options.statusPath,\n disableHttpLogger: options.disableHttpLogger ?? true,\n },\n }).pipe(Effect.provide(NodeHttpServer.layer(createServer, { port: options.port })));\n });\n","export { check, type CheckOptions, type CheckResult, type ResourceCheckResult } from \"./check\";\nexport { start, type App, type StartOptions } from \"./start\";\n"],"mappings":";;;;;;;;AAuBA,MAAMA,KAA0B,EAAE,MAAM,MAAM;AAE9C,MAAM,SAAS,aAA0C;CAAE,MAAM;CAAS;CAAS;AAEnF,MAAM,eACJ,YAC+B,OAAO,YAAY,QAAQ;AAE5D,MAAM,cAAmC,OAA4B,WACnE,YAAY,MAAM,KAAK,SAAS,MAAM,KAAK,MAAM,OAAO,CAAC,CAAC;;;;;AAM5D,SAAgB,MAOd,SACA,OACA,SACuD;AACvD,KAAI,QAAQ,UAAU,WAAW,EAC/B,QAAO,OAAO,QAAQ,YAAkB,EAAE,CAAC,CAAC;AAG9C,QAAO,QAAQ,KACb,OAAO,SAAS,cACd,OAAO,QAAQ,QAAQ,YAAY,SAAS;EAC1C,MAAM,WAAW,UAAU,UAAU,MAAM,cAAc,UAAU,SAAS,KAAK;AAUjF,UATe,WACX,SAAS,MAAM,KACb,OAAO,MAAM;GACX,YAAY,YAAY,MAAM,QAAQ,QAAQ;GAC9C,iBAAiB;GAClB,CAAC,CACH,GACD,OAAO,QAAQ,MAAM,+BAA+B,OAAO,CAAC,EAElD,KAAK,OAAO,KAAK,WAAW,MAAM,KAAK,MAAM,OAAO,CAAC,CAAC;GACpE,CAAC,KAAK,OAAO,IAAI,YAAY,CAAC,CACjC,EACD,OAAO,QAAQ,MAAM,EACrB,OAAO,MAAM;EACX,YAAY,YAAY,WAAW,QAAQ,WAAW,MAAM,QAAQ,QAAQ,CAAC;EAC7E,YAAY,YAAY;EACzB,CAAC,CACH;;;;;ACrDH,MAAa,SAAS,KAAU,YAC9B,OAAO,IAAI,aAAa;CACtB,MAAM,gBACJ,QAAQ,kBAAkB,OAAO,SAAS,IAAI,KAAK,OAAO,IAAI,SAAS,UAAU,CAAC;CACpF,MAAM,SAAS,IAAI,UAAU,KAAK,UAAU,MAAM,KAAK,IAAI,EAAE;AAE7D,QAAO,OAAO,QAAQ,uBAAuB,CAAC,KAC5C,OAAO,aAAa;EAAE,MAAM,QAAQ;EAAM;EAAQ,CAAC,CACpD;AAED,QAAO,OAAOC,IAAa,KAAK;EAC9B;EACA,SAAS;GACP,QAAQ,IAAI,YAAY,EAAE;GAC1B,YAAY,QAAQ,cAAc;GAClC,aAAa,QAAQ;GACrB,YAAY,QAAQ;GACpB,mBAAmB,QAAQ,qBAAqB;GACjD;EACF,CAAC,CAAC,KAAK,OAAO,QAAQ,eAAe,MAAM,cAAc,EAAE,MAAM,QAAQ,MAAM,CAAC,CAAC,CAAC;EACnF"}
1
+ {"version":3,"file":"connector-app-BljHd0Pe.js","names":["ok: ResourceCheckResult","runIngestion"],"sources":["../src/connector-app/check.ts","../src/connector-app/start.ts","../src/connector-app/index.ts"],"sourcesContent":["import { Context, Effect, Layer, Tuple } from \"effect\";\n\nimport type { ConnectorDefinition, ResourceDefinition, ResourceName } from \"../core/types\";\n\nexport type ResourceCheckResult =\n | { readonly _tag: \"ok\" }\n | { readonly _tag: \"error\"; readonly message: string };\n\nexport type CheckOptions<Name extends string> = {\n readonly resources: ReadonlyArray<Name>;\n};\n\ntype ResourceCheckResults<Name extends PropertyKey> = {\n readonly [Key in Name]: ResourceCheckResult;\n};\n\nexport type CheckResult<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Name extends ResourceName<Resources> = ResourceName<Resources>,\n> = ResourceCheckResults<Name>;\n\ntype CheckFailure = { readonly message: string };\n\nconst ok: ResourceCheckResult = { _tag: \"ok\" };\n\nconst error = (message: string): ResourceCheckResult => ({ _tag: \"error\", message });\n\nconst fromEntries = <Name extends string>(\n entries: ReadonlyArray<readonly [Name, ResourceCheckResult]>,\n): ResourceCheckResults<Name> => Object.fromEntries(entries) as ResourceCheckResults<Name>;\n\nconst resultsFor = <Name extends string>(names: ReadonlyArray<Name>, result: ResourceCheckResult) =>\n fromEntries(names.map((name) => Tuple.make(name, result)));\n\n/**\n * Builds the connector service from its layer and validates only the selected\n * resources. The layer remains open until every check finishes.\n */\nexport function check<\n Identifier,\n const Resources extends ReadonlyArray<ResourceDefinition>,\n E extends CheckFailure,\n R,\n const Name extends ResourceName<Resources>,\n>(\n service: Context.Key<Identifier, ConnectorDefinition<Resources>>,\n layer: Layer.Layer<Identifier, E, R>,\n options: CheckOptions<Name>,\n): Effect.Effect<CheckResult<Resources, Name>, never, R> {\n if (options.resources.length === 0) {\n return Effect.succeed(fromEntries<Name>([]));\n }\n\n return service.pipe(\n Effect.flatMap((connector) =>\n Effect.forEach(options.resources, (name) => {\n const resource = connector.resources.find((candidate) => candidate.name === name);\n const result = resource\n ? resource.check.pipe(\n Effect.match({\n onFailure: (failure) => error(failure.message),\n onSuccess: () => ok,\n }),\n )\n : Effect.succeed(error(`Unknown connector resource: ${name}`));\n\n return result.pipe(Effect.map((result) => Tuple.make(name, result)));\n }).pipe(Effect.map(fromEntries)),\n ),\n Effect.provide(layer),\n Effect.match({\n onFailure: (failure) => resultsFor(options.resources, error(failure.message)),\n onSuccess: (results) => results,\n }),\n );\n}\n","import { NodeHttpServer } from \"@effect/platform-node\";\nimport { DateTime, Effect } from \"effect\";\nimport { HttpRouter } from \"effect/unstable/http\";\nimport { createServer } from \"node:http\";\n\nimport type { ConnectorDefinition } from \"../core\";\nimport type { Cursor } from \"../core/types\";\n\nimport { run as runIngestion } from \"../ingestion\";\n\nexport type App = ConnectorDefinition;\n\nexport type StartOptions = {\n readonly port: number;\n readonly initialCutoff?: Cursor.Value;\n readonly healthPath?: HttpRouter.PathInput;\n readonly metricsPath?: HttpRouter.PathInput | false;\n readonly statusPath?: HttpRouter.PathInput | false;\n readonly disableHttpLogger?: boolean;\n};\n\nexport const start = (app: App, options: StartOptions) =>\n Effect.gen(function* () {\n const initialCutoff =\n options.initialCutoff ?? (yield* DateTime.now.pipe(Effect.map(DateTime.formatIso)));\n const routes = app.webhooks?.map((route) => route.path) ?? [];\n\n yield* Effect.logInfo(\"webhook server ready\").pipe(\n Effect.annotateLogs({ port: options.port, routes }),\n );\n\n return yield* runIngestion(app, {\n initialCutoff,\n webhook: {\n routes: app.webhooks ?? [],\n healthPath: options.healthPath ?? \"/health\",\n metricsPath: options.metricsPath,\n statusPath: options.statusPath,\n disableHttpLogger: options.disableHttpLogger ?? true,\n },\n }).pipe(Effect.provide(NodeHttpServer.layer(createServer, { port: options.port })));\n });\n","export { check, type CheckOptions, type CheckResult, type ResourceCheckResult } from \"./check\";\nexport { start, type App, type StartOptions } from \"./start\";\n"],"mappings":";;;;;;;;AAuBA,MAAMA,KAA0B,EAAE,MAAM,MAAM;AAE9C,MAAM,SAAS,aAA0C;CAAE,MAAM;CAAS;CAAS;AAEnF,MAAM,eACJ,YAC+B,OAAO,YAAY,QAAQ;AAE5D,MAAM,cAAmC,OAA4B,WACnE,YAAY,MAAM,KAAK,SAAS,MAAM,KAAK,MAAM,OAAO,CAAC,CAAC;;;;;AAM5D,SAAgB,MAOd,SACA,OACA,SACuD;AACvD,KAAI,QAAQ,UAAU,WAAW,EAC/B,QAAO,OAAO,QAAQ,YAAkB,EAAE,CAAC,CAAC;AAG9C,QAAO,QAAQ,KACb,OAAO,SAAS,cACd,OAAO,QAAQ,QAAQ,YAAY,SAAS;EAC1C,MAAM,WAAW,UAAU,UAAU,MAAM,cAAc,UAAU,SAAS,KAAK;AAUjF,UATe,WACX,SAAS,MAAM,KACb,OAAO,MAAM;GACX,YAAY,YAAY,MAAM,QAAQ,QAAQ;GAC9C,iBAAiB;GAClB,CAAC,CACH,GACD,OAAO,QAAQ,MAAM,+BAA+B,OAAO,CAAC,EAElD,KAAK,OAAO,KAAK,WAAW,MAAM,KAAK,MAAM,OAAO,CAAC,CAAC;GACpE,CAAC,KAAK,OAAO,IAAI,YAAY,CAAC,CACjC,EACD,OAAO,QAAQ,MAAM,EACrB,OAAO,MAAM;EACX,YAAY,YAAY,WAAW,QAAQ,WAAW,MAAM,QAAQ,QAAQ,CAAC;EAC7E,YAAY,YAAY;EACzB,CAAC,CACH;;;;;ACrDH,MAAa,SAAS,KAAU,YAC9B,OAAO,IAAI,aAAa;CACtB,MAAM,gBACJ,QAAQ,kBAAkB,OAAO,SAAS,IAAI,KAAK,OAAO,IAAI,SAAS,UAAU,CAAC;CACpF,MAAM,SAAS,IAAI,UAAU,KAAK,UAAU,MAAM,KAAK,IAAI,EAAE;AAE7D,QAAO,OAAO,QAAQ,uBAAuB,CAAC,KAC5C,OAAO,aAAa;EAAE,MAAM,QAAQ;EAAM;EAAQ,CAAC,CACpD;AAED,QAAO,OAAOC,IAAa,KAAK;EAC9B;EACA,SAAS;GACP,QAAQ,IAAI,YAAY,EAAE;GAC1B,YAAY,QAAQ,cAAc;GAClC,aAAa,QAAQ;GACrB,YAAY,QAAQ;GACpB,mBAAmB,QAAQ,qBAAqB;GACjD;EACF,CAAC,CAAC,KAAK,OAAO,QAAQ,eAAe,MAAM,cAAc,EAAE,MAAM,QAAQ,MAAM,CAAC,CAAC,CAAC;EACnF"}
@@ -4,6 +4,8 @@ import { HashSet } from "effect";
4
4
  /** Shared runtime keys owned by Airfoil rather than an individual connector. */
5
5
  const PlatformRuntimeKey = {
6
6
  configPath: "AIRFOIL_CONFIG_PATH",
7
+ httpPort: "AIRFOIL_HTTP_PORT",
8
+ tableBindings: "AIRFOIL_TABLE_BINDINGS",
7
9
  connectorInstanceId: "AIRFOIL_CONNECTOR_INSTANCE_ID",
8
10
  stateTable: "AIRFOIL_STATE_TABLE",
9
11
  postgresConnectionString: "POSTGRES_CONNECTION_STRING",
@@ -17,11 +19,14 @@ const PlatformRuntimeKey = {
17
19
  otelResourceAttributes: "OTEL_RESOURCE_ATTRIBUTES"
18
20
  };
19
21
  /** Defaults for optional platform-owned runtime configuration. */
20
- const PlatformRuntimeDefault = { stateTable: "_airfoil_connectors_state" };
22
+ const PlatformRuntimeDefault = {
23
+ httpPort: 8080,
24
+ stateTable: "_airfoil_connectors_state"
25
+ };
21
26
  const platformRuntimeKeys = HashSet.fromIterable(Object.values(PlatformRuntimeKey));
22
27
  /** @internal */
23
28
  const isPlatformRuntimeKey = (key) => HashSet.has(platformRuntimeKeys, key);
24
29
 
25
30
  //#endregion
26
31
  export { PlatformRuntimeKey as n, isPlatformRuntimeKey as r, PlatformRuntimeDefault as t };
27
- //# sourceMappingURL=constants-BRhIX_rz.js.map
32
+ //# sourceMappingURL=constants-D113Ut1x.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants-D113Ut1x.js","names":[],"sources":["../src/runtime-config/constants.ts"],"sourcesContent":["import { HashSet } from \"effect\";\n\n/** Shared runtime keys owned by Airfoil rather than an individual connector. */\nexport const PlatformRuntimeKey = {\n configPath: \"AIRFOIL_CONFIG_PATH\",\n httpPort: \"AIRFOIL_HTTP_PORT\",\n tableBindings: \"AIRFOIL_TABLE_BINDINGS\",\n connectorInstanceId: \"AIRFOIL_CONNECTOR_INSTANCE_ID\",\n stateTable: \"AIRFOIL_STATE_TABLE\",\n postgresConnectionString: \"POSTGRES_CONNECTION_STRING\",\n wingsHost: \"WINGS_HOST\",\n wingsNamespace: \"WINGS_NAMESPACE\",\n otelEnabled: \"OTEL_ENABLED\",\n otelExporterOtlpEndpoint: \"OTEL_EXPORTER_OTLP_ENDPOINT\",\n otelExporterOtlpHeaders: \"OTEL_EXPORTER_OTLP_HEADERS\",\n otelServiceName: \"OTEL_SERVICE_NAME\",\n otelServiceVersion: \"OTEL_SERVICE_VERSION\",\n otelResourceAttributes: \"OTEL_RESOURCE_ATTRIBUTES\",\n} as const;\n\n/** Defaults for optional platform-owned runtime configuration. */\nexport const PlatformRuntimeDefault = {\n httpPort: 8080,\n stateTable: \"_airfoil_connectors_state\",\n} as const;\n\nconst platformRuntimeKeys = HashSet.fromIterable(Object.values(PlatformRuntimeKey));\n\n/** @internal */\nexport const isPlatformRuntimeKey = (key: string): boolean => HashSet.has(platformRuntimeKeys, key);\n"],"mappings":";;;;AAGA,MAAa,qBAAqB;CAChC,YAAY;CACZ,UAAU;CACV,eAAe;CACf,qBAAqB;CACrB,YAAY;CACZ,0BAA0B;CAC1B,WAAW;CACX,gBAAgB;CAChB,aAAa;CACb,0BAA0B;CAC1B,yBAAyB;CACzB,iBAAiB;CACjB,oBAAoB;CACpB,wBAAwB;CACzB;;AAGD,MAAa,yBAAyB;CACpC,UAAU;CACV,YAAY;CACb;AAED,MAAM,sBAAsB,QAAQ,aAAa,OAAO,OAAO,mBAAmB,CAAC;;AAGnF,MAAa,wBAAwB,QAAyB,QAAQ,IAAI,qBAAqB,IAAI"}
@@ -1,2 +1,2 @@
1
- import { t as ConnectorError } from "../index-D54ySAKn.js";
1
+ import { t as ConnectorError } from "../index-DKoRwyFn.js";
2
2
  export { ConnectorError };
@@ -1,25 +1,31 @@
1
- import { t as ConnectorError } from "./index-D54ySAKn.js";
2
- import { c as ResourceBatch, n as ConnectorDefinition } from "./types-B35J5YPu.js";
3
- import { a as PublisherService, i as Publisher, n as PublishOptions, r as PublishSource, t as PublishAck } from "./service-IE5qaf9x.js";
1
+ import { t as ConnectorError } from "./index-DKoRwyFn.js";
2
+ import { c as ResourceBatch, n as ConnectorDefinition } from "./types-jVD5Ys43.js";
3
+ import { a as PublisherService, i as Publisher, n as PublishOptions, r as PublishSource, t as PublishAck } from "./service-CUjGhe-7.js";
4
+ import { d as RuntimeConfigError } from "./index-ZSuiZX5H.js";
4
5
  import { Layer } from "effect";
5
6
  import * as Wings from "@useairfoil/wings";
6
7
 
7
8
  //#region src/publisher/wings.d.ts
9
+ /** Programmatic mapping between a connector resource and a Wings table. */
8
10
  type WingsTableMapping = {
9
11
  readonly name: string;
10
12
  readonly partitionValue?: Wings.PartitionValue.PartitionValue;
11
13
  };
14
+ /** Direct Wings publisher configuration, mainly for tests and local runtimes. */
12
15
  type WingsPublisherConfig = {
13
16
  readonly connector: ConnectorDefinition;
14
17
  readonly tables: Record<string, string | WingsTableMapping>;
15
18
  };
19
+ /** Builds a Wings publisher from explicit table mappings. */
16
20
  declare const layerWings: (config: WingsPublisherConfig) => Layer.Layer<Publisher, ConnectorError, Wings.WingsClient.WingsClient>;
21
+ /** Builds a Wings publisher from the complete hosted `AIRFOIL_TABLE_BINDINGS` document. */
22
+ declare const layerWingsConfig: (connector: ConnectorDefinition) => Layer.Layer<Publisher, ConnectorError | RuntimeConfigError, Wings.WingsClient.WingsClient>;
17
23
  //#endregion
18
24
  //#region src/publisher/console.d.ts
19
25
  declare const layerConsole: Layer.Layer<Publisher, never, never>;
20
26
  declare namespace index_d_exports {
21
- export { PublishAck, PublishOptions, PublishSource, Publisher, PublisherService, ResourceBatch, WingsPublisherConfig, layerConsole, layerWings };
27
+ export { PublishAck, PublishOptions, PublishSource, Publisher, PublisherService, ResourceBatch, WingsPublisherConfig, layerConsole, layerWings, layerWingsConfig };
22
28
  }
23
29
  //#endregion
24
- export { layerWings as i, layerConsole as n, WingsPublisherConfig as r, index_d_exports as t };
25
- //# sourceMappingURL=index-Byr0Lf0C.d.ts.map
30
+ export { layerWingsConfig as a, layerWings as i, layerConsole as n, WingsPublisherConfig as r, index_d_exports as t };
31
+ //# sourceMappingURL=index-BA8ASHKr.d.ts.map
@@ -1,5 +1,5 @@
1
- import { C as WebhookRouteInput, S as WebhookRouteContext, c as ResourceBatch, l as ResourceDefinition, x as WebhookRoute, y as WebhookAckMode } from "./types-B35J5YPu.js";
2
- import { i as Publisher } from "./service-IE5qaf9x.js";
1
+ import { C as WebhookRouteInput, S as WebhookRouteContext, c as ResourceBatch, l as ResourceDefinition, x as WebhookRoute, y as WebhookAckMode } from "./types-jVD5Ys43.js";
2
+ import { i as Publisher } from "./service-CUjGhe-7.js";
3
3
  import { Context, Queue } from "effect";
4
4
  import { HttpRouter } from "effect/unstable/http";
5
5
  import * as effect_Layer1 from "effect/Layer";
@@ -22,4 +22,4 @@ declare namespace index_d_exports {
22
22
  declare const route: <const Resources extends ReadonlyArray<ResourceDefinition>, Payload>(definition: WebhookRouteInput<Resources, Payload>) => WebhookRoute<Resources, Payload>;
23
23
  //#endregion
24
24
  export { route as n, router as r, index_d_exports as t };
25
- //# sourceMappingURL=index-DKWIh6M1.d.ts.map
25
+ //# sourceMappingURL=index-BKw7jA2a.d.ts.map
@@ -1,7 +1,7 @@
1
- import { t as ConnectorError } from "./index-D54ySAKn.js";
2
- import { b as WebhookHandler, d as ResourceMutation, f as ResourceName, g as ResourceSchema, i as DeleteValue, l as ResourceDefinition, n as ConnectorDefinition, r as Cursor, s as PageFetch, t as ChangesFetch } from "./types-B35J5YPu.js";
3
- import { i as Publisher } from "./service-IE5qaf9x.js";
4
- import { i as StateStore } from "./index-Coh_SkBs.js";
1
+ import { t as ConnectorError } from "./index-DKoRwyFn.js";
2
+ import { b as WebhookHandler, d as ResourceMutation, f as ResourceName, g as ResourceSchema, i as DeleteValue, l as ResourceDefinition, n as ConnectorDefinition, r as Cursor, s as PageFetch, t as ChangesFetch } from "./types-jVD5Ys43.js";
3
+ import { i as Publisher } from "./service-CUjGhe-7.js";
4
+ import { i as StateStore } from "./index-DYpEMJf-.js";
5
5
  import { Config, Context, Duration, Effect, Layer } from "effect";
6
6
  import { HttpRouter } from "effect/unstable/http";
7
7
  import * as effect_unstable_http_HttpClient0 from "effect/unstable/http/HttpClient";
@@ -52,7 +52,7 @@ declare const Cursor$1: {
52
52
  nowIsoDateTime: Effect.Effect<string, never, never>;
53
53
  };
54
54
  declare namespace telemetry_d_exports {
55
- export { Attr, EventAttr, EventName, OtlpMetricsOptions, OtlpTracingConfig, OtlpTracingOptions, SpanName, addCurrentSpanEvent, annotateError, layer, layerConfig, layerMetricsConsoleDump, layerOtlp, layerOtlpMetrics, layerOtlpTracing };
55
+ export { Attr, EventAttr, EventName, OtlpMetricsOptions, OtlpTracingConfig, OtlpTracingOptions, ResourceAttr, SpanName, addCurrentSpanEvent, annotateError, layer, layerConfig, layerMetricsConsoleDump, layerOtlp, layerOtlpMetrics, layerOtlpTracing };
56
56
  }
57
57
  /** Canonical span names emitted by connector-kit runtime instrumentation. */
58
58
  declare const SpanName: {
@@ -70,7 +70,11 @@ declare const Attr: {
70
70
  readonly resourceName: "airfoil.resource.name";
71
71
  readonly resourceSource: "airfoil.resource.source";
72
72
  readonly batchMutations: "airfoil.batch.mutations";
73
+ readonly batchOutcome: "airfoil.batch.outcome";
73
74
  readonly webhookPath: "airfoil.webhook.path";
75
+ readonly webhookOutcome: "airfoil.webhook.outcome";
76
+ readonly syncState: "airfoil.connector.sync.state";
77
+ readonly apiRetryReason: "airfoil.connector.api.retry.reason";
74
78
  readonly publisherSuccess: "airfoil.publisher.success";
75
79
  readonly stateKey: "airfoil.state.key";
76
80
  readonly apiPath: "airfoil.api.path";
@@ -79,6 +83,12 @@ declare const Attr: {
79
83
  readonly errorMessage: "airfoil.error.message";
80
84
  readonly errorDetails: "airfoil.error.details";
81
85
  };
86
+ /** Resource attributes injected by the hosted operator through standard OTel environment keys. */
87
+ declare const ResourceAttr: {
88
+ readonly serviceInstanceId: "service.instance.id";
89
+ readonly connectorRevision: "airfoil.connector.revision";
90
+ readonly teamId: "airfoil.team.id";
91
+ };
82
92
  /** Span event names for high-cardinality reproduction details. */
83
93
  declare const EventName: {
84
94
  readonly batchCheckpoint: "airfoil.batch.checkpoint";
@@ -102,6 +112,7 @@ type OtlpTracingOptions = {
102
112
  /** Additional connector-specific header names or regexes to redact from HTTP logs/traces. */
103
113
  readonly redactedHeaders?: ReadonlyArray<string | RegExp>;
104
114
  };
115
+ /** OTLP metric export settings. */
105
116
  type OtlpMetricsOptions = {
106
117
  readonly exportInterval?: Duration.Input;
107
118
  };
@@ -130,8 +141,11 @@ declare const layerConfig: (config: Config.Wrap<OtlpTracingConfig>, options?: Ot
130
141
  * `OTEL_SERVICE_NAME`, `OTEL_SERVICE_VERSION`, and `OTEL_RESOURCE_ATTRIBUTES`.
131
142
  */
132
143
  declare const layerOtlpTracing: (options?: OtlpTracingOptions) => Layer.Layer<never, Error | Config.ConfigError, effect_unstable_http_HttpClient0.HttpClient>;
144
+ /** Exports connector metrics over OTLP when telemetry is enabled. */
133
145
  declare const layerOtlpMetrics: (options?: OtlpMetricsOptions) => Layer.Layer<never, Error | Config.ConfigError, effect_unstable_http_HttpClient0.HttpClient>;
146
+ /** Enables OTLP traces and metrics with shared environment configuration. */
134
147
  declare const layerOtlp: (options?: OtlpTracingOptions & OtlpMetricsOptions) => Layer.Layer<never, Error | Config.ConfigError, effect_unstable_http_HttpClient0.HttpClient>;
148
+ /** Periodically logs the in-memory metric snapshot for local debugging. */
135
149
  declare const layerMetricsConsoleDump: (interval?: Duration.Input) => Layer.Layer<never, never, never>;
136
150
  //#endregion
137
151
  //#region src/connector-app/start.d.ts
@@ -144,10 +158,10 @@ type StartOptions = {
144
158
  readonly statusPath?: HttpRouter.PathInput | false;
145
159
  readonly disableHttpLogger?: boolean;
146
160
  };
147
- declare const start: (app: App, options: StartOptions) => Effect.Effect<void, ConnectorError | effect_unstable_http_HttpServerError0.ServeError, StateStore | Publisher>;
161
+ declare const start: (app: App, options: StartOptions) => Effect.Effect<void, ConnectorError | effect_unstable_http_HttpServerError0.ServeError, Publisher | StateStore>;
148
162
  declare namespace index_d_exports {
149
163
  export { App, CheckOptions, CheckResult, ResourceCheckResult, StartOptions, check, start };
150
164
  }
151
165
  //#endregion
152
166
  export { telemetry_d_exports as a, Fetch as c, CheckResult as d, ResourceCheckResult as f, start as i, Resource as l, App as n, Connector as o, check as p, StartOptions as r, Cursor$1 as s, index_d_exports as t, CheckOptions as u };
153
- //# sourceMappingURL=index-DtJX_tic.d.ts.map
167
+ //# sourceMappingURL=index-C5Ma7V7t.d.ts.map
@@ -170,4 +170,4 @@ declare namespace index_d_exports {
170
170
  }
171
171
  //#endregion
172
172
  export { number as _, configSchema as a, select as b, ConnectorManifest as c, ConfigField as d, ConfigFieldSpec as f, define as g, boolean as h, RuntimeConfigDocument as i, ResourceCapability as l, ConnectorConfigDef as m, ConnectorConfigSchema as n, decodeConfig as o, ConfigValuesOf as p, ConnectorConfigValues as r, toRuntimeDocument as s, index_d_exports as t, define$1 as u, optional as v, string as x, secret as y };
173
- //# sourceMappingURL=index-CBT-JX-T.d.ts.map
173
+ //# sourceMappingURL=index-CR9HJDdr.d.ts.map
@@ -11,4 +11,4 @@ declare class ConnectorError extends ConnectorError_base<{
11
11
  }> {}
12
12
  //#endregion
13
13
  export { ConnectorError as t };
14
- //# sourceMappingURL=index-D54ySAKn.d.ts.map
14
+ //# sourceMappingURL=index-DKoRwyFn.d.ts.map
@@ -38,4 +38,4 @@ declare namespace index_d_exports {
38
38
  }
39
39
  //#endregion
40
40
  export { makeTokenCache as i, ExpiringToken as n, TokenCache as r, index_d_exports as t };
41
- //# sourceMappingURL=index-CTHVudvQ.d.ts.map
41
+ //# sourceMappingURL=index-DXa26Ry5.d.ts.map
@@ -1,4 +1,4 @@
1
- import { t as ConnectorError } from "./index-D54ySAKn.js";
1
+ import { t as ConnectorError } from "./index-DKoRwyFn.js";
2
2
  import { Config, Context, Effect, Layer, Schema } from "effect";
3
3
  import { SqlClient } from "effect/unstable/sql";
4
4
 
@@ -92,4 +92,4 @@ declare namespace index_d_exports {
92
92
  }
93
93
  //#endregion
94
94
  export { StateStoreService as a, StateStore as i, layerSql as n, layerMemory as r, index_d_exports as t };
95
- //# sourceMappingURL=index-Coh_SkBs.d.ts.map
95
+ //# sourceMappingURL=index-DYpEMJf-.d.ts.map
@@ -1,5 +1,5 @@
1
- import { n as ConnectorDefinition } from "./types-B35J5YPu.js";
2
- import { i as StateStore } from "./index-Coh_SkBs.js";
1
+ import { n as ConnectorDefinition } from "./types-jVD5Ys43.js";
2
+ import { i as StateStore } from "./index-DYpEMJf-.js";
3
3
  import { Schema } from "effect";
4
4
  import { HttpRouter } from "effect/unstable/http";
5
5
  import * as effect_Layer0 from "effect/Layer";
@@ -77,4 +77,4 @@ declare namespace index_d_exports {
77
77
  }
78
78
  //#endregion
79
79
  export { ResourceStatusSchema as a, StatusUnavailableResponse as c, SyncStateSchema as d, statusRoute as f, ResourceStatus as i, StatusUnavailableResponseSchema as l, ResourceError as n, StatusResponse as o, ResourceErrorSchema as r, StatusResponseSchema as s, index_d_exports as t, SyncState as u };
80
- //# sourceMappingURL=index-Cq2IzY7T.d.ts.map
80
+ //# sourceMappingURL=index-VpHaZXZw.d.ts.map
@@ -0,0 +1,85 @@
1
+ import { f as ResourceName, n as ConnectorDefinition } from "./types-jVD5Ys43.js";
2
+ import { Config, Effect, FileSystem } from "effect";
3
+ import * as Wings from "@useairfoil/wings";
4
+ import * as effect_Types0 from "effect/Types";
5
+ import * as effect_Cause0 from "effect/Cause";
6
+ import * as effect_Layer0 from "effect/Layer";
7
+
8
+ //#region src/runtime-config/error.d.ts
9
+ type RuntimeConfigErrorCode = "CONFIG_PATH_MISSING" | "CONFIG_FILE_UNREADABLE" | "CONFIG_JSON_INVALID" | "TABLE_BINDINGS_MISSING" | "TABLE_BINDINGS_INVALID" | "TABLE_BINDINGS_MISMATCH";
10
+ declare const RuntimeConfigError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
11
+ readonly _tag: "RuntimeConfigError";
12
+ } & Readonly<A>;
13
+ /** Expected hosted-config failure with a stable code and diagnostic cause. */
14
+ declare class RuntimeConfigError extends RuntimeConfigError_base<{
15
+ readonly code: RuntimeConfigErrorCode;
16
+ readonly message: string;
17
+ readonly cause: Error;
18
+ }> {}
19
+ //#endregion
20
+ //#region src/runtime-config/config.d.ts
21
+ /** Shared HTTP port used by hosted and sandbox connector entrypoints. */
22
+ declare const httpPort: Config.Config<number>;
23
+ /** Shared Wings client configuration supplied by the hosting platform. */
24
+ declare const wingsClient: {
25
+ host: Config.Config<string>;
26
+ namespace: Config.Config<string>;
27
+ };
28
+ //#endregion
29
+ //#region src/runtime-config/constants.d.ts
30
+ /** Shared runtime keys owned by Airfoil rather than an individual connector. */
31
+ declare const PlatformRuntimeKey: {
32
+ readonly configPath: "AIRFOIL_CONFIG_PATH";
33
+ readonly httpPort: "AIRFOIL_HTTP_PORT";
34
+ readonly tableBindings: "AIRFOIL_TABLE_BINDINGS";
35
+ readonly connectorInstanceId: "AIRFOIL_CONNECTOR_INSTANCE_ID";
36
+ readonly stateTable: "AIRFOIL_STATE_TABLE";
37
+ readonly postgresConnectionString: "POSTGRES_CONNECTION_STRING";
38
+ readonly wingsHost: "WINGS_HOST";
39
+ readonly wingsNamespace: "WINGS_NAMESPACE";
40
+ readonly otelEnabled: "OTEL_ENABLED";
41
+ readonly otelExporterOtlpEndpoint: "OTEL_EXPORTER_OTLP_ENDPOINT";
42
+ readonly otelExporterOtlpHeaders: "OTEL_EXPORTER_OTLP_HEADERS";
43
+ readonly otelServiceName: "OTEL_SERVICE_NAME";
44
+ readonly otelServiceVersion: "OTEL_SERVICE_VERSION";
45
+ readonly otelResourceAttributes: "OTEL_RESOURCE_ATTRIBUTES";
46
+ };
47
+ /** Defaults for optional platform-owned runtime configuration. */
48
+ declare const PlatformRuntimeDefault: {
49
+ readonly httpPort: 8080;
50
+ readonly stateTable: "_airfoil_connectors_state";
51
+ };
52
+ //#endregion
53
+ //#region src/runtime-config/layer.d.ts
54
+ /**
55
+ * Loads the required JSON file and lets environment values override it per key.
56
+ * Connector field validation remains in the connector's Effect Config.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * program.pipe(Effect.provide(layerHosted()));
61
+ * ```
62
+ */
63
+ declare const layerHosted: () => effect_Layer0.Layer<never, RuntimeConfigError, FileSystem.FileSystem>;
64
+ //#endregion
65
+ //#region src/runtime-config/table-bindings.d.ts
66
+ /** Table binding shape accepted in `AIRFOIL_TABLE_BINDINGS`. */
67
+ type HostedTableBinding = string | {
68
+ readonly name: string;
69
+ readonly partition?: Wings.PartitionValue.Json;
70
+ };
71
+ /** Validated table binding ready for the Wings publisher. */
72
+ type ResolvedTableBinding = {
73
+ readonly name: string;
74
+ readonly partitionValue?: Wings.PartitionValue.PartitionValue;
75
+ };
76
+ /** One resolved binding for each resource in a connector manifest. */
77
+ type ResolvedTableBindings<Connector extends ConnectorDefinition> = Readonly<Record<ResourceName<Connector["resources"]>, ResolvedTableBinding>>;
78
+ /** Loads and validates the complete hosted Wings table map for a connector. */
79
+ declare const loadTableBindings: <const Connector extends ConnectorDefinition>(connector: Connector) => Effect.Effect<ResolvedTableBindings<Connector>, RuntimeConfigError>;
80
+ declare namespace index_d_exports {
81
+ export { HostedTableBinding, PlatformRuntimeDefault, PlatformRuntimeKey, ResolvedTableBinding, ResolvedTableBindings, RuntimeConfigError, RuntimeConfigErrorCode, httpPort, layerHosted, loadTableBindings, wingsClient };
82
+ }
83
+ //#endregion
84
+ export { loadTableBindings as a, PlatformRuntimeKey as c, RuntimeConfigError as d, RuntimeConfigErrorCode as f, ResolvedTableBindings as i, httpPort as l, HostedTableBinding as n, layerHosted as o, ResolvedTableBinding as r, PlatformRuntimeDefault as s, index_d_exports as t, wingsClient as u };
85
+ //# sourceMappingURL=index-ZSuiZX5H.d.ts.map
@@ -1,7 +1,7 @@
1
- import { t as ConnectorError } from "./index-D54ySAKn.js";
2
- import { l as ResourceDefinition, n as ConnectorDefinition, r as Cursor, x as WebhookRoute } from "./types-B35J5YPu.js";
3
- import { i as Publisher } from "./service-IE5qaf9x.js";
4
- import { i as StateStore } from "./index-Coh_SkBs.js";
1
+ import { t as ConnectorError } from "./index-DKoRwyFn.js";
2
+ import { l as ResourceDefinition, n as ConnectorDefinition, r as Cursor, x as WebhookRoute } from "./types-jVD5Ys43.js";
3
+ import { i as Publisher } from "./service-CUjGhe-7.js";
4
+ import { i as StateStore } from "./index-DYpEMJf-.js";
5
5
  import { Effect } from "effect";
6
6
  import { HttpRouter, HttpServer } from "effect/unstable/http";
7
7
 
@@ -35,4 +35,4 @@ declare namespace index_d_exports {
35
35
  }
36
36
  //#endregion
37
37
  export { RunOptions as n, run as r, index_d_exports as t };
38
- //# sourceMappingURL=index-J42AZaXU.d.ts.map
38
+ //# sourceMappingURL=index-bfjH7Yb0.d.ts.map
package/dist/index.d.ts CHANGED
@@ -1,14 +1,14 @@
1
- import { t as index_d_exports } from "./index-CTHVudvQ.js";
2
- import { t as ConnectorError } from "./index-D54ySAKn.js";
3
- import { S as WebhookRouteContext, _ as ResourceState, a as FetchChangesResult, b as WebhookHandler, c as ResourceBatch, d as ResourceMutation, g as ResourceSchema, h as ResourceRows, l as ResourceDefinition, m as ResourceRow, n as ConnectorDefinition, o as FetchPageResult, p as ResourcePayload, r as Cursor$1, s as PageFetch, t as ChangesFetch, u as ResourceField, x as WebhookRoute, y as WebhookAckMode } from "./types-B35J5YPu.js";
4
- import { a as telemetry_d_exports, c as Fetch, l as Resource, o as Connector, s as Cursor, t as index_d_exports$1 } from "./index-DtJX_tic.js";
5
- import "./service-IE5qaf9x.js";
6
- import { t as index_d_exports$6 } from "./index-Coh_SkBs.js";
7
- import { t as index_d_exports$2 } from "./index-J42AZaXU.js";
8
- import { t as index_d_exports$3 } from "./index-CBT-JX-T.js";
9
- import { g as metrics_d_exports } from "./metrics-CVAk1ALR.js";
10
- import { t as index_d_exports$4 } from "./index-Byr0Lf0C.js";
11
- import { t as index_d_exports$5 } from "./index-o1-Z3n7V.js";
12
- import { t as index_d_exports$7 } from "./index-Cq2IzY7T.js";
13
- import { t as index_d_exports$8 } from "./index-DKWIh6M1.js";
1
+ import { t as index_d_exports } from "./index-DXa26Ry5.js";
2
+ import { t as ConnectorError } from "./index-DKoRwyFn.js";
3
+ import { S as WebhookRouteContext, _ as ResourceState, a as FetchChangesResult, b as WebhookHandler, c as ResourceBatch, d as ResourceMutation, g as ResourceSchema, h as ResourceRows, l as ResourceDefinition, m as ResourceRow, n as ConnectorDefinition, o as FetchPageResult, p as ResourcePayload, r as Cursor$1, s as PageFetch, t as ChangesFetch, u as ResourceField, x as WebhookRoute, y as WebhookAckMode } from "./types-jVD5Ys43.js";
4
+ import { a as telemetry_d_exports, c as Fetch, l as Resource, o as Connector, s as Cursor, t as index_d_exports$1 } from "./index-C5Ma7V7t.js";
5
+ import "./service-CUjGhe-7.js";
6
+ import { t as index_d_exports$6 } from "./index-DYpEMJf-.js";
7
+ import { t as index_d_exports$2 } from "./index-bfjH7Yb0.js";
8
+ import { t as index_d_exports$3 } from "./index-CR9HJDdr.js";
9
+ import { g as metrics_d_exports } from "./metrics-C4V1pm6v.js";
10
+ import { t as index_d_exports$5 } from "./index-ZSuiZX5H.js";
11
+ import { t as index_d_exports$4 } from "./index-BA8ASHKr.js";
12
+ import { t as index_d_exports$7 } from "./index-VpHaZXZw.js";
13
+ import { t as index_d_exports$8 } from "./index-BKw7jA2a.js";
14
14
  export { index_d_exports as Auth, ChangesFetch, Connector, index_d_exports$1 as ConnectorApp, ConnectorDefinition, ConnectorError, Cursor, Cursor$1 as CursorTypes, Fetch, FetchChangesResult, FetchPageResult, index_d_exports$2 as Ingestion, index_d_exports$3 as Manifest, metrics_d_exports as Metrics, PageFetch, index_d_exports$4 as Publisher, Resource, ResourceBatch, ResourceDefinition, ResourceField, ResourceMutation, ResourcePayload, ResourceRow, ResourceRows, ResourceSchema, ResourceState, index_d_exports$5 as RuntimeConfig, index_d_exports$6 as StateStore, index_d_exports$7 as Status, telemetry_d_exports as Telemetry, index_d_exports$8 as Webhook, WebhookAckMode, WebhookHandler, WebhookRoute, WebhookRouteContext };
package/dist/index.js CHANGED
@@ -1,17 +1,19 @@
1
1
  import { t as ConnectorError } from "./errors-DHWylqRZ.js";
2
2
  import { t as auth_exports } from "./auth-DvU_CZ7C.js";
3
- import { t as connector_app_exports } from "./connector-app-d7Z-SZLQ.js";
4
- import { s as metrics_exports } from "./metrics-CWPy2Aqc.js";
5
- import "./constants-BRhIX_rz.js";
6
- import { c as telemetry_exports } from "./service-DuFiQwid.js";
7
- import "./server-CXTQ7odl.js";
8
- import { t as state_store_exports } from "./state-store-yl6LiTQ0.js";
9
- import { t as status_exports } from "./status-B-oZBc33.js";
10
- import { t as ingestion_exports } from "./ingestion-BQo4cbGw.js";
11
- import { t as manifest_exports } from "./manifest-ByE6YPG0.js";
12
- import { t as publisher_exports } from "./publisher-BYT3RLVO.js";
13
- import { t as runtime_config_exports } from "./runtime-config-BpB-d_bF.js";
14
- import { n as webhook_exports } from "./webhook-DI-Afxkg.js";
3
+ import { t as connector_app_exports } from "./connector-app-BljHd0Pe.js";
4
+ import "./constants-D113Ut1x.js";
5
+ import { s as telemetry_exports } from "./telemetry-j_nxwYfh.js";
6
+ import { s as metrics_exports } from "./metrics-inkCAxKq.js";
7
+ import "./service-DiP-XETo.js";
8
+ import "./server-D-eLX3yN.js";
9
+ import { t as state_store_exports } from "./state-store-BdYulQOY.js";
10
+ import { t as status_exports } from "./status-BTTd7AUR.js";
11
+ import { t as ingestion_exports } from "./ingestion-QBGKrFr9.js";
12
+ import { t as manifest_exports } from "./manifest-P7kBnch9.js";
13
+ import { t as publisher_exports } from "./publisher-BdWJOfer.js";
14
+ import "./table-bindings-Dp1DhTeS.js";
15
+ import { t as runtime_config_exports } from "./runtime-config-IbyCVpei.js";
16
+ import { n as webhook_exports } from "./webhook-MhFcLW-o.js";
15
17
  import { DateTime, Effect } from "effect";
16
18
 
17
19
  //#region src/core/builder.ts