@useairfoil/connector-kit 0.5.3 → 0.6.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.
- package/METRICS.md +20 -19
- package/README.md +127 -430
- package/dist/annotations-BE74YmAO.d.mts +39 -0
- package/dist/auth/index.d.mts +2 -0
- package/dist/{auth-DvU_CZ7C.js → auth/index.mjs} +6 -8
- package/dist/auth/index.mjs.map +1 -0
- package/dist/connector-app/index.d.mts +2 -0
- package/dist/connector-app/index.mjs +2 -0
- package/dist/connector-app-C-L4QqG6.mjs +123 -0
- package/dist/connector-app-C-L4QqG6.mjs.map +1 -0
- package/dist/{constants-BRhIX_rz.js → constants-D-GQzpHZ.mjs} +10 -6
- package/dist/constants-D-GQzpHZ.mjs.map +1 -0
- package/dist/demo/index.d.mts +2 -0
- package/dist/demo/index.mjs +2 -0
- package/dist/demo-B30Vlkk2.mjs +191 -0
- package/dist/demo-B30Vlkk2.mjs.map +1 -0
- package/dist/errors/index.d.mts +2 -0
- package/dist/errors/index.mjs +2 -0
- package/dist/{errors-DHWylqRZ.js → errors-pT0YVJU5.mjs} +2 -3
- package/dist/errors-pT0YVJU5.mjs.map +1 -0
- package/dist/iceberg/index.d.mts +3 -0
- package/dist/iceberg/index.mjs +3 -0
- package/dist/iceberg-D6L8I6vA.mjs +39 -0
- package/dist/iceberg-D6L8I6vA.mjs.map +1 -0
- package/dist/{index-Cq2IzY7T.d.ts → index-BUHSGm9Q.d.mts} +11 -13
- package/dist/{index-CTHVudvQ.d.ts → index-BX8G7d41.d.mts} +1 -2
- package/dist/{index-J42AZaXU.d.ts → index-BfXpgxk9.d.mts} +9 -10
- package/dist/{index-DKWIh6M1.d.ts → index-CRVAwJ5-.d.mts} +10 -8
- package/dist/index-CUPP2A_m.d.mts +27 -0
- package/dist/{index-Coh_SkBs.d.ts → index-CgvFomO6.d.mts} +6 -7
- package/dist/index-DJhDp4Xc.d.mts +58 -0
- package/dist/index-Dk7urvpF.d.mts +76 -0
- package/dist/{index-D54ySAKn.d.ts → index-DkVNO6ks.d.mts} +2 -5
- package/dist/{index-DtJX_tic.d.ts → index-NnCutIqM.d.mts} +77 -38
- package/dist/{index-CBT-JX-T.d.ts → index-eFuoMZZ3.d.mts} +18 -20
- package/dist/index-ygpml2kC.d.mts +73 -0
- package/dist/index.d.mts +16 -0
- package/dist/index.mjs +45 -0
- package/dist/index.mjs.map +1 -0
- package/dist/ingestion/index.d.mts +2 -0
- package/dist/ingestion/index.mjs +2 -0
- package/dist/ingestion-q0WwqUSt.mjs +275 -0
- package/dist/ingestion-q0WwqUSt.mjs.map +1 -0
- package/dist/ingestor/index.d.mts +3 -0
- package/dist/ingestor/index.mjs +4 -0
- package/dist/ingestor-D4L-HPkg.mjs +26 -0
- package/dist/ingestor-D4L-HPkg.mjs.map +1 -0
- package/dist/instrumented-Bhp7fyvh.mjs +29 -0
- package/dist/instrumented-Bhp7fyvh.mjs.map +1 -0
- package/dist/manifest/index.d.mts +2 -0
- package/dist/manifest/{index.js → index.mjs} +2 -4
- package/dist/{manifest-ByE6YPG0.js → manifest-BGKxmKLy.mjs} +14 -19
- package/dist/manifest-BGKxmKLy.mjs.map +1 -0
- package/dist/metrics-BaEX__MN.mjs +352 -0
- package/dist/metrics-BaEX__MN.mjs.map +1 -0
- package/dist/metrics-CVXFL7YT.d.mts +64 -0
- package/dist/metrics.d.mts +2 -0
- package/dist/metrics.mjs +2 -0
- package/dist/{chunk-Bp6m_JJh.js → rolldown-runtime-D7D4PA-g.mjs} +4 -4
- package/dist/runtime-config/index.d.mts +2 -0
- package/dist/runtime-config/index.mjs +3 -0
- package/dist/runtime-config-Oa55gAew.mjs +97 -0
- package/dist/runtime-config-Oa55gAew.mjs.map +1 -0
- package/dist/{server-CXTQ7odl.js → server-CMnxz3h0.mjs} +21 -60
- package/dist/server-CMnxz3h0.mjs.map +1 -0
- package/dist/service-DLkhuxYl.d.mts +27 -0
- package/dist/service-jWxxfEht.mjs +7 -0
- package/dist/service-jWxxfEht.mjs.map +1 -0
- package/dist/state-store/index.d.mts +2 -0
- package/dist/state-store/index.mjs +2 -0
- package/dist/{state-store-yl6LiTQ0.js → state-store-uFvHY7Ax.mjs} +15 -22
- package/dist/state-store-uFvHY7Ax.mjs.map +1 -0
- package/dist/status/{index.d.ts → index.d.mts} +1 -4
- package/dist/status/{index.js → index.mjs} +2 -6
- package/dist/{status-B-oZBc33.js → status-CKb9IhQ9.mjs} +14 -16
- package/dist/status-CKb9IhQ9.mjs.map +1 -0
- package/dist/table-V0tgUC5i.mjs +370 -0
- package/dist/table-V0tgUC5i.mjs.map +1 -0
- package/dist/types-xZtSmrGA.d.mts +220 -0
- package/dist/webhook/index.d.mts +3 -0
- package/dist/webhook/index.mjs +12 -0
- package/dist/webhook/index.mjs.map +1 -0
- package/dist/wings-I56hGtNv.mjs +325 -0
- package/dist/wings-I56hGtNv.mjs.map +1 -0
- package/package.json +64 -51
- package/src/catalog/table.ts +201 -0
- package/src/connector-app/create-table.ts +47 -0
- package/src/connector-app/demo.ts +42 -0
- package/src/connector-app/index.ts +2 -0
- package/src/connector-app/start.ts +1 -1
- package/src/core/builder.ts +15 -23
- package/src/core/index.ts +11 -1
- package/src/core/types.ts +114 -39
- package/src/demo/definition.ts +68 -0
- package/src/demo/generate.ts +167 -0
- package/src/demo/index.ts +3 -0
- package/src/demo/run.ts +142 -0
- package/src/iceberg/annotations.ts +62 -0
- package/src/iceberg/error.ts +9 -0
- package/src/iceberg/index.ts +3 -0
- package/src/iceberg/table.ts +511 -0
- package/src/index.ts +3 -1
- package/src/ingestion/engine.ts +240 -60
- package/src/ingestor/arrow.ts +248 -0
- package/src/ingestor/console.ts +13 -0
- package/src/ingestor/index.ts +9 -0
- package/src/ingestor/instrumented.ts +61 -0
- package/src/ingestor/service.ts +30 -0
- package/src/ingestor/wings.ts +143 -0
- package/src/manifest/config.ts +3 -3
- package/src/metrics.ts +125 -33
- package/src/runtime-config/config.ts +14 -0
- package/src/runtime-config/constants.ts +5 -2
- package/src/runtime-config/error.ts +4 -1
- package/src/runtime-config/index.ts +2 -0
- package/src/runtime-config/layer.ts +1 -1
- package/src/runtime-config/table-bindings.ts +92 -0
- package/src/state-store/layer-key-value-store.ts +8 -3
- package/src/state-store/layer-memory.ts +1 -1
- package/src/state-store/layer-sql.ts +4 -4
- package/src/state-store/schema.ts +2 -2
- package/src/state-store/state.ts +14 -2
- package/src/status/route.ts +2 -2
- package/src/telemetry.ts +25 -10
- package/src/webhook/server.ts +39 -40
- package/dist/auth/index.d.ts +0 -2
- package/dist/auth/index.js +0 -3
- package/dist/auth-DvU_CZ7C.js.map +0 -1
- package/dist/connector-app/index.d.ts +0 -14
- package/dist/connector-app/index.js +0 -11
- package/dist/connector-app-d7Z-SZLQ.js +0 -64
- package/dist/connector-app-d7Z-SZLQ.js.map +0 -1
- package/dist/constants-BRhIX_rz.js.map +0 -1
- package/dist/errors/index.d.ts +0 -2
- package/dist/errors/index.js +0 -3
- package/dist/errors-DHWylqRZ.js.map +0 -1
- package/dist/index-Byr0Lf0C.d.ts +0 -25
- package/dist/index-o1-Z3n7V.d.ts +0 -55
- package/dist/index.d.ts +0 -14
- package/dist/index.js +0 -58
- package/dist/index.js.map +0 -1
- package/dist/ingestion/index.d.ts +0 -6
- package/dist/ingestion/index.js +0 -10
- package/dist/ingestion-BQo4cbGw.js +0 -200
- package/dist/ingestion-BQo4cbGw.js.map +0 -1
- package/dist/manifest/index.d.ts +0 -2
- package/dist/manifest-ByE6YPG0.js.map +0 -1
- package/dist/metrics-CVAk1ALR.d.ts +0 -53
- package/dist/metrics-CWPy2Aqc.js +0 -96
- package/dist/metrics-CWPy2Aqc.js.map +0 -1
- package/dist/metrics.d.ts +0 -4
- package/dist/metrics.js +0 -3
- package/dist/publisher/index.d.ts +0 -5
- package/dist/publisher/index.js +0 -6
- package/dist/publisher-BYT3RLVO.js +0 -131
- package/dist/publisher-BYT3RLVO.js.map +0 -1
- package/dist/runtime-config/index.d.ts +0 -2
- package/dist/runtime-config/index.js +0 -4
- package/dist/runtime-config-BpB-d_bF.js +0 -51
- package/dist/runtime-config-BpB-d_bF.js.map +0 -1
- package/dist/server-CXTQ7odl.js.map +0 -1
- package/dist/service-DuFiQwid.js +0 -191
- package/dist/service-DuFiQwid.js.map +0 -1
- package/dist/service-IE5qaf9x.d.ts +0 -32
- package/dist/state-store/index.d.ts +0 -3
- package/dist/state-store/index.js +0 -5
- package/dist/state-store-yl6LiTQ0.js.map +0 -1
- package/dist/status-B-oZBc33.js.map +0 -1
- package/dist/types-B35J5YPu.d.ts +0 -174
- package/dist/webhook/index.d.ts +0 -6
- package/dist/webhook/index.js +0 -8
- package/dist/webhook-DI-Afxkg.js +0 -13
- package/dist/webhook-DI-Afxkg.js.map +0 -1
- package/src/publisher/console.ts +0 -18
- package/src/publisher/index.ts +0 -7
- package/src/publisher/instrumented.ts +0 -68
- package/src/publisher/service.ts +0 -37
- package/src/publisher/wings.ts +0 -204
package/dist/types-B35J5YPu.d.ts
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { t as ConnectorError } from "./index-D54ySAKn.js";
|
|
2
|
-
import { Duration, Effect, Schema } from "effect";
|
|
3
|
-
import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect/unstable/http";
|
|
4
|
-
|
|
5
|
-
//#region src/core/types.d.ts
|
|
6
|
-
declare namespace Cursor {
|
|
7
|
-
type Value = string | number | Date;
|
|
8
|
-
type Kind = "string" | "number" | "isoDateTime";
|
|
9
|
-
type Definition<T extends Value = Value> = {
|
|
10
|
-
readonly kind: Kind;
|
|
11
|
-
readonly decode: (value: unknown) => Effect.Effect<T, ConnectorError>;
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
type DeleteValue = string | number | boolean | Date;
|
|
15
|
-
type ResourceMutation<Row extends object = object> = {
|
|
16
|
-
readonly op: "upsert";
|
|
17
|
-
readonly row: Row;
|
|
18
|
-
} | {
|
|
19
|
-
readonly op: "delete";
|
|
20
|
-
readonly key: DeleteValue;
|
|
21
|
-
readonly version: DeleteValue;
|
|
22
|
-
};
|
|
23
|
-
type ResourceBatch<Row extends object = object> = {
|
|
24
|
-
readonly cursor?: Cursor.Value;
|
|
25
|
-
readonly mutations: ReadonlyArray<ResourceMutation<Row>>;
|
|
26
|
-
};
|
|
27
|
-
type ResourceState = {
|
|
28
|
-
readonly backfill?: {
|
|
29
|
-
readonly cutoff: Cursor.Value;
|
|
30
|
-
readonly pageCursor?: Cursor.Value;
|
|
31
|
-
readonly completed: boolean;
|
|
32
|
-
readonly lastSuccessAt?: string;
|
|
33
|
-
};
|
|
34
|
-
readonly changes?: {
|
|
35
|
-
readonly cursor: Cursor.Value;
|
|
36
|
-
readonly lastSuccessAt?: string;
|
|
37
|
-
};
|
|
38
|
-
readonly lastError?: {
|
|
39
|
-
readonly source: "backfill" | "changes";
|
|
40
|
-
readonly operation: "fetch" | "publish" | "checkpoint";
|
|
41
|
-
readonly code: "fetch_failed" | "publish_failed" | "checkpoint_failed";
|
|
42
|
-
readonly message: string;
|
|
43
|
-
readonly at: string;
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
type SyncState = "pending" | "backfilling" | "live" | "error";
|
|
47
|
-
type ResourceSchema = Schema.Decoder<object>;
|
|
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
|
-
type ResourceRow<S$1 extends ResourceSchema> = Schema.Schema.Type<S$1>;
|
|
60
|
-
/**
|
|
61
|
-
* Takes a resource schema and returns the string keys available on its row type.
|
|
62
|
-
*
|
|
63
|
-
* @example
|
|
64
|
-
* ```ts
|
|
65
|
-
* const ProductSchema = Schema.Struct({ id: Schema.String, updatedAt: Schema.String });
|
|
66
|
-
* type ProductField = ResourceField<typeof ProductSchema>;
|
|
67
|
-
* // Result:
|
|
68
|
-
* // type ProductField = "id" | "updatedAt"
|
|
69
|
-
*
|
|
70
|
-
* const key: ResourceField<typeof ProductSchema> = "id";
|
|
71
|
-
* ```
|
|
72
|
-
*/
|
|
73
|
-
type ResourceField<S$1 extends ResourceSchema> = keyof ResourceRow<S$1> & string;
|
|
74
|
-
type FetchPageResult<Row extends object> = {
|
|
75
|
-
readonly mutations: ReadonlyArray<ResourceMutation<Row>>;
|
|
76
|
-
readonly nextPageCursor?: Cursor.Value;
|
|
77
|
-
readonly hasMore: boolean;
|
|
78
|
-
};
|
|
79
|
-
type PageFetch<Row extends object, R = never> = {
|
|
80
|
-
readonly pageCursor: Cursor.Definition;
|
|
81
|
-
readonly cutoff: Cursor.Definition;
|
|
82
|
-
readonly fetch: (input: {
|
|
83
|
-
readonly pageCursor?: Cursor.Value;
|
|
84
|
-
readonly cutoff: Cursor.Value;
|
|
85
|
-
}) => Effect.Effect<FetchPageResult<Row>, ConnectorError, R>;
|
|
86
|
-
};
|
|
87
|
-
type FetchChangesResult<Row extends object> = {
|
|
88
|
-
readonly mutations: ReadonlyArray<ResourceMutation<Row>>;
|
|
89
|
-
readonly cursor: Cursor.Value;
|
|
90
|
-
};
|
|
91
|
-
type ChangesFetch<Row extends object, R = never> = {
|
|
92
|
-
readonly cursor: Cursor.Definition;
|
|
93
|
-
readonly interval?: Duration.Input;
|
|
94
|
-
readonly fetch: (input: {
|
|
95
|
-
readonly cursor: Cursor.Value;
|
|
96
|
-
}) => Effect.Effect<FetchChangesResult<Row>, ConnectorError, R>;
|
|
97
|
-
};
|
|
98
|
-
type WebhookHandler<Row extends object, Payload$1> = {
|
|
99
|
-
readonly schema: Schema.Decoder<Payload$1>;
|
|
100
|
-
handler(input: {
|
|
101
|
-
readonly payload: Payload$1;
|
|
102
|
-
}): Effect.Effect<ReadonlyArray<ResourceMutation<Row>>, ConnectorError>;
|
|
103
|
-
};
|
|
104
|
-
type ResourceDefinition<S$1 extends ResourceSchema = ResourceSchema, Payload$1 = unknown, R = never, Name extends string = string> = {
|
|
105
|
-
readonly name: Name;
|
|
106
|
-
readonly schema: S$1;
|
|
107
|
-
readonly key: ResourceField<NoInfer<S$1>>;
|
|
108
|
-
readonly version: ResourceField<NoInfer<S$1>>;
|
|
109
|
-
readonly partition?: {
|
|
110
|
-
readonly required: boolean;
|
|
111
|
-
};
|
|
112
|
-
/** Read-only validation used before provisioning this resource. */
|
|
113
|
-
readonly check: Effect.Effect<void, ConnectorError>;
|
|
114
|
-
readonly backfill?: PageFetch<ResourceRow<NoInfer<S$1>>, R>;
|
|
115
|
-
readonly changes?: ChangesFetch<ResourceRow<NoInfer<S$1>>, R>;
|
|
116
|
-
readonly webhook?: WebhookHandler<ResourceRow<NoInfer<S$1>>, Payload$1>;
|
|
117
|
-
};
|
|
118
|
-
/**
|
|
119
|
-
* Takes a connector resource tuple and returns a `{ [resourceName]: rowType }`
|
|
120
|
-
* map.
|
|
121
|
-
*
|
|
122
|
-
* @example
|
|
123
|
-
* ```ts
|
|
124
|
-
* type Rows = ResourceRows<[typeof Products, typeof Orders]>;
|
|
125
|
-
* // Result:
|
|
126
|
-
* // type Rows = {
|
|
127
|
-
* // readonly products: Product;
|
|
128
|
-
* // readonly orders: Order;
|
|
129
|
-
* // }
|
|
130
|
-
*
|
|
131
|
-
* type ProductRow = Rows["products"];
|
|
132
|
-
* // Result:
|
|
133
|
-
* // type ProductRow = Product
|
|
134
|
-
* ```
|
|
135
|
-
*/
|
|
136
|
-
type ResourceRows<Resources extends ReadonlyArray<ResourceDefinition>> = { readonly [Resource in Resources[number] as Resource["name"]]: Resource extends ResourceDefinition<infer S, unknown, unknown> ? ResourceRow<S> : never };
|
|
137
|
-
/** Resource names preserved from a connector's resource tuple. */
|
|
138
|
-
type ResourceName<Resources extends ReadonlyArray<ResourceDefinition>> = keyof ResourceRows<Resources> & string;
|
|
139
|
-
/**
|
|
140
|
-
* Takes a resource definition and returns the payload type accepted by
|
|
141
|
-
* `to(resource, payload)`.
|
|
142
|
-
*
|
|
143
|
-
* @example
|
|
144
|
-
* ```ts
|
|
145
|
-
* type ProductPayload = ResourcePayload<typeof Products>;
|
|
146
|
-
* // Result, if Products was defined with a ProductEvent webhook schema:
|
|
147
|
-
* // type ProductPayload = ProductEvent
|
|
148
|
-
* ```
|
|
149
|
-
*/
|
|
150
|
-
type ResourcePayload<R> = R extends ResourceDefinition<ResourceSchema, infer Payload, unknown> ? Payload : never;
|
|
151
|
-
type WebhookAckMode = "after-enqueue" | "after-publish";
|
|
152
|
-
type WebhookRouteContext<Resources extends ReadonlyArray<ResourceDefinition> = ReadonlyArray<ResourceDefinition>, Payload$1 = unknown> = {
|
|
153
|
-
readonly request: HttpServerRequest.HttpServerRequest;
|
|
154
|
-
readonly rawBody: Uint8Array;
|
|
155
|
-
readonly payload: Payload$1;
|
|
156
|
-
/** Decodes and collects mutations for a resource-owned webhook handler. */
|
|
157
|
-
readonly to: <Resource$1 extends Resources[number]>(resource: Resource$1, payload: ResourcePayload<Resource$1>) => Effect.Effect<void, ConnectorError>;
|
|
158
|
-
};
|
|
159
|
-
type WebhookRoute<Resources extends ReadonlyArray<ResourceDefinition> = ReadonlyArray<ResourceDefinition>, Payload$1 = unknown> = {
|
|
160
|
-
readonly path: HttpRouter.PathInput;
|
|
161
|
-
readonly ackMode: WebhookAckMode;
|
|
162
|
-
readonly schema: Schema.Decoder<Payload$1>;
|
|
163
|
-
handler(context: WebhookRouteContext<Resources, Payload$1>): Effect.Effect<HttpServerResponse.HttpServerResponse, ConnectorError>;
|
|
164
|
-
};
|
|
165
|
-
type WebhookRouteInput<Resources extends ReadonlyArray<ResourceDefinition>, Payload$1> = WebhookRoute<Resources, Payload$1>;
|
|
166
|
-
type ConnectorDefinition<Resources extends ReadonlyArray<ResourceDefinition> = ReadonlyArray<ResourceDefinition>> = {
|
|
167
|
-
readonly name: string;
|
|
168
|
-
readonly title?: string;
|
|
169
|
-
readonly resources: Resources;
|
|
170
|
-
readonly webhooks?: ReadonlyArray<WebhookRoute>;
|
|
171
|
-
};
|
|
172
|
-
//#endregion
|
|
173
|
-
export { WebhookRouteInput as C, WebhookRouteContext as S, ResourceState as _, FetchChangesResult as a, WebhookHandler as b, ResourceBatch as c, ResourceMutation as d, ResourceName as f, ResourceSchema as g, ResourceRows as h, DeleteValue as i, ResourceDefinition as l, ResourceRow as m, ConnectorDefinition as n, FetchPageResult as o, ResourcePayload as p, Cursor as r, PageFetch as s, ChangesFetch as t, ResourceField as u, SyncState as v, WebhookRoute as x, WebhookAckMode as y };
|
|
174
|
-
//# sourceMappingURL=types-B35J5YPu.d.ts.map
|
package/dist/webhook/index.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import "../index-D54ySAKn.js";
|
|
2
|
-
import { C as WebhookRouteInput, S as WebhookRouteContext, x as WebhookRoute, y as WebhookAckMode } from "../types-B35J5YPu.js";
|
|
3
|
-
import "../service-IE5qaf9x.js";
|
|
4
|
-
import "../index-Byr0Lf0C.js";
|
|
5
|
-
import { n as route, r as router } from "../index-DKWIh6M1.js";
|
|
6
|
-
export { WebhookAckMode, WebhookRoute, WebhookRouteContext, WebhookRouteInput, route, router };
|
package/dist/webhook/index.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import "../errors-DHWylqRZ.js";
|
|
2
|
-
import "../metrics-CWPy2Aqc.js";
|
|
3
|
-
import "../constants-BRhIX_rz.js";
|
|
4
|
-
import "../service-DuFiQwid.js";
|
|
5
|
-
import { n as router } from "../server-CXTQ7odl.js";
|
|
6
|
-
import { t as route } from "../webhook-DI-Afxkg.js";
|
|
7
|
-
|
|
8
|
-
export { route, router };
|
package/dist/webhook-DI-Afxkg.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { t as __export } from "./chunk-Bp6m_JJh.js";
|
|
2
|
-
import { n as router } from "./server-CXTQ7odl.js";
|
|
3
|
-
|
|
4
|
-
//#region src/webhook/index.ts
|
|
5
|
-
var webhook_exports = /* @__PURE__ */ __export({
|
|
6
|
-
route: () => route,
|
|
7
|
-
router: () => router
|
|
8
|
-
});
|
|
9
|
-
const route = (definition) => definition;
|
|
10
|
-
|
|
11
|
-
//#endregion
|
|
12
|
-
export { webhook_exports as n, route as t };
|
|
13
|
-
//# sourceMappingURL=webhook-DI-Afxkg.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-DI-Afxkg.js","names":[],"sources":["../src/webhook/index.ts"],"sourcesContent":["import type { ResourceDefinition, WebhookRoute, WebhookRouteInput } from \"../core/types\";\n\nexport { router } from \"./server\";\nexport type { WebhookAckMode, WebhookRoute, WebhookRouteContext, WebhookRouteInput } from \"./types\";\n\nexport const route = <const Resources extends ReadonlyArray<ResourceDefinition>, Payload>(\n definition: WebhookRouteInput<Resources, Payload>,\n): WebhookRoute<Resources, Payload> => definition;\n"],"mappings":";;;;;;;;AAKA,MAAa,SACX,eACqC"}
|
package/src/publisher/console.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Effect, Layer } from "effect";
|
|
2
|
-
|
|
3
|
-
import { Publisher } from "./service";
|
|
4
|
-
|
|
5
|
-
export const layerConsole = Layer.succeed(Publisher)({
|
|
6
|
-
publish: ({ resource, source, batch }) =>
|
|
7
|
-
Effect.gen(function* () {
|
|
8
|
-
yield* Effect.logInfo(`[publisher] -> Source: ${source} | Resource: ${resource}`).pipe(
|
|
9
|
-
Effect.annotateLogs({
|
|
10
|
-
mutations: batch.mutations.length,
|
|
11
|
-
cursor: batch.cursor,
|
|
12
|
-
source,
|
|
13
|
-
}),
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
return { status: "accepted" as const, resource };
|
|
17
|
-
}),
|
|
18
|
-
});
|
package/src/publisher/index.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export type { ResourceBatch } from "../core/types";
|
|
2
|
-
export type { PublishAck, PublishOptions, PublisherService, PublishSource } from "./service";
|
|
3
|
-
export type { WingsPublisherConfig } from "./wings";
|
|
4
|
-
|
|
5
|
-
export { layerConsole } from "./console";
|
|
6
|
-
export { Publisher } from "./service";
|
|
7
|
-
export { layerWings } from "./wings";
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { Effect, Metric } from "effect";
|
|
2
|
-
|
|
3
|
-
import type { ResourceBatch } from "../core/types";
|
|
4
|
-
|
|
5
|
-
import { ConnectorError } from "../errors";
|
|
6
|
-
import * as Metrics from "../metrics";
|
|
7
|
-
import { Attr, EventAttr, EventName, addCurrentSpanEvent } from "../telemetry";
|
|
8
|
-
import { Publisher, type PublishSource } from "./service";
|
|
9
|
-
|
|
10
|
-
export const publishBatch = Effect.fnUntraced(function* (options: {
|
|
11
|
-
readonly connector?: string;
|
|
12
|
-
readonly resource: string;
|
|
13
|
-
readonly source: PublishSource;
|
|
14
|
-
readonly batch: ResourceBatch;
|
|
15
|
-
}) {
|
|
16
|
-
const metric = {
|
|
17
|
-
connector: options.connector ?? "unknown",
|
|
18
|
-
resource: options.resource,
|
|
19
|
-
source: options.source,
|
|
20
|
-
};
|
|
21
|
-
const upserts = options.batch.mutations.filter((mutation) => mutation.op === "upsert").length;
|
|
22
|
-
const deletes = options.batch.mutations.length - upserts;
|
|
23
|
-
|
|
24
|
-
const publisher = yield* Publisher;
|
|
25
|
-
const [duration, ack] = yield* Effect.timed(
|
|
26
|
-
publisher.publish({
|
|
27
|
-
resource: options.resource,
|
|
28
|
-
source: options.source,
|
|
29
|
-
batch: options.batch,
|
|
30
|
-
}),
|
|
31
|
-
).pipe(
|
|
32
|
-
Effect.catchCause((cause) =>
|
|
33
|
-
Metric.update(
|
|
34
|
-
Metric.withAttributes(Metrics.batchesTotal, { ...metric, outcome: "error" }),
|
|
35
|
-
1,
|
|
36
|
-
).pipe(Effect.andThen(Effect.failCause(cause))),
|
|
37
|
-
),
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
yield* Metric.update(Metric.withAttributes(Metrics.publishDuration, metric), duration);
|
|
41
|
-
yield* Metric.update(
|
|
42
|
-
Metric.withAttributes(Metrics.batchesTotal, { ...metric, outcome: ack.status }),
|
|
43
|
-
1,
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
yield* Effect.annotateCurrentSpan({ [Attr.publisherSuccess]: ack.status === "accepted" });
|
|
47
|
-
if (ack.status === "rejected") {
|
|
48
|
-
yield* Effect.annotateCurrentSpan({ [Attr.errorPhase]: "publish" });
|
|
49
|
-
return yield* Effect.fail(
|
|
50
|
-
new ConnectorError({
|
|
51
|
-
message: `Publisher rejected batch for ${options.resource}: ${ack.reason}`,
|
|
52
|
-
}),
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
yield* Metric.update(Metric.withAttributes(Metrics.entitiesUpsertedTotal, metric), upserts);
|
|
57
|
-
yield* Metric.update(Metric.withAttributes(Metrics.entitiesDeletedTotal, metric), deletes);
|
|
58
|
-
yield* Metric.update(
|
|
59
|
-
Metric.withAttributes(Metrics.batchSize, metric),
|
|
60
|
-
options.batch.mutations.length,
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
if (options.batch.cursor !== undefined) {
|
|
64
|
-
yield* addCurrentSpanEvent(EventName.batchCheckpoint, {
|
|
65
|
-
[EventAttr.batchCursor]: options.batch.cursor,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
});
|
package/src/publisher/service.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type * as Wings from "@useairfoil/wings";
|
|
2
|
-
import type * as Effect from "effect/Effect";
|
|
3
|
-
|
|
4
|
-
import { Context } from "effect";
|
|
5
|
-
|
|
6
|
-
import type { ResourceBatch } from "../core/types";
|
|
7
|
-
import type { ConnectorError } from "../errors";
|
|
8
|
-
|
|
9
|
-
export type PublishSource = "backfill" | "changes" | "webhook";
|
|
10
|
-
|
|
11
|
-
export type PublishAck =
|
|
12
|
-
| {
|
|
13
|
-
readonly status: "accepted";
|
|
14
|
-
readonly resource: string;
|
|
15
|
-
readonly partition?: Wings.PartitionValue.PartitionValue;
|
|
16
|
-
}
|
|
17
|
-
| {
|
|
18
|
-
readonly status: "rejected";
|
|
19
|
-
readonly resource: string;
|
|
20
|
-
readonly reason: string;
|
|
21
|
-
readonly rejectedRows?: number;
|
|
22
|
-
readonly partition?: Wings.PartitionValue.PartitionValue;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type PublishOptions = {
|
|
26
|
-
readonly resource: string;
|
|
27
|
-
readonly source: PublishSource;
|
|
28
|
-
readonly batch: ResourceBatch;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export interface PublisherService {
|
|
32
|
-
readonly publish: (options: PublishOptions) => Effect.Effect<PublishAck, ConnectorError>;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export class Publisher extends Context.Service<Publisher, PublisherService>()(
|
|
36
|
-
"@useairfoil/connector-kit/Publisher",
|
|
37
|
-
) {}
|
package/src/publisher/wings.ts
DELETED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import * as Wings from "@useairfoil/wings";
|
|
2
|
-
import { Effect, Layer } from "effect";
|
|
3
|
-
|
|
4
|
-
import type { ConnectorDefinition, ResourceDefinition } from "../core/types";
|
|
5
|
-
|
|
6
|
-
import { ConnectorError } from "../errors";
|
|
7
|
-
import { SpanName } from "../telemetry";
|
|
8
|
-
import { Publisher, type PublishAck, type PublisherService } from "./service";
|
|
9
|
-
|
|
10
|
-
type Rows = Record<string, unknown>;
|
|
11
|
-
|
|
12
|
-
export type WingsTableMapping = {
|
|
13
|
-
readonly name: string;
|
|
14
|
-
readonly partitionValue?: Wings.PartitionValue.PartitionValue;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export type WingsPublisherConfig = {
|
|
18
|
-
readonly connector: ConnectorDefinition;
|
|
19
|
-
readonly tables: Record<string, string | WingsTableMapping>;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
type PublisherEntry = {
|
|
23
|
-
readonly resource: ResourceDefinition;
|
|
24
|
-
readonly table: Wings.Cluster.Table.Table;
|
|
25
|
-
readonly publisher: Wings.WingsClient.Publisher;
|
|
26
|
-
readonly partitionValue?: Wings.PartitionValue.PartitionValue;
|
|
27
|
-
readonly keyField: Wings.Cluster.ArrowType.Field;
|
|
28
|
-
readonly versionField: Wings.Cluster.ArrowType.Field;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const normalizeMapping = (mapping: string | WingsTableMapping): WingsTableMapping =>
|
|
32
|
-
typeof mapping === "string" ? { name: mapping } : mapping;
|
|
33
|
-
|
|
34
|
-
const buildRecordBatch = (rows: ReadonlyArray<Rows>) => {
|
|
35
|
-
const table = Wings.Arrow.tableFromJSON(Array.from(rows));
|
|
36
|
-
const [batch] = table.batches;
|
|
37
|
-
return batch
|
|
38
|
-
? Effect.succeed(batch)
|
|
39
|
-
: Effect.fail(new ConnectorError({ message: "No rows to publish" }));
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const validateTableMapping = (options: {
|
|
43
|
-
readonly resource: ResourceDefinition;
|
|
44
|
-
readonly table: Wings.Cluster.Table.Table;
|
|
45
|
-
readonly partitionValue?: Wings.PartitionValue.PartitionValue;
|
|
46
|
-
}) =>
|
|
47
|
-
Effect.try({
|
|
48
|
-
try: () => {
|
|
49
|
-
const keyField = Wings.TableUtils.getKeyField(options.table);
|
|
50
|
-
const versionField = Wings.TableUtils.getVersionField(options.table);
|
|
51
|
-
const partitionField = Wings.TableUtils.getPartitionField(options.table);
|
|
52
|
-
|
|
53
|
-
if (keyField.name !== options.resource.key) {
|
|
54
|
-
throw new Error(
|
|
55
|
-
`Resource ${options.resource.name} key '${options.resource.key}' does not match Wings table key '${keyField.name}'`,
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
if (versionField.name !== options.resource.version) {
|
|
59
|
-
throw new Error(
|
|
60
|
-
`Resource ${options.resource.name} version '${options.resource.version}' does not match Wings table version '${versionField.name}'`,
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
if (options.resource.partition?.required === true && !options.partitionValue) {
|
|
64
|
-
throw new Error(`Resource ${options.resource.name} requires a partition value`);
|
|
65
|
-
}
|
|
66
|
-
if (partitionField && !options.partitionValue) {
|
|
67
|
-
throw new Error(
|
|
68
|
-
`Wings table ${options.table.name} is partitioned but no partition value was provided`,
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
if (!partitionField && options.partitionValue) {
|
|
72
|
-
throw new Error(
|
|
73
|
-
`Wings table ${options.table.name} is not partitioned but a partition value was provided`,
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return { keyField, versionField };
|
|
78
|
-
},
|
|
79
|
-
catch: (cause) =>
|
|
80
|
-
new ConnectorError({
|
|
81
|
-
message: `Invalid Wings table mapping for ${options.resource.name}`,
|
|
82
|
-
cause,
|
|
83
|
-
}),
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
const accepted = (entry: PublisherEntry): PublishAck => ({
|
|
87
|
-
status: "accepted",
|
|
88
|
-
resource: entry.resource.name,
|
|
89
|
-
partition: entry.partitionValue,
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
const rejected = (entry: PublisherEntry, reason: string, rejectedRows: number): PublishAck => ({
|
|
93
|
-
status: "rejected",
|
|
94
|
-
resource: entry.resource.name,
|
|
95
|
-
reason,
|
|
96
|
-
rejectedRows,
|
|
97
|
-
partition: entry.partitionValue,
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
export const layerWings = (
|
|
101
|
-
config: WingsPublisherConfig,
|
|
102
|
-
): Layer.Layer<Publisher, ConnectorError, Wings.WingsClient.WingsClient> =>
|
|
103
|
-
Layer.effect(Publisher)(
|
|
104
|
-
Effect.gen(function* () {
|
|
105
|
-
const entries = new Map<string, PublisherEntry>();
|
|
106
|
-
const clusterClient = yield* Wings.WingsClient.clusterClient;
|
|
107
|
-
|
|
108
|
-
for (const resource of config.connector.resources) {
|
|
109
|
-
const mappingInput = config.tables[resource.name];
|
|
110
|
-
if (!mappingInput) {
|
|
111
|
-
return yield* Effect.fail(
|
|
112
|
-
new ConnectorError({ message: `Missing table for ${resource.name}` }),
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const mapping = normalizeMapping(mappingInput);
|
|
117
|
-
const table = yield* clusterClient.getTable({ name: mapping.name }).pipe(
|
|
118
|
-
Effect.mapError(
|
|
119
|
-
(error) =>
|
|
120
|
-
new ConnectorError({
|
|
121
|
-
message: `Failed to resolve Wings table for ${resource.name}`,
|
|
122
|
-
cause: error,
|
|
123
|
-
}),
|
|
124
|
-
),
|
|
125
|
-
);
|
|
126
|
-
const { keyField, versionField } = yield* validateTableMapping({
|
|
127
|
-
resource,
|
|
128
|
-
table,
|
|
129
|
-
partitionValue: mapping.partitionValue,
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
const publisher = yield* Wings.WingsClient.publisher({
|
|
133
|
-
table,
|
|
134
|
-
partitionValue: mapping.partitionValue,
|
|
135
|
-
}).pipe(
|
|
136
|
-
Effect.mapError((error) => new ConnectorError({ message: error.message, cause: error })),
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
entries.set(resource.name, {
|
|
140
|
-
resource,
|
|
141
|
-
table,
|
|
142
|
-
publisher,
|
|
143
|
-
partitionValue: mapping.partitionValue,
|
|
144
|
-
keyField,
|
|
145
|
-
versionField,
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const pushRows = (
|
|
150
|
-
entry: PublisherEntry,
|
|
151
|
-
operation: "upsert" | "delete",
|
|
152
|
-
rows: ReadonlyArray<Rows>,
|
|
153
|
-
) =>
|
|
154
|
-
Effect.gen(function* () {
|
|
155
|
-
if (rows.length === 0) return accepted(entry);
|
|
156
|
-
const batch = yield* buildRecordBatch(rows);
|
|
157
|
-
return yield* entry.publisher
|
|
158
|
-
.push({ operation, batch, partitionValue: entry.partitionValue })
|
|
159
|
-
.pipe(
|
|
160
|
-
Effect.matchEffect({
|
|
161
|
-
onFailure: (error) => Effect.succeed(rejected(entry, error.message, rows.length)),
|
|
162
|
-
onSuccess: () => Effect.succeed(accepted(entry)),
|
|
163
|
-
}),
|
|
164
|
-
);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
const service: PublisherService = {
|
|
168
|
-
publish: Effect.fn(SpanName.publish, { kind: "producer" })(function* ({
|
|
169
|
-
resource,
|
|
170
|
-
source: _source,
|
|
171
|
-
batch,
|
|
172
|
-
}) {
|
|
173
|
-
const entry = entries.get(resource);
|
|
174
|
-
if (!entry) {
|
|
175
|
-
return yield* Effect.fail(
|
|
176
|
-
new ConnectorError({ message: `Unknown resource ${resource}` }),
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (batch.mutations.length === 0) return accepted(entry);
|
|
181
|
-
|
|
182
|
-
const upserts: Rows[] = [];
|
|
183
|
-
const deletes: Rows[] = [];
|
|
184
|
-
for (const mutation of batch.mutations) {
|
|
185
|
-
if (mutation.op === "upsert") {
|
|
186
|
-
upserts.push(mutation.row as Rows);
|
|
187
|
-
} else {
|
|
188
|
-
deletes.push({
|
|
189
|
-
[entry.keyField.name]: mutation.key,
|
|
190
|
-
[entry.versionField.name]: mutation.version,
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const upsertAck = yield* pushRows(entry, "upsert", upserts);
|
|
196
|
-
if (upsertAck.status === "rejected") return upsertAck;
|
|
197
|
-
|
|
198
|
-
return yield* pushRows(entry, "delete", deletes);
|
|
199
|
-
}),
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
return Publisher.of(service);
|
|
203
|
-
}),
|
|
204
|
-
);
|