@useairfoil/connector-kit 0.6.1 → 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 (102) hide show
  1. package/LICENSE.txt +201 -0
  2. package/METRICS.md +27 -30
  3. package/README.md +33 -51
  4. package/dist/{annotations-BE74YmAO.d.mts → annotations-vzSzXtr-.d.mts} +5 -10
  5. package/dist/{wings-I56hGtNv.mjs → arrow-flight-DDQ0ktx9.mjs} +25 -99
  6. package/dist/arrow-flight-DDQ0ktx9.mjs.map +1 -0
  7. package/dist/connector-app/index.d.mts +2 -2
  8. package/dist/connector-app/index.mjs +2 -2
  9. package/dist/connector-app-C6_dZnhE.mjs +256 -0
  10. package/dist/connector-app-C6_dZnhE.mjs.map +1 -0
  11. package/dist/{constants-D-GQzpHZ.mjs → constants-v3UX-hf6.mjs} +3 -2
  12. package/dist/constants-v3UX-hf6.mjs.map +1 -0
  13. package/dist/demo/index.d.mts +1 -1
  14. package/dist/demo/index.mjs +1 -1
  15. package/dist/{demo-B30Vlkk2.mjs → demo-DqTJ7TWI.mjs} +32 -19
  16. package/dist/demo-DqTJ7TWI.mjs.map +1 -0
  17. package/dist/iceberg/index.d.mts +3 -3
  18. package/dist/iceberg/index.mjs +3 -3
  19. package/dist/iceberg-Cj2PwlNm.mjs +30 -0
  20. package/dist/iceberg-Cj2PwlNm.mjs.map +1 -0
  21. package/dist/{index-DJhDp4Xc.d.mts → index-BTAbexBp.d.mts} +13 -16
  22. package/dist/{index-BUHSGm9Q.d.mts → index-Byr8NTdG.d.mts} +2 -2
  23. package/dist/{index-Dk7urvpF.d.mts → index-CV6V6fyx.d.mts} +9 -6
  24. package/dist/{index-NnCutIqM.d.mts → index-CZKx2Yce.d.mts} +29 -19
  25. package/dist/{index-BfXpgxk9.d.mts → index-DeTwIUKl.d.mts} +3 -3
  26. package/dist/{index-CRVAwJ5-.d.mts → index-dHS59EZl.d.mts} +4 -4
  27. package/dist/{index-ygpml2kC.d.mts → index-fHIJJoRe.d.mts} +17 -10
  28. package/dist/index-uFa2wwYo.d.mts +27 -0
  29. package/dist/index.d.mts +11 -11
  30. package/dist/index.mjs +10 -10
  31. package/dist/ingestion/index.d.mts +1 -1
  32. package/dist/ingestion/index.mjs +1 -1
  33. package/dist/{ingestion-q0WwqUSt.mjs → ingestion-DoCUwm5N.mjs} +6 -6
  34. package/dist/{ingestion-q0WwqUSt.mjs.map → ingestion-DoCUwm5N.mjs.map} +1 -1
  35. package/dist/ingestor/index.d.mts +3 -3
  36. package/dist/ingestor/index.mjs +3 -3
  37. package/dist/{ingestor-D4L-HPkg.mjs → ingestor-DjCEzBzZ.mjs} +6 -6
  38. package/dist/ingestor-DjCEzBzZ.mjs.map +1 -0
  39. package/dist/{instrumented-Bhp7fyvh.mjs → instrumented-Bq1WX2L5.mjs} +2 -2
  40. package/dist/{instrumented-Bhp7fyvh.mjs.map → instrumented-Bq1WX2L5.mjs.map} +1 -1
  41. package/dist/manifest/index.mjs +1 -1
  42. package/dist/{manifest-BGKxmKLy.mjs → manifest-CABeIhAG.mjs} +2 -2
  43. package/dist/{manifest-BGKxmKLy.mjs.map → manifest-CABeIhAG.mjs.map} +1 -1
  44. package/dist/{metrics-BaEX__MN.mjs → metrics-C901IIYZ.mjs} +6 -11
  45. package/dist/metrics-C901IIYZ.mjs.map +1 -0
  46. package/dist/{metrics-CVXFL7YT.d.mts → metrics-DoJ0WeKu.d.mts} +2 -2
  47. package/dist/metrics.d.mts +1 -1
  48. package/dist/metrics.mjs +1 -1
  49. package/dist/runtime-config/index.d.mts +2 -2
  50. package/dist/runtime-config/index.mjs +3 -3
  51. package/dist/{runtime-config-Oa55gAew.mjs → runtime-config-Bn8Fivt1.mjs} +11 -8
  52. package/dist/runtime-config-Bn8Fivt1.mjs.map +1 -0
  53. package/dist/{server-CMnxz3h0.mjs → server-D1TTN0_D.mjs} +3 -3
  54. package/dist/{server-CMnxz3h0.mjs.map → server-D1TTN0_D.mjs.map} +1 -1
  55. package/dist/{service-DLkhuxYl.d.mts → service-BRoy_EId.d.mts} +2 -2
  56. package/dist/state-store/index.mjs +1 -1
  57. package/dist/{state-store-uFvHY7Ax.mjs → state-store-DhSrKVEH.mjs} +2 -2
  58. package/dist/{state-store-uFvHY7Ax.mjs.map → state-store-DhSrKVEH.mjs.map} +1 -1
  59. package/dist/status/index.d.mts +1 -1
  60. package/dist/status/index.mjs +1 -1
  61. package/dist/{status-CKb9IhQ9.mjs → status-4h6Oxh-O.mjs} +2 -2
  62. package/dist/{status-CKb9IhQ9.mjs.map → status-4h6Oxh-O.mjs.map} +1 -1
  63. package/dist/{table-V0tgUC5i.mjs → table-CxM09xf7.mjs} +22 -85
  64. package/dist/table-CxM09xf7.mjs.map +1 -0
  65. package/dist/{types-xZtSmrGA.d.mts → types-NtSv6gwl.d.mts} +3 -3
  66. package/dist/webhook/index.d.mts +2 -2
  67. package/dist/webhook/index.mjs +1 -1
  68. package/package.json +19 -18
  69. package/src/catalog/retry.ts +25 -0
  70. package/src/catalog/table.ts +73 -37
  71. package/src/connector-app/create-table.ts +8 -8
  72. package/src/connector-app/demo.ts +24 -19
  73. package/src/connector-app/index.ts +1 -0
  74. package/src/connector-app/setup.ts +69 -0
  75. package/src/core/types.ts +1 -1
  76. package/src/demo/definition.ts +1 -1
  77. package/src/demo/generate.ts +1 -1
  78. package/src/demo/run.ts +60 -30
  79. package/src/iceberg/annotations.ts +3 -16
  80. package/src/iceberg/index.ts +2 -2
  81. package/src/iceberg/table.ts +28 -78
  82. package/src/ingestion/engine.ts +1 -1
  83. package/src/ingestor/{wings.ts → arrow-flight.ts} +25 -27
  84. package/src/ingestor/console.ts +1 -1
  85. package/src/ingestor/index.ts +5 -1
  86. package/src/runtime-config/config.ts +8 -3
  87. package/src/runtime-config/constants.ts +2 -1
  88. package/src/runtime-config/index.ts +1 -1
  89. package/src/runtime-config/table-bindings.ts +6 -4
  90. package/src/telemetry.ts +11 -19
  91. package/dist/connector-app-C-L4QqG6.mjs +0 -123
  92. package/dist/connector-app-C-L4QqG6.mjs.map +0 -1
  93. package/dist/constants-D-GQzpHZ.mjs.map +0 -1
  94. package/dist/demo-B30Vlkk2.mjs.map +0 -1
  95. package/dist/iceberg-D6L8I6vA.mjs +0 -39
  96. package/dist/iceberg-D6L8I6vA.mjs.map +0 -1
  97. package/dist/index-CUPP2A_m.d.mts +0 -27
  98. package/dist/ingestor-D4L-HPkg.mjs.map +0 -1
  99. package/dist/metrics-BaEX__MN.mjs.map +0 -1
  100. package/dist/runtime-config-Oa55gAew.mjs.map +0 -1
  101. package/dist/table-V0tgUC5i.mjs.map +0 -1
  102. package/dist/wings-I56hGtNv.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import type {
2
- CommitTableRequest,
2
+ CreateTableRequest,
3
3
  IcebergType,
4
4
  MapType,
5
5
  StructField,
@@ -12,11 +12,10 @@ import { Effect, Schema, type SchemaRepresentation } from "effect";
12
12
  import { IcebergSchemaError } from "./error";
13
13
 
14
14
  /** Options for creating a table. */
15
- export type CreateTableCommitOptions = {
15
+ export type CreateTableOptions = {
16
+ readonly name: string;
16
17
  /** Where the table's files go. The catalog may choose this when omitted. */
17
18
  readonly location?: string | undefined;
18
- /** UUID for the table. Random by default. */
19
- readonly uuid?: string | undefined;
20
19
  /** Extra table properties. These win over the ones from the schema. */
21
20
  readonly properties?: Readonly<Record<string, string>> | undefined;
22
21
  };
@@ -35,9 +34,6 @@ export type CompiledTable = {
35
34
  readonly description: string | undefined;
36
35
  };
37
36
 
38
- // Iceberg reserves its highest 200 field IDs.
39
- const maxFieldId = 2_147_483_447;
40
-
41
37
  const anonymousDeclaration =
42
38
  "Schemas without a name, such as Schema.Class, do not work here; use Schema.Struct";
43
39
 
@@ -121,7 +117,8 @@ class Compiler {
121
117
  readonly #activeObjects = new Set<SchemaRepresentation.Objects>();
122
118
  readonly #activeReferences = new Set<string>();
123
119
  readonly #activeSuspends = new Set<SchemaRepresentation.Suspend>();
124
- readonly #fieldIds = new Map<number, string>();
120
+ // The REST request needs IDs. Only the catalog's returned IDs are authoritative.
121
+ #nextId = 0;
125
122
 
126
123
  constructor(private readonly references: SchemaRepresentation.References) {}
127
124
 
@@ -156,35 +153,6 @@ class Compiler {
156
153
  });
157
154
  }
158
155
 
159
- #readId(annotations: Annotations | undefined, path: string, source: string): number {
160
- const id = annotations?.fieldId;
161
-
162
- if (typeof id !== "number") {
163
- return fail(path, `Missing fieldId; add it with ${source}`);
164
- }
165
- if (!Number.isInteger(id)) return fail(path, "fieldId must be a whole number");
166
- if (id < 1 || id > maxFieldId) {
167
- return fail(path, `fieldId must be between 1 and ${maxFieldId}`);
168
- }
169
- const previousPath = this.#fieldIds.get(id);
170
- if (previousPath !== undefined) {
171
- return fail(path, `fieldId ${id} is already used at ${previousPath}`);
172
- }
173
-
174
- this.#fieldIds.set(id, path);
175
- return id;
176
- }
177
-
178
- #readNodeId(representation: Representation, path: string): number {
179
- return this.#withReference(representation, path, (resolved) =>
180
- this.#readId(
181
- resolveAnnotations(resolved),
182
- path,
183
- ".annotate({ fieldId }) on the schema itself",
184
- ),
185
- );
186
- }
187
-
188
156
  #withReference<A>(
