GithubHelp home page GithubHelp logo

reactor-sdk-javascript's Introduction

JavaScript Reactor SDK

Travis badge npm version Greenkeeper badge

A Library for accessing the Adobe Experience Platform Reactor API.

This API is fairly low-level. The Reactor methods are one-to-one with the RESTful API endpoints, and they provide very little help in constructing your payloads. This is intended to meet the expectations of JavaScript developers, but we welcome your feedback.

Installation

Using npm

You can use the Reactor SDK from npm with a bundler like Webpack, Rollup, or Parcel. If you use npm for client package management, you can install the SDK with:

npm install @adobe/reactor-sdk

Using a CDN

If you'd prefer not to use npm to manage your client packages, reactor-sdk also provides a UMD distribution in a dist folder which is hosted on a CDN:

<script src="https://unpkg.com/@adobe/reactor-sdk/dist/reactor-sdk.min.js"></script>

The Reactor constructor will be installed as window.Reactor, so typical usage would go something like this:

<script src="https://unpkg.com/@adobe/reactor-sdk/dist/reactor-sdk.min.js"></script>
<script>
  const tok = 'Your Access Token';
  const orgId = 'Your Org Id';
  const url = 'https://reactor.adobe.io';
  const reactor = new window.Reactor(tok, {
    reactorUrl: url,
    customHeaders: {'x-gw-ims-org-id': orgId}
  });
  const acme = await reactor.getCompany('CO0123456789012345678901');
  ...
</script>

How to retrieve your Access Token.

How to retrieve your Org ID.

Usage

The example below is a nodejs script that lists the ID's and names of all your Company's properties.

Put this text in a file named list-properties.js:

#!/usr/bin/env node
const Reactor = require('@adobe/reactor-sdk').default;

(async function() {
  const accessToken = process.env['ACCESS_TOKEN'];
  const orgId = process.env['ORG_ID'];
  const reactorUrl = 'https://reactor.adobe.io';
  const reactor = new Reactor(accessToken, { reactorUrl: reactorUrl, customHeaders: {'x-gw-ims-org-id': orgId} });
  // Example API call: list Companies for the authenticated organization
  const companyList = await reactor.listCompanies();
  for (var company of companyList.data) {
    console.log(`${company.id} ${company.attributes.name}`);
    // Example API call: list Properties for the identified Company
    const list = await reactor.listPropertiesForCompany(company.id);
    for (var property of list.data) {
      console.log(`- ${property.id} ${property.attributes.name}`);
    }
  }
})();

Note: If you are provisioned for multiple orgs, you will need to specify your org ID under customHeaders as shown below.

You can optionally add other custom headers that will be sent with each request by also specifying them in the customHeaders object.

const reactor = new window.Reactor(
  tok, {
    reactorUrl: url,
    customHeaders: {
      'x-gw-ims-org-id': orgId,
      'another-header-example': 42
    }
  }
);

Run it...

export ACCESS_TOKEN=... # see instructions below
export ORG_ID=... # see instructions belor
chmod u+x ./list-properties.js
./list-properties.js

...and you should get output similar to:

"COb711272b544e8359eab4492484893f77" "Fredigar and Bagginses"
"- PR090c7b576f892bf7a7f5e783d0e9ab75" "Shire Real Estate Holdings, LLC"
"- PR399e5b7dbcfc83db37051b43f5ac4d3b" "Mathom Recyclers, Ltd."
success

A browser implementation of this functionality would differ in two ways:

  1. it would use the pre-initialized window.Reactor rather than const Reactor = require('@adobe/reactor-sdk')
  2. providing your access token needs a different approach, since process.env is not available in browsers. Note: you don't want to inline the text of your access token, unless you are sure no adversary will have access to your page.

The SDK and the API

The Adobe Experience Platform Reactor API is a RESTful {json:api}-compliant service.

Each Reactor API endpoint has a corresponding function in this library. For example, the "Fetch a Profile" endpoint is accessed via the getProfile() SDK function.

Since the correspondence between API endpoints and SDK functions is one-to-one, the Reactor API documentation is the primary source of information.

(In addition to the live API documentation, the code that builds that documentation is available under open source, at reactor-developer-docs. For example, the source code of the "Fetch a Profile" documentation is at profiles/fetch.md.)

Every SDK function has an integration test that demonstrates its correctness. (Well, correct for at least one use). These tests also provide you working examples for every library function. [This isn't quite true yet. We're almost there, but a few remain to be implemented.]

For a complete and self-contained example program, see test.spec.js. This is also included in the integration tests, see examples.test.js. It's a JavaScript implementation of the ReactorPostman query set.

Developer Setup

If you want to contribute to development of this library,

git clone [email protected]:adobe/reactor-sdk-javascript.git
cd reactor-sdk-javascript
npm ci           # install dependencies and build Reactor SDK library

