@automate.ax/integration-contracts 0.124.0 → 0.126.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/apify/index.d.ts +1085 -0
- package/dist/apify/index.js +169 -0
- package/dist/apify/schemas.d.ts +100 -0
- package/dist/apify/schemas.js +203 -0
- package/dist/linear/schemas.d.ts +8 -8
- package/dist/notion/schemas.d.ts +33 -33
- package/dist/reddit/api.d.ts +56 -0
- package/dist/reddit/api.js +135 -0
- package/dist/reddit/events.d.ts +439 -0
- package/dist/reddit/events.js +53 -0
- package/dist/reddit/index.d.ts +3 -0
- package/dist/reddit/index.js +3 -0
- package/dist/reddit/schemas.d.ts +816 -0
- package/dist/reddit/schemas.js +398 -0
- package/dist/triggers.d.ts +3 -1
- package/dist/vercel/index.d.ts +16 -16
- package/dist/vercel/schemas.d.ts +24 -24
- package/package.json +14 -2
- package/src/apify/index.ts +210 -0
- package/src/apify/schemas.ts +214 -0
- package/src/reddit/api.ts +183 -0
- package/src/reddit/events.ts +68 -0
- package/src/reddit/index.ts +3 -0
- package/src/reddit/schemas.ts +442 -0
- package/src/triggers.ts +4 -0
package/dist/notion/schemas.d.ts
CHANGED
|
@@ -1419,8 +1419,8 @@ declare const RAW_NOTION_EVENT_SCHEMA: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1419
1419
|
}>;
|
|
1420
1420
|
}, z.core.$strip>;
|
|
1421
1421
|
updated_fields: z.ZodArray<z.ZodEnum<{
|
|
1422
|
-
name: "name";
|
|
1423
1422
|
filter: "filter";
|
|
1423
|
+
name: "name";
|
|
1424
1424
|
sorts: "sorts";
|
|
1425
1425
|
configuration: "configuration";
|
|
1426
1426
|
}>>;
|
|
@@ -2877,8 +2877,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
2877
2877
|
}>;
|
|
2878
2878
|
}, z.core.$strip>;
|
|
2879
2879
|
updated_fields: z.ZodArray<z.ZodEnum<{
|
|
2880
|
-
name: "name";
|
|
2881
2880
|
filter: "filter";
|
|
2881
|
+
name: "name";
|
|
2882
2882
|
sorts: "sorts";
|
|
2883
2883
|
configuration: "configuration";
|
|
2884
2884
|
}>>;
|
|
@@ -2919,8 +2919,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
2919
2919
|
workspace_name: z.ZodString;
|
|
2920
2920
|
}, z.core.$catchall<z.ZodJSONSchema>>], "type">, z.ZodTransform<{
|
|
2921
2921
|
type: "comment.created";
|
|
2922
|
-
timestamp: string;
|
|
2923
2922
|
id: string;
|
|
2923
|
+
timestamp: string;
|
|
2924
2924
|
data: {
|
|
2925
2925
|
parent: {
|
|
2926
2926
|
id: string;
|
|
@@ -2951,8 +2951,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
2951
2951
|
}[];
|
|
2952
2952
|
} | {
|
|
2953
2953
|
type: "comment.deleted";
|
|
2954
|
-
timestamp: string;
|
|
2955
2954
|
id: string;
|
|
2955
|
+
timestamp: string;
|
|
2956
2956
|
data: {
|
|
2957
2957
|
parent: {
|
|
2958
2958
|
id: string;
|
|
@@ -2983,8 +2983,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
2983
2983
|
}[];
|
|
2984
2984
|
} | {
|
|
2985
2985
|
type: "comment.updated";
|
|
2986
|
-
timestamp: string;
|
|
2987
2986
|
id: string;
|
|
2987
|
+
timestamp: string;
|
|
2988
2988
|
data: {
|
|
2989
2989
|
parent: {
|
|
2990
2990
|
id: string;
|
|
@@ -3015,8 +3015,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3015
3015
|
}[];
|
|
3016
3016
|
} | {
|
|
3017
3017
|
type: "data_source.content_updated";
|
|
3018
|
-
timestamp: string;
|
|
3019
3018
|
id: string;
|
|
3019
|
+
timestamp: string;
|
|
3020
3020
|
data: {
|
|
3021
3021
|
parent: {
|
|
3022
3022
|
id: string;
|
|
@@ -3051,8 +3051,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3051
3051
|
}[];
|
|
3052
3052
|
} | {
|
|
3053
3053
|
type: "data_source.created";
|
|
3054
|
-
timestamp: string;
|
|
3055
3054
|
id: string;
|
|
3055
|
+
timestamp: string;
|
|
3056
3056
|
data: {
|
|
3057
3057
|
parent: {
|
|
3058
3058
|
id: string;
|
|
@@ -3083,8 +3083,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3083
3083
|
}[];
|
|
3084
3084
|
} | {
|
|
3085
3085
|
type: "data_source.deleted";
|
|
3086
|
-
timestamp: string;
|
|
3087
3086
|
id: string;
|
|
3087
|
+
timestamp: string;
|
|
3088
3088
|
data: {
|
|
3089
3089
|
parent: {
|
|
3090
3090
|
id: string;
|
|
@@ -3115,8 +3115,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3115
3115
|
}[];
|
|
3116
3116
|
} | {
|
|
3117
3117
|
type: "data_source.moved";
|
|
3118
|
-
timestamp: string;
|
|
3119
3118
|
id: string;
|
|
3119
|
+
timestamp: string;
|
|
3120
3120
|
data: {
|
|
3121
3121
|
parent: {
|
|
3122
3122
|
id: string;
|
|
@@ -3147,8 +3147,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3147
3147
|
}[];
|
|
3148
3148
|
} | {
|
|
3149
3149
|
type: "data_source.schema_updated";
|
|
3150
|
-
timestamp: string;
|
|
3151
3150
|
id: string;
|
|
3151
|
+
timestamp: string;
|
|
3152
3152
|
data: {
|
|
3153
3153
|
parent: {
|
|
3154
3154
|
id: string;
|
|
@@ -3184,8 +3184,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3184
3184
|
}[];
|
|
3185
3185
|
} | {
|
|
3186
3186
|
type: "data_source.undeleted";
|
|
3187
|
-
timestamp: string;
|
|
3188
3187
|
id: string;
|
|
3188
|
+
timestamp: string;
|
|
3189
3189
|
data: {
|
|
3190
3190
|
parent: {
|
|
3191
3191
|
id: string;
|
|
@@ -3216,8 +3216,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3216
3216
|
}[];
|
|
3217
3217
|
} | {
|
|
3218
3218
|
type: "database.created";
|
|
3219
|
-
timestamp: string;
|
|
3220
3219
|
id: string;
|
|
3220
|
+
timestamp: string;
|
|
3221
3221
|
data: {
|
|
3222
3222
|
parent: {
|
|
3223
3223
|
id: string;
|
|
@@ -3248,8 +3248,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3248
3248
|
}[];
|
|
3249
3249
|
} | {
|
|
3250
3250
|
type: "database.deleted";
|
|
3251
|
-
timestamp: string;
|
|
3252
3251
|
id: string;
|
|
3252
|
+
timestamp: string;
|
|
3253
3253
|
data: {
|
|
3254
3254
|
parent: {
|
|
3255
3255
|
id: string;
|
|
@@ -3280,8 +3280,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3280
3280
|
}[];
|
|
3281
3281
|
} | {
|
|
3282
3282
|
type: "database.moved";
|
|
3283
|
-
timestamp: string;
|
|
3284
3283
|
id: string;
|
|
3284
|
+
timestamp: string;
|
|
3285
3285
|
data: {
|
|
3286
3286
|
parent: {
|
|
3287
3287
|
id: string;
|
|
@@ -3312,8 +3312,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3312
3312
|
}[];
|
|
3313
3313
|
} | {
|
|
3314
3314
|
type: "database.undeleted";
|
|
3315
|
-
timestamp: string;
|
|
3316
3315
|
id: string;
|
|
3316
|
+
timestamp: string;
|
|
3317
3317
|
data: {
|
|
3318
3318
|
parent: {
|
|
3319
3319
|
id: string;
|
|
@@ -3344,8 +3344,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3344
3344
|
}[];
|
|
3345
3345
|
} | {
|
|
3346
3346
|
type: "file_upload.completed";
|
|
3347
|
-
timestamp: string;
|
|
3348
3347
|
id: string;
|
|
3348
|
+
timestamp: string;
|
|
3349
3349
|
workspaceId: string;
|
|
3350
3350
|
workspaceName: string;
|
|
3351
3351
|
subscriptionId: string;
|
|
@@ -3369,8 +3369,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3369
3369
|
}[];
|
|
3370
3370
|
} | {
|
|
3371
3371
|
type: "file_upload.created";
|
|
3372
|
-
timestamp: string;
|
|
3373
3372
|
id: string;
|
|
3373
|
+
timestamp: string;
|
|
3374
3374
|
workspaceId: string;
|
|
3375
3375
|
workspaceName: string;
|
|
3376
3376
|
subscriptionId: string;
|
|
@@ -3394,8 +3394,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3394
3394
|
}[];
|
|
3395
3395
|
} | {
|
|
3396
3396
|
type: "file_upload.expired";
|
|
3397
|
-
timestamp: string;
|
|
3398
3397
|
id: string;
|
|
3398
|
+
timestamp: string;
|
|
3399
3399
|
workspaceId: string;
|
|
3400
3400
|
workspaceName: string;
|
|
3401
3401
|
subscriptionId: string;
|
|
@@ -3419,8 +3419,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3419
3419
|
}[];
|
|
3420
3420
|
} | {
|
|
3421
3421
|
type: "file_upload.upload_failed";
|
|
3422
|
-
timestamp: string;
|
|
3423
3422
|
id: string;
|
|
3423
|
+
timestamp: string;
|
|
3424
3424
|
data: {
|
|
3425
3425
|
fileImportResult: {
|
|
3426
3426
|
type: "success";
|
|
@@ -3463,8 +3463,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3463
3463
|
}[];
|
|
3464
3464
|
} | {
|
|
3465
3465
|
type: "page.content_updated";
|
|
3466
|
-
timestamp: string;
|
|
3467
3466
|
id: string;
|
|
3467
|
+
timestamp: string;
|
|
3468
3468
|
data: {
|
|
3469
3469
|
parent: {
|
|
3470
3470
|
id: string;
|
|
@@ -3499,8 +3499,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3499
3499
|
}[];
|
|
3500
3500
|
} | {
|
|
3501
3501
|
type: "page.created";
|
|
3502
|
-
timestamp: string;
|
|
3503
3502
|
id: string;
|
|
3503
|
+
timestamp: string;
|
|
3504
3504
|
data: {
|
|
3505
3505
|
parent: {
|
|
3506
3506
|
id: string;
|
|
@@ -3531,8 +3531,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3531
3531
|
}[];
|
|
3532
3532
|
} | {
|
|
3533
3533
|
type: "page.deleted";
|
|
3534
|
-
timestamp: string;
|
|
3535
3534
|
id: string;
|
|
3535
|
+
timestamp: string;
|
|
3536
3536
|
data: {
|
|
3537
3537
|
parent: {
|
|
3538
3538
|
id: string;
|
|
@@ -3563,8 +3563,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3563
3563
|
}[];
|
|
3564
3564
|
} | {
|
|
3565
3565
|
type: "page.locked";
|
|
3566
|
-
timestamp: string;
|
|
3567
3566
|
id: string;
|
|
3567
|
+
timestamp: string;
|
|
3568
3568
|
data: {
|
|
3569
3569
|
parent: {
|
|
3570
3570
|
id: string;
|
|
@@ -3595,8 +3595,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3595
3595
|
}[];
|
|
3596
3596
|
} | {
|
|
3597
3597
|
type: "page.moved";
|
|
3598
|
-
timestamp: string;
|
|
3599
3598
|
id: string;
|
|
3599
|
+
timestamp: string;
|
|
3600
3600
|
data: {
|
|
3601
3601
|
parent: {
|
|
3602
3602
|
id: string;
|
|
@@ -3627,8 +3627,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3627
3627
|
}[];
|
|
3628
3628
|
} | {
|
|
3629
3629
|
type: "page.properties_updated";
|
|
3630
|
-
timestamp: string;
|
|
3631
3630
|
id: string;
|
|
3631
|
+
timestamp: string;
|
|
3632
3632
|
data: {
|
|
3633
3633
|
parent: {
|
|
3634
3634
|
id: string;
|
|
@@ -3660,8 +3660,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3660
3660
|
}[];
|
|
3661
3661
|
} | {
|
|
3662
3662
|
type: "page.transcription_block.transcript_deleted";
|
|
3663
|
-
timestamp: string;
|
|
3664
3663
|
id: string;
|
|
3664
|
+
timestamp: string;
|
|
3665
3665
|
data: {
|
|
3666
3666
|
target: {
|
|
3667
3667
|
id: string;
|
|
@@ -3692,8 +3692,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3692
3692
|
}[];
|
|
3693
3693
|
} | {
|
|
3694
3694
|
type: "page.undeleted";
|
|
3695
|
-
timestamp: string;
|
|
3696
3695
|
id: string;
|
|
3696
|
+
timestamp: string;
|
|
3697
3697
|
data: {
|
|
3698
3698
|
parent: {
|
|
3699
3699
|
id: string;
|
|
@@ -3724,8 +3724,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3724
3724
|
}[];
|
|
3725
3725
|
} | {
|
|
3726
3726
|
type: "page.unlocked";
|
|
3727
|
-
timestamp: string;
|
|
3728
3727
|
id: string;
|
|
3728
|
+
timestamp: string;
|
|
3729
3729
|
data: {
|
|
3730
3730
|
parent: {
|
|
3731
3731
|
id: string;
|
|
@@ -3756,8 +3756,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3756
3756
|
}[];
|
|
3757
3757
|
} | {
|
|
3758
3758
|
type: "view.created";
|
|
3759
|
-
timestamp: string;
|
|
3760
3759
|
id: string;
|
|
3760
|
+
timestamp: string;
|
|
3761
3761
|
data: {
|
|
3762
3762
|
parent: {
|
|
3763
3763
|
id: string;
|
|
@@ -3789,8 +3789,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3789
3789
|
}[];
|
|
3790
3790
|
} | {
|
|
3791
3791
|
type: "view.deleted";
|
|
3792
|
-
timestamp: string;
|
|
3793
3792
|
id: string;
|
|
3793
|
+
timestamp: string;
|
|
3794
3794
|
data: {
|
|
3795
3795
|
parent: {
|
|
3796
3796
|
id: string;
|
|
@@ -3821,15 +3821,15 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3821
3821
|
}[];
|
|
3822
3822
|
} | {
|
|
3823
3823
|
type: "view.updated";
|
|
3824
|
-
timestamp: string;
|
|
3825
3824
|
id: string;
|
|
3825
|
+
timestamp: string;
|
|
3826
3826
|
data: {
|
|
3827
3827
|
parent: {
|
|
3828
3828
|
id: string;
|
|
3829
3829
|
type: "team" | "page" | "space" | "agent" | "block" | "database";
|
|
3830
3830
|
dataSourceId?: string | undefined;
|
|
3831
3831
|
};
|
|
3832
|
-
updatedFields: ("
|
|
3832
|
+
updatedFields: ("filter" | "name" | "sorts" | "configuration")[];
|
|
3833
3833
|
};
|
|
3834
3834
|
workspaceId: string;
|
|
3835
3835
|
workspaceName: string;
|
|
@@ -4956,7 +4956,7 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
4956
4956
|
type: "team" | "page" | "space" | "agent" | "block" | "database";
|
|
4957
4957
|
data_source_id?: string | undefined;
|
|
4958
4958
|
};
|
|
4959
|
-
updated_fields: ("
|
|
4959
|
+
updated_fields: ("filter" | "name" | "sorts" | "configuration")[];
|
|
4960
4960
|
};
|
|
4961
4961
|
entity: {
|
|
4962
4962
|
id: string;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
export declare const REDDIT_OAUTH_SECRET_SCHEMA: z.ZodObject<{
|
|
3
|
+
accessToken: z.ZodString;
|
|
4
|
+
expiresAt: z.ZodNumber;
|
|
5
|
+
refreshToken: z.ZodString;
|
|
6
|
+
tokenType: z.ZodString;
|
|
7
|
+
userAgent: z.ZodString;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
export declare const REDDIT_ERROR_TUPLE_SCHEMA: z.ZodTuple<[z.ZodString, z.ZodString, z.ZodNullable<z.ZodString>], null>;
|
|
10
|
+
export declare const REDDIT_JSON_STATUS_SCHEMA: z.ZodObject<{
|
|
11
|
+
json: z.ZodObject<{
|
|
12
|
+
errors: z.ZodArray<z.ZodTuple<[z.ZodString, z.ZodString, z.ZodNullable<z.ZodString>], null>>;
|
|
13
|
+
}, z.core.$strip>;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
export interface RedditRequestOptions<TSchema extends z.ZodType> {
|
|
16
|
+
body?: Record<string, boolean | number | string | undefined>;
|
|
17
|
+
method?: "DELETE" | "GET" | "POST" | "PUT";
|
|
18
|
+
query?: Record<string, boolean | number | string | readonly string[] | null | undefined>;
|
|
19
|
+
responseSchema: TSchema;
|
|
20
|
+
}
|
|
21
|
+
/** Error returned by a rejected Reddit Data API request. */
|
|
22
|
+
export declare class RedditApiError extends Error {
|
|
23
|
+
readonly details: {
|
|
24
|
+
error?: number;
|
|
25
|
+
message?: string;
|
|
26
|
+
reason?: string;
|
|
27
|
+
} | {
|
|
28
|
+
errors: [string, string, null | string][];
|
|
29
|
+
} | {
|
|
30
|
+
response: string;
|
|
31
|
+
};
|
|
32
|
+
readonly retryAfter?: string;
|
|
33
|
+
readonly status: number;
|
|
34
|
+
/**
|
|
35
|
+
* Creates an error from a rejected Reddit response.
|
|
36
|
+
*
|
|
37
|
+
* @param status - HTTP response status.
|
|
38
|
+
* @param details - Parsed Reddit failure details.
|
|
39
|
+
* @param retryAfter - Provider retry delay in seconds, when present.
|
|
40
|
+
*/
|
|
41
|
+
constructor(status: number, details: RedditApiError["details"], retryAfter?: string);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Creates an authenticated Reddit Data API client.
|
|
45
|
+
*
|
|
46
|
+
* @param secret - Stored Reddit OAuth credentials and registered User-Agent.
|
|
47
|
+
*/
|
|
48
|
+
export declare function getRedditApi(secret: unknown): {
|
|
49
|
+
/**
|
|
50
|
+
* Sends one request below Reddit's OAuth API origin.
|
|
51
|
+
*
|
|
52
|
+
* @param path - Relative Reddit API path.
|
|
53
|
+
* @param options - Request method, parameters, and response contract.
|
|
54
|
+
*/
|
|
55
|
+
request<TSchema extends z.ZodType>(path: string, options: RedditRequestOptions<TSchema>): Promise<z.output<TSchema>>;
|
|
56
|
+
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
const REDDIT_API_ORIGIN = "https://oauth.reddit.com/";
|
|
3
|
+
const REDDIT_API_URL = new URL(REDDIT_API_ORIGIN);
|
|
4
|
+
export const REDDIT_OAUTH_SECRET_SCHEMA = z.object({
|
|
5
|
+
accessToken: z.string().min(1),
|
|
6
|
+
expiresAt: z.number().int().positive(),
|
|
7
|
+
refreshToken: z.string().min(1),
|
|
8
|
+
tokenType: z.string().min(1),
|
|
9
|
+
userAgent: z.string().min(1),
|
|
10
|
+
});
|
|
11
|
+
const REDDIT_API_ERROR_SCHEMA = z.looseObject({
|
|
12
|
+
error: z.number().int().optional(),
|
|
13
|
+
message: z.string().optional(),
|
|
14
|
+
reason: z.string().optional(),
|
|
15
|
+
});
|
|
16
|
+
export const REDDIT_ERROR_TUPLE_SCHEMA = z.tuple([
|
|
17
|
+
z.string(),
|
|
18
|
+
z.string(),
|
|
19
|
+
z.string().nullable(),
|
|
20
|
+
]);
|
|
21
|
+
const REDDIT_JSON_ERRORS_SCHEMA = z.looseObject({
|
|
22
|
+
json: z.object({
|
|
23
|
+
errors: REDDIT_ERROR_TUPLE_SCHEMA.array(),
|
|
24
|
+
}),
|
|
25
|
+
});
|
|
26
|
+
export const REDDIT_JSON_STATUS_SCHEMA = z.object({
|
|
27
|
+
json: z.object({ errors: REDDIT_ERROR_TUPLE_SCHEMA.array() }),
|
|
28
|
+
});
|
|
29
|
+
/** Error returned by a rejected Reddit Data API request. */
|
|
30
|
+
export class RedditApiError extends Error {
|
|
31
|
+
details;
|
|
32
|
+
retryAfter;
|
|
33
|
+
status;
|
|
34
|
+
/**
|
|
35
|
+
* Creates an error from a rejected Reddit response.
|
|
36
|
+
*
|
|
37
|
+
* @param status - HTTP response status.
|
|
38
|
+
* @param details - Parsed Reddit failure details.
|
|
39
|
+
* @param retryAfter - Provider retry delay in seconds, when present.
|
|
40
|
+
*/
|
|
41
|
+
constructor(status, details, retryAfter) {
|
|
42
|
+
const jsonError = "errors" in details ? details.errors[0]?.[1] : undefined;
|
|
43
|
+
super(("message" in details
|
|
44
|
+
? (details.message ?? details.reason)
|
|
45
|
+
: undefined) ??
|
|
46
|
+
jsonError ??
|
|
47
|
+
`Reddit API request failed (${status}).`);
|
|
48
|
+
this.name = "RedditApiError";
|
|
49
|
+
this.details = details;
|
|
50
|
+
this.retryAfter = retryAfter;
|
|
51
|
+
this.status = status;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Creates an authenticated Reddit Data API client.
|
|
56
|
+
*
|
|
57
|
+
* @param secret - Stored Reddit OAuth credentials and registered User-Agent.
|
|
58
|
+
*/
|
|
59
|
+
export function getRedditApi(secret) {
|
|
60
|
+
const credentials = REDDIT_OAUTH_SECRET_SCHEMA.parse(secret);
|
|
61
|
+
return {
|
|
62
|
+
/**
|
|
63
|
+
* Sends one request below Reddit's OAuth API origin.
|
|
64
|
+
*
|
|
65
|
+
* @param path - Relative Reddit API path.
|
|
66
|
+
* @param options - Request method, parameters, and response contract.
|
|
67
|
+
*/
|
|
68
|
+
async request(path, options) {
|
|
69
|
+
const normalizedPath = path.replace(/^\/+/, "");
|
|
70
|
+
if (!normalizedPath ||
|
|
71
|
+
normalizedPath.includes("://") ||
|
|
72
|
+
normalizedPath.includes("\\")) {
|
|
73
|
+
throw new TypeError("Reddit API paths must be relative.");
|
|
74
|
+
}
|
|
75
|
+
const url = new URL(normalizedPath, REDDIT_API_ORIGIN);
|
|
76
|
+
if (url.origin !== REDDIT_API_URL.origin) {
|
|
77
|
+
throw new TypeError("Reddit API paths must remain on oauth.reddit.com.");
|
|
78
|
+
}
|
|
79
|
+
url.searchParams.set("raw_json", "1");
|
|
80
|
+
for (const [key, value] of Object.entries(options.query ?? {})) {
|
|
81
|
+
if (value == null)
|
|
82
|
+
continue;
|
|
83
|
+
url.searchParams.set(key, Array.isArray(value) ? value.join(",") : String(value));
|
|
84
|
+
}
|
|
85
|
+
const headers = new Headers({
|
|
86
|
+
Accept: "application/json",
|
|
87
|
+
Authorization: `${credentials.tokenType} ${credentials.accessToken}`,
|
|
88
|
+
"User-Agent": credentials.userAgent,
|
|
89
|
+
});
|
|
90
|
+
const body = options.body
|
|
91
|
+
? new URLSearchParams(Object.entries(options.body).flatMap(([key, value]) => value === undefined
|
|
92
|
+
? []
|
|
93
|
+
: [[key, String(value)]]))
|
|
94
|
+
: undefined;
|
|
95
|
+
if (body) {
|
|
96
|
+
headers.set("Content-Type", "application/x-www-form-urlencoded");
|
|
97
|
+
}
|
|
98
|
+
const response = await fetch(url, {
|
|
99
|
+
body,
|
|
100
|
+
headers,
|
|
101
|
+
method: options.method ?? "GET",
|
|
102
|
+
});
|
|
103
|
+
const text = await response.text();
|
|
104
|
+
const parsed = parseJson(text);
|
|
105
|
+
const jsonErrors = REDDIT_JSON_ERRORS_SCHEMA.safeParse(parsed);
|
|
106
|
+
const retryAfter = response.headers.get("Retry-After") ??
|
|
107
|
+
response.headers.get("X-Ratelimit-Reset") ??
|
|
108
|
+
undefined;
|
|
109
|
+
if (jsonErrors.success && jsonErrors.data.json.errors.length > 0) {
|
|
110
|
+
throw new RedditApiError(response.ok ? 400 : response.status, { errors: jsonErrors.data.json.errors }, retryAfter);
|
|
111
|
+
}
|
|
112
|
+
if (!response.ok) {
|
|
113
|
+
const error = REDDIT_API_ERROR_SCHEMA.safeParse(parsed);
|
|
114
|
+
throw new RedditApiError(response.status, error.success ? error.data : { response: text }, retryAfter);
|
|
115
|
+
}
|
|
116
|
+
const result = options.responseSchema.safeParse(parsed);
|
|
117
|
+
if (!result.success) {
|
|
118
|
+
throw new RedditApiError(response.status, { response: text });
|
|
119
|
+
}
|
|
120
|
+
return result.data;
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/** Parses a provider body while preserving non-JSON failure text. */
|
|
125
|
+
/** @param value - Raw provider response body. */
|
|
126
|
+
function parseJson(value) {
|
|
127
|
+
if (!value)
|
|
128
|
+
return undefined;
|
|
129
|
+
try {
|
|
130
|
+
return JSON.parse(value);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return value;
|
|
134
|
+
}
|
|
135
|
+
}
|