Skip to content

Commit

Permalink
Release v1.0.0
Browse files Browse the repository at this point in the history
- Removed traces of the iDEAL API
- Added keywords
- Added the signal API
- Moved the JSONRequest class to a separate directory
- Added some tests for both signal and address
  • Loading branch information
Cyberuben committed Jun 26, 2016
1 parent 7f98a1b commit 342a0c8
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 99 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ API wrapper for the Postcode.nl API.
Features:
- gathering addresses using postcode, house number and house number addition
- verifying address data
- processing iDEAL payments

# Example

Expand Down
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "node-postcode",
"version": "0.0.3",
"version": "1.0.0",
"description": "API wrapper for the Postcode.nl APIs",
"main": "lib/postcode.js",
"scripts": {
Expand All @@ -17,6 +17,11 @@
"bugs": {
"url": "https://github.com/Cyberuben/node-postcode/issues"
},
"keywords": [
"postcode",
"postcode.nl",
"address"
],
"homepage": "https://github.com/Cyberuben/node-postcode#readme",
"devDependencies": {
"babel-cli": "^6.10.1",
Expand Down
115 changes: 23 additions & 92 deletions src/postcode.js
Original file line number Diff line number Diff line change
@@ -1,90 +1,10 @@
var https = require("https");

class JSONRequest {
constructor(options) {
this._options = options;
}

_requestOptions(method, path, headers, encoding) {
if(!headers) {
headers = {
"Content-Type": "application/json"
};
}

if(!encoding) {
encoding = "utf8";
}

return {
method, headers, encoding,
protocol: "https:",
hostname: "api.postcode.nl",
path: "/rest" + path,
auth: this._options.key+":"+this._options.secret
}
}

_parseJsonResponse(response) {
return new Promise((resolve, reject) => {
const strings = [];

response.on("data", (chunk) => {
strings.push(chunk);
});

response.on("end", () => {
try {
const string = strings.join("");
if(response.statusCode === 200) {
resolve(JSON.parse(string));
}else if(response.statusCode === 401) {
reject(Object.assign(new Error("Invalid credentials for call"), {
statusCode: response.statusCode,
headers: response.headers
}));
}else{
var json;
var error = "Request returned HTTP code "+response.statusCode;
try {
json = JSON.parse(string);
if(json && json.exception) {
error = json.exception;
}
} catch (err) {

}
reject(Object.assign(new Error(error), {
string, json,
statusCode: response.statusCode,
headers: response.headers
}));
}
} catch (err) {
reject(err);
}
});

response.on("error", reject);
});
}

get(path) {
return new Promise((resolve, reject) => {
const opts = this._requestOptions("GET", path);
const request = https.request(opts, res => {
resolve(this._parseJsonResponse(res));
});
request.on("error", reject);
request.end();
});
}
};
const JSONRequest = require("./request");

class PostcodeClient {
constructor (options) {
if(!options.hasOwnProperty("key")) throw new TypeError("'options.key' has to be set");
if(!options.hasOwnProperty("secret")) throw new TypeError("'options.secret' has to be set");
if(!options) throw new TypeError("'options' has to be set");
if(!options.key) throw new TypeError("'options.key' has to be set");
if(!options.secret) throw new TypeError("'options.secret' has to be set");

this._options = options;

Expand Down Expand Up @@ -138,15 +58,26 @@ class PostcodeClient {
});
});
}
};

class iDEAL {

};

class PostcodeiDEALClient {
signal(options) {
if(!options || typeof options != "object") throw new TypeError("'options' is required and should be an object");
if(Object.keys(options).length == 0) throw new TypeError("'options' must have at least one option");

return new Promise((resolve, reject) => {
this._r.post("/signal/check", options)
.then((res) => {
resolve(res);
})
.catch((err) => {
if(err.statusCode === 400) {
err.code = err.json.exceptionId;
reject(err);
}else{
reject(error);
}
});
});
}
};

module.exports.Postcode = PostcodeClient;
module.exports.iDEAL = PostcodeiDEALClient;
module.exports = PostcodeClient;
100 changes: 100 additions & 0 deletions src/request.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
const https = require("https");

