@freqhole/api-client 0.1.30
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/auth-test.html +651 -0
- package/package.json +42 -0
- package/src/AdminClient.ts +154 -0
- package/src/CharnelLocalTransport.ts +598 -0
- package/src/CharnelTransport.ts +616 -0
- package/src/FreqholeClient.ts +261 -0
- package/src/WasmTransport.ts +1077 -0
- package/src/automerge/IrohNetworkAdapter.ts +727 -0
- package/src/automerge/index.ts +14 -0
- package/src/codegen/admin_commands.ts +61 -0
- package/src/codegen/routes.ts +213 -0
- package/src/codegen/schema.ts +6721 -0
- package/src/domains/admin.ts +97 -0
- package/src/domains/app.ts +98 -0
- package/src/domains/auth.ts +191 -0
- package/src/domains/favorites.types.ts +52 -0
- package/src/domains/jobs.ts +48 -0
- package/src/domains/music.ts +1935 -0
- package/src/domains/types.ts +19 -0
- package/src/domains/upload.ts +214 -0
- package/src/index.ts +48 -0
- package/src/permissions.ts +468 -0
- package/src/playlistz/convert.ts +267 -0
- package/src/playlistz/index.ts +6 -0
- package/src/playlistz/mutations.ts +181 -0
- package/src/playlistz/protocol.ts +222 -0
- package/src/playlistz/schema.ts +138 -0
- package/src/playlistz/shareLink.ts +76 -0
- package/src/storage/blobs.ts +272 -0
- package/src/storage/identity.ts +190 -0
- package/src/storage/index.ts +5 -0
- package/src/storage/webLocks.ts +92 -0
- package/src/test/automerge.ts +796 -0
- package/src/test/coverage.ts +105 -0
- package/src/test/fixtures.ts +460 -0
- package/src/test/integration.ts +320 -0
- package/src/test/playlistz.ts +631 -0
- package/src/test/stateful.ts +561 -0
- package/src/test/storage.ts +443 -0
- package/src/test.ts +75 -0
- package/src/transport.ts +391 -0
- package/src/utils.ts +79 -0
- package/src/webauthn.ts +228 -0
- package/tsconfig.json +22 -0
- package/vite.config.js +9 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// admin domain methods for FreqholeClient
|
|
2
|
+
// includes knock management endpoints
|
|
3
|
+
|
|
4
|
+
import { routes } from "../codegen/routes.js";
|
|
5
|
+
import type * as s from "../codegen/schema.js";
|
|
6
|
+
import type { CallFn } from "./types.js";
|
|
7
|
+
|
|
8
|
+
export function createAdminMethods(call: CallFn) {
|
|
9
|
+
return {
|
|
10
|
+
// knock management (admin)
|
|
11
|
+
listKnocks: () => {
|
|
12
|
+
return call(
|
|
13
|
+
"admin", "list_knocks",
|
|
14
|
+
routes.admin.list_knocks.resp,
|
|
15
|
+
routes.admin.list_knocks.req,
|
|
16
|
+
routes.admin.list_knocks.method,
|
|
17
|
+
routes.admin.list_knocks.path,
|
|
18
|
+
);
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
listAllKnocks: () => {
|
|
22
|
+
return call(
|
|
23
|
+
"admin", "list_all_knocks",
|
|
24
|
+
routes.admin.list_all_knocks.resp,
|
|
25
|
+
routes.admin.list_all_knocks.req,
|
|
26
|
+
routes.admin.list_all_knocks.method,
|
|
27
|
+
routes.admin.list_all_knocks.path,
|
|
28
|
+
);
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
getKnock: (params: { id: string }) => {
|
|
32
|
+
return call(
|
|
33
|
+
"admin", "get_knock",
|
|
34
|
+
routes.admin.get_knock.resp,
|
|
35
|
+
routes.admin.get_knock.req,
|
|
36
|
+
routes.admin.get_knock.method,
|
|
37
|
+
routes.admin.get_knock.path,
|
|
38
|
+
params,
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
acceptKnock: (params: { id: string } & s.ProcessKnockRequest) => {
|
|
43
|
+
return call(
|
|
44
|
+
"admin", "accept_knock",
|
|
45
|
+
routes.admin.accept_knock.resp,
|
|
46
|
+
routes.admin.accept_knock.req,
|
|
47
|
+
routes.admin.accept_knock.method,
|
|
48
|
+
routes.admin.accept_knock.path,
|
|
49
|
+
params,
|
|
50
|
+
);
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
rejectKnock: (params: { id: string }) => {
|
|
54
|
+
return call(
|
|
55
|
+
"admin", "reject_knock",
|
|
56
|
+
routes.admin.reject_knock.resp,
|
|
57
|
+
routes.admin.reject_knock.req,
|
|
58
|
+
routes.admin.reject_knock.method,
|
|
59
|
+
routes.admin.reject_knock.path,
|
|
60
|
+
params,
|
|
61
|
+
);
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
deleteKnock: (params: { id: string }) => {
|
|
65
|
+
return call(
|
|
66
|
+
"admin", "delete_knock",
|
|
67
|
+
routes.admin.delete_knock.resp,
|
|
68
|
+
routes.admin.delete_knock.req,
|
|
69
|
+
routes.admin.delete_knock.method,
|
|
70
|
+
routes.admin.delete_knock.path,
|
|
71
|
+
params,
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
// public knock endpoints (for P2P access requests)
|
|
76
|
+
createKnockPublic: (params: s.CreateKnockRequest) => {
|
|
77
|
+
return call(
|
|
78
|
+
"admin", "create_knock_public",
|
|
79
|
+
routes.admin.create_knock_public.resp,
|
|
80
|
+
routes.admin.create_knock_public.req,
|
|
81
|
+
routes.admin.create_knock_public.method,
|
|
82
|
+
routes.admin.create_knock_public.path,
|
|
83
|
+
params,
|
|
84
|
+
);
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
getKnockStatusPublic: () => {
|
|
88
|
+
return call(
|
|
89
|
+
"admin", "get_knock_status_public",
|
|
90
|
+
routes.admin.get_knock_status_public.resp,
|
|
91
|
+
routes.admin.get_knock_status_public.req,
|
|
92
|
+
routes.admin.get_knock_status_public.method,
|
|
93
|
+
routes.admin.get_knock_status_public.path,
|
|
94
|
+
);
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// app domain methods for FreqholeClient
|
|
2
|
+
|
|
3
|
+
import { routes } from "../codegen/routes.js";
|
|
4
|
+
import type { CallFn } from "./types.js";
|
|
5
|
+
|
|
6
|
+
export function createAppMethods(call: CallFn) {
|
|
7
|
+
return {
|
|
8
|
+
healthCheck: () => {
|
|
9
|
+
return call(
|
|
10
|
+
"app", "health_check",
|
|
11
|
+
routes.app.health_check.resp,
|
|
12
|
+
routes.app.health_check.req,
|
|
13
|
+
routes.app.health_check.method,
|
|
14
|
+
routes.app.health_check.path,
|
|
15
|
+
);
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
serverInfo: () => {
|
|
19
|
+
return call(
|
|
20
|
+
"app", "server_info",
|
|
21
|
+
routes.app.server_info.resp,
|
|
22
|
+
routes.app.server_info.req,
|
|
23
|
+
routes.app.server_info.method,
|
|
24
|
+
routes.app.server_info.path,
|
|
25
|
+
);
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
radioInfo: () => {
|
|
29
|
+
return call(
|
|
30
|
+
"app", "radio_info",
|
|
31
|
+
routes.app.radio_info.resp,
|
|
32
|
+
routes.app.radio_info.req,
|
|
33
|
+
routes.app.radio_info.method,
|
|
34
|
+
routes.app.radio_info.path,
|
|
35
|
+
);
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
radioStations: () => {
|
|
39
|
+
return call(
|
|
40
|
+
"app", "radio_stations",
|
|
41
|
+
routes.app.radio_stations.resp,
|
|
42
|
+
routes.app.radio_stations.req,
|
|
43
|
+
routes.app.radio_stations.method,
|
|
44
|
+
routes.app.radio_stations.path,
|
|
45
|
+
);
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
// get blob metadata for a station blob
|
|
49
|
+
radioPublicBlob: (params: { station_id: string; blob_id: string }) => {
|
|
50
|
+
return call(
|
|
51
|
+
"app", "radio_public_blob",
|
|
52
|
+
routes.app.radio_public_blob.resp,
|
|
53
|
+
routes.app.radio_public_blob.req,
|
|
54
|
+
routes.app.radio_public_blob.method,
|
|
55
|
+
routes.app.radio_public_blob.path,
|
|
56
|
+
params,
|
|
57
|
+
);
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
// stream the binary data for a station blob
|
|
61
|
+
radioPublicBlobData: (params: { station_id: string; blob_id: string }) => {
|
|
62
|
+
return call(
|
|
63
|
+
"app", "radio_public_blob_data",
|
|
64
|
+
routes.app.radio_public_blob_data.resp,
|
|
65
|
+
routes.app.radio_public_blob_data.req,
|
|
66
|
+
routes.app.radio_public_blob_data.method,
|
|
67
|
+
routes.app.radio_public_blob_data.path,
|
|
68
|
+
params,
|
|
69
|
+
);
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
// get a thumbnail for a station blob at a given size
|
|
73
|
+
radioPublicBlobThumbnail: (params: { station_id: string; blob_id: string; size: string }) => {
|
|
74
|
+
return call(
|
|
75
|
+
"app", "radio_public_blob_thumbnail",
|
|
76
|
+
routes.app.radio_public_blob_thumbnail.resp,
|
|
77
|
+
routes.app.radio_public_blob_thumbnail.req,
|
|
78
|
+
routes.app.radio_public_blob_thumbnail.method,
|
|
79
|
+
routes.app.radio_public_blob_thumbnail.path,
|
|
80
|
+
params,
|
|
81
|
+
);
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
// get the public timeline manifest for a station
|
|
85
|
+
radioPublicTimeline: (params: { station_id: string }) => {
|
|
86
|
+
return call(
|
|
87
|
+
"app", "radio_public_timeline",
|
|
88
|
+
routes.app.radio_public_timeline.resp,
|
|
89
|
+
routes.app.radio_public_timeline.req,
|
|
90
|
+
routes.app.radio_public_timeline.method,
|
|
91
|
+
routes.app.radio_public_timeline.path,
|
|
92
|
+
params,
|
|
93
|
+
);
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export type AppMethods = ReturnType<typeof createAppMethods>;
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// auth domain methods for FreqholeClient
|
|
2
|
+
|
|
3
|
+
import { routes } from "../codegen/routes.js";
|
|
4
|
+
import type * as s from "../codegen/schema.js";
|
|
5
|
+
import type { CallFn } from "./types.js";
|
|
6
|
+
|
|
7
|
+
export function createAuthMethods(call: CallFn) {
|
|
8
|
+
return {
|
|
9
|
+
registerStart: (params: s.RegisterStartRequest) => {
|
|
10
|
+
return call(
|
|
11
|
+
"auth", "register_start",
|
|
12
|
+
routes.auth.register_start.resp,
|
|
13
|
+
routes.auth.register_start.req,
|
|
14
|
+
routes.auth.register_start.method,
|
|
15
|
+
routes.auth.register_start.path,
|
|
16
|
+
params,
|
|
17
|
+
);
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
registerFinish: (params: any) => {
|
|
21
|
+
return call(
|
|
22
|
+
"auth", "register_finish",
|
|
23
|
+
routes.auth.register_finish.resp,
|
|
24
|
+
routes.auth.register_finish.req,
|
|
25
|
+
routes.auth.register_finish.method,
|
|
26
|
+
routes.auth.register_finish.path,
|
|
27
|
+
params,
|
|
28
|
+
);
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
loginStart: (params: s.StartLoginRequest) => {
|
|
32
|
+
return call(
|
|
33
|
+
"auth", "login_start",
|
|
34
|
+
routes.auth.login_start.resp,
|
|
35
|
+
routes.auth.login_start.req,
|
|
36
|
+
routes.auth.login_start.method,
|
|
37
|
+
routes.auth.login_start.path,
|
|
38
|
+
params,
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
loginFinish: (params: any) => {
|
|
43
|
+
return call(
|
|
44
|
+
"auth", "login_finish",
|
|
45
|
+
routes.auth.login_finish.resp,
|
|
46
|
+
routes.auth.login_finish.req,
|
|
47
|
+
routes.auth.login_finish.method,
|
|
48
|
+
routes.auth.login_finish.path,
|
|
49
|
+
params,
|
|
50
|
+
);
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
whoami: () => {
|
|
54
|
+
return call(
|
|
55
|
+
"auth", "whoami",
|
|
56
|
+
routes.auth.whoami.resp,
|
|
57
|
+
routes.auth.whoami.req,
|
|
58
|
+
routes.auth.whoami.method,
|
|
59
|
+
routes.auth.whoami.path,
|
|
60
|
+
);
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
logout: () => {
|
|
64
|
+
return call(
|
|
65
|
+
"auth", "logout",
|
|
66
|
+
routes.auth.logout.resp,
|
|
67
|
+
routes.auth.logout.req,
|
|
68
|
+
routes.auth.logout.method,
|
|
69
|
+
routes.auth.logout.path,
|
|
70
|
+
);
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
regenerateApiKey: () => {
|
|
74
|
+
return call(
|
|
75
|
+
"auth", "regenerate_api_key",
|
|
76
|
+
routes.auth.regenerate_api_key.resp,
|
|
77
|
+
routes.auth.regenerate_api_key.req,
|
|
78
|
+
routes.auth.regenerate_api_key.method,
|
|
79
|
+
routes.auth.regenerate_api_key.path,
|
|
80
|
+
);
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
apiKeyStatus: () => {
|
|
84
|
+
return call(
|
|
85
|
+
"auth", "api_key_status",
|
|
86
|
+
routes.auth.api_key_status.resp,
|
|
87
|
+
routes.auth.api_key_status.req,
|
|
88
|
+
routes.auth.api_key_status.method,
|
|
89
|
+
routes.auth.api_key_status.path,
|
|
90
|
+
);
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
redeemInvite: (params: s.RedeemInviteRequest) => {
|
|
94
|
+
return call(
|
|
95
|
+
"auth", "redeem_invite",
|
|
96
|
+
routes.auth.redeem_invite.resp,
|
|
97
|
+
routes.auth.redeem_invite.req,
|
|
98
|
+
routes.auth.redeem_invite.method,
|
|
99
|
+
routes.auth.redeem_invite.path,
|
|
100
|
+
params,
|
|
101
|
+
);
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
listPasskeys: () => {
|
|
105
|
+
return call(
|
|
106
|
+
"auth", "list_passkeys",
|
|
107
|
+
routes.auth.list_passkeys.resp,
|
|
108
|
+
routes.auth.list_passkeys.req,
|
|
109
|
+
routes.auth.list_passkeys.method,
|
|
110
|
+
routes.auth.list_passkeys.path,
|
|
111
|
+
);
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
deletePasskey: (params: s.DeletePasskeyRequest) => {
|
|
115
|
+
return call(
|
|
116
|
+
"auth", "delete_passkey",
|
|
117
|
+
routes.auth.delete_passkey.resp,
|
|
118
|
+
routes.auth.delete_passkey.req,
|
|
119
|
+
routes.auth.delete_passkey.method,
|
|
120
|
+
routes.auth.delete_passkey.path,
|
|
121
|
+
params,
|
|
122
|
+
);
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
linkNode: (params: s.LinkNodeRequest) => {
|
|
126
|
+
return call(
|
|
127
|
+
"auth", "link_node",
|
|
128
|
+
routes.auth.link_node.resp,
|
|
129
|
+
routes.auth.link_node.req,
|
|
130
|
+
routes.auth.link_node.method,
|
|
131
|
+
routes.auth.link_node.path,
|
|
132
|
+
params,
|
|
133
|
+
);
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
updateUsername: (params: s.UpdateUsernameRequest) => {
|
|
137
|
+
return call(
|
|
138
|
+
"auth", "update_username",
|
|
139
|
+
routes.auth.update_username.resp,
|
|
140
|
+
routes.auth.update_username.req,
|
|
141
|
+
routes.auth.update_username.method,
|
|
142
|
+
routes.auth.update_username.path,
|
|
143
|
+
params,
|
|
144
|
+
);
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
generateSelfAccountLink: () => {
|
|
148
|
+
return call(
|
|
149
|
+
"auth", "generate_self_account_link",
|
|
150
|
+
routes.auth.generate_self_account_link.resp,
|
|
151
|
+
routes.auth.generate_self_account_link.req,
|
|
152
|
+
routes.auth.generate_self_account_link.method,
|
|
153
|
+
routes.auth.generate_self_account_link.path,
|
|
154
|
+
);
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
listOwnInvites: () => {
|
|
158
|
+
return call(
|
|
159
|
+
"auth", "list_own_invites",
|
|
160
|
+
routes.auth.list_own_invites.resp,
|
|
161
|
+
routes.auth.list_own_invites.req,
|
|
162
|
+
routes.auth.list_own_invites.method,
|
|
163
|
+
routes.auth.list_own_invites.path,
|
|
164
|
+
);
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
revokeOwnInvite: (params: s.RevokeOwnInviteRequest) => {
|
|
168
|
+
return call(
|
|
169
|
+
"auth", "revoke_own_invite",
|
|
170
|
+
routes.auth.revoke_own_invite.resp,
|
|
171
|
+
routes.auth.revoke_own_invite.req,
|
|
172
|
+
routes.auth.revoke_own_invite.method,
|
|
173
|
+
routes.auth.revoke_own_invite.path,
|
|
174
|
+
params,
|
|
175
|
+
);
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
updatePasskeyName: (params: s.UpdatePasskeyNameRequest) => {
|
|
179
|
+
return call(
|
|
180
|
+
"auth", "update_passkey_name",
|
|
181
|
+
routes.auth.update_passkey_name.resp,
|
|
182
|
+
routes.auth.update_passkey_name.req,
|
|
183
|
+
routes.auth.update_passkey_name.method,
|
|
184
|
+
routes.auth.update_passkey_name.path,
|
|
185
|
+
params,
|
|
186
|
+
);
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export type AuthMethods = ReturnType<typeof createAuthMethods>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// hand-rolled favorites types with proper discriminated union support
|
|
2
|
+
// the codegen doesn't handle rust's #[serde(tag = "type")] properly yet
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import {
|
|
5
|
+
SongQueryResultSchema,
|
|
6
|
+
AlbumQueryResultSchema,
|
|
7
|
+
ArtistQueryResultSchema,
|
|
8
|
+
PlaylistQueryResultSchema,
|
|
9
|
+
} from "../codegen/schema.js";
|
|
10
|
+
|
|
11
|
+
// discriminated union for favorite items
|
|
12
|
+
// matches rust's FavoriteItem enum with #[serde(tag = "type", rename_all = "lowercase")]
|
|
13
|
+
const FavoriteItemSchema = z.discriminatedUnion("type", [
|
|
14
|
+
z.object({
|
|
15
|
+
type: z.literal("song"),
|
|
16
|
+
favorited_at: z.number(),
|
|
17
|
+
song: SongQueryResultSchema,
|
|
18
|
+
}),
|
|
19
|
+
z.object({
|
|
20
|
+
type: z.literal("album"),
|
|
21
|
+
favorited_at: z.number(),
|
|
22
|
+
album: AlbumQueryResultSchema,
|
|
23
|
+
}),
|
|
24
|
+
z.object({
|
|
25
|
+
type: z.literal("artist"),
|
|
26
|
+
favorited_at: z.number(),
|
|
27
|
+
artist: ArtistQueryResultSchema,
|
|
28
|
+
}),
|
|
29
|
+
z.object({
|
|
30
|
+
type: z.literal("playlist"),
|
|
31
|
+
favorited_at: z.number(),
|
|
32
|
+
playlist: PlaylistQueryResultSchema,
|
|
33
|
+
}),
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
export type FavoriteItem = z.infer<typeof FavoriteItemSchema>;
|
|
37
|
+
|
|
38
|
+
// properly typed response from list_favorites endpoint
|
|
39
|
+
const ListFavoritesResponseSchema = z.object({
|
|
40
|
+
favorites: z.array(FavoriteItemSchema),
|
|
41
|
+
total_count: z.number(),
|
|
42
|
+
has_more: z.boolean(),
|
|
43
|
+
offset: z.number(),
|
|
44
|
+
limit: z.number(),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
export type ListFavoritesResponse = z.infer<
|
|
48
|
+
typeof ListFavoritesResponseSchema
|
|
49
|
+
>;
|
|
50
|
+
|
|
51
|
+
// export schemas for runtime validation if needed
|
|
52
|
+
export { FavoriteItemSchema, ListFavoritesResponseSchema };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// jobs domain methods for FreqholeClient.
|
|
2
|
+
//
|
|
3
|
+
// thin wrappers over the transport's `snapshotJobEvents` /
|
|
4
|
+
// `subscribeJobEvents` capability. transports that don't implement
|
|
5
|
+
// these fall back to the http polling iterator (see transport.ts).
|
|
6
|
+
|
|
7
|
+
import type { Transport } from "../transport.js";
|
|
8
|
+
import {
|
|
9
|
+
pollingJobEvents,
|
|
10
|
+
snapshotJobEventsViaRequest,
|
|
11
|
+
} from "../transport.js";
|
|
12
|
+
import type {
|
|
13
|
+
EventFilter,
|
|
14
|
+
JobEvent,
|
|
15
|
+
JobStateSnapshot,
|
|
16
|
+
} from "../codegen/schema.js";
|
|
17
|
+
|
|
18
|
+
export function createJobsMethods(transport: Transport) {
|
|
19
|
+
return {
|
|
20
|
+
events: {
|
|
21
|
+
/**
|
|
22
|
+
* one-shot snapshot of currently-active jobs the caller can see.
|
|
23
|
+
* use this to rehydrate state on mount / after a page reload.
|
|
24
|
+
*/
|
|
25
|
+
snapshot: async (filter?: EventFilter): Promise<JobStateSnapshot[]> => {
|
|
26
|
+
if (transport.snapshotJobEvents) {
|
|
27
|
+
return transport.snapshotJobEvents(filter);
|
|
28
|
+
}
|
|
29
|
+
return snapshotJobEventsViaRequest(transport, filter);
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* live subscription to job events. iterates `JobEvent`s until the
|
|
34
|
+
* stream ends or the optional `signal` is aborted. transports
|
|
35
|
+
* without native streaming use the http polling fallback.
|
|
36
|
+
*/
|
|
37
|
+
subscribe: (
|
|
38
|
+
filter?: EventFilter,
|
|
39
|
+
signal?: AbortSignal,
|
|
40
|
+
): AsyncIterable<JobEvent> => {
|
|
41
|
+
if (transport.subscribeJobEvents) {
|
|
42
|
+
return transport.subscribeJobEvents(filter, signal);
|
|
43
|
+
}
|
|
44
|
+
return pollingJobEvents(transport, filter, signal);
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|