@useairfoil/connector-kit 0.4.0 → 0.5.1

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 (117) hide show
  1. package/METRICS.md +78 -0
  2. package/README.md +450 -88
  3. package/dist/auth/index.d.ts +2 -0
  4. package/dist/auth/index.js +3 -0
  5. package/dist/auth-DvU_CZ7C.js +42 -0
  6. package/dist/auth-DvU_CZ7C.js.map +1 -0
  7. package/dist/chunk-Bp6m_JJh.js +13 -0
  8. package/dist/connector-app/index.d.ts +14 -0
  9. package/dist/connector-app/index.js +11 -0
  10. package/dist/connector-app-d7Z-SZLQ.js +64 -0
  11. package/dist/connector-app-d7Z-SZLQ.js.map +1 -0
  12. package/dist/constants-BRhIX_rz.js +27 -0
  13. package/dist/constants-BRhIX_rz.js.map +1 -0
  14. package/dist/errors/index.d.ts +2 -0
  15. package/dist/errors/index.js +3 -0
  16. package/dist/errors-DHWylqRZ.js +8 -0
  17. package/dist/errors-DHWylqRZ.js.map +1 -0
  18. package/dist/index-Byr0Lf0C.d.ts +25 -0
  19. package/dist/index-CBT-JX-T.d.ts +173 -0
  20. package/dist/index-CTHVudvQ.d.ts +41 -0
  21. package/dist/index-CTLYQ74P.d.ts +80 -0
  22. package/dist/index-Coh_SkBs.d.ts +95 -0
  23. package/dist/index-D54ySAKn.d.ts +14 -0
  24. package/dist/index-DtJX_tic.d.ts +153 -0
  25. package/dist/index-J42AZaXU.d.ts +38 -0
  26. package/dist/index-fIIBVAai.d.ts +25 -0
  27. package/dist/index-o1-Z3n7V.d.ts +55 -0
  28. package/dist/index.d.ts +14 -165
  29. package/dist/index.js +50 -228
  30. package/dist/index.js.map +1 -1
  31. package/dist/ingestion/index.d.ts +6 -0
  32. package/dist/ingestion/index.js +10 -0
  33. package/dist/ingestion-BQo4cbGw.js +200 -0
  34. package/dist/ingestion-BQo4cbGw.js.map +1 -0
  35. package/dist/manifest/index.d.ts +2 -0
  36. package/dist/manifest/index.js +4 -0
  37. package/dist/manifest-ByE6YPG0.js +221 -0
  38. package/dist/manifest-ByE6YPG0.js.map +1 -0
  39. package/dist/metrics-CVAk1ALR.d.ts +53 -0
  40. package/dist/metrics-CWPy2Aqc.js +96 -0
  41. package/dist/metrics-CWPy2Aqc.js.map +1 -0
  42. package/dist/metrics.d.ts +4 -0
  43. package/dist/metrics.js +3 -0
  44. package/dist/publisher/index.d.ts +5 -0
  45. package/dist/publisher/index.js +6 -0
  46. package/dist/publisher-BYT3RLVO.js +131 -0
  47. package/dist/publisher-BYT3RLVO.js.map +1 -0
  48. package/dist/runtime-config/index.d.ts +2 -0
  49. package/dist/runtime-config/index.js +4 -0
  50. package/dist/runtime-config-BpB-d_bF.js +51 -0
  51. package/dist/runtime-config-BpB-d_bF.js.map +1 -0
  52. package/dist/server-CXTQ7odl.js +183 -0
  53. package/dist/server-CXTQ7odl.js.map +1 -0
  54. package/dist/service-DuFiQwid.js +191 -0
  55. package/dist/service-DuFiQwid.js.map +1 -0
  56. package/dist/service-IE5qaf9x.d.ts +32 -0
  57. package/dist/state-store/index.d.ts +3 -0
  58. package/dist/state-store/index.js +5 -0
  59. package/dist/state-store-yl6LiTQ0.js +198 -0
  60. package/dist/state-store-yl6LiTQ0.js.map +1 -0
  61. package/dist/status/index.d.ts +5 -0
  62. package/dist/status/index.js +6 -0
  63. package/dist/status-B-oZBc33.js +84 -0
  64. package/dist/status-B-oZBc33.js.map +1 -0
  65. package/dist/types-B35J5YPu.d.ts +174 -0
  66. package/dist/webhook/index.d.ts +6 -0
  67. package/dist/webhook/index.js +8 -0
  68. package/dist/webhook-DI-Afxkg.js +13 -0
  69. package/dist/webhook-DI-Afxkg.js.map +1 -0
  70. package/package.json +66 -8
  71. package/src/auth/index.ts +1 -0
  72. package/src/auth/token-cache.ts +54 -0
  73. package/src/connector-app/check.ts +76 -0
  74. package/src/connector-app/index.ts +2 -0
  75. package/src/connector-app/start.ts +42 -0
  76. package/src/core/builder.ts +81 -9
  77. package/src/core/index.ts +22 -0
  78. package/src/core/types.ts +204 -76
  79. package/src/errors/index.ts +1 -0
  80. package/src/index.ts +13 -28
  81. package/src/ingestion/engine.ts +409 -174
  82. package/src/ingestion/index.ts +1 -0
  83. package/src/manifest/config.ts +232 -0
  84. package/src/manifest/index.ts +14 -0
  85. package/src/manifest/manifest.ts +31 -0
  86. package/src/manifest/number-schema.ts +17 -0
  87. package/src/manifest/schema.ts +160 -0
  88. package/src/metrics.ts +128 -0
  89. package/src/publisher/console.ts +18 -0
  90. package/src/publisher/index.ts +7 -0
  91. package/src/publisher/instrumented.ts +68 -0
  92. package/src/publisher/service.ts +30 -13
  93. package/src/publisher/wings.ts +159 -72
  94. package/src/runtime/context.ts +15 -0
  95. package/src/runtime-config/constants.ts +27 -0
  96. package/src/runtime-config/error.ts +13 -0
  97. package/src/runtime-config/index.ts +3 -0
  98. package/src/runtime-config/layer.ts +56 -0
  99. package/src/state-store/index.ts +3 -0
  100. package/src/state-store/keys.ts +22 -0
  101. package/src/state-store/layer-key-value-store.ts +132 -0
  102. package/src/state-store/layer-memory.ts +11 -0
  103. package/src/state-store/layer-sql.ts +50 -0
  104. package/src/state-store/schema.ts +57 -0
  105. package/src/state-store/service.ts +51 -0
  106. package/src/state-store/state.ts +17 -0
  107. package/src/status/index.ts +2 -0
  108. package/src/status/route.ts +77 -0
  109. package/src/status/types.ts +33 -0
  110. package/src/telemetry.ts +288 -0
  111. package/src/webhook/index.ts +8 -0
  112. package/src/webhook/server.ts +209 -39
  113. package/src/webhook/types.ts +6 -17
  114. package/src/ingestion/state-store.ts +0 -36
  115. package/src/streams/pull-stream.ts +0 -54
  116. package/src/streams/webhook-queue.ts +0 -14
  117. /package/src/{core/errors.ts → errors/connector-error.ts} +0 -0
