Improve Client Library

The following were done:
- Make it work with a front end example (for RESTful feature).
- Make npm run build work properly.
- Refine methods list.
- Introduce supabase.unsubscribe().
- Clean up BaseRequest.js.
- Clean up BaseChannel.js.
- Implement Helpers.js to introduce uuid().
This commit is contained in:
Angelico
2020-01-08 17:45:47 +08:00
parent 6008777cbd
commit 3f4afdcdfd
5 changed files with 51 additions and 44 deletions

View File

@@ -40,9 +40,9 @@
"babel-plugin-add-module-exports": "^1.0.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.1",
"babel-preset-minify": "^0.5.0",
"babel-preset-minify": "^0.3.0",
"chai": "^4.1.2",
"cross-env": "^5.1.3",
"cross-env": "^5.2.1",
"mocha": "^6.1.3",
"nyc": "^13.3.0",
"rimraf": "^2.6.2"

View File

@@ -1,10 +1,10 @@
import { Socket } from 'phoenix-channels'
export default class BaseChannel {
constructor(tableName, apiSocket){
constructor(tableName, apiSocket, uuid){
this.socket = new Socket(apiSocket)
this.uuid = uuid
this.channel = this.socket.channel(tableName)
this.listeners = {}
this.start()
@@ -17,23 +17,7 @@ export default class BaseChannel {
}
on(eventName, callbackFunction){
let ref = this.channel.on(eventName, callbackFunction)
this.listeners[ref] = eventName
return ref
}
off(eventName, ref = null){
// if ref is null, we just want to remove everything that has the eventName
if(typeof ref === 'null'){
for (var ref in this.listeners){
let eventNameValue = this.listeners[ref]
if(eventName === eventNameValue){
this.off(eventName, ref)
}
}
}
this.channel.off(eventName, ref)
this.channel.on(eventName, callbackFunction)
}
start(){

View File

@@ -34,7 +34,7 @@ class BaseRequest extends Request {
*
* @param {string|object} The user, bearer token, or user/pass object.
* @param {string|void} The pass or undefined.
* @returns {ApiRequest} The API request object.
* @returns {BaseRequest} The API request object.
*/
auth (user, pass) {
@@ -56,7 +56,7 @@ class BaseRequest extends Request {
* All values are prefixed with `eq.`.
*
* @param {object} The object to match against.
* @returns {ApiRequest} The API request object.
* @returns {BaseRequest} The API request object.
*/
match (query) {
@@ -70,7 +70,7 @@ class BaseRequest extends Request {
* set as a query string value. Also always forces a root @id column.
*
* @param {string} The unformatted select string.
* @returns {ApiRequest} The API request object.
* @returns {BaseRequest} The API request object.
*/
select (select) {
@@ -87,7 +87,7 @@ class BaseRequest extends Request {
* @param {string} The property name to order by.
* @param {bool} True for descending results, false by default.
* @param {bool} True for nulls first, false by default.
* @returns {ApiRequest} The API request object.
* @returns {BaseRequest} The API request object.
*/
order (property, ascending = false, nullsFirst = false) {
@@ -101,7 +101,7 @@ class BaseRequest extends Request {
*
* @param {number} The first object to select.
* @param {number|void} The last object to select.
* @returns {ApiRequest} The API request object.
* @returns {BaseRequest} The API request object.
*/
range (from, to) {
@@ -114,7 +114,7 @@ class BaseRequest extends Request {
* Sets the header which signifies to PostgREST the response must be a single
* object or 404.
*
* @returns {ApiRequest} The API request object.
* @returns {BaseRequest} The API request object.
*/
single () {
@@ -135,20 +135,22 @@ class BaseRequest extends Request {
return reject(error)
}
const { body, headers } = response
const { body, headers, status, statusCode, statusText } = response
const contentRange = headers['content-range']
if (Array.isArray(body) && contentRange && contentRangeStructure.test(contentRange)) {
body.fullLength = parseInt(contentRangeStructure.exec(contentRange)[3], 10)
}
return resolve(body)
const returnBody = { body, status, statusCode, statusText}
return resolve(returnBody)
})
)
}
/**
* Makes the ApiRequest object then-able. Allows for usage with
* Makes the BaseRequest object then-able. Allows for usage with
* `Promise.resolve` and async/await contexts. Just a proxy for `.then()` on
* the promise returned from `.end()`.
*
@@ -178,13 +180,13 @@ class BaseRequest extends Request {
*
* @param {string} The name of the column.
* @param {any} The value of the column to be filtered.
* @returns {ApiRequest} The API request object.
* @returns {BaseRequest} The API request object.
*/
const filters = ['eq', 'gt', 'lt', 'gte', 'lte', 'like', 'ilike', 'is', 'in', 'not']
filters.forEach(filter =>
ApiRequest.prototype[filter] = function filterValue (name, value) {
BaseRequest.prototype[filter] = function filterValue (name, value) {
return this.query(`${name}=${filter}.${Array.isArray(value) ? value.join(',') : value}`)
}
)

View File

@@ -1,20 +1,32 @@
import BaseRequest from './BaseRequest'
import BaseChannel from './BaseChannel'
import { uuid } from './utils/Helpers'
class SupabaseClient {
constructor(supbaseUrl, supabaseKey, options) {
constructor(supabaseUrl, supabaseKey, options) {
this.supabaseUrl = supabaseUrl
this.supabaseKey = supabaseKey
// this will be the case for now
this.restUrl = supabaseUrl
this.apiSocket = ''
this.subscriptions = {}
}
/**
* @todo
*/
subscribe (tableName) {
return new BaseChannel(tableName, this.apiSocket)
subscribe(tableName) {
let uuid = uuid()
this.subscriptions[uuid] = new BaseChannel(tableName, this.apiSocket, uuid)
return this.subscriptions[uuid]
}
unsubscribe(subscription){
subscription.stop()
delete this.subscriptions[subscription.uuid]
}
/**
@@ -26,9 +38,10 @@ class SupabaseClient {
* @returns {BaseRequest} The API request object.
*/
request (method, path) {
request(method, path) {
return new BaseRequest(method, this.restUrl + path)
}
}
/**
@@ -38,23 +51,23 @@ class SupabaseClient {
* @returns {BaseRequest} The API request object.
*/
const methods = ['POST', 'GET', 'PATCH', 'PUT', 'DELETE']
const methods = ['POST', 'GET', 'PATCH', 'DELETE']
methods.forEach(method =>
SupabaseClient.prototype[method.toLowerCase()] = tableName => {
path = `/${tableName}`
methods.forEach(method => {
SupabaseClient.prototype[method.toLowerCase()] = function requestMethod(tableName) {
let path = `/${tableName}`
return this.request(method, path)
}
)
})
const createClient = (supabaseUrl, supabaseKey, options = {}) => {
return new SupabaseClient(supabseUrl, supabaseKey, options)
return new SupabaseClient(supabaseUrl, supabaseKey, options)
}
export { createClient }
/**
* TO BE REMOVED SOON
* TO BE REMOVED SOON
*/
// const defaultAwesomeFunction = (name) => {

View File

@@ -0,0 +1,8 @@
export function uuid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1)
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4()
}