189
157
  representation: Representation,
190
158
  path: string,
@@ -231,7 +199,7 @@ class Compiler {
231
199
 
232
200
  const fieldPath = propertyPath(path, property.name);
233
201
  this.#checkRecursion(property.type, fieldPath);
234
- const id = this.#readId(property.annotations, fieldPath, "Iceberg.field(id)");
202
+ const id = ++this.#nextId;
235
203
  const compiled = this.#compileType(property.type, fieldPath);
236
204
  const fieldDescription = description(property.annotations);
237
205
 
@@ -332,7 +300,7 @@ class Compiler {
332
300
 
333
301
  const elementPath = `${path}.element`;
334
302
  const elementRepresentation = representation.rest[0]!;
335
- const elementId = this.#readNodeId(elementRepresentation, elementPath);
303
+ const elementId = ++this.#nextId;
336
304
  const compiled = this.#compileType(elementRepresentation, elementPath);
337
305
 
338
306
  return {
@@ -375,12 +343,12 @@ class Compiler {
375
343
  const valuePath = `${path}.value`;
376
344
  const keyRepresentation = representation.typeParameters[0]!;
377
345
  const valueRepresentation = representation.typeParameters[1]!;
378
- const keyId = this.#readNodeId(keyRepresentation, keyPath);
346
+ const keyId = ++this.#nextId;
379
347
  const compiledKey = this.#compileType(keyRepresentation, keyPath);
380
348
 
381
349
  if (compiledKey.nullable) return fail(keyPath, "Map keys cannot be null");
382
350
 
383
- const valueId = this.#readNodeId(valueRepresentation, valuePath);
351
+ const valueId = ++this.#nextId;
384
352
  const compiledValue = this.#compileType(valueRepresentation, valuePath);
385
353
 
386
354
  return {
@@ -448,42 +416,23 @@ export const compileTable = (
448
416
  }),
449
417
  });
450
418
 
451
- export const makeCommitRequest = (
419
+ export const makeCreateRequest = (
452
420
  table: CompiledTable,
453
- options: CreateTableCommitOptions,
454
- ): CommitTableRequest => {
455
- const properties = {
421
+ options: CreateTableOptions,
422
+ ): CreateTableRequest => ({
423
+ name: options.name,
424
+ schema: table.schema,
425
+ ...(options.location === undefined ? {} : { location: options.location }),
426
+ properties: {
456
427
  ...(table.description === undefined ? {} : { comment: table.description }),
457
428
  ...options.properties,
458
- };
459
-
460
- return {
461
- requirements: [{ type: "assert-create" }],
462
- updates: [
463
- { action: "assign-uuid", uuid: options.uuid ?? crypto.randomUUID() },
464
- { action: "upgrade-format-version", "format-version": 2 },
465
- { action: "add-schema", schema: table.schema },
466
- { action: "set-current-schema", "schema-id": -1 },
467
- { action: "add-spec", spec: { "spec-id": 0, fields: [] } },
468
- { action: "set-default-spec", "spec-id": -1 },
469
- { action: "add-sort-order", "sort-order": { "order-id": 0, fields: [] } },
470
- { action: "set-default-sort-order", "sort-order-id": -1 },
471
- ...(options.location === undefined
472
- ? []
473
- : [{ action: "set-location" as const, location: options.location }]),
474
- ...(Object.keys(properties).length === 0
475
- ? []
476
- : [{ action: "set-properties" as const, updates: properties }]),
477
- ],
478
- };
479
- };
429
+ "format-version": "3",
430
+ },
431
+ });
480
432
 
481
433
  /**
482
- * Builds the commit that creates an Iceberg table from an Effect schema.
483
- *
484
- * The field IDs come from the schema, so the table has to keep them. Send the
485
- * commit with `commitTable`. Then load the table and check the IDs before you
486
- * write any rows. Don't use `createTable` here, because it can change the IDs.
434
+ * Builds a REST create-table request from an Effect schema.
435
+ * The catalog assigns the stored field IDs.
487
436
  *
488
437
  * A root `description` becomes the table `comment`, and a field `description`
489
438
  * becomes its `doc`. `title` and `examples` are dropped.
@@ -494,18 +443,19 @@ export const makeCommitRequest = (
494
443
  * @example
495
444
  * ```ts
496
445
  * const Row = Schema.Struct({
497
- * id: Schema.String.pipe(Iceberg.field(1, { description: "Stable row identifier" })),
446
+ * id: Schema.String.pipe(Schema.annotateKey({ description: "Row identifier" })),
498
447
  * })
499
448
  * .annotate({ description: "Connector rows" })
500
449
  * .pipe(Iceberg.identifier("id"))
501
450
  *
502
- * const request = yield* Iceberg.makeCreateTableCommitRequest(Row, {
451
+ * const request = yield* Iceberg.makeCreateTableRequest(Row, {
452
+ * name: "rows",
503
453
  * location: "s3://warehouse/rows"
504
454
  * })
505
455
  * ```
506
456
  */
507
- export const makeCreateTableCommitRequest = (
457
+ export const makeCreateTableRequest = (
508
458
  schema: Schema.Top,
509
- options: CreateTableCommitOptions,
510
- ): Effect.Effect<CommitTableRequest, IcebergSchemaError> =>
511
- Effect.map(compileTable(schema), (table) => makeCommitRequest(table, options));
459
+ options: CreateTableOptions,
460
+ ): Effect.Effect<CreateTableRequest, IcebergSchemaError> =>
461
+ Effect.map(compileTable(schema), (table) => makeCreateRequest(table, options));
@@ -480,7 +480,7 @@ const runChanges = Effect.fnUntraced(function* (
480
480
  }).pipe(recordResourceError(connector, resource, "changes", "ingest"));
481
481
 
482
482
  const lastSuccessAt = yield* DateTime.now.pipe(Effect.map(DateTime.formatIso));
483
- // Advance the durable cursor only after Wings acknowledges the page.
483
+ // Advance the durable cursor only after the engine acknowledges the page.
484
484
  yield* Effect.withSpan(
485
485
  store
486
486
  .setChangesState(resource.name, {
@@ -1,20 +1,20 @@
1
1
  import type { RecordBatch, TypeMap } from "apache-arrow";
2
2
  import type { TableIdentifier } from "iceberg-js";
3
3
 
4
- import * as Wings from "@useairfoil/wings";
4
+ import { CatalogManager } from "@useairfoil/api";
5
5
  import { Config, Effect, Layer } from "effect";
6
6
  import { FetchHttpClient } from "effect/http";
7
7
 
8
8
  import type { TableSource } from "../core/types";
9
9
 
10
- import { ensureTable } from "../catalog/table";
11
10
  import { ConnectorError } from "../errors";
11
+ import { compileTable } from "../iceberg/table";
12
12
  import * as RuntimeConfig from "../runtime-config";
13
13
  import { makeRowEncoder, type RowEncoder } from "./arrow";
14
14
  import { Ingestor, type IngestorService } from "./service";
15
15
 
16
16
  /** One catalog and an Iceberg table for each resource that runs. */
17
- export type WingsIngestorConfig<Source extends TableSource = TableSource> = {
17
+ export type ArrowFlightIngestorConfig<Source extends TableSource = TableSource> = {
18
18
  readonly connector: Source;
19
19
  readonly catalog: string;
20
20
  readonly tables: RuntimeConfig.ResolvedTableBindings<Source>;
@@ -33,17 +33,13 @@ type PreparedTable = {
33
33
 
34
34
  const connectorError = (message: string, cause?: unknown) => new ConnectorError({ message, cause });
35
35
 
36
- /** Loads each table schema and opens one Wings stream per bound resource. */
37
- export const layerWings = <const Source extends TableSource>(
38
- config: WingsIngestorConfig<Source>,
39
- ): Layer.Layer<Ingestor, ConnectorError, Wings.CatalogManager.CatalogManager> =>
36
+ /** Compiles local schemas and opens one Arrow Flight stream per bound resource. */
37
+ export const layerArrowFlight = <const Source extends TableSource>(
38
+ config: ArrowFlightIngestorConfig<Source>,
39
+ ): Layer.Layer<Ingestor, ConnectorError, CatalogManager.CatalogManager> =>
40
40
  Layer.effect(Ingestor)(
41
41
  Effect.gen(function* () {
42
- const manager = yield* Wings.CatalogManager.CatalogManager;
43
- const catalog = yield* manager
44
- .getIcebergCatalog(config.catalog)
45
- .pipe(Effect.mapError((cause) => connectorError("Failed to load Wings catalog", cause)));
46
-
42
+ const manager = yield* CatalogManager.CatalogManager;
47
43
  const bindings: Partial<Record<string, RuntimeConfig.TableBinding>> = config.tables;
48
44
 
49
45
  const prepared: Array<PreparedTable> = [];
@@ -51,15 +47,11 @@ export const layerWings = <const Source extends TableSource>(
51
47
  const binding = bindings[resource.name];
52
48
  if (!binding) continue;
53
49
 
54
- const { namespace, name, location } = binding;
50
+ const { namespace, name } = binding;
55
51
  const identifier = { namespace, name };
56
- const schema = yield* ensureTable(resource.rowSchema, {
57
- catalog,
58
- identifier,
59
- location,
60
- }).pipe(
52
+ const { schema } = yield* compileTable(resource.rowSchema).pipe(
61
53
  Effect.mapError((cause) =>
62
- connectorError(`Failed to prepare table for ${resource.name}: ${cause.message}`, cause),
54
+ connectorError(`Invalid schema for ${resource.name}: ${cause.message}`, cause),
63
55
  ),
64
56
  );
65
57
 
@@ -118,26 +110,32 @@ export const layerWings = <const Source extends TableSource>(
118
110
  }),
119
111
  );
120
112
 
121
- /** Reads the Wings URL, catalog and table bindings from hosted config. */
122
- export const layerWingsConfig = (connector: TableSource) =>
113
+ /** Configures Arrow Flight ingestion from the hosted URL, catalog and table bindings. */
114
+ export const layerArrowFlightConfig = (connector: TableSource) =>
123
115
  Layer.unwrap(
124
116
  Effect.gen(function* () {
125
- const { catalog, uri } = yield* Config.all({
117
+ const { catalog, uri, flightUri } = yield* Config.all({
126
118
  catalog: RuntimeConfig.catalog,
127
- uri: RuntimeConfig.wingsUri,
128
- }).pipe(Effect.mapError((cause) => connectorError("Invalid Wings configuration", cause)));
119
+ uri: RuntimeConfig.engineUri,
120
+ flightUri: RuntimeConfig.flightUri,
121
+ }).pipe(
122
+ Effect.mapError((cause) => connectorError("Invalid Arrow Flight configuration", cause)),
123
+ );
129
124
 
130
125
  if (uri.protocol !== "http:" && uri.protocol !== "https:") {
131
- return yield* Effect.fail(connectorError("Invalid Wings URL"));
126
+ return yield* Effect.fail(connectorError("Invalid Arrow Flight URL"));
127
+ }
128
+ if (flightUri.protocol !== "http:" && flightUri.protocol !== "https:") {
129
+ return yield* Effect.fail(connectorError("Invalid Arrow Flight URL"));
132
130
  }
133
131
 
134
132
  const tables = yield* RuntimeConfig.loadTableBindings(connector).pipe(
135
133
  Effect.mapError((cause) => connectorError(cause.message, cause)),
136
134
  );
137
- const manager = Wings.CatalogManager.layer({ baseUrl: uri.href }).pipe(
135
+ const manager = CatalogManager.layer({ engineUri: uri.href, flightUri: flightUri.href }).pipe(
138
136
  Layer.provide(FetchHttpClient.layer),
139
137
  );
140
138
 
141
- return layerWings({ connector, catalog, tables }).pipe(Layer.provide(manager));
139
+ return layerArrowFlight({ connector, catalog, tables }).pipe(Layer.provide(manager));
142
140
  }),
143
141
  );
@@ -2,7 +2,7 @@ import { Effect, Layer } from "effect";
2
2
 
3
3
  import { Ingestor } from "./service";
4
4
 
5
- /** Logs batches without sending them to Wings. */
5
+ /** Logs batches without sending them over Arrow Flight. */
6
6
  export const layerConsole = Layer.succeed(Ingestor)({
7
7
  ingest: ({ resource, source, batch }) =>
8
8
  Effect.logInfo(`[ingestor] -> Source: ${source} | Resource: ${resource}`).pipe(
@@ -6,4 +6,8 @@ export {
6
6
  type IngestResult,
7
7
  type IngestSource,
8
8
  } from "./service";
9
- export { layerWings, layerWingsConfig, type WingsIngestorConfig } from "./wings";
9
+ export {
10
+ layerArrowFlight,
11
+ layerArrowFlightConfig,
12
+ type ArrowFlightIngestorConfig,
13
+ } from "./arrow-flight";
@@ -7,8 +7,13 @@ export const httpPort = Config.Port(PlatformRuntimeKey.httpPort).pipe(
7
7
  Config.withDefault(PlatformRuntimeDefault.httpPort),
8
8
  );
9
9
 
10
- /** Wings URL, including the protocol. */
11
- export const wingsUri = Config.URL(PlatformRuntimeKey.wingsUri);
10
+ /** Engine URL, including the protocol. */
11
+ export const engineUri = Config.URL(PlatformRuntimeKey.engineUri);
12
12
 
13
- /** Wings catalog ID. */
13
+ /** Arrow Flight URL. Uses the engine URL when unset. */
14
+ export const flightUri = engineUri.pipe(
15
+ Config.flatMap((uri) => Config.URL(PlatformRuntimeKey.flightUri).pipe(Config.withDefault(uri))),
16
+ );
17
+
18
+ /** Catalog ID. */
14
19
  export const catalog = Config.NonEmptyString(PlatformRuntimeKey.catalog);
@@ -8,7 +8,8 @@ export const PlatformRuntimeKey = {
8
8
  connectorInstanceId: "AIRFOIL_CONNECTOR_INSTANCE_ID",
9
9
  stateTable: "AIRFOIL_STATE_TABLE",
10
10
  postgresConnectionString: "POSTGRES_CONNECTION_STRING",
11
- wingsUri: "WINGS_URI",
11
+ engineUri: "ENGINE_URI",
12
+ flightUri: "FLIGHT_URI",
12
13
  catalog: "AIRFOIL_CATALOG",
13
14
  otelEnabled: "OTEL_ENABLED",
14
15
  otelExporterOtlpEndpoint: "OTEL_EXPORTER_OTLP_ENDPOINT",
@@ -1,5 +1,5 @@
1
1
  export { RuntimeConfigError, type RuntimeConfigErrorCode } from "./error";
2
- export { catalog, httpPort, wingsUri } from "./config";
2
+ export { catalog, engineUri, flightUri, httpPort } from "./config";
3
3
  export { PlatformRuntimeDefault, PlatformRuntimeKey } from "./constants";
4
4
  export { layerHosted } from "./layer";
5
5
  export { type ResolvedTableBindings, type TableBinding, loadTableBindings } from "./table-bindings";
@@ -2,15 +2,17 @@ import type { TableIdentifier } from "iceberg-js";
2
2
 
3
3
  import { Config, Effect, Schema } from "effect";
4
4
 
5
- import type { TableSource } from "../core/types";
6
-
7
5
  import { PlatformRuntimeKey } from "./constants";
8
6
  import { RuntimeConfigError } from "./error";
9
7
 
8
+ type BindingSource = {
9
+ readonly resources: ReadonlyArray<{ readonly name: string }>;
10
+ };
11
+
10
12
  /** An Iceberg table and its storage location for each connector resource. */
11
13
  export type TableBinding = TableIdentifier & { readonly location?: string | undefined };
12
14
 
13
- export type ResolvedTableBindings<Source extends TableSource> = Readonly<
15
+ export type ResolvedTableBindings<Source extends BindingSource> = Readonly<
14
16
  Partial<Record<Source["resources"][number]["name"], TableBinding>>
15
17
  >;
16
18
 
@@ -31,7 +33,7 @@ const fail = (code: "TABLE_BINDINGS_INVALID" | "TABLE_BINDINGS_MISMATCH", messag
31
33
  new RuntimeConfigError({ code, message, cause: new Error(message) });
32
34
 
33
35
  /** Reads hosted table bindings and checks they name resources of the connector. */
34
- export const loadTableBindings = <const Source extends TableSource>(
36
+ export const loadTableBindings = <const Source extends BindingSource>(
35
37
  connector: Source,
36
38
  ): Effect.Effect<ResolvedTableBindings<Source>, RuntimeConfigError> =>
37
39
  Effect.gen(function* () {
package/src/telemetry.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Cause, Config, Effect, Layer, Metric, Option, type Duration } from "effect";
1
+ import { Cause, Config, Effect, Layer, Metric, Option, Schema, type Duration } from "effect";
2
2
  import { Headers } from "effect/http";
3
3
  import * as Observability from "effect/observability";
4
4
 
@@ -60,7 +60,14 @@ const maxErrorMessageLength = 500;
60
60
  const OtlpEnvConfig = Config.all({
61
61
  enabled: Config.Boolean(PlatformRuntimeKey.otelEnabled).pipe(Config.withDefault(false)),
62
62
  baseUrl: Config.option(Config.String(PlatformRuntimeKey.otelExporterOtlpEndpoint)),
63
- rawHeaders: Config.option(Config.String(PlatformRuntimeKey.otelExporterOtlpHeaders)),
63
+ headers: Config.option(
64
+ Config.Record(
65
+ Schema.String,
66
+ Schema.StringFromUriComponent,
67
+ PlatformRuntimeKey.otelExporterOtlpHeaders,
68
+ { trim: true },
69
+ ),
70
+ ),
64
71
  });
65
72
 
66
73
  const defaultRedactedHeaders: ReadonlyArray<string | RegExp> = [
@@ -74,19 +81,6 @@ const defaultRedactedHeaders: ReadonlyArray<string | RegExp> = [
74
81
  /token/i,
75
82
  ];
76
83
 
77
- const parseOtelHeaders = (value: string): Record<string, string> =>
78
- Object.fromEntries(
79
- value
80
- .split(",")
81
- .map((entry) => entry.trim())
82
- .filter(Boolean)
83
- .flatMap((entry) => {
84
- const separator = entry.indexOf("=");
85
- if (separator < 1) return [];
86
- return [[entry.slice(0, separator).trim(), entry.slice(separator + 1).trim()]];
87
- }),
88
- );
89
-
90
84
  const appendPath = (baseUrl: string, path: string) =>
91
85
  `${baseUrl.replace(/\/$/, "")}/${path.replace(/^\//, "")}`;
92
86
 
@@ -254,9 +248,7 @@ export const layerOtlpTracing = (options: OtlpTracingOptions = {}) =>
254
248
  {
255
249
  enabled: raw.enabled,
256
250
  endpoint: Option.getOrUndefined(raw.baseUrl),
257
- headers: Option.isSome(raw.rawHeaders)
258
- ? parseOtelHeaders(raw.rawHeaders.value)
259
- : undefined,
251
+ headers: Option.getOrUndefined(raw.headers),
260
252
  },
261
253
  options,
262
254
  );
@@ -276,7 +268,7 @@ export const layerOtlpMetrics = (options: OtlpMetricsOptions = {}) =>
276
268
  );
277
269
  return Observability.OtlpMetrics.layer({
278
270
  url: appendPath(endpoint, "/v1/metrics"),
279
- headers: Option.isSome(raw.rawHeaders) ? parseOtelHeaders(raw.rawHeaders.value) : undefined,
271
+ headers: Option.getOrUndefined(raw.headers),
280
272
  exportInterval: options.exportInterval,
281
273
  temporality: "cumulative",
282
274
  }).pipe(Layer.provide(Observability.OtlpSerialization.layerJson));
@@ -1,123 +0,0 @@
1
- import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
- import { n as layerWingsConfig, r as createTableFromWings } from "./wings-I56hGtNv.mjs";
3
- import { s as wingsUri } from "./runtime-config-Oa55gAew.mjs";
4
- import { n as run } from "./demo-B30Vlkk2.mjs";
5
- import { n as run$1 } from "./ingestion-q0WwqUSt.mjs";
6
- import { ByteSize, DateTime, Effect, Option, Tuple } from "effect";
7
- import { Argument, CliError, Command, Flag } from "effect/cli";
8
- import "effect/http";
9
- import { NodeHttpServer } from "@effect/platform-node";
10
- import { createServer } from "node:http";
11
- //#region src/connector-app/check.ts
12
- const ok = { _tag: "ok" };
13
- const error = (message) => ({
14
- _tag: "error",
15
- message
16
- });
17
- const fromEntries = (entries) => Object.fromEntries(entries);
18
- const resultsFor = (names, result) => fromEntries(names.map((name) => Tuple.make(name, result)));
19
- /**
20
- * Builds the connector service from its layer and validates only the selected
21
- * resources. The layer remains open until every check finishes.
22
- */
23
- function check(service, layer, options) {
24
- if (options.resources.length === 0) return Effect.succeed(fromEntries([]));
25
- return service.pipe(Effect.flatMap((connector) => Effect.forEach(options.resources, (name) => {
26
- const resource = connector.resources.find((candidate) => candidate.name === name);
27
- return (resource ? resource.check.pipe(Effect.match({
28
- onFailure: (failure) => error(failure.message),
29
- onSuccess: () => ok
30
- })) : Effect.succeed(error(`Unknown connector resource: ${name}`))).pipe(Effect.map((result) => Tuple.make(name, result)));
31
- }).pipe(Effect.map(fromEntries))), Effect.provide(layer), Effect.match({
32
- onFailure: (failure) => resultsFor(options.resources, error(failure.message)),
33
- onSuccess: (results) => results
34
- }));
35
- }
36
- //#endregion
37
- //#region src/connector-app/create-table.ts
38
- /** Creates the table command for a connector's row schemas. */
39
- const makeCreateTableCommand = (schemas) => Command.make("create-table", {
40
- table: Argument.String("table"),
41
- catalog: Flag.String("catalog"),
42
- location: Flag.String("location").pipe(Flag.optional),
43
- resource: Flag.String("resource").pipe(Flag.optional)
44
- }, ({ table, catalog, location, resource }) => Effect.gen(function* () {
45
- const namespace = table.split(".");
46
- const name = namespace.pop();
47
- if (!name || namespace.length === 0 || namespace.some((part) => part.length === 0)) return yield* new CliError.UserError({
48
- cause: "Invalid table name",
49
- userMessage: "Use a table name like my.namespace.table"
50
- });
51
- const resourceName = Option.getOrElse(resource, () => name);
52
- const schema = Object.hasOwn(schemas, resourceName) ? schemas[resourceName] : void 0;
53
- if (!schema) return yield* new CliError.UserError({
54
- cause: "Unknown resource",
55
- userMessage: `Unknown resource: ${resourceName}`
56
- });
57
- const uri = yield* wingsUri;
58
- yield* createTableFromWings(schema, {
59
- wingsUri: uri.href,
60
- catalogId: catalog,
61
- identifier: {
62
- namespace,
63
- name
64
- },
65
- location: Option.getOrUndefined(location)
66
- });
67
- yield* Effect.log(`Created ${table}`);
68
- })).pipe(Command.withDescription("Create an Iceberg table for a connector resource"));
69
- //#endregion
70
- //#region src/connector-app/demo.ts
71
- /** Reads sizes such as `512KiB`, `128MiB` or `1GiB`. */
72
- const parseSize = (input) => {
73
- if (!/^\d+(KiB|MiB|GiB)$/.test(input)) return Option.none();
74
- return ByteSize.fromString(input).pipe(Option.flatMap(ByteSize.toNumber), Option.filter((bytes) => bytes > 0));
75
- };
76
- /**
77
- * Creates the command that writes the demo data to Wings, then exits.
78
- * It reads Wings and table bindings from Config, so provide `RuntimeConfig.layerHosted()`.
79
- */
80
- const makeDemoCommand = (demo) => Command.make("demo", {
81
- size: Flag.String("size").pipe(Flag.filterMap(parseSize, () => "a size like 512KiB, 128MiB or 1GiB")),
82
- seed: Flag.Int("seed").pipe(Flag.withDefault(1))
83
- }, ({ size, seed }) => Effect.gen(function* () {
84
- const now = yield* DateTime.nowAsDate;
85
- yield* run(demo, {
86
- bytes: size,
87
- seed,
88
- now
89
- }).pipe(Effect.provide(layerWingsConfig({ resources: [...demo.setup.tables, ...demo.group.tables] })));
90
- })).pipe(Command.withDescription("Write demo data for the bound tables, then exit"));
91
- //#endregion
92
- //#region src/connector-app/start.ts
93
- const start = (app, options) => Effect.gen(function* () {
94
- const initialCutoff = options.initialCutoff ?? (yield* DateTime.now.pipe(Effect.map(DateTime.formatIso)));
95
- const routes = app.webhooks?.map((route) => route.path) ?? [];
96
- yield* Effect.logInfo("webhook server ready").pipe(Effect.annotateLogs({
97
- port: options.port,
98
- routes
99
- }));
100
- return yield* run$1(app, {
101
- initialCutoff,
102
- webhook: {
103
- routes: app.webhooks ?? [],
104
- healthPath: options.healthPath ?? "/health",
105
- metricsPath: options.metricsPath,
106
- statusPath: options.statusPath,
107
- disableHttpLogger: options.disableHttpLogger ?? true
108
- }
109
- }).pipe(Effect.provide(NodeHttpServer.layer(createServer, { port: options.port })));
110
- });
111
- //#endregion
112
- //#region src/connector-app/index.ts
113
- var connector_app_exports = /* @__PURE__ */ __exportAll({
114
- check: () => check,
115
- makeCreateTableCommand: () => makeCreateTableCommand,
116
- makeDemoCommand: () => makeDemoCommand,
117
- parseSize: () => parseSize,
118
- start: () => start
119
- });
120
- //#endregion
121
- export { makeCreateTableCommand as a, parseSize as i, start as n, check as o, makeDemoCommand as r, connector_app_exports as t };
122
-
123
- //# sourceMappingURL=connector-app-C-L4QqG6.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"connector-app-C-L4QqG6.mjs","names":["runIngestion"],"sources":["../src/connector-app/check.ts","../src/connector-app/create-table.ts","../src/connector-app/demo.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 { Effect, Option, type Schema } from \"effect\";\nimport { Argument, CliError, Command, Flag } from \"effect/cli\";\n\nimport { createTableFromWings } from \"../catalog/table\";\nimport { wingsUri } from \"../runtime-config/config\";\n\n/** Creates the table command for a connector's row schemas. */\nexport const makeCreateTableCommand = (schemas: Readonly<Record<string, Schema.Top>>) =>\n Command.make(\n \"create-table\",\n {\n table: Argument.String(\"table\"),\n catalog: Flag.String(\"catalog\"),\n location: Flag.String(\"location\").pipe(Flag.optional),\n resource: Flag.String(\"resource\").pipe(Flag.optional),\n },\n ({ table, catalog, location, resource }) =>\n Effect.gen(function* () {\n const namespace = table.split(\".\");\n const name = namespace.pop();\n\n if (!name || namespace.length === 0 || namespace.some((part) => part.length === 0)) {\n return yield* new CliError.UserError({\n cause: \"Invalid table name\",\n userMessage: \"Use a table name like my.namespace.table\",\n });\n }\n\n const resourceName = Option.getOrElse(resource, () => name);\n const schema = Object.hasOwn(schemas, resourceName) ? schemas[resourceName] : undefined;\n if (!schema) {\n return yield* new CliError.UserError({\n cause: \"Unknown resource\",\n userMessage: `Unknown resource: ${resourceName}`,\n });\n }\n\n const uri = yield* wingsUri;\n yield* createTableFromWings(schema, {\n wingsUri: uri.href,\n catalogId: catalog,\n identifier: { namespace, name },\n location: Option.getOrUndefined(location),\n });\n yield* Effect.log(`Created ${table}`);\n }),\n ).pipe(Command.withDescription(\"Create an Iceberg table for a connector resource\"));\n","import { ByteSize, DateTime, Effect, Option } from \"effect\";\nimport { Command, Flag } from \"effect/cli\";\n\nimport { run, type DemoDefinition } from \"../demo\";\nimport { layerWingsConfig } from \"../ingestor/wings\";\n\n/** Reads sizes such as `512KiB`, `128MiB` or `1GiB`. */\nexport const parseSize = (input: string): Option.Option<number> => {\n if (!/^\\d+(KiB|MiB|GiB)$/.test(input)) return Option.none();\n\n return ByteSize.fromString(input).pipe(\n Option.flatMap(ByteSize.toNumber),\n Option.filter((bytes) => bytes > 0),\n );\n};\n\n/**\n * Creates the command that writes the demo data to Wings, then exits.\n * It reads Wings and table bindings from Config, so provide `RuntimeConfig.layerHosted()`.\n */\nexport const makeDemoCommand = (demo: DemoDefinition) =>\n Command.make(\n \"demo\",\n {\n size: Flag.String(\"size\").pipe(\n Flag.filterMap(parseSize, () => \"a size like 512KiB, 128MiB or 1GiB\"),\n ),\n seed: Flag.Int(\"seed\").pipe(Flag.withDefault(1)),\n },\n ({ size, seed }) =>\n Effect.gen(function* () {\n const now = yield* DateTime.nowAsDate;\n\n yield* run(demo, { bytes: size, seed, now }).pipe(\n Effect.provide(\n layerWingsConfig({\n resources: [...demo.setup.tables, ...demo.group.tables],\n }),\n ),\n );\n }),\n ).pipe(Command.withDescription(\"Write demo data for the bound tables, then exit\"));\n","import { NodeHttpServer } from \"@effect/platform-node\";\nimport { DateTime, Effect } from \"effect\";\nimport { HttpRouter } from \"effect/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 { makeCreateTableCommand } from \"./create-table\";\nexport { makeDemoCommand, parseSize } from \"./demo\";\nexport { start, type App, type StartOptions } from \"./start\";\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants-D-GQzpHZ.mjs","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 wingsUri: \"WINGS_URI\",\n catalog: \"AIRFOIL_CATALOG\",\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,UAAU;CACV,SAAS;CACT,aAAa;CACb,0BAA0B;CAC1B,yBAAyB;CACzB,iBAAiB;CACjB,oBAAoB;CACpB,wBAAwB;AAC1B;;AAGA,MAAa,yBAAyB;CACpC,UAAU;CACV,YAAY;AACd;AAEA,MAAM,sBAAsB,QAAQ,aAAa,OAAO,OAAO,kBAAkB,CAAC;;AAGlF,MAAa,wBAAwB,QAAyB,QAAQ,IAAI,qBAAqB,GAAG"}