package/src/core/types.ts CHANGED
@@ -1,100 +1,228 @@
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;
18
+
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
+ };
11
29
 
12
- export type StreamState<C = Cursor> = {
13
- readonly cutoff: C;
14
- readonly current?: C;
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
+ readonly lastSuccessAt?: string;
41
+ };
42
+ readonly changes?: {
43
+ readonly cursor: Cursor.Value;
44
+ readonly lastSuccessAt?: string;
45
+ };
46
+ readonly lastError?: {
47
+ readonly source: "backfill" | "changes";
48
+ readonly operation: "fetch" | "publish" | "checkpoint";
49
+ readonly code: "fetch_failed" | "publish_failed" | "checkpoint_failed";
50
+ readonly message: string;
51
+ readonly at: string;
52
+ };
20
53
  };
21
54
 
22
- export type Transform<T> = (row: T) => Effect.Effect<T, ConnectorError>;
55
+ export type SyncState = "pending" | "backfilling" | "live" | "error";
23
56
 
24
- export type LiveStream<T> = Stream.Stream<Batch<T>, ConnectorError>;
57
+ export type ResourceSchema = Schema.Decoder<object>;
25
58
 
26
- export type BackfillStream<T> = Stream.Stream<Batch<T>, ConnectorError>;
59
+ /**
60
+ * Takes a resource schema and returns its decoded row object type.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * const ProductSchema = Schema.Struct({ id: Schema.String, updatedAt: Schema.String });
65
+ * type Product = ResourceRow<typeof ProductSchema>;
66
+ * // Result:
67
+ * // type Product = { readonly id: string; readonly updatedAt: string }
68
+ * ```
69
+ */
70
+ export type ResourceRow<S extends ResourceSchema> = Schema.Schema.Type<S>;
27
71
 
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>;
72
+ /**
73
+ * Takes a resource schema and returns the string keys available on its row type.
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * const ProductSchema = Schema.Struct({ id: Schema.String, updatedAt: Schema.String });
78
+ * type ProductField = ResourceField<typeof ProductSchema>;
79
+ * // Result:
80
+ * // type ProductField = "id" | "updatedAt"
81
+ *
82
+ * const key: ResourceField<typeof ProductSchema> = "id";
83
+ * ```
84
+ */
85
+ export type ResourceField<S extends ResourceSchema> = keyof ResourceRow<S> & string;
86
+
87
+ export type FetchPageResult<Row extends object> = {
88
+ readonly mutations: ReadonlyArray<ResourceMutation<Row>>;
89
+ readonly nextPageCursor?: Cursor.Value;
90
+ readonly hasMore: boolean;
37
91
  };