class JSONRequest {
constructor(options) {
this._options = options;
}

_requestOptions(method, path, headers, encoding) {
if(!headers) {
headers = {
"Content-Type": "application/json"
};
}

if(!encoding) {
encoding = "utf8";
}

return {
method, headers, encoding,
hostname: "api.postcode.nl",
path: "/rest" + path,
auth: this._options.key+":"+this._options.secret
}
}

_parseJsonResponse(response) {
return new Promise((resolve, reject) => {
const strings = [];

response.on("data", (chunk) => {
strings.push(chunk);
});

response.on("end", () => {
try {
const string = strings.join("");
if(response.statusCode === 200) {
resolve(JSON.parse(string));
}else if(response.statusCode === 401) {
reject(Object.assign(new Error("Invalid credentials for call"), {
statusCode: response.statusCode,
headers: response.headers
}));
}else{
let json;
let error = "Request returned HTTP code "+response.statusCode;
try {
json = JSON.parse(string);
if(json && json.exception) {
error = json.exception;
}
} catch (err) {

}
reject(Object.assign(new Error(error), {
string, json,
statusCode: response.statusCode,
headers: response.headers
}));
}
} catch (err) {
reject(err);
}
});

response.on("error", reject);
});
}

get(path) {
return new Promise((resolve, reject) => {
const opts = this._requestOptions("GET", path);
const request = https.request(opts, (res) => {
resolve(this._parseJsonResponse(res));
});
request.on("error", reject);
request.end();
});
}

post(path, data) {
return new Promise((resolve, reject) => {
const postData = JSON.stringify(data);
const opts = this._requestOptions("POST", path, {
"Content-Type": "application/json",
"Content-Length": postData.length
});

const request = https.request(opts, (res) => {
resolve(this._parseJsonResponse(res));
});
request.write(postData);
request.on("error", reject);
request.end();
});
}
};

module.exports = JSONRequest;
57 changes: 52 additions & 5 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ const API_SECRET = process.env.API_SECRET;

chai.should();

let postcode = require("../lib/postcode");
let PostcodeClient = postcode.Postcode;
let PostcodeiDEALClient = postcode.iDEAL;
let PostcodeClient = require("../lib/postcode");
let JSONRequest = require("../lib/request");

describe("Postcode.nl API wrapper", () => {
describe("PostcodeClient", () => {
Expand All @@ -35,6 +34,12 @@ describe("Postcode.nl API wrapper", () => {
new PostcodeClient({key: "test", secret: "test"});
}).should.not.throw(TypeError);
});

it("should have an instance of JSONRequest and options", () => {
var client = new PostcodeClient({key: "test", secret: "test"});
client._r.should.be.instanceof(JSONRequest);
client._options.should.be.an("object");
});
});

describe("#address()", () => {
Expand Down Expand Up @@ -111,9 +116,51 @@ describe("Postcode.nl API wrapper", () => {
});
});
});
});

describe("class PostcodeiDEALClient", () => {
describe("#signal()", () => {
expect(API_KEY).to.be.ok;
expect(API_SECRET).to.be.ok;

var client = new PostcodeClient({
key: API_KEY,
secret: API_SECRET
});

it("should error on empty / invalid options object", () => {
(() => {
client.signal();
}).should.throw(TypeError);

(() => {
client.signal({});
}).should.throw(TypeError);
});

it("should return a promise on 'valid' options object", () => {
client.signal({
test: "test"
}).should.be.instanceof(Promise);
});

it("should be able to generate a response", () => {
return client.signal({
transaction: {
deliveryAddress: {
postcode: "1111AA",
houseNumber: 1,
country: "NL"
}
}
})
.then((signalDetails) => {
signalDetails.should.be.an("object");
signalDetails.checkId.should.be.a("string");
})
.catch((err) => {
assert(err === undefined, "Error calling the API: "+err.message);
done();
});
});
});
});
});

0 comments on commit 342a0c8

Please sign in to comment.