The clean install generates three versions of the library:

  1. ./lib/node/*.js, intended for use by nodejs projects
  2. ./lib/browser/*.js, intended for use by bundlers in browser projects
  3. ./dist/reactor.min.js, intended for loading directly into an HTML page (i.e., for non-bundled browser use)

With the SDK built, you can run its nodejs unit tests:

npm link "$(pwd)"           # make this SDK available to tests
npm run unit-tests          # run the tests in test/unit/**

The integration tests need a current access token, a provisioned Company, and your provisioned Org ID. You are expected to provide them to the tests via the environment variables ACCESS_TOKEN, COMPANY_ID, and ORG_ID. Instructions for getting your Access Token, your Company Id, and your Org ID are given below.

The in-browser integration tests require a local static-file web server, because loading their HTML using a file:// URL is not effective: the browser rejects all the resulting Reactor requests because they violate CORS restrictions. The necessary bare-bones web server is provided with this project, as scripts/static-server.js.

Once you've collected the necessary values for your environment variables, you can run the integration tests:

export ACCESS_TOKEN="your_reactor_access_token"
export COMPANY_ID="your_reactor_test_company_id" # "CO" followed by 32 hex digits
export ORG_ID="your_org_id" # 24 characters followed by "@AdobeOrg"
NODE_TLS_REJECT_UNAUTHORIZED=0 scripts/static-server.js --dir ./tmp.tests/

Switch to another terminal window, since you want that server to keep running.

npm run integration-tests   # run the tests in test/integration/**
# The library and bundled integration tests are not currently functioning,
# but the node ones are. Getting them all running is in the backlog. - CR

[Update] As of 24 August 2021, current versions of Google Chrome still won't allow the files to be loaded, even with the static server. Apparently, localhost:5000 and localhost:9010 are too different, and trigger CORS blocking. On MacOS, I've been able to get the tests to work by shutting down Chrome and relaunching with:

  • Bundled Library Test
open -a "Google Chrome" ./tmp.tests/integration-bundled-sdk/integration-tests-bundled-sdk.html \
     --args --disable-web-security --user-data-dir="/tmp/chrome"
  • Non-bundled Library Test
open -a "Google Chrome" ./tmp.tests/integration-library-sdk/integration-tests-library-sdk.html \
     --args --disable-web-security --user-data-dir="/tmp/chrome"

While developing the Reactor SDK, these are handy for auto-building when you change the source code:

# re-run {lint, prettier, build} when src/**/*.js changes
npm run src-watch

# re-run {lint, prettier, build, and test} when {dist,test/unit}/**/*.js changes
npm run unit-watch

# re-run {lint, prettier, build, and test} when {dist,test/integration}/**/*.js changes
npm run integration-watch

# re-run {lint, prettier, build, and test} when {src,test}/**/*.js changes
npm run all-watch

# Periodically, you'll want to remove the Properties created during integration tests
scripts/delete-test-properties

Determining Your Personal Information

Your Access Token

Here we provide instructions on two ways that you can retrieve your Access Token for use with the reactor-sdk project.

Programmatically via Adobe's nodejs programmatic token project.

#!/usr/bin/env node
// The @adobe/auth-token project also supports import syntax natively.
// here is a commonjs example.
const getAuthToken = (...args) => import('@adobe/auth-token').then(({ auth: adobeAuth }) => adobeAuth(...args));
const Reactor = require('@adobe/reactor-sdk').default;

(async function() {
  // @adobe/auth-token config object: https://github.com/adobe/auth-token?tab=readme-ov-file#config-object
  const config = {
    clientId: 'YOUR_CLIENT_ID',
    clientSecret: "YOUR_CLIENT_SECRET",
    scope: "your,scopes,here" // https://developer.adobe.com/developer-console/docs/guides/authentication/UserAuthentication/implementation/#oauth-20-scopes
  };
  const tokenResponse = await getAuthToken(config);
  const accessToken = tokenResponse['access_token'];

  const orgId = process.env['ORG_ID'];
  const reactorUrl = 'https://reactor.adobe.io';
  const reactor = new Reactor(accessToken, { reactorUrl: reactorUrl, customHeaders: {'x-gw-ims-org-id': orgId} });

  // perform API calls here
})();

Through the Adobe Tags user interface

  • Using Google Chrome, log in to https://launch.adobe.com/companies
  • Open the developer console
  • Change the JavaScript context from "top" to "Main Content" using the dropdown menu Switch JavaScriptContext
  • Execute copy(userData.imsAccessToken)
  • The access token is now in your system clipboard. Paste it into an environment variable definition:
    • export ACCESS_TOKEN='<paste>'

Your Company ID

  • Log in to https://launch.adobe.com/companies
  • While looking at your Properties page, the address bar will show a URL like https://launch.adobe.com/companies/CO81f8cb0aca3a4ab8927ee1798c0d4f8a/properties.
  • Your Company ID is the 'CO' followed by 32 hexadecimal digits (i.e., from "CO" up to the following slash). Copy that company ID to an environment variable:
    • export COMPANY_ID=CO81f8cb0aca3a4ab8927ee1798c0d4f8a

Your Org ID

  • Log into https://launch.adobe.com/companies
  • Open the developer console
  • Change the JavaScript context from "top" to "Main Content" using the dropdown menu Switch JavaScriptContext
  • Execute copy(userData.profile.attributes.activeOrg)
  • The Org ID is now in your system clipboard. Paste it into an environment variable definition:
    • export ORG_ID='<paste>'

