scaleleap / amazon-advertising-api-sdk Goto Github PK
View Code? Open in Web Editor NEWAmazon Advertising API TypeScript and Node.js Unofficial SDK
Home Page: https://npm.im/@scaleleap/amazon-advertising-api-sdk
License: MIT License
Amazon Advertising API TypeScript and Node.js Unofficial SDK
Home Page: https://npm.im/@scaleleap/amazon-advertising-api-sdk
License: MIT License
Enums defined in src/operations/commons/types.ts
are available from @scaleleap/amazon-marketplaces
package.
E.g. use SponsoredBrandsKeywordStateEnum
instead of SBKeywordStateEnum
.
And all other similar instances.
There is a super weird issue that I have been banging my head against the wall on this one.
When you run:
npm run build
It creates the following structure:
lib
├── package.json
└── src
├── index.d.ts
├── index.js
...
But what we want is:
lib
├── index.d.ts
├── index.js
├── index.js.map
Basically, the package.json
does not need to be there, and then the src
will flattened into the lib
.
I just don't understand why the package.json
is copied over.
The strange thing, that this project is configured almost identical to https://github.com/ScaleLeap/amazon-marketplaces yet amazon-marketplaces
does not copy package.json
over.
Please continue in PR #248 which I already started.
Each operation method needs documentation as to what it does. Copying from API docs is fine.
Reporting for Sponsored Display campaigns that use interest and product audiences is now available. This functionality allows users to retrieve reports for recently created Sponsored Display campaigns that use these audiences and for Sponsored Display campaigns that were previously Product Display Ads (PDA) campaigns. This functionality is only relevant for vendors as we have not rolled out Sponsored Display interest and product audiences for sellers yet.
https://advertising.amazon.com/API/docs/en-us/sponsored-display/3-0/openapi#/Reports/requestReport
https://advertising.amazon.com/API/docs/en-us/info/release-notes
The docs list a new account type: agency
.
Please add it.
Use the keyword placement report to get better insight into your keyword performance across different placement types.
https://advertising.amazon.com/API/docs/en-us/reference/sponsored-products/2/reports
https://advertising.amazon.com/API/docs/en-us/info/release-notes
Right now it returns location
, fileSize
, and expiration
regardless of whether it was a successful response or not.
Here is some info about discriminated union types:
https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions
See: https://advertising.amazon.com/API/docs/en-us/reference/sponsored-brands/2/reports
Ctrl+F for "Sponsored Brands report metrics"
Please add a rule that will catch console.log
statements.
Please create code examples in examples/
directory for each operation type.
Please make them a bit realistic. In other words, not just dumb data like "abc" or "lorem ipsum".
These examples will be part of the documentation.
Docs: https://advertising.amazon.com/API/docs/v2/reference/profiles
See src/operations/profiles/types.ts
I added the examples for the Profile operation.
We need to describe data model using io-ts
types for each of the possible objects that API can return.
Please create similar files:
src/operations/portfolios/types.ts
and
src/operations/campaigns/types.ts
And create similar type structures.
Since Amazon dates are often arbitrary and don't always come with a timezone attached, we could use @js-joda/core
package LocalDate class.
That way, the math on dates can still be done, and user can cast a date object to a specific timezone, if they wanted to.
Also, we could figure out a way to cast the date objects to a timezone, as we have the enum list of timezones.
Or we could provide that as a config option for when creating a provider.
Thougts?
In src/http-client.ts
, lets rename the following interface:
export interface HttpClientAuth {
authorizationToken: string
clientId: string
scope: number
}
From authorizationToken
to accessToken
.
That way it'll be more consistent with the token interface returned from oAuth.
This page has a full list: https://advertising.amazon.com/API/docs/en-us/reference/sponsored-brands/2/reports
Search page for "Sponsored Brands report metrics".
Note that these metrics are different from the reports in other metrics. E.g. all metrics related to brands (e.g. attributedOrdersNewToBrand14d
and the like) only exist in brand reports.
Meaning we cannot just use a single enum for all of them.
As we have an example: https://github.com/ScaleLeap/amazon-advertising-api-sdk#api-operations
There are too many steps to get started quickly.
Ideally we should have a main class, something like AmazonAdvertising
that accepts:
And creates all of the moving parts internally, exposing a simple and clean API.
We still want to export the internals, just in case as stand-alone classes.
But the main use case would be via the entry point class.
Please create a proposal / PoC for this class.
Soon we will start writing methods, and we'll need to record and replay back HTTP calls that go out and come back from the API.
I think Polly.JS is a good tool, although I have not tried it on any other project yet.
Please set it up to work with tests and write one basic test to request something. E.g. make and record a request to https://httpstat.us/200
URL.
https://netflix.github.io/pollyjs/#/test-frameworks/jest-jasmine
Please abstract away setupPolly
into a separate re-usable file. As we'll be using that in many tests.
https://netflix.github.io/pollyjs/#/examples?id=jest-node-fetch
For making HTTP requests, please use cross-fetch
.
But for Polly, I think we still want to use @pollyjs/adapter-node-http
to catch the requests, as cross-fetch probably uses that under the hood. But if that doesn't work, let me know. I am not 100% sure myself about this. This is just an experiment.
It is true that ESLint is not producing any errors anymore, but it also seems not fix formatting issues.
E.g. if you remove the trailing comma, it does not report it as an issue.
Daily Budget for Sponsored Brands has changed. New campaigns with a daily budget are calculated as an average over a calendar month, just like Sponsored Products campaigns.
It seems like SponsoredBrandsRecordTypeEnum
is not exported, which makes it not possible to actually do operations.
E.g.:
const provider = new OperationProvider(httpClient)
const op = provider.create(SponsoredBrandsSnapshotOperation)
op.requestSnapshot(...)
The first param to requestSnapshot
is the enum, but it is not exported, and it is thus not possible to make this request.
Please make sure all enums are exported for use.
Thanks.
There is a circular reference:
./amazon-advertising
imports from ./index
./index.ts
exports from ./amazon-advertising
./amazon-advertising
should import from the right files themselves, not from index
.
We should not bundle the marketplace package as a "dependency", but only depend in dev and suggest as peer dep (same minimum version as dev dep).
This actually may not work, but please try.
I added a PR #33 where I ported HTTP client library from V1.
Switched to using setup-polly-jest
, because it automatically calls stop
and also creates recording names according to test names. We have a wrapper for it in test/polly.ts
now, which also filters sensitive info.
Please refactor other test test/o-auth-client.test.ts
to use this Polly setup.
Please remove test/pollyjs
dir as the proof of concept no longer needed and the wrapper also.
Please complete and finish the rest of the tests in test/http-client.test.ts
(the ones that are marked as skipped).
Please migrate the tests from v1 for errors and buffer anything else that is currently useful for this PR.
Please create a separate issue for each operation we still have to complete. This way it'll be easier for me to track progress. Thanks.
There are three regions, which have unique URIs for everything (API, auth, token refresh).
We need to be able to supply the region information during HTTP object creation, and then pass it down to other objects.
There are regions defined in @scaleleap/amazon-marketplaces
marketplace classes.
Same idea as #2, but for profiles. I have started the example, but didn't finish it.
Let's get rid of the POLLY_PASSTHROUGH_TAG
from the test names.
This will change the name of the test, and all of the Polly recordings will need to be re-recorded. So I think we should do this in stages. E.g. do one file, then push, it will re-record, then do another file and push.
Instead, we'll work on custom set of integration tests that tests the surface area.
Thanks.
We seem to be using a mix of cases. Directory names are camelCase
and file names are kebab-case
.
Let's standardize on kebab-case
and have all of the names in the repository in that case.
Please start working on the campaign operations as soon as you can. We will actually start using this in a project then. Thanks.
This doesn't seem to be used anywhere. Do we need it or is there a method that is not implemented yet?
It isn't used anywhere as a type, just only as a reference in tests.
E.g. used here:
And res.code
should be of KeywordResponseStatusEnum
type.
Please fix this when refactoring enums to union of strings.
And please make sure to use discriminated union types.
Right now, Jest seems to pick up ./lib
dir, which contains transpiled .js
files.
Need to exclude that dir from tests.
❯ npm t
> [email protected] test ~/amazon-advertising-api-nodejs-sdk-2
> jest
PASS lib/commons/types.test.js
PASS lib/profiles/types.test.js
PASS lib/portfolios/types.test.js
PASS lib/campaigns/types.test.js
PASS src/operations/profiles/types.test.ts
PASS src/operations/commons/types.test.ts
PASS src/operations/campaigns/types.test.ts
PASS src/operations/portfolios/types.test.ts
PASS test/pollyjs/pollyjs.test.ts
Test Suites: 9 passed, 9 total
Tests: 61 passed, 61 total
Snapshots: 0 total
Time: 5.906s
Ran all test suites.
We need to think about how to structure the whole API interface and expose it to the end user (consumer).
In the original repository, I used the following convention:
const client = new Client()
// sp = Sponsored Products
client.sp.getCampaign({ })
But I think it got messy very fast.
Also, I was thinking that if this code ever needs to be used on the frontend, then we'd need to load the whole heavy library with all of the methods.
So, I was thinking if we could decouple every operation into individual modules.
Something like:
class SponsoredBrandsCampaigns {
public getCampaign() {
return {}
}
}
And then each of these classes can be instantiated separately:
const sbc = new SponsoredBrandsCampaigns({})
sbc.getCampaign()
But, that would get tedious for every type of operation, so I think we could have a provider class that instantiates these for us. Kind of like a container or inversion of control.
class OperationProvider {
private httpClient = {}
private someOptions = {}
create(OperationClass) {
return new OperationClass(this.httpClient, this.someOptions)
}
}
Then, in the main application, the module consumer would only need to instantiate the provider once and then get instances of operation classes easily:
import { OperationProvider, SponsoredBrandsCampaigns } from 'module-name'
const provider = new OperationProvider()
const sbc = provider.create(SponsoredBrandsCampaigns)
sbc.getCampaign()
What do you think about this architecture?
And do you have any other ideas or suggestions how we can have a clean, easy to use, and efficient interface?
Amazon API returns dates as epoch in seconds.
Example:
"creationDate": 1526510030,
We need a type that converts this epoch numeric date to a JS Date
object.
There is a good example here, but I think it uses milliseconds.
The full object with suggestedBid
and expression
props only describes a SUCCESS
response.
I think this could benefit from discriminated union type.
Everything that is not SUCCESS
should not have the props.
E.g.:
export const BidRecommendationList = t.strict({
/**
* The suggested bid
*/
suggestedBid: SuggestedBid,
/**
* The targeting expression
*/
expression: BiddingTargetingExpression,
/**
* The response code
*/
code: t.literal('SUCCESS'),
})
src/index.ts
should export all of the operation classes
Once snapshot is generated, the returning object has a location
(URI).
We want to provide a convenience method on the snapshot operation.
public download(snapshot: SuccessSnapshot) {
return httpClient.download(snapshot.location)
}
See src/http-client.ts
it has a download method already. And you can see the original implementation for how to use it.
There is a type that needs to be provided as a generic to the download method.
download<SnapshotResultType>(...)
```
I've been using the package now for a few days. And it feels like the ergonomics of the enum are really not developer friendly. I feel like I've made a bad choice. 😬
I am wondering if it'd be worth it to replace enums with just string unions?
E.g. instead of:
op.requestReport({
recordType: SponsoredBrandsReportTypeEnum.CAMPAIGNS,
metrics: [
CampaignReportMetricsEnum.CAMPAIGN_NAME,
],
reportDate: '',
})
It would be:
op.requestReport({
recordType: "campaigns",
metrics: [
"campaignName"
],
reportDate: '',
})
But using t.literal()
unions. So there would still be type suggestions support.
My only concern is that t.unions have a limited number of things you can unionize, i think. Or does it accept array?
How much work do you think it is?
I have added API Extractor tooling to CI to run additional checks in #375.
It is producing quite a bit of warnings about our type docs.
Please fix the warnings in that PR.
E.g.: src/operations/campaigns/sb-campaign-operation.ts
exports SponsoredBrandsCampaignOperation
.
Then the file name should be sponsored-brands-campaign-operation
.
Same for all other instances.
master
branch failed. 🚨I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.
You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can resolve this 💪.
Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.
Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master
branch. You can also manually restart the failed CI job that runs semantic-release.
If you are not sure how to resolve this, here is some links that can help you:
If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.
The npm token configured in the NPM_TOKEN
environment variable must be a valid token allowing to publish to the registry https://registry.npmjs.org/
.
If you are using Two-Factor Authentication, make configure the auth-only
level is supported. semantic-release cannot publish with the default auth-and-writes
level.
Please make sure to set the NPM_TOKEN
environment variable in your CI with the exact value of the npm token.
Good luck with your project ✨
Your semantic-release bot 📦🚀
This is a first, easy issue. Can't get ESLint for work for some reason. Config seems to be ok, but still getting:
1:1 error Parsing error: The keyword 'import' is reserved
To test linting:
npm run lint
E.g. we need an ESLint rule that disables the following behaviour:
if (foo)
throw ...
It should always be surrounded by braces:
if (foo) {
throw ...
}
Even when running the tests in replay
mode, many of the recordings get re-recorded, because the POST
data is not deterministic. E.g. in some tests we use current date, which changes every day (of course) and thus Polly thinks it is a new request.
Same idea with profile name, it is randomly generated, which makes Polly think it is a new request.
Please make sure all tests are deterministic and when running via npm t
there are no external requests made at all.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.