38
92
 
39
- export type LiveSource<T> = LiveStream<T> | WebhookStream<T>;
93
+ export type PageFetch<Row extends object, R = never> = {
94
+ readonly pageCursor: Cursor.Definition;
95
+ readonly cutoff: Cursor.Definition;
96
+ readonly fetch: (input: {
97
+ readonly pageCursor?: Cursor.Value;
98
+ readonly cutoff: Cursor.Value;
99
+ }) => Effect.Effect<FetchPageResult<Row>, ConnectorError, R>;
100
+ };
40
101
 
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>;
102
+ export type FetchChangesResult<Row extends object> = {
103
+ readonly mutations: ReadonlyArray<ResourceMutation<Row>>;
104
+ readonly cursor: Cursor.Value;
105
+ };
50
106
 
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>>;
107
+ export type ChangesFetch<Row extends object, R = never> = {
108
+ readonly cursor: Cursor.Definition;
109
+ readonly interval?: Duration.Input;
110
+ readonly fetch: (input: {
111
+ readonly cursor: Cursor.Value;
112
+ }) => Effect.Effect<FetchChangesResult<Row>, ConnectorError, R>;
70
113
  };
71
114
 
72
- export type EventDefinition<S extends EntitySchema> = {
73
- readonly name: string;
115
+ export type WebhookHandler<Row extends object, Payload> = {
116
+ readonly schema: Schema.Decoder<Payload>;
117
+ handler(input: {
118
+ readonly payload: Payload;
119
+ }): Effect.Effect<ReadonlyArray<ResourceMutation<Row>>, ConnectorError>;
120
+ };
121
+
122
+ export type ResourceDefinition<
123
+ S extends ResourceSchema = ResourceSchema,
124
+ Payload = unknown,
125
+ R = never,
126
+ Name extends string = string,
127
+ > = {
128
+ readonly name: Name;
74
129
  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>>;
130
+ readonly key: ResourceField<NoInfer<S>>;
131
+ readonly version: ResourceField<NoInfer<S>>;
132
+ readonly partition?: {
133
+ readonly required: boolean;
134
+ };
135
+ /** Read-only validation used before provisioning this resource. */
136
+ readonly check: Effect.Effect<void, ConnectorError>;
137
+ readonly backfill?: PageFetch<ResourceRow<NoInfer<S>>, R>;
138
+ readonly changes?: ChangesFetch<ResourceRow<NoInfer<S>>, R>;
139
+ readonly webhook?: WebhookHandler<ResourceRow<NoInfer<S>>, Payload>;
87
140
  };
88
141
 
142
+ /**
143
+ * Takes a connector resource tuple and returns a `{ [resourceName]: rowType }`
144
+ * map.
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * type Rows = ResourceRows<[typeof Products, typeof Orders]>;
149
+ * // Result:
150
+ * // type Rows = {
151
+ * // readonly products: Product;
152
+ * // readonly orders: Order;
153
+ * // }
154
+ *
155
+ * type ProductRow = Rows["products"];
156
+ * // Result:
157
+ * // type ProductRow = Product
158
+ * ```
159
+ */
160
+ export type ResourceRows<Resources extends ReadonlyArray<ResourceDefinition>> = {
161
+ readonly [Resource in Resources[number] as Resource["name"]]: Resource extends ResourceDefinition<
162
+ infer S,
163
+ unknown,
164
+ unknown
165
+ >
166
+ ? ResourceRow<S>
167
+ : never;
168
+ };
169
+
170
+ /** Resource names preserved from a connector's resource tuple. */
171
+ export type ResourceName<Resources extends ReadonlyArray<ResourceDefinition>> =
172
+ keyof ResourceRows<Resources> & string;
173
+
174
+ /**
175
+ * Takes a resource definition and returns the payload type accepted by
176
+ * `to(resource, payload)`.
177
+ *
178
+ * @example
179
+ * ```ts
180
+ * type ProductPayload = ResourcePayload<typeof Products>;
181
+ * // Result, if Products was defined with a ProductEvent webhook schema:
182
+ * // type ProductPayload = ProductEvent
183
+ * ```
184
+ */
185
+ export type ResourcePayload<R> =
186
+ R extends ResourceDefinition<ResourceSchema, infer Payload, unknown> ? Payload : never;
187
+
188
+ export type WebhookAckMode = "after-enqueue" | "after-publish";
189
+
190
+ export type WebhookRouteContext<
191
+ Resources extends ReadonlyArray<ResourceDefinition> = ReadonlyArray<ResourceDefinition>,
192
+ Payload = unknown,
193
+ > = {
194
+ readonly request: HttpServerRequest.HttpServerRequest;
195
+ readonly rawBody: Uint8Array;
196
+ readonly payload: Payload;
197
+ /** Decodes and collects mutations for a resource-owned webhook handler. */
198
+ readonly to: <Resource extends Resources[number]>(
199
+ resource: Resource,
200
+ payload: ResourcePayload<Resource>,
201
+ ) => Effect.Effect<void, ConnectorError>;
202
+ };
203
+
204
+ export type WebhookRoute<
205
+ Resources extends ReadonlyArray<ResourceDefinition> = ReadonlyArray<ResourceDefinition>,
206
+ Payload = unknown,
207
+ > = {
208
+ readonly path: HttpRouter.PathInput;
209
+ readonly ackMode: WebhookAckMode;
210
+ readonly schema: Schema.Decoder<Payload>;
211
+ handler(
212
+ context: WebhookRouteContext<Resources, Payload>,
213
+ ): Effect.Effect<HttpServerResponse.HttpServerResponse, ConnectorError>;
214
+ };
215
+
216
+ export type WebhookRouteInput<
217
+ Resources extends ReadonlyArray<ResourceDefinition>,
218
+ Payload,
219
+ > = WebhookRoute<Resources, Payload>;
220
+
89
221
  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
- >,
222
+ Resources extends ReadonlyArray<ResourceDefinition> = ReadonlyArray<ResourceDefinition>,
96
223
  > = {
97
224
  readonly name: string;
98
- readonly entities: Entities;
99
- readonly events: Events;
225
+ readonly title?: string;
226
+ readonly resources: Resources;
227
+ readonly webhooks?: ReadonlyArray<WebhookRoute>;
100
228
  };
@@ -0,0 +1 @@
1
+ export { ConnectorError } from "./connector-error";
package/src/index.ts CHANGED
@@ -1,28 +1,13 @@
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 Auth from "./auth";
3
+ export * as ConnectorApp from "./connector-app";
4
+ export * as Ingestion from "./ingestion";
5
+ export * as Manifest from "./manifest";
6
+ export * as Metrics from "./metrics";
7
+ export * as Publisher from "./publisher";
8
+ export * as RuntimeConfig from "./runtime-config";
9
+ export * as StateStore from "./state-store";
10
+ export * as Status from "./status";
11
+ export * as Telemetry from "./telemetry";
12
+ export * as Webhook from "./webhook";
13
+ export * from "./errors";