Future Work

  • Implement integration tests for the handful of functions not yet covered.
  • Include a section here on library function naming conventions.
  • Describe how query parameters are passed in this SDK.

Contributing

Contributions are welcomed! Read the Contributing Guide for more information.

Before submitting your PR

# commit your changes
$ git add .
$ git commit -m 'your commit message'
$ npm version {major|minor|patch}
$ git push

reactor-sdk-javascript's People

Contributors

aaronius avatar brenthosie avatar celesterobinson avatar filmaj avatar gciltaru avatar greenkeeper[bot] avatar haktober avatar matissjanis avatar michael-buser-sdi avatar perlmonger42 avatar thebenrob avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

reactor-sdk-javascript's Issues

[Question] 'http://localhost:3000' has been blocked by CORS policy

The request URL I am accessing works with node-fetch and Postman. And when I try the same URL and Access Token the SDK throws the error:
Access to fetch at 'https://reactor.adobe.io/companies' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field cache-control is not allowed by Access-Control-Allow-Headers in preflight response.

I am sure that there are Header differences, but how can I add the headers in this SDK?
Is there anyway to not block the localhost environment?

filter[published] not working for listRevisionsForRule

Expected Behaviour

filter[published]: 'EQ true' should return the rule version that it's currently published. This filter is listed as a proper filter for this method in the API docs: https://developer.adobelaunch.com/api/reference/1.0/rules/list/

Actual Behaviour

It does not filter. Probably there is a problem with the booleans.

Sample Code that illustrates the problem

let ruleRevisionsList =
await launchApiClient
.listRevisionsForRule(rule.data.id, {
'filter[published]': 'EQ true'
})

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on Greenkeeper branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please click the 'fix repo' button on account.greenkeeper.io.

Error while installing adobe/reactor

Hi Team,

While executing the 'npm install @adobe/reactor-sdk --save' we are getting the following error.
If we change the name in package.json then it executed normally. Is this a know issue?

npm ERR! code ENOSELF
npm ERR! Refusing to install package with name "@adobe/reactor-sdk" under a package
npm ERR! also called "@adobe/reactor-sdk". Did you name your project the same
npm ERR! as the dependency you're installing?
npm ERR!
npm ERR! For more information, see:
npm ERR! https://docs.npmjs.com/cli/install#limitations-of-npms-install-algorithm

No way to provide x-gw-ims-org-id header

Expected Behaviour

I need a way to provide the x-gw-ims-org-id header when using the SDK.

Actual Behaviour

There is not currently a mechanism to provide this, with the recent change to enforce usage of this header in the API, I can no longer use the SDK.

Seems like the reactor is not working on corporate proxy

Hi Team,

While using the reactor javascript sdk over the corporate proxy we are getting the following error.

{ FetchError: request to https://reactor.adobe.io/properties/3333/extensions failed, reason: getaddrinfo ENOTFOUND reactor.adobe.io reactor.adobe.io:443
13:42:33 at ClientRequest. (/home/node_modules/node-fetch/lib/index.js:1444:11)
13:42:33 at ClientRequest.emit (events.js:198:13)
13:42:33 at TLSSocket.socketErrorListener (_http_client.js:392:9)
13:42:33 at TLSSocket.emit (events.js:198:13)
13:42:33 at emitErrorNT (internal/streams/destroy.js:91:8)
13:42:33 at emitErrorAndCloseNT (internal/streams/destroy.js:59:3)
13:42:33 at process._tickCallback (internal/process/next_tick.js:63:19)
13:42:33 message:
13:42:33 'request to https://reactor.adobe.io/properties/3333/extensions failed, reason: getaddrinfo ENOTFOUND reactor.adobe.io reactor.adobe.io:443',
13:42:33 type: 'system',
13:42:33 errno: 'ENOTFOUND',
13:42:33 code: 'ENOTFOUND' }

Seems like the proxying is not supported by node-fetch node-fetch/node-fetch#79
node-fetch/node-fetch#81

Inconsistancy between extension and other resources for update method signature

The current method signature for extension is reactor.updateExtension(extensionId, extensionPatch), where extensionPatch = {data: {id, attribute}}:

export function updateExtension(extensionId, extensionPatch) {
return this.patch(`/extensions/${extensionId}`, extensionPatch);
}

Doesn't match method signature for other resources look like reactor.updateSomeType(someTypePatch), where someTypePatch = {id, attribute}:

export function updateRule(rulePatch) {
return this.patch(`/rules/${rulePatch.id}`, {
data: rulePatch
});
}

export function updateLibrary(libraryPatch) {
return this.patch(`/libraries/${libraryPatch.id}`, {
data: libraryPatch
});
}

export function updateDataElement(dataElementPatch) {
return this.patch(`/data_elements/${dataElementPatch.id}`, {
data: dataElementPatch
});
}

export function updateProperty(propertyPatch) {
return this.patch(`/properties/${propertyPatch.id}`, { data: propertyPatch });
}

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on Greenkeeper branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please click the 'fix repo' button on account.greenkeeper.io.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.