@automate.ax/integration-contracts 0.147.0 → 0.148.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.
- package/dist/close/events.d.ts +4 -4
- package/dist/close/schemas.d.ts +6 -6
- package/dist/google-drive/index.d.ts +3 -3
- package/dist/kit/api.d.ts +78 -0
- package/dist/kit/api.js +386 -0
- package/dist/kit/events.d.ts +437 -0
- package/dist/kit/events.js +285 -0
- package/dist/kit/index.d.ts +6 -0
- package/dist/kit/index.js +5 -0
- package/dist/kit/openapi-operations.generated.d.ts +5 -0
- package/dist/kit/openapi-operations.generated.js +5 -0
- package/dist/kit/openapi-types.generated.d.ts +9485 -0
- package/dist/kit/openapi-types.generated.js +1 -0
- package/dist/kit/operation-manifest.d.ts +657 -0
- package/dist/kit/operation-manifest.js +98 -0
- package/dist/kit/schemas.d.ts +42 -0
- package/dist/kit/schemas.js +43 -0
- package/dist/kit/types.d.ts +41 -0
- package/dist/kit/types.js +1 -0
- package/dist/notion/schemas.d.ts +108 -108
- package/dist/resend/action-schemas.d.ts +14 -14
- package/dist/tally/api.js +5 -2
- package/dist/tally/events.d.ts +12 -12
- package/dist/tally/openapi-schemas.generated.json +39 -5
- package/dist/tally/openapi-types.generated.d.ts +6 -5
- package/dist/triggers.d.ts +2 -1
- package/package.json +9 -2
- package/src/kit/api.ts +523 -0
- package/src/kit/events.ts +352 -0
- package/src/kit/index.ts +6 -0
- package/src/kit/openapi-operations.generated.ts +7 -0
- package/src/kit/openapi-types.generated.ts +9710 -0
- package/src/kit/operation-manifest.ts +771 -0
- package/src/kit/schemas.ts +93 -0
- package/src/kit/types.ts +87 -0
- package/src/tally/api.ts +4 -2
- package/src/tally/openapi-schemas.generated.json +39 -5
- package/src/tally/openapi-types.generated.ts +6 -5
- package/src/triggers.ts +2 -0
package/dist/close/events.d.ts
CHANGED
|
@@ -487,9 +487,9 @@ export declare const closeTriggerContracts: {
|
|
|
487
487
|
error: "error";
|
|
488
488
|
draft: "draft";
|
|
489
489
|
sent: "sent";
|
|
490
|
+
scheduled: "scheduled";
|
|
490
491
|
inbox: "inbox";
|
|
491
492
|
outbox: "outbox";
|
|
492
|
-
scheduled: "scheduled";
|
|
493
493
|
}>>;
|
|
494
494
|
subject: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
495
495
|
templateId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -575,9 +575,9 @@ export declare const closeTriggerContracts: {
|
|
|
575
575
|
error: "error";
|
|
576
576
|
draft: "draft";
|
|
577
577
|
sent: "sent";
|
|
578
|
+
scheduled: "scheduled";
|
|
578
579
|
inbox: "inbox";
|
|
579
580
|
outbox: "outbox";
|
|
580
|
-
scheduled: "scheduled";
|
|
581
581
|
}>>;
|
|
582
582
|
subject: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
583
583
|
templateId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -2162,9 +2162,9 @@ export declare const closeTriggerContracts: {
|
|
|
2162
2162
|
error: "error";
|
|
2163
2163
|
draft: "draft";
|
|
2164
2164
|
sent: "sent";
|
|
2165
|
+
scheduled: "scheduled";
|
|
2165
2166
|
inbox: "inbox";
|
|
2166
2167
|
outbox: "outbox";
|
|
2167
|
-
scheduled: "scheduled";
|
|
2168
2168
|
}>>;
|
|
2169
2169
|
templateId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
2170
2170
|
text: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -2233,9 +2233,9 @@ export declare const closeTriggerContracts: {
|
|
|
2233
2233
|
error: "error";
|
|
2234
2234
|
draft: "draft";
|
|
2235
2235
|
sent: "sent";
|
|
2236
|
+
scheduled: "scheduled";
|
|
2236
2237
|
inbox: "inbox";
|
|
2237
2238
|
outbox: "outbox";
|
|
2238
|
-
scheduled: "scheduled";
|
|
2239
2239
|
}>>;
|
|
2240
2240
|
templateId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
2241
2241
|
text: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
package/dist/close/schemas.d.ts
CHANGED
|
@@ -907,9 +907,9 @@ export declare const CLOSE_EMAIL_SCHEMA: z.ZodObject<{
|
|
|
907
907
|
error: "error";
|
|
908
908
|
draft: "draft";
|
|
909
909
|
sent: "sent";
|
|
910
|
+
scheduled: "scheduled";
|
|
910
911
|
inbox: "inbox";
|
|
911
912
|
outbox: "outbox";
|
|
912
|
-
scheduled: "scheduled";
|
|
913
913
|
}>;
|
|
914
914
|
subject: z.ZodNullable<z.ZodString>;
|
|
915
915
|
templateId: z.ZodNullable<z.ZodString>;
|
|
@@ -962,9 +962,9 @@ export declare const CLOSE_SMS_SCHEMA: z.ZodObject<{
|
|
|
962
962
|
error: "error";
|
|
963
963
|
draft: "draft";
|
|
964
964
|
sent: "sent";
|
|
965
|
+
scheduled: "scheduled";
|
|
965
966
|
inbox: "inbox";
|
|
966
967
|
outbox: "outbox";
|
|
967
|
-
scheduled: "scheduled";
|
|
968
968
|
}>;
|
|
969
969
|
templateId: z.ZodNullable<z.ZodString>;
|
|
970
970
|
text: z.ZodNullable<z.ZodString>;
|
|
@@ -1129,9 +1129,9 @@ export declare const CLOSE_ACTIVITY_SCHEMA: z.ZodDiscriminatedUnion<[z.ZodObject
|
|
|
1129
1129
|
error: "error";
|
|
1130
1130
|
draft: "draft";
|
|
1131
1131
|
sent: "sent";
|
|
1132
|
+
scheduled: "scheduled";
|
|
1132
1133
|
inbox: "inbox";
|
|
1133
1134
|
outbox: "outbox";
|
|
1134
|
-
scheduled: "scheduled";
|
|
1135
1135
|
}>;
|
|
1136
1136
|
subject: z.ZodNullable<z.ZodString>;
|
|
1137
1137
|
templateId: z.ZodNullable<z.ZodString>;
|
|
@@ -1271,9 +1271,9 @@ export declare const CLOSE_ACTIVITY_SCHEMA: z.ZodDiscriminatedUnion<[z.ZodObject
|
|
|
1271
1271
|
error: "error";
|
|
1272
1272
|
draft: "draft";
|
|
1273
1273
|
sent: "sent";
|
|
1274
|
+
scheduled: "scheduled";
|
|
1274
1275
|
inbox: "inbox";
|
|
1275
1276
|
outbox: "outbox";
|
|
1276
|
-
scheduled: "scheduled";
|
|
1277
1277
|
}>;
|
|
1278
1278
|
templateId: z.ZodNullable<z.ZodString>;
|
|
1279
1279
|
text: z.ZodNullable<z.ZodString>;
|
|
@@ -1411,9 +1411,9 @@ export declare const CLOSE_ACTIVITY_SCHEMA: z.ZodDiscriminatedUnion<[z.ZodObject
|
|
|
1411
1411
|
error: "error";
|
|
1412
1412
|
draft: "draft";
|
|
1413
1413
|
sent: "sent";
|
|
1414
|
+
scheduled: "scheduled";
|
|
1414
1415
|
inbox: "inbox";
|
|
1415
1416
|
outbox: "outbox";
|
|
1416
|
-
scheduled: "scheduled";
|
|
1417
1417
|
}>;
|
|
1418
1418
|
subject: z.ZodNullable<z.ZodString>;
|
|
1419
1419
|
templateId: z.ZodNullable<z.ZodString>;
|
|
@@ -1507,9 +1507,9 @@ export declare const CLOSE_ACTIVITY_SCHEMA: z.ZodDiscriminatedUnion<[z.ZodObject
|
|
|
1507
1507
|
error: "error";
|
|
1508
1508
|
draft: "draft";
|
|
1509
1509
|
sent: "sent";
|
|
1510
|
+
scheduled: "scheduled";
|
|
1510
1511
|
inbox: "inbox";
|
|
1511
1512
|
outbox: "outbox";
|
|
1512
|
-
scheduled: "scheduled";
|
|
1513
1513
|
}>;
|
|
1514
1514
|
subject: z.ZodNullable<z.ZodString>;
|
|
1515
1515
|
to: z.ZodArray<z.ZodString>;
|
|
@@ -45,6 +45,7 @@ export declare const GOOGLE_DRIVE_EVENT_SCHEMA: z.ZodObject<{
|
|
|
45
45
|
completed: "completed";
|
|
46
46
|
deleted: "deleted";
|
|
47
47
|
resolved: "resolved";
|
|
48
|
+
trashed: "trashed";
|
|
48
49
|
moved: "moved";
|
|
49
50
|
contentChanged: "contentChanged";
|
|
50
51
|
edited: "edited";
|
|
@@ -53,7 +54,6 @@ export declare const GOOGLE_DRIVE_EVENT_SCHEMA: z.ZodObject<{
|
|
|
53
54
|
reset: "reset";
|
|
54
55
|
responded: "responded";
|
|
55
56
|
reviewersChanged: "reviewersChanged";
|
|
56
|
-
trashed: "trashed";
|
|
57
57
|
untrashed: "untrashed";
|
|
58
58
|
}>;
|
|
59
59
|
assigneeEmailAddress: z.ZodOptional<z.ZodEmail>;
|
|
@@ -959,6 +959,7 @@ export declare const googleDriveTriggerContracts: {
|
|
|
959
959
|
completed: "completed";
|
|
960
960
|
deleted: "deleted";
|
|
961
961
|
resolved: "resolved";
|
|
962
|
+
trashed: "trashed";
|
|
962
963
|
moved: "moved";
|
|
963
964
|
contentChanged: "contentChanged";
|
|
964
965
|
edited: "edited";
|
|
@@ -967,7 +968,6 @@ export declare const googleDriveTriggerContracts: {
|
|
|
967
968
|
reset: "reset";
|
|
968
969
|
responded: "responded";
|
|
969
970
|
reviewersChanged: "reviewersChanged";
|
|
970
|
-
trashed: "trashed";
|
|
971
971
|
untrashed: "untrashed";
|
|
972
972
|
}>;
|
|
973
973
|
assigneeEmailAddress: z.ZodOptional<z.ZodEmail>;
|
|
@@ -1038,7 +1038,7 @@ export declare function toGoogleDriveTriggerType(providerEventType: string): Goo
|
|
|
1038
1038
|
* @param eventType - Stable internal semantic event type.
|
|
1039
1039
|
*/
|
|
1040
1040
|
export declare function parseGoogleDriveTriggerType(eventType: GoogleDriveTriggerType): {
|
|
1041
|
-
action: "created" | "cancelled" | "completed" | "deleted" | "resolved" | "moved" | "contentChanged" | "edited" | "reopened" | "renamed" | "reset" | "responded" | "reviewersChanged" | "
|
|
1041
|
+
action: "created" | "cancelled" | "completed" | "deleted" | "resolved" | "trashed" | "moved" | "contentChanged" | "edited" | "reopened" | "renamed" | "reset" | "responded" | "reviewersChanged" | "untrashed";
|
|
1042
1042
|
resourceType: "file" | "comment" | "reply" | "accessProposal" | "approval" | "permission";
|
|
1043
1043
|
};
|
|
1044
1044
|
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type Encodable } from "@automate.ax/codec";
|
|
2
|
+
import type { KitOperationKey } from "./operation-manifest.js";
|
|
3
|
+
import type { KitOperationInput, KitOperationOutput } from "./types.js";
|
|
4
|
+
/** Resolved account accepted by the shared Kit API client. */
|
|
5
|
+
export interface KitResolvedAccount {
|
|
6
|
+
connectionMethodId: string;
|
|
7
|
+
secret: Record<string, unknown>;
|
|
8
|
+
serviceId: "kit";
|
|
9
|
+
}
|
|
10
|
+
/** Options for an internal provider-native Kit request. */
|
|
11
|
+
export interface KitRequestOptions {
|
|
12
|
+
body?: Encodable;
|
|
13
|
+
method?: "DELETE" | "GET" | "PATCH" | "POST" | "PUT";
|
|
14
|
+
query?: Record<string, boolean | number | string | (boolean | number | string)[] | null | undefined>;
|
|
15
|
+
}
|
|
16
|
+
/** Structured error returned by a rejected Kit request. */
|
|
17
|
+
export declare class KitApiError extends Error {
|
|
18
|
+
readonly body?: Encodable;
|
|
19
|
+
readonly retryAfter?: string;
|
|
20
|
+
readonly status: number;
|
|
21
|
+
/**
|
|
22
|
+
* Creates a structured provider error.
|
|
23
|
+
*
|
|
24
|
+
* @param options Error properties.
|
|
25
|
+
* @param options.body Parsed provider response body.
|
|
26
|
+
* @param options.retryAfter Provider retry guidance.
|
|
27
|
+
* @param options.status HTTP status code.
|
|
28
|
+
*/
|
|
29
|
+
constructor(options: {
|
|
30
|
+
body?: Encodable;
|
|
31
|
+
retryAfter?: string;
|
|
32
|
+
status: number;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates an authenticated Kit V4 API client.
|
|
37
|
+
*
|
|
38
|
+
* @param account Resolved Kit account.
|
|
39
|
+
*/
|
|
40
|
+
export declare function getKitApi(account: KitResolvedAccount): {
|
|
41
|
+
/**
|
|
42
|
+
* Executes and validates one named public Kit operation.
|
|
43
|
+
*
|
|
44
|
+
* @param key Public operation name.
|
|
45
|
+
* @param input Flattened operation input.
|
|
46
|
+
*/
|
|
47
|
+
operation<TKey extends KitOperationKey>(key: TKey, input: KitOperationInput<TKey>): Promise<KitOperationOutput<TKey>>;
|
|
48
|
+
/**
|
|
49
|
+
* Sends an internal provider-native request used for managed webhooks.
|
|
50
|
+
*
|
|
51
|
+
* This is not exposed as an automation action.
|
|
52
|
+
*
|
|
53
|
+
* @param path Provider-relative Kit V4 path.
|
|
54
|
+
* @param options Request options.
|
|
55
|
+
*/
|
|
56
|
+
requestJson(path: string, options?: KitRequestOptions): Promise<unknown>;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Encodes every interpolation as one Kit URL path segment.
|
|
60
|
+
*
|
|
61
|
+
* @param strings Template string segments.
|
|
62
|
+
* @param values Interpolated path values.
|
|
63
|
+
*/
|
|
64
|
+
export declare function kitPath(strings: TemplateStringsArray, ...values: (number | string)[]): string;
|
|
65
|
+
/**
|
|
66
|
+
* Converts public camelCase fields to documented Kit wire fields.
|
|
67
|
+
*
|
|
68
|
+
* @param value Public value.
|
|
69
|
+
* @param schema Provider wire schema.
|
|
70
|
+
*/
|
|
71
|
+
export declare function kitPublicToWire(value: unknown, schema: Record<string, unknown>): Encodable;
|
|
72
|
+
/**
|
|
73
|
+
* Converts documented Kit wire fields to public camelCase fields.
|
|
74
|
+
*
|
|
75
|
+
* @param value Provider value.
|
|
76
|
+
* @param schema Provider wire schema.
|
|
77
|
+
*/
|
|
78
|
+
export declare function kitWireToPublic(value: unknown, schema: Record<string, unknown>): Encodable;
|
package/dist/kit/api.js
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import { encodableSchema } from "@automate.ax/codec";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
import { KIT_WIRE_DEFINITIONS, kitOperation, kitOperationOutputSchema, } from "./schemas.js";
|
|
4
|
+
const KIT_API_BASE_URL = "https://api.kit.com/v4/";
|
|
5
|
+
const KIT_API_ORIGIN = new URL(KIT_API_BASE_URL).origin;
|
|
6
|
+
const KIT_API_KEY_SECRET_SCHEMA = z.object({
|
|
7
|
+
apiKey: z.string().trim().min(1),
|
|
8
|
+
});
|
|
9
|
+
const KIT_OAUTH_SECRET_SCHEMA = z.object({
|
|
10
|
+
accessToken: z.string().trim().min(1),
|
|
11
|
+
});
|
|
12
|
+
/** Structured error returned by a rejected Kit request. */
|
|
13
|
+
export class KitApiError extends Error {
|
|
14
|
+
body;
|
|
15
|
+
retryAfter;
|
|
16
|
+
status;
|
|
17
|
+
/**
|
|
18
|
+
* Creates a structured provider error.
|
|
19
|
+
*
|
|
20
|
+
* @param options Error properties.
|
|
21
|
+
* @param options.body Parsed provider response body.
|
|
22
|
+
* @param options.retryAfter Provider retry guidance.
|
|
23
|
+
* @param options.status HTTP status code.
|
|
24
|
+
*/
|
|
25
|
+
constructor(options) {
|
|
26
|
+
super(getErrorMessage(options.body) ??
|
|
27
|
+
`Kit API request failed with status ${options.status}.`);
|
|
28
|
+
this.name = "KitApiError";
|
|
29
|
+
this.body = options.body;
|
|
30
|
+
this.retryAfter = options.retryAfter;
|
|
31
|
+
this.status = options.status;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Creates an authenticated Kit V4 API client.
|
|
36
|
+
*
|
|
37
|
+
* @param account Resolved Kit account.
|
|
38
|
+
*/
|
|
39
|
+
export function getKitApi(account) {
|
|
40
|
+
const authorization = getAuthorization(account);
|
|
41
|
+
return {
|
|
42
|
+
/**
|
|
43
|
+
* Executes and validates one named public Kit operation.
|
|
44
|
+
*
|
|
45
|
+
* @param key Public operation name.
|
|
46
|
+
* @param input Flattened operation input.
|
|
47
|
+
*/
|
|
48
|
+
async operation(key, input) {
|
|
49
|
+
const definition = kitOperation(key);
|
|
50
|
+
const inputRecord = input;
|
|
51
|
+
// Build the path before request assembly so every interpolation is encoded.
|
|
52
|
+
const path = definition.path
|
|
53
|
+
.replace(/^\/v4\//, "")
|
|
54
|
+
.replace(/\{([^}]+)\}/g, (_match, providerName) => {
|
|
55
|
+
const parameter = definition.pathParameters.find((candidate) => candidate.providerName === providerName);
|
|
56
|
+
if (!parameter) {
|
|
57
|
+
throw new TypeError(`Unknown Kit path parameter: ${providerName}`);
|
|
58
|
+
}
|
|
59
|
+
return encodePathSegment(inputRecord[parameter.name], parameter.name);
|
|
60
|
+
});
|
|
61
|
+
// Preserve undefined query fields for the shared serializer to omit.
|
|
62
|
+
const query = Object.fromEntries(definition.queryParameters.map((parameter) => [
|
|
63
|
+
parameter.providerName,
|
|
64
|
+
parseQueryValue(inputRecord[parameter.name]),
|
|
65
|
+
]));
|
|
66
|
+
const body = Object.fromEntries(definition.bodyParameters.flatMap((name) => inputRecord[name] === undefined ? [] : [[name, inputRecord[name]]]));
|
|
67
|
+
const parsed = await sendKitRequest(authorization, path, {
|
|
68
|
+
...(definition.bodyParameters.length > 0 && {
|
|
69
|
+
body: kitPublicToWire(body, definition.bodyWireSchema ?? {}),
|
|
70
|
+
}),
|
|
71
|
+
method: definition.method,
|
|
72
|
+
query,
|
|
73
|
+
});
|
|
74
|
+
// Normalize provider fields before validating the public return type.
|
|
75
|
+
const output = definition.responseMode === "void"
|
|
76
|
+
? {}
|
|
77
|
+
: kitWireToPublic(parsed, definition.outputWireSchema);
|
|
78
|
+
return kitOperationOutputSchema(key).parse(output);
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* Sends an internal provider-native request used for managed webhooks.
|
|
82
|
+
*
|
|
83
|
+
* This is not exposed as an automation action.
|
|
84
|
+
*
|
|
85
|
+
* @param path Provider-relative Kit V4 path.
|
|
86
|
+
* @param options Request options.
|
|
87
|
+
*/
|
|
88
|
+
async requestJson(path, options = {}) {
|
|
89
|
+
return await sendKitRequest(authorization, path, options);
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Encodes every interpolation as one Kit URL path segment.
|
|
95
|
+
*
|
|
96
|
+
* @param strings Template string segments.
|
|
97
|
+
* @param values Interpolated path values.
|
|
98
|
+
*/
|
|
99
|
+
export function kitPath(strings, ...values) {
|
|
100
|
+
return strings.reduce((path, part, index) => `${path}${index === 0 ? "" : encodeURIComponent(String(values[index - 1]))}${part}`, "");
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Converts public camelCase fields to documented Kit wire fields.
|
|
104
|
+
*
|
|
105
|
+
* @param value Public value.
|
|
106
|
+
* @param schema Provider wire schema.
|
|
107
|
+
*/
|
|
108
|
+
export function kitPublicToWire(value, schema) {
|
|
109
|
+
return encodableSchema.parse(transformKitValue(value, schema, "toWire"));
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Converts documented Kit wire fields to public camelCase fields.
|
|
113
|
+
*
|
|
114
|
+
* @param value Provider value.
|
|
115
|
+
* @param schema Provider wire schema.
|
|
116
|
+
*/
|
|
117
|
+
export function kitWireToPublic(value, schema) {
|
|
118
|
+
return encodableSchema.parse(transformKitValue(value, schema, "toPublic"));
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Returns the authorization header for a resolved Kit account.
|
|
122
|
+
*
|
|
123
|
+
* @param account Resolved Kit account.
|
|
124
|
+
* @throws When the connection method is unsupported.
|
|
125
|
+
*/
|
|
126
|
+
function getAuthorization(account) {
|
|
127
|
+
if (account.connectionMethodId === "oauth") {
|
|
128
|
+
return {
|
|
129
|
+
Authorization: `Bearer ${KIT_OAUTH_SECRET_SCHEMA.parse(account.secret).accessToken}`,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (account.connectionMethodId === "api-key") {
|
|
133
|
+
return {
|
|
134
|
+
"X-Kit-Api-Key": KIT_API_KEY_SECRET_SCHEMA.parse(account.secret).apiKey,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
throw new Error(`Unsupported Kit connection method: ${account.connectionMethodId}`);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Sends one guarded request to the Kit V4 API.
|
|
141
|
+
*
|
|
142
|
+
* @param authorization Authentication headers.
|
|
143
|
+
* @param path Provider-relative API path.
|
|
144
|
+
* @param options Request options.
|
|
145
|
+
*/
|
|
146
|
+
async function sendKitRequest(authorization, path, options) {
|
|
147
|
+
const normalizedPath = path.replace(/^\/+/, "");
|
|
148
|
+
const url = new URL(normalizedPath, KIT_API_BASE_URL);
|
|
149
|
+
if (!normalizedPath ||
|
|
150
|
+
normalizedPath.includes("://") ||
|
|
151
|
+
normalizedPath.includes("\\") ||
|
|
152
|
+
normalizedPath.includes("?") ||
|
|
153
|
+
normalizedPath.includes("#") ||
|
|
154
|
+
url.origin !== KIT_API_ORIGIN ||
|
|
155
|
+
!url.pathname.startsWith(new URL(KIT_API_BASE_URL).pathname)) {
|
|
156
|
+
throw new TypeError("Kit API paths must remain provider-relative.");
|
|
157
|
+
}
|
|
158
|
+
for (const [name, value] of Object.entries(options.query ?? {})) {
|
|
159
|
+
appendQuery(url, { explode: true, name, providerName: name, style: "form" }, value);
|
|
160
|
+
}
|
|
161
|
+
const response = await fetch(url, {
|
|
162
|
+
body: options.body === undefined ? undefined : JSON.stringify(options.body),
|
|
163
|
+
headers: {
|
|
164
|
+
Accept: "application/json",
|
|
165
|
+
...authorization,
|
|
166
|
+
...(options.body === undefined
|
|
167
|
+
? {}
|
|
168
|
+
: { "Content-Type": "application/json" }),
|
|
169
|
+
},
|
|
170
|
+
method: options.method ?? "GET",
|
|
171
|
+
redirect: "error",
|
|
172
|
+
});
|
|
173
|
+
const parsed = await parseResponse(response);
|
|
174
|
+
if (!response.ok) {
|
|
175
|
+
const body = encodableSchema.safeParse(parsed);
|
|
176
|
+
throw new KitApiError({
|
|
177
|
+
...(body.success && { body: body.data }),
|
|
178
|
+
retryAfter: response.headers.get("Retry-After") ?? undefined,
|
|
179
|
+
status: response.status,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
return parsed;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Appends one documented query parameter.
|
|
186
|
+
*
|
|
187
|
+
* @param url Mutable request URL.
|
|
188
|
+
* @param parameter Query parameter metadata.
|
|
189
|
+
* @param value Public parameter value.
|
|
190
|
+
*/
|
|
191
|
+
function appendQuery(url, parameter, value) {
|
|
192
|
+
if (value == null)
|
|
193
|
+
return;
|
|
194
|
+
if (Array.isArray(value)) {
|
|
195
|
+
if (parameter.style === "form" && parameter.explode) {
|
|
196
|
+
for (const item of value) {
|
|
197
|
+
url.searchParams.append(parameter.providerName, stringifyQueryValue(item));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
url.searchParams.set(parameter.providerName, value.map(stringifyQueryValue).join(","));
|
|
202
|
+
}
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
url.searchParams.set(parameter.providerName, stringifyQueryValue(value));
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Converts a query value to its wire representation.
|
|
209
|
+
*
|
|
210
|
+
* @param value Public query value.
|
|
211
|
+
* @throws When the value is not scalar.
|
|
212
|
+
*/
|
|
213
|
+
function stringifyQueryValue(value) {
|
|
214
|
+
if (typeof value !== "boolean" &&
|
|
215
|
+
typeof value !== "number" &&
|
|
216
|
+
typeof value !== "string") {
|
|
217
|
+
throw new TypeError("Kit query parameters must be scalar.");
|
|
218
|
+
}
|
|
219
|
+
return String(value);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Validates a flattened action query value.
|
|
223
|
+
*
|
|
224
|
+
* @param value Public action field.
|
|
225
|
+
* @throws When the value is not a scalar or scalar array.
|
|
226
|
+
*/
|
|
227
|
+
function parseQueryValue(value) {
|
|
228
|
+
if (value === null ||
|
|
229
|
+
value === undefined ||
|
|
230
|
+
typeof value === "boolean" ||
|
|
231
|
+
typeof value === "number" ||
|
|
232
|
+
typeof value === "string") {
|
|
233
|
+
return value;
|
|
234
|
+
}
|
|
235
|
+
if (Array.isArray(value) &&
|
|
236
|
+
value.every((item) => typeof item === "boolean" ||
|
|
237
|
+
typeof item === "number" ||
|
|
238
|
+
typeof item === "string")) {
|
|
239
|
+
return value;
|
|
240
|
+
}
|
|
241
|
+
throw new TypeError("Kit query parameters must be scalar or scalar arrays.");
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Encodes one required path parameter.
|
|
245
|
+
*
|
|
246
|
+
* @param value Public path value.
|
|
247
|
+
* @param name Public parameter name.
|
|
248
|
+
* @throws When the path value is missing or invalid.
|
|
249
|
+
*/
|
|
250
|
+
function encodePathSegment(value, name) {
|
|
251
|
+
if (typeof value !== "number" && typeof value !== "string") {
|
|
252
|
+
throw new TypeError(`Kit path parameter ${name} is required.`);
|
|
253
|
+
}
|
|
254
|
+
return encodeURIComponent(String(value));
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Recursively maps Kit fields between public and wire names.
|
|
258
|
+
*
|
|
259
|
+
* @param value Value to transform.
|
|
260
|
+
* @param schema Provider wire schema.
|
|
261
|
+
* @param direction Mapping direction.
|
|
262
|
+
*/
|
|
263
|
+
function transformKitValue(value, schema, direction) {
|
|
264
|
+
const resolved = resolveWireSchema(schema);
|
|
265
|
+
if (Array.isArray(value)) {
|
|
266
|
+
const itemSchema = isRecord(resolved.items) ? resolved.items : {};
|
|
267
|
+
return value.map((item) => transformKitValue(item, itemSchema, direction));
|
|
268
|
+
}
|
|
269
|
+
if (!isRecord(value))
|
|
270
|
+
return value;
|
|
271
|
+
const properties = collectWireProperties(resolved);
|
|
272
|
+
return Object.fromEntries(Object.entries(value).map(([name, item]) => {
|
|
273
|
+
const providerName = direction === "toPublic"
|
|
274
|
+
? name
|
|
275
|
+
: (Object.keys(properties).find((candidate) => camelCase(candidate) === name) ?? name);
|
|
276
|
+
const publicName = direction === "toPublic" && providerName in properties
|
|
277
|
+
? camelCase(providerName)
|
|
278
|
+
: name;
|
|
279
|
+
const childSchemas = propertySchemas(resolved, providerName);
|
|
280
|
+
// Combine alternate provider shapes before recursively mapping nested keys.
|
|
281
|
+
const childSchema = childSchemas.length === 0
|
|
282
|
+
? {}
|
|
283
|
+
: childSchemas.length === 1
|
|
284
|
+
? (childSchemas[0] ?? {})
|
|
285
|
+
: { anyOf: childSchemas };
|
|
286
|
+
return [
|
|
287
|
+
direction === "toPublic" ? publicName : providerName,
|
|
288
|
+
transformKitValue(item, childSchema, direction),
|
|
289
|
+
];
|
|
290
|
+
}));
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Collects schema properties across composition branches.
|
|
294
|
+
*
|
|
295
|
+
* @param schema Provider wire schema.
|
|
296
|
+
*/
|
|
297
|
+
function collectWireProperties(schema) {
|
|
298
|
+
const resolved = resolveWireSchema(schema);
|
|
299
|
+
const properties = {};
|
|
300
|
+
return Object.assign(properties, isRecord(resolved.properties) ? resolved.properties : {}, ...schemaBranches(resolved).map(collectWireProperties));
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Finds every schema declared for one provider field.
|
|
304
|
+
*
|
|
305
|
+
* @param schema Provider wire schema.
|
|
306
|
+
* @param providerName Provider field name.
|
|
307
|
+
*/
|
|
308
|
+
function propertySchemas(schema, providerName) {
|
|
309
|
+
const resolved = resolveWireSchema(schema);
|
|
310
|
+
// Inspect the direct declaration before recursively visiting composed branches.
|
|
311
|
+
const direct = isRecord(resolved.properties) && isRecord(resolved.properties[providerName])
|
|
312
|
+
? [resolved.properties[providerName]]
|
|
313
|
+
: [];
|
|
314
|
+
return [
|
|
315
|
+
...direct,
|
|
316
|
+
...schemaBranches(resolved).flatMap((branch) => propertySchemas(branch, providerName)),
|
|
317
|
+
];
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Returns all composed schema branches.
|
|
321
|
+
*
|
|
322
|
+
* @param schema Provider wire schema.
|
|
323
|
+
*/
|
|
324
|
+
function schemaBranches(schema) {
|
|
325
|
+
return ["allOf", "anyOf", "oneOf"].flatMap((keyword) => Array.isArray(schema[keyword]) ? schema[keyword].filter(isRecord) : []);
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Resolves a top-level provider component reference.
|
|
329
|
+
*
|
|
330
|
+
* @param schema Provider wire schema.
|
|
331
|
+
*/
|
|
332
|
+
function resolveWireSchema(schema) {
|
|
333
|
+
if (typeof schema.$ref !== "string")
|
|
334
|
+
return schema;
|
|
335
|
+
const name = /^#\/components\/schemas\/(.+)$/.exec(schema.$ref)?.[1];
|
|
336
|
+
return name ? (KIT_WIRE_DEFINITIONS[name] ?? schema) : schema;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Parses a provider response without assuming JSON on errors.
|
|
340
|
+
*
|
|
341
|
+
* @param response Provider response.
|
|
342
|
+
*/
|
|
343
|
+
async function parseResponse(response) {
|
|
344
|
+
const text = await response.text();
|
|
345
|
+
if (!text)
|
|
346
|
+
return {};
|
|
347
|
+
try {
|
|
348
|
+
return JSON.parse(text);
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
return { response: text };
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Extracts Kit's documented error messages.
|
|
356
|
+
*
|
|
357
|
+
* @param value Parsed provider response.
|
|
358
|
+
*/
|
|
359
|
+
function getErrorMessage(value) {
|
|
360
|
+
if (!isRecord(value))
|
|
361
|
+
return undefined;
|
|
362
|
+
if (Array.isArray(value.errors)) {
|
|
363
|
+
const messages = value.errors.filter((item) => typeof item === "string" && item.length > 0);
|
|
364
|
+
if (messages.length > 0)
|
|
365
|
+
return messages.join("; ");
|
|
366
|
+
}
|
|
367
|
+
return typeof value.message === "string" && value.message
|
|
368
|
+
? value.message
|
|
369
|
+
: undefined;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Converts one provider snake_case field name to camelCase.
|
|
373
|
+
*
|
|
374
|
+
* @param value Provider field name.
|
|
375
|
+
*/
|
|
376
|
+
function camelCase(value) {
|
|
377
|
+
return value.replace(/_([a-z\d])/g, (_match, letter) => letter.toUpperCase());
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Narrows an unknown value to a record.
|
|
381
|
+
*
|
|
382
|
+
* @param value Candidate object.
|
|
383
|
+
*/
|
|
384
|
+
function isRecord(value) {
|
|
385
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
386
|
+
}
|