From 39fed87bb451dd1b06160d3dd78640a74a803acb Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 4 Mar 2015 17:24:20 +0000 Subject: [PATCH] Add examples to show it working in node and browser --- examples/browser/browserTest.js | 10 + examples/browser/index.html | 13 + examples/browser/lib/browser-request.js | 498 +++++++++++++++++++ examples/browser/lib/matrix.js | 605 ++++++++++++++++++++++++ examples/node/app.js | 11 + examples/node/lib/matrix.js | 605 ++++++++++++++++++++++++ 6 files changed, 1742 insertions(+) create mode 100644 examples/browser/browserTest.js create mode 100644 examples/browser/index.html create mode 100644 examples/browser/lib/browser-request.js create mode 100644 examples/browser/lib/matrix.js create mode 100644 examples/node/app.js create mode 100644 examples/node/lib/matrix.js diff --git a/examples/browser/browserTest.js b/examples/browser/browserTest.js new file mode 100644 index 000000000..418ac0614 --- /dev/null +++ b/examples/browser/browserTest.js @@ -0,0 +1,10 @@ +"use strict"; +console.log("Loading browser sdk"); + +matrixcs.request(request); + +var client = matrixcs.createClient("http://matrix.org"); +client.publicRooms(function (err, data) { + console.log("data %s", JSON.stringify(data)); + console.error("err %s", JSON.stringify(err)); +}); diff --git a/examples/browser/index.html b/examples/browser/index.html new file mode 100644 index 000000000..5ca6e221e --- /dev/null +++ b/examples/browser/index.html @@ -0,0 +1,13 @@ + + +Test + + + + + + Sanity Testing (check the console) : This example is here to make sure that + the SDK works inside a browser. It simply does a GET /publicRooms on + matrix.org + + diff --git a/examples/browser/lib/browser-request.js b/examples/browser/lib/browser-request.js new file mode 100644 index 000000000..ed0cc5d4c --- /dev/null +++ b/examples/browser/lib/browser-request.js @@ -0,0 +1,498 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.request = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 299) && body.error) { + // The body is a Couch JSON object indicating the error. + er = new Error('CouchDB error: ' + (body.error.reason || body.error.error)) + for (var key in body) + er[key] = body[key] + return callback(er, resp, body); + } + + return callback(er, resp, body); + } +} + +// +// Utility +// + +function noop() {} + +function getLogger() { + var logger = {} + , levels = ['trace', 'debug', 'info', 'warn', 'error'] + , level, i + + for(i = 0; i < levels.length; i++) { + level = levels[i] + + logger[level] = noop + if(typeof console !== 'undefined' && console && console[level]) + logger[level] = formatted(console, level) + } + + return logger +} + +function formatted(obj, method) { + return formatted_logger + + function formatted_logger(str, context) { + if(typeof context === 'object') + str += ' ' + JSON.stringify(context) + + return obj[method].call(obj, str) + } +} + +// Return whether a URL is a cross-domain request. +function is_crossDomain(url) { + var rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/ + + // jQuery #8138, IE may throw an exception when accessing + // a field from window.location if document.domain has been set + var ajaxLocation + try { ajaxLocation = location.href } + catch (e) { + // Use the href attribute of an A element since IE will modify it given document.location + ajaxLocation = document.createElement( "a" ); + ajaxLocation.href = ""; + ajaxLocation = ajaxLocation.href; + } + + var ajaxLocParts = rurl.exec(ajaxLocation.toLowerCase()) || [] + , parts = rurl.exec(url.toLowerCase() ) + + var result = !!( + parts && + ( parts[1] != ajaxLocParts[1] + || parts[2] != ajaxLocParts[2] + || (parts[3] || (parts[1] === "http:" ? 80 : 443)) != (ajaxLocParts[3] || (ajaxLocParts[1] === "http:" ? 80 : 443)) + ) + ) + + //console.debug('is_crossDomain('+url+') -> ' + result) + return result +} + +// MIT License from http://phpjs.org/functions/base64_encode:358 +function b64_enc (data) { + // Encodes string using MIME base64 algorithm + var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc="", tmp_arr = []; + + if (!data) { + return data; + } + + // assume utf8 data + // data = this.utf8_encode(data+''); + + do { // pack three octets into four hexets + o1 = data.charCodeAt(i++); + o2 = data.charCodeAt(i++); + o3 = data.charCodeAt(i++); + + bits = o1<<16 | o2<<8 | o3; + + h1 = bits>>18 & 0x3f; + h2 = bits>>12 & 0x3f; + h3 = bits>>6 & 0x3f; + h4 = bits & 0x3f; + + // use hexets to index into b64, and append result to encoded string + tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); + } while (i < data.length); + + enc = tmp_arr.join(''); + + switch (data.length % 3) { + case 1: + enc = enc.slice(0, -2) + '=='; + break; + case 2: + enc = enc.slice(0, -1) + '='; + break; + } + + return enc; +} + return request; +//UMD FOOTER START +})); +//UMD FOOTER END + +},{}]},{},[1])(1) +}); \ No newline at end of file diff --git a/examples/browser/lib/matrix.js b/examples/browser/lib/matrix.js new file mode 100644 index 000000000..d04a39593 --- /dev/null +++ b/examples/browser/lib/matrix.js @@ -0,0 +1,605 @@ +"use strict"; + +/* +TODO: +- CS: complete register function (doing stages) +- Internal: rate limiting +- Identity server: linkEmail, authEmail, bindEmail, lookup3pid +- uploadContent (?) +*/ + +// wrap in a closure for browsers +var init = function(exports){ + // expose the underlying request object so different environments can use + // different request libs (e.g. request or browser-request) + var request; + exports.request = function(r) { + request = r; + }; + + // entry point + function MatrixClient(credentials) { + if (typeof credentials === "string") { + credentials = { + "baseUrl": credentials + }; + } + var requiredKeys = [ + "baseUrl" + ]; + for (var i=0; i 0) { + // these are thumbnailing params so they probably want the + // thumbnailing API... + prefix = "/_matrix/media/v1/thumbnail/"; + } + + var fragmentOffset = serverAndMediaId.indexOf("#"), + fragment = ""; + if (fragmentOffset >= 0) { + fragment = serverAndMediaId.substr(fragmentOffset); + serverAndMediaId = serverAndMediaId.substr(0, fragmentOffset); + } + return this.credentials.baseUrl + prefix + serverAndMediaId + + (Object.keys(params).length === 0 ? "" : + ("?" + encodeParams(params))) + fragment; + }, + + getIdenticonUri: function(identiconString, width, height) { + if (!identiconString) { + return; + } + if (!width) { width = 96; } + if (!height) { height = 96; } + var params = { + width: width, + height: height + }; + + var path = encodeUri("/_matrix/media/v1/identicon/$ident", { + $ident: identiconString + }); + return this.credentials.baseUrl + path + + (Object.keys(params).length === 0 ? "" : + ("?" + encodeParams(params))); + }, + + /** + * Get the content repository url with query parameters. + * @returns An object with a 'base', 'path' and 'params' for base URL, + * path and query parameters respectively. + */ + getContentUri: function() { + var params = { + access_token: this.credentials.accessToken + }; + return { + base: this.credentials.baseUrl, + path: "/_matrix/media/v1/upload", + params: params + }; + }, + + // Internals + // ========= + + _doAuthedRequest: function(callback, method, path, params, data) { + if (!params) { params = {}; } + params.access_token = this.credentials.accessToken; + return this._doRequest(callback, method, path, params, data); + }, + + _doRequest: function(callback, method, path, params, data) { + var fullUri = this.credentials.baseUrl + CLIENT_PREFIX + path; + if (!params) { params = {}; } + return this._request(callback, method, fullUri, params, data); + }, + + _request: function(callback, method, uri, params, data) { + console.log(" => %s", uri); + console.log(" %s", JSON.stringify(data)); + if (callback !== undefined && !isFunction(callback)) { + throw Error("Expected callback to be a function"); + } + + return request( + { + uri: uri, + method: method, + withCredentials: false, + qs: params, + body: data, + json: true, + headers: HEADERS + }, + requestCallback(callback) + ); + } + }; + + var encodeUri = function(pathTemplate, variables) { + for (var key in variables) { + if (!variables.hasOwnProperty(key)) { continue; } + pathTemplate = pathTemplate.replace( + key, encodeURIComponent(variables[key]) + ); + } + return pathTemplate; + }; + + // avoiding deps on jquery and co + var encodeParams = function(params) { + var qs = ""; + for (var key in params) { + if (!params.hasOwnProperty(key)) { continue; } + qs += "&" + encodeURIComponent(key) + "=" + + encodeURIComponent(params[key]); + } + return qs.substring(1); + }; + + var requestCallback = function(userDefinedCallback) { + if (!userDefinedCallback) { + return undefined; + } + return function(err, response, body) { + if (err) { + return userDefinedCallback(err); + } + if (response.statusCode >= 400) { + return userDefinedCallback(body); + } + else { + userDefinedCallback(null, body); + } + }; + }; + + var isFunction = function(value) { + return Object.prototype.toString.call(value) == "[object Function]"; + }; +}; + +if (typeof exports === 'undefined') { + init(this['matrixcs']={}); // this assigns to "window" on browsers +} +else { + init(exports); +} \ No newline at end of file diff --git a/examples/node/app.js b/examples/node/app.js new file mode 100644 index 000000000..7b1d7e14d --- /dev/null +++ b/examples/node/app.js @@ -0,0 +1,11 @@ +"use strict"; +console.log("Loading node sdk"); + +var matrix = require("./lib/matrix"); +matrix.request(require("request")); + +var client = matrix.createClient("http://matrix.org"); +client.publicRooms(function (err, data) { + console.log("data %s", JSON.stringify(data)); + console.error("err %s", JSON.stringify(err)); +}); diff --git a/examples/node/lib/matrix.js b/examples/node/lib/matrix.js new file mode 100644 index 000000000..d04a39593 --- /dev/null +++ b/examples/node/lib/matrix.js @@ -0,0 +1,605 @@ +"use strict"; + +/* +TODO: +- CS: complete register function (doing stages) +- Internal: rate limiting +- Identity server: linkEmail, authEmail, bindEmail, lookup3pid +- uploadContent (?) +*/ + +// wrap in a closure for browsers +var init = function(exports){ + // expose the underlying request object so different environments can use + // different request libs (e.g. request or browser-request) + var request; + exports.request = function(r) { + request = r; + }; + + // entry point + function MatrixClient(credentials) { + if (typeof credentials === "string") { + credentials = { + "baseUrl": credentials + }; + } + var requiredKeys = [ + "baseUrl" + ]; + for (var i=0; i 0) { + // these are thumbnailing params so they probably want the + // thumbnailing API... + prefix = "/_matrix/media/v1/thumbnail/"; + } + + var fragmentOffset = serverAndMediaId.indexOf("#"), + fragment = ""; + if (fragmentOffset >= 0) { + fragment = serverAndMediaId.substr(fragmentOffset); + serverAndMediaId = serverAndMediaId.substr(0, fragmentOffset); + } + return this.credentials.baseUrl + prefix + serverAndMediaId + + (Object.keys(params).length === 0 ? "" : + ("?" + encodeParams(params))) + fragment; + }, + + getIdenticonUri: function(identiconString, width, height) { + if (!identiconString) { + return; + } + if (!width) { width = 96; } + if (!height) { height = 96; } + var params = { + width: width, + height: height + }; + + var path = encodeUri("/_matrix/media/v1/identicon/$ident", { + $ident: identiconString + }); + return this.credentials.baseUrl + path + + (Object.keys(params).length === 0 ? "" : + ("?" + encodeParams(params))); + }, + + /** + * Get the content repository url with query parameters. + * @returns An object with a 'base', 'path' and 'params' for base URL, + * path and query parameters respectively. + */ + getContentUri: function() { + var params = { + access_token: this.credentials.accessToken + }; + return { + base: this.credentials.baseUrl, + path: "/_matrix/media/v1/upload", + params: params + }; + }, + + // Internals + // ========= + + _doAuthedRequest: function(callback, method, path, params, data) { + if (!params) { params = {}; } + params.access_token = this.credentials.accessToken; + return this._doRequest(callback, method, path, params, data); + }, + + _doRequest: function(callback, method, path, params, data) { + var fullUri = this.credentials.baseUrl + CLIENT_PREFIX + path; + if (!params) { params = {}; } + return this._request(callback, method, fullUri, params, data); + }, + + _request: function(callback, method, uri, params, data) { + console.log(" => %s", uri); + console.log(" %s", JSON.stringify(data)); + if (callback !== undefined && !isFunction(callback)) { + throw Error("Expected callback to be a function"); + } + + return request( + { + uri: uri, + method: method, + withCredentials: false, + qs: params, + body: data, + json: true, + headers: HEADERS + }, + requestCallback(callback) + ); + } + }; + + var encodeUri = function(pathTemplate, variables) { + for (var key in variables) { + if (!variables.hasOwnProperty(key)) { continue; } + pathTemplate = pathTemplate.replace( + key, encodeURIComponent(variables[key]) + ); + } + return pathTemplate; + }; + + // avoiding deps on jquery and co + var encodeParams = function(params) { + var qs = ""; + for (var key in params) { + if (!params.hasOwnProperty(key)) { continue; } + qs += "&" + encodeURIComponent(key) + "=" + + encodeURIComponent(params[key]); + } + return qs.substring(1); + }; + + var requestCallback = function(userDefinedCallback) { + if (!userDefinedCallback) { + return undefined; + } + return function(err, response, body) { + if (err) { + return userDefinedCallback(err); + } + if (response.statusCode >= 400) { + return userDefinedCallback(body); + } + else { + userDefinedCallback(null, body); + } + }; + }; + + var isFunction = function(value) { + return Object.prototype.toString.call(value) == "[object Function]"; + }; +}; + +if (typeof exports === 'undefined') { + init(this['matrixcs']={}); // this assigns to "window" on browsers +} +else { + init(exports); +} \ No newline at end of file