Skip to content

Commit 8135d67

Browse files
committed
Updates to Quarto Pub publishing
1 parent 1497e92 commit 8135d67

File tree

1 file changed

+172
-66
lines changed

1 file changed

+172
-66
lines changed

src/publish/quarto-pub/api/index.ts

Lines changed: 172 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@ import {
1313
Ticket,
1414
} from "./types.ts";
1515

16+
// The Accept: application/json header.
17+
const acceptApplicationJsonHeader = {
18+
Accept: "application/json",
19+
};
20+
21+
// The Content-Type: application/json header.
22+
const contentTypeApplicationJsonHeader = {
23+
"Content-Type": "application/json",
24+
};
25+
26+
// Creates an authorization header, if a token was supplied.
27+
const authorizationHeader = (
28+
token?: string,
29+
): HeadersInit => (!token ? {} : { Authorization: `Bearer ${token}` });
30+
1631
// TODO.
1732
export class ApiError extends Error {
1833
public constructor(
@@ -39,124 +54,215 @@ export class QuartoPubClient {
3954
}
4055

4156
// Creates a ticket.
42-
public createTicket = (client_id: string): Promise<Ticket> =>
43-
this.fetchJSON(
44-
"POST",
45-
`tickets?${new URLSearchParams({ application_id: client_id })}`,
57+
public createTicket = async (client_id: string): Promise<Ticket> => {
58+
const response = await fetch(
59+
this.createURL(
60+
`tickets?${new URLSearchParams({ application_id: client_id })}`,
61+
),
62+
{
63+
method: "POST",
64+
headers: {
65+
...authorizationHeader(this.token_),
66+
...acceptApplicationJsonHeader,
67+
},
68+
},
4669
);
4770

71+
// If the response was not OK, throw an ApiError.
72+
if (!response.ok) {
73+
throw new ApiError(response.status, response.statusText);
74+
}
75+
76+
// Return the result.
77+
return <Ticket> await response.json();
78+
};
79+
4880
// Shows a ticket.
49-
public showTicket = (id: string): Promise<Ticket> =>
50-
this.fetchJSON("GET", `tickets/${id}`);
81+
public showTicket = async (id: string): Promise<Ticket> => {
82+
// Perform the operation.
83+
const response = await fetch(this.createURL(`tickets/${id}`), {
84+
method: "GET",
85+
headers: {
86+
...authorizationHeader(this.token_),
87+
...acceptApplicationJsonHeader,
88+
},
89+
});
90+
91+
// If the response was not OK, throw an ApiError.
92+
if (!response.ok) {
93+
throw new ApiError(response.status, response.statusText);
94+
}
95+
96+
// Return the result.
97+
return <Ticket> await response.json();
98+
};
5199

52100
// Exchanges a ticket for an access token.
53-
public exchangeTicket = (id: string): Promise<AccessToken> =>
54-
this.fetchJSON("POST", `tickets/${id}/exchange`);
101+
public exchangeTicket = async (id: string): Promise<AccessToken> => {
102+
// Perform the operation.
103+
const response = await fetch(this.createURL(`tickets/${id}/exchange`), {
104+
method: "POST",
105+
headers: {
106+
...authorizationHeader(this.token_),
107+
...acceptApplicationJsonHeader,
108+
},
109+
});
110+
111+
// If the response was not OK, throw an ApiError.
112+
if (!response.ok) {
113+
throw new ApiError(response.status, response.statusText);
114+
}
115+
116+
// Return the result.
117+
return <AccessToken> await response.json();
118+
};
55119

56120
// Checks if a slug is available.
57121
public slugAvailable = async (slug: string): Promise<boolean> => {
58-
try {
59-
await this.fetch("HEAD", `slugs/${slug}`);
122+
// Perform the operation.
123+
const response = await fetch(this.createURL(`slugs/${slug}`), {
124+
method: "HEAD",
125+
headers: {
126+
...authorizationHeader(this.token_),
127+
},
128+
});
129+
130+
// If the response was not OK, the slug is unavailable.
131+
if (response.ok) {
60132
return false;
61-
} catch (error) {
62-
if (error instanceof ApiError && error.status === 404) {
63-
return true;
64-
}
133+
}
65134

66-
throw error;
135+
// If the response was 404, the slug is available.
136+
if (response.status == 404) {
137+
return true;
67138
}
139+
140+
// Any other response is an error.
141+
throw new ApiError(response.status, response.statusText);
68142
};
69143

70144
// Creates a site.
71-
public createSite = (
145+
public createSite = async (
72146
type: string,
73147
title: string,
74148
slug: string,
75-
): Promise<Site> =>
76-
this.fetchJSON("POST", "sites", new URLSearchParams({ type, title, slug }));
149+
): Promise<Site> => {
150+
// Perform the operation.
151+
const response = await fetch(this.createURL("sites"), {
152+
method: "POST",
153+
headers: {
154+
...authorizationHeader(this.token_),
155+
...acceptApplicationJsonHeader,
156+
},
157+
body: new URLSearchParams({ type, title, slug }),
158+
});
159+
160+
// If the response was not OK, throw an ApiError.
161+
if (!response.ok) {
162+
throw new ApiError(response.status, response.statusText);
163+
}
164+
165+
// Return the result.
166+
return <Site> await response.json();
167+
};
77168

78169
// Creates a site deploy.
79-
public createDeploy = (
170+
public createDeploy = async (
80171
siteId: string,
81172
files: Record<string, string>,
82173
size: number,
83174
): Promise<PublishDeploy> => {
84-
return this.fetchJSON(
85-
"POST",
86-
`sites/${siteId}/deploys`,
87-
JSON.stringify({
88-
size,
89-
files,
90-
}),
175+
// Perform the operation.
176+
const response = await fetch(
177+
this.createURL(`sites/${siteId}/deploys`),
178+
{
179+
method: "POST",
180+
headers: {
181+
...authorizationHeader(this.token_),
182+
...acceptApplicationJsonHeader,
183+
...contentTypeApplicationJsonHeader,
184+
},
185+
body: JSON.stringify({
186+
size,
187+
files,
188+
}),
189+
// body: JSON.stringify(files),
190+
},
91191
);
92-
};
93-
94-
// Gets a deploy.
95-
public getDeploy = (deployId: string): Promise<PublishDeploy> =>
96-
this.fetchJSON("GET", `deploys/${deployId}`);
97192

98-
// Uploads a deploy file.
99-
public uploadDeployFile = (
100-
deployId: string,
101-
path: string,
102-
fileBody: Blob,
103-
): Promise<void> =>
104-
this.fetch("PUT", `deploys/${deployId}/files/${path}`, fileBody);
193+
// If the response was not OK, throw an ApiError.
194+
if (!response.ok) {
195+
throw new ApiError(response.status, response.statusText);
196+
}
105197

106-
public updateAccountSite = (): Promise<AccountSite> =>
107-
this.fetchJSON("PUT", "update-account-site");
198+
// Return the result.
199+
return <PublishDeploy> await response.json();
200+
};
108201

109-
// Performs a fetch returning JSON.
110-
private fetchJSON = async <T>(
111-
method: string,
112-
path: string,
113-
body?: BodyInit | null,
114-
): Promise<T> => {
115-
// Perform the fetch.
116-
const response = await fetch(this.createURL(path), {
117-
method,
202+
// Gets a deploy.
203+
public getDeploy = async (deployId: string): Promise<PublishDeploy> => {
204+
// Perform the operation.
205+
const response = await fetch(this.createURL(`deploys/${deployId}`), {
206+
method: "GET",
118207
headers: {
119-
Accept: "application/json",
120208
...authorizationHeader(this.token_),
209+
...acceptApplicationJsonHeader,
121210
},
122-
body,
123211
});
124212

125213
// If the response was not OK, throw an ApiError.
126214
if (!response.ok) {
127215
throw new ApiError(response.status, response.statusText);
128216
}
129217

130-
// Return the JSON as the specified type.
131-
return <T> await response.json();
218+
// Return the result.
219+
return <PublishDeploy> await response.json();
132220
};
133221

134-
// Performs a fetch.
135-
private fetch = async (
136-
method: string,
222+
// Uploads a deploy file.
223+
public uploadDeployFile = async (
224+
deployId: string,
137225
path: string,
138-
body?: BodyInit | null,
226+
fileBody: Blob,
139227
): Promise<void> => {
140-
// Perform the fetch.
141-
const response = await fetch(this.createURL(path), {
142-
method,
228+
// Perform the operation.
229+
const response = await fetch(
230+
this.createURL(`deploys/${deployId}/files/${path}`),
231+
{
232+
method: "PUT",
233+
headers: {
234+
...authorizationHeader(this.token_),
235+
},
236+
body: fileBody,
237+
},
238+
);
239+
240+
// If the response was not OK, throw an ApiError.
241+
if (!response.ok) {
242+
throw new ApiError(response.status, response.statusText);
243+
}
244+
};
245+
246+
// Updates the account site.
247+
public updateAccountSite = async (): Promise<AccountSite> => {
248+
// Perform the operation.
249+
const response = await fetch(this.createURL("update-account-site"), {
250+
method: "PUT",
143251
headers: {
144252
...authorizationHeader(this.token_),
253+
...acceptApplicationJsonHeader,
145254
},
146-
body,
147255
});
148256

149257
// If the response was not OK, throw an ApiError.
150258
if (!response.ok) {
151259
throw new ApiError(response.status, response.statusText);
152260
}
261+
262+
// Return the result.
263+
return <AccountSite> await response.json();
153264
};
154265

155266
// Creates a URL.
156267
private createURL = (path: string) => `${this.baseURL_}/${path}`;
157268
}
158-
159-
// Creates an authorization header, if a token was supplied.
160-
const authorizationHeader = (
161-
token?: string,
162-
): HeadersInit => (!token ? {} : { Authorization: `Bearer ${token}` });

0 commit comments

Comments
 (0)