@useairfoil/connector-kit 0.4.0 → 0.5.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 (67) hide show
  1. package/README.md +283 -90
  2. package/dist/chunk-Bp6m_JJh.js +13 -0
  3. package/dist/connector-app/index.d.ts +9 -0
  4. package/dist/connector-app/index.js +8 -0
  5. package/dist/connector-app-CvqbfN6R.js +32 -0
  6. package/dist/connector-app-CvqbfN6R.js.map +1 -0
  7. package/dist/errors/index.d.ts +2 -0
  8. package/dist/errors/index.js +3 -0
  9. package/dist/errors-DHWylqRZ.js +8 -0
  10. package/dist/errors-DHWylqRZ.js.map +1 -0
  11. package/dist/index-8KnVpoZp.d.ts +32 -0
  12. package/dist/index-BlhJCpEk.d.ts +124 -0
  13. package/dist/index-CQJsFJs3.d.ts +23 -0
  14. package/dist/index-DK9YcR6W.d.ts +25 -0
  15. package/dist/index-DaNW63Mv.d.ts +21 -0
  16. package/dist/index-DyuT2jzP.d.ts +14 -0
  17. package/dist/index.d.ts +9 -165
  18. package/dist/index.js +44 -228
  19. package/dist/index.js.map +1 -1
  20. package/dist/ingestion/index.d.ts +6 -0
  21. package/dist/ingestion/index.js +7 -0
  22. package/dist/ingestion-CMCroK7Y.js +171 -0
  23. package/dist/ingestion-CMCroK7Y.js.map +1 -0
  24. package/dist/publisher/index.d.ts +5 -0
  25. package/dist/publisher/index.js +5 -0
  26. package/dist/publisher-DusgYvaV.js +131 -0
  27. package/dist/publisher-DusgYvaV.js.map +1 -0
  28. package/dist/server-DAeFWT4o.js +113 -0
  29. package/dist/server-DAeFWT4o.js.map +1 -0
  30. package/dist/service-B7g_lHMI.d.ts +32 -0
  31. package/dist/state-store/index.d.ts +4 -0
  32. package/dist/state-store/index.js +3 -0
  33. package/dist/state-store-DG_4QpWG.js +31 -0
  34. package/dist/state-store-DG_4QpWG.js.map +1 -0
  35. package/dist/telemetry-p0dE5Mdu.js +171 -0
  36. package/dist/telemetry-p0dE5Mdu.js.map +1 -0
  37. package/dist/types-ZNrA-Dn0.d.ts +160 -0
  38. package/dist/webhook/index.d.ts +5 -0
  39. package/dist/webhook/index.js +6 -0
  40. package/dist/webhook-BSA-tXtU.js +13 -0
  41. package/dist/webhook-BSA-tXtU.js.map +1 -0
  42. package/package.json +36 -7
  43. package/src/connector-app/index.ts +1 -0
  44. package/src/connector-app/start.ts +38 -0
  45. package/src/core/builder.ts +76 -9
  46. package/src/core/index.ts +22 -0
  47. package/src/core/types.ts +185 -75
  48. package/src/errors/index.ts +1 -0
  49. package/src/index.ts +8 -28
  50. package/src/ingestion/engine.ts +301 -179
  51. package/src/ingestion/index.ts +1 -0
  52. package/src/publisher/console.ts +18 -0
  53. package/src/publisher/index.ts +7 -0
  54. package/src/publisher/service.ts +30 -13
  55. package/src/publisher/wings.ts +159 -72
  56. package/src/runtime/context.ts +15 -0
  57. package/src/state-store/index.ts +2 -0
  58. package/src/state-store/memory.ts +25 -0
  59. package/src/state-store/service.ts +18 -0
  60. package/src/telemetry.ts +246 -0
  61. package/src/webhook/index.ts +8 -0
  62. package/src/webhook/server.ts +172 -37
  63. package/src/webhook/types.ts +6 -17
  64. package/src/ingestion/state-store.ts +0 -36
  65. package/src/streams/pull-stream.ts +0 -54
  66. package/src/streams/webhook-queue.ts +0 -14
  67. /package/src/{core/errors.ts → errors/connector-error.ts} +0 -0
