Skip to content

Commit

Permalink
Merge pull request #87 from vernak2539/publish-v1.1
Browse files Browse the repository at this point in the history
feat(api-v1.1): enable publish API v1.1
  • Loading branch information
louisgv authored Jan 6, 2025
2 parents 9cef7b6 + a0b14cc commit 79ddd55
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 46 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ npm install --save-dev @plasmohq/edge-addons-api

### Authentication

You'll need to get a `productId`, `clientId`, `clientSecret`, and `accessTokenUrl` for your project.
You'll need to get a `productId`, `clientId`, and `apiKey` for your project.

You can get these for your project by following the [Microsoft Edge Add-Ons API guide](https://docs.microsoft.com/en-us/microsoft-edge/extensions-chromium/publish/api/using-addons-api).

Expand All @@ -59,8 +59,7 @@ import { EdgeAddonsAPI } from "@plasmohq/edge-addons-api"
const client = new EdgeAddonsAPI({
productId,
clientId,
clientSecret,
accessTokenUrl
apiKey
})

await client.submit({
Expand Down
64 changes: 21 additions & 43 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@ import got, { type OptionsOfTextResponseBody } from "got"

export type Options = {
productId: string

clientId: string
clientSecret: string

accessTokenUrl: string

apiKey: string;
uploadOnly?: boolean
}

Expand Down Expand Up @@ -43,10 +39,8 @@ export const errorMap = {
"Product ID is required. To get one, go to: https://partner.microsoft.com/en-us/dashboard/microsoftedge/{product-id}/package/dashboard",
clientId:
"Client ID is required. To get one: https://partner.microsoft.com/en-us/dashboard/microsoftedge/publishapi",
clientSecret:
"Client Secret is required. To get one: https://partner.microsoft.com/en-us/dashboard/microsoftedge/publishapi",
accessTokenUrl:
"Access token URL is required. To get one: https://partner.microsoft.com/en-us/dashboard/microsoftedge/publishapi"
apiKey:
"API Key is required. To get one: https://partner.microsoft.com/en-us/dashboard/microsoftedge/publishapi",
}

export const requiredFields = Object.keys(errorMap) as Array<
Expand Down Expand Up @@ -84,28 +78,23 @@ export class EdgeAddonsAPI {
* @returns the publish operation id
*/
async submit({ filePath = "", notes = "" }) {
const accessToken = await this.getAccessToken()

const uploadResp = await this.upload(
createReadStream(filePath),
accessToken
createReadStream(filePath)
)

await this.waitForUpload(uploadResp, accessToken)
await this.waitForUpload(uploadResp)

if (this.options.uploadOnly) {
return
}

return this.publish(notes, accessToken)
return this.publish(notes)
}

async publish(notes = "", _accessToken = null as string) {
const accessToken = _accessToken || (await this.getAccessToken())

async publish(notes = "") {
const options = {
headers: {
Authorization: `Bearer ${accessToken}`,
...this.getPublishApiDefaultHeaders(),
"Content-Type": "application/x-www-form-urlencoded"
}
} as OptionsOfTextResponseBody
Expand All @@ -121,13 +110,11 @@ export class EdgeAddonsAPI {
return publishResp.headers.location
}

async upload(readStream = null as ReadStream, _accessToken = null as string) {
const accessToken = _accessToken || (await this.getAccessToken())

async upload(readStream = null as ReadStream) {
const uploadResp = await got.post(this.uploadEndpoint, {
body: readStream,
headers: {
Authorization: `Bearer ${accessToken}`,
...this.getPublishApiDefaultHeaders(),
"Content-Type": "application/zip"
}
})
Expand All @@ -137,26 +124,21 @@ export class EdgeAddonsAPI {
return uploadResp.headers.location
}

async getPublishStatus(operationId: string, _accessToken = null as string) {
const accessToken = _accessToken || (await this.getAccessToken())
async getPublishStatus(operationId: string) {
const statusEndpoint = `${this.publishEndpoint}/operations/${operationId}`

return got
.get(statusEndpoint, {
headers: {
Authorization: `Bearer ${accessToken}`
}
headers: this.getPublishApiDefaultHeaders()
})
.json<OperationResponse>()
}

async waitForUpload(
operationId: string,
_accessToken = null as string,
retryCount = 5,
pollTime = 3000
) {
const accessToken = _accessToken || (await this.getAccessToken())
const statusEndpoint = `${this.uploadEndpoint}/operations/${operationId}`

let successMessage: string
Expand All @@ -167,9 +149,7 @@ export class EdgeAddonsAPI {
while (uploadStatus !== "Succeeded" && attempts < retryCount) {
const statusResp = await got
.get(statusEndpoint, {
headers: {
Authorization: `Bearer ${accessToken}`
}
headers: this.getPublishApiDefaultHeaders()
})
.json<OperationResponse>()

Expand Down Expand Up @@ -202,16 +182,14 @@ export class EdgeAddonsAPI {
}
}

getAccessToken = async () => {
const data = await got
.post(`${this.options.accessTokenUrl}`, {
body: `client_id=${this.options.clientId}&scope=${baseApiUrl}/.default&client_secret=${this.options.clientSecret}&grant_type=client_credentials`,
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
})
.json<AuthTokenResponse>()
private getPublishApiDefaultHeaders() {
// All requests need the following headers (https://learn.microsoft.com/en-us/microsoft-edge/extensions-chromium/publish/api/using-addons-api?tabs=v1-1):
// - Authorization: ApiKey $ApiKey;
// - X-ClientID: $ClientID;

return data.access_token
return {
Authorization: `ApiKey ${this.options.apiKey}`,
'X-ClientID': this.options.clientId
}
}
}

0 comments on commit 79ddd55

Please sign in to comment.