package/src/core/types.ts CHANGED
@@ -1,100 +1,210 @@
1
- import type { Effect, Queue, Schema, Stream } from "effect";
1
+ import type { Duration, Effect, Schema } from "effect";
2
+ import type { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect/unstable/http";
2
3
 
3
- import type { ConnectorError } from "./errors";
4
+ import type { ConnectorError } from "../errors";
4
5
 
5
- export type Cursor = string | number | bigint | Date;
6
+ export namespace Cursor {
7
+ export type Value = string | number | Date;
6
8
 
7
- export type Batch<T> = {
8
- readonly cursor: Cursor;
9
- readonly rows: ReadonlyArray<T>;
10
- };
9
+ export type Kind = "string" | "number" | "isoDateTime";
10
+
11
+ export type Definition<T extends Value = Value> = {
12
+ readonly kind: Kind;
13
+ readonly decode: (value: unknown) => Effect.Effect<T, ConnectorError>;
14
+ };
15
+ }
16
+
17
+ export type DeleteValue = string | number | boolean | Date;
11
18
 
12
- export type StreamState<C = Cursor> = {
13
- readonly cutoff: C;
14
- readonly current?: C;
19
+ export type ResourceMutation<Row extends object = object> =
20
+ | {
21
+ readonly op: "upsert";
22
+ readonly row: Row;
23
+ }
24
+ | {
25
+ readonly op: "delete";
26
+ readonly key: DeleteValue;
27
+ readonly version: DeleteValue;
28
+ };
29
+
30
+ export type ResourceBatch<Row extends object = object> = {
31
+ readonly cursor?: Cursor.Value;
32
+ readonly mutations: ReadonlyArray<ResourceMutation<Row>>;
15
33
  };
16
34
 
17
- export type IngestionState<C = Cursor> = {
18
- readonly backfill: StreamState<C>;
19
- readonly live: StreamState<C>;
35
+ export type ResourceState = {
36
+ readonly backfill?: {
37
+ readonly cutoff: Cursor.Value;
38
+ readonly pageCursor?: Cursor.Value;
39
+ readonly completed: boolean;
40
+ };
41
+ readonly changes?: {
42
+ readonly cursor: Cursor.Value;
43
+ };
20
44
  };
21
45
 
22
- export type Transform<T> = (row: T) => Effect.Effect<T, ConnectorError>;
46
+ export type ResourceSchema = Schema.Decoder<object>;
23
47
 
24
- export type LiveStream<T> = Stream.Stream<Batch<T>, ConnectorError>;
48
+ /**
49
+ * Takes a resource schema and returns its decoded row object type.
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * const ProductSchema = Schema.Struct({ id: Schema.String, updatedAt: Schema.String });
54
+ * type Product = ResourceRow<typeof ProductSchema>;
55
+ * // Result:
56
+ * // type Product = { readonly id: string; readonly updatedAt: string }
57
+ * ```
58
+ */
59
+ export type ResourceRow<S extends ResourceSchema> = Schema.Schema.Type<S>;
25
60
 
26
- export type BackfillStream<T> = Stream.Stream<Batch<T>, ConnectorError>;
61
+ /**
62
+ * Takes a resource schema and returns the string keys available on its row type.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * const ProductSchema = Schema.Struct({ id: Schema.String, updatedAt: Schema.String });
67
+ * type ProductField = ResourceField<typeof ProductSchema>;
68
+ * // Result:
69
+ * // type ProductField = "id" | "updatedAt"
70
+ *
71
+ * const key: ResourceField<typeof ProductSchema> = "id";
72
+ * ```
73
+ */
74
+ export type ResourceField<S extends ResourceSchema> = keyof ResourceRow<S> & string;
27
75
 
28
- export type WebhookStream<T> = {
29
- /**
30
- * The queue is used to store the batches that are received from the webhook.
31
- */
32
- readonly queue: Queue.Queue<Batch<T>>;
33
- /**
34
- * The stream is used to process the batches that are received from the webhook.
35
- */
36
- readonly stream: Stream.Stream<Batch<T>, ConnectorError>;
76
+ export type FetchPageResult<Row extends object> = {
77
+ readonly mutations: ReadonlyArray<ResourceMutation<Row>>;
78
+ readonly nextPageCursor?: Cursor.Value;
79
+ readonly hasMore: boolean;
37
80
  };
38
81
 
39
- export type LiveSource<T> = LiveStream<T> | WebhookStream<T>;
82
+ export type PageFetch<Row extends object, R = never> = {
83
+ readonly pageCursor: Cursor.Definition;
84
+ readonly cutoff: Cursor.Definition;
85
+ readonly fetch: (input: {
86
+ readonly pageCursor?: Cursor.Value;
87
+ readonly cutoff: Cursor.Value;
88
+ }) => Effect.Effect<FetchPageResult<Row>, ConnectorError, R>;
89
+ };
40
90
 
41
- /** Schema type used by connector definitions. */
42
- export type EntitySchema = Schema.Schema<unknown>;
43
- /** Decoded row type produced by a schema. */
44
- export type EntityType<S extends EntitySchema> = Schema.Schema.Type<S>;
45
- /** Primary key type derived from the decoded schema shape. */
46
- export type EntityKey<S extends EntitySchema> =
47
- EntityType<S> extends Record<string, unknown> ? keyof EntityType<S> & string : never;
48
- /** Row type constrained to object-like shapes for ingestion. */
49
- export type EntityRow<S extends EntitySchema> = EntityType<S> & Record<string, unknown>;
91
+ export type FetchChangesResult<Row extends object> = {
92
+ readonly mutations: ReadonlyArray<ResourceMutation<Row>>;
93
+ readonly cursor: Cursor.Value;
94
+ };
50
95
 
51
- export type EntityDefinition<S extends EntitySchema> = {
52
- readonly name: string;
53
- readonly schema: S;
54
- /**
55
- * The primary key is used to identify the rows in the database.
56
- */
57
- readonly primaryKey: EntityKey<S>;
58
- /**
59
- * The live source is used to stream the live data from the database.
60
- */
61
- readonly live: LiveSource<EntityRow<S>>;
62
- /**
63
- * The backfill stream is used to stream the backfill data from the database.
64
- */
65
- readonly backfill: BackfillStream<EntityRow<S>>;
66
- /**
67
- * The transform is used to transform the rows before they are published.
68
- */
69
- readonly transform?: Transform<EntityRow<S>>;
96
+ export type ChangesFetch<Row extends object, R = never> = {
97
+ readonly cursor: Cursor.Definition;
98
+ readonly interval?: Duration.Input;
99
+ readonly fetch: (input: {
100
+ readonly cursor: Cursor.Value;
101
+ }) => Effect.Effect<FetchChangesResult<Row>, ConnectorError, R>;
70
102
  };
71
103
 
72
- export type EventDefinition<S extends EntitySchema> = {
104
+ export type WebhookHandler<Row extends object, Payload> = {
105
+ readonly schema: Schema.Decoder<Payload>;
106
+ handler(input: {
107
+ readonly payload: Payload;
108
+ }): Effect.Effect<ReadonlyArray<ResourceMutation<Row>>, ConnectorError>;
109
+ };
110
+
111
+ export type ResourceDefinition<
112
+ S extends ResourceSchema = ResourceSchema,
113
+ Payload = unknown,
114
+ R = never,
115
+ > = {
73
116
  readonly name: string;
74
117
  readonly schema: S;
75
- /**
76
- * The live source is used to stream the live data from the database.
77
- */
78
- readonly live: LiveSource<EntityRow<S>>;
79
- /**
80
- * The backfill stream is used to stream the backfill data from the database.
81
- */
82
- readonly backfill?: BackfillStream<EntityRow<S>>;
83
- /**
84
- * The transform is used to transform the rows before they are published.
85
- */
86
- readonly transform?: Transform<EntityRow<S>>;
118
+ readonly key: ResourceField<NoInfer<S>>;
119
+ readonly version: ResourceField<NoInfer<S>>;
120
+ readonly partition?: {
121
+ readonly required: boolean;
122
+ };
123
+ readonly backfill?: PageFetch<ResourceRow<NoInfer<S>>, R>;
124
+ readonly changes?: ChangesFetch<ResourceRow<NoInfer<S>>, R>;
125
+ readonly webhook?: WebhookHandler<ResourceRow<NoInfer<S>>, Payload>;
87
126
  };
88
127
 
128
+ /**
129
+ * Takes a connector resource tuple and returns a `{ [resourceName]: rowType }`
130
+ * map.
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * type Rows = ResourceRows<[typeof Products, typeof Orders]>;
135
+ * // Result:
136
+ * // type Rows = {
137
+ * // readonly products: Product;
138
+ * // readonly orders: Order;
139
+ * // }
140
+ *
141
+ * type ProductRow = Rows["products"];
142
+ * // Result:
143
+ * // type ProductRow = Product
144
+ * ```
145
+ */
146
+ export type ResourceRows<Resources extends ReadonlyArray<ResourceDefinition>> = {
147
+ readonly [Resource in Resources[number] as Resource["name"]]: Resource extends ResourceDefinition<
148
+ infer S,
149
+ unknown,
150
+ unknown
151
+ >
152
+ ? ResourceRow<S>
153
+ : never;
154
+ };
155
+
156
+ /**
157
+ * Takes a resource definition and returns the payload type accepted by
158
+ * `to(resource, payload)`.
159
+ *
160
+ * @example
161
+ * ```ts
162
+ * type ProductPayload = ResourcePayload<typeof Products>;
163
+ * // Result, if Products was defined with a ProductEvent webhook schema:
164
+ * // type ProductPayload = ProductEvent
165
+ * ```
166
+ */
167
+ export type ResourcePayload<R> =
168
+ R extends ResourceDefinition<ResourceSchema, infer Payload, unknown> ? Payload : never;
169
+
170
+ export type WebhookAckMode = "after-enqueue" | "after-publish";
171
+
172
+ export type WebhookRouteContext<
173
+ Resources extends ReadonlyArray<ResourceDefinition> = ReadonlyArray<ResourceDefinition>,
174
+ Payload = unknown,
175
+ > = {
176
+ readonly request: HttpServerRequest.HttpServerRequest;
177
+ readonly rawBody: Uint8Array;
178
+ readonly payload: Payload;
179
+ /** Decodes and collects mutations for a resource-owned webhook handler. */
180
+ readonly to: <Resource extends Resources[number]>(
181
+ resource: Resource,
182
+ payload: ResourcePayload<Resource>,
183
+ ) => Effect.Effect<void, ConnectorError>;
184
+ };
185
+
186
+ export type WebhookRoute<
187
+ Resources extends ReadonlyArray<ResourceDefinition> = ReadonlyArray<ResourceDefinition>,
188
+ Payload = unknown,
189
+ > = {
190
+ readonly path: HttpRouter.PathInput;
191
+ readonly ackMode: WebhookAckMode;
192
+ readonly schema: Schema.Decoder<Payload>;
193
+ handler(
194
+ context: WebhookRouteContext<Resources, Payload>,
195
+ ): Effect.Effect<HttpServerResponse.HttpServerResponse, unknown>;
196
+ };
197
+
198
+ export type WebhookRouteInput<
199
+ Resources extends ReadonlyArray<ResourceDefinition>,
200
+ Payload,
201
+ > = WebhookRoute<Resources, Payload>;
202
+
89
203
  export type ConnectorDefinition<
90
- Entities extends ReadonlyArray<EntityDefinition<EntitySchema>> = ReadonlyArray<
91
- EntityDefinition<EntitySchema>
92
- >,
93
- Events extends ReadonlyArray<EventDefinition<EntitySchema>> = ReadonlyArray<
94
- EventDefinition<EntitySchema>
95
- >,
204
+ Resources extends ReadonlyArray<ResourceDefinition> = ReadonlyArray<ResourceDefinition>,
96
205
  > = {
97
206
  readonly name: string;
98
- readonly entities: Entities;
99
- readonly events: Events;
207
+ readonly title?: string;
208
+ readonly resources: Resources;
209
+ readonly webhooks?: ReadonlyArray<WebhookRoute>;
100
210
  };
@@ -0,0 +1 @@
1
+ export { ConnectorError } from "./connector-error";
package/src/index.ts CHANGED
@@ -1,28 +1,8 @@
1
- export { defineConnector, defineEntity, defineEvent } from "./core/builder";
2
- export { ConnectorError } from "./core/errors";
3
- export type {
4
- BackfillStream,
5
- Batch,
6
- ConnectorDefinition,
7
- Cursor,
8
- EntityDefinition,
9
- EntityKey,
10
- EntityRow,
11
- EntitySchema,
12
- EntityType,
13
- EventDefinition,
14
- IngestionState,
15
- LiveSource,
16
- LiveStream,
17
- StreamState,
18
- Transform,
19
- WebhookStream,
20
- } from "./core/types";
21
- export { runConnector } from "./ingestion/engine";
22
- export { StateStore, StateStoreInMemory } from "./ingestion/state-store";
23
- export { Publisher } from "./publisher/service";
24
- export { WingsPublisherLayer } from "./publisher/wings";
25
- export { makePullStream } from "./streams/pull-stream";
26
- export { makeWebhookQueue } from "./streams/webhook-queue";
27
- export { buildWebhookRouter } from "./webhook/server";
28
- export type { WebhookRoute } from "./webhook/types";
1
+ export * from "./core";
2
+ export * as ConnectorApp from "./connector-app";
3
+ export * as Ingestion from "./ingestion";
4
+ export * as Publisher from "./publisher";
5
+ export * as StateStore from "./state-store";
6
+ export * as Telemetry from "./telemetry";
7
+ export * as Webhook from "./webhook";
8
+ export * from "./errors";