Browse Source

client source

tags/v1.0.0-alpha.0
ojizero 1 year ago
parent
commit
26b1f5197b
No account linked to committer's email address
6 changed files with 134 additions and 38 deletions
  1. 1
    0
      .node-version
  2. 4
    1
      .npmignore
  3. 123
    5
      src/client.ts
  4. 2
    28
      src/index.ts
  5. 3
    3
      src/method.ts
  6. 1
    1
      test/client.spec.ts

+ 1
- 0
.node-version View File

@@ -0,0 +1 @@
11.5.0

+ 4
- 1
.npmignore View File

@@ -1 +1,4 @@
# TODO:
./src
./test
./examples
./tsconfig*.json

+ 123
- 5
src/client.ts View File

@@ -1,6 +1,33 @@
import got, { GotFn } from 'got'
import { RequestOptions } from 'https'
import querystring from 'querystring'
import { IncomingHttpHeaders } from 'http';
import { OutgoingHttpHeaders } from 'http'
import defaultsDeep from 'lodash.defaultsdeep'

export enum AuthenticationTypes {
BasicAuth = 'basic',
TokenAuth = 'token',
ApiKeyAuth = 'key',
BearerAuth = 'bearer',
}

export interface Authentication {
type: AuthenticationTypes,
username?: string,
password?: string,
authToken?: string,
}

interface AuthSpec {
useHeader: boolean,
usePayload: boolean,
useQueryString: boolean,

key: string,
value: string,
}

export type Seconds = number

export interface Response {
status: {
@@ -12,15 +39,28 @@ export interface Response {
_rawResponse: got.Response<any>, // raw string response
}

export interface Config {
baseUrl: string,
// protocol?: 'http' | 'https',
// port?: number,
headers?: OutgoingHttpHeaders,
authentication?: Authentication,
retries?: number,
timeout?: Seconds,
onError?: 'reject' | 'resolve',
}

export interface Client {
request (method: string, path: string, payload: {}, options: any): Promise<Response>
}

export class PortalClient implements Client {
client: GotFn
config: Config

constructor (client: GotFn) {
constructor (client: GotFn, config: Config) {
this.client = client
this.config = config
}

async request (method: string, path: string, payload: {}, options: any): Promise<Response> {
@@ -33,16 +73,94 @@ export class PortalClient implements Client {
code: response.statusCode,
word: response.statusMessage,
},
body: response.body,
body: response.body, // TODO: should it be parsed if needed ?
headers: response.headers,
_rawResponse: response,
}
}

constructRequestOptions (method: string, path: string, payload: {}, options: any): RequestOptions {
constructRequestOptions (method: string, path: string, payload: { [k: string]: any }, options: any): { [s: string]: any } {
const {
baseUrl,
headers,
retries,
timeout,
onError,
authentication,
} = defaultsDeep({
// port: 443,
retries: 0,
headers: {},
timeout: 30_000,
onError: 'reject',
// protocol: 'https',
}, this.config, options)

if (typeof authentication !== 'undefined') {
const {
useHeader,
usePayload,
useQueryString,
key,
value,
} = this.setupAuthentication(authentication)

if (useHeader) {
headers[key] = value
} else if (usePayload) {
payload[key] = value
} else if (useQueryString) {
const [url, queryString = ''] = path.split('?', 2)

const query = querystring.parse(queryString)
query[key] = value

path = `${url}?${querystring.stringify(query)}`
}
}

const isJson = headers['Content-Type'] === 'application/json'

return {
// TODO:
method,
baseUrl,
url: path,
headers,
retries,
json: isJson,
timeout: timeout * 1000,
body: JSON.stringify(payload),
throwHttpErrors: onError !== 'resolve',
}
}

setupAuthentication (auth: Authentication): AuthSpec {
switch (auth.type) {
case AuthenticationTypes.BasicAuth: {
const token = Buffer.from(`${auth.username}:${auth.password}`).toString('base64')

return {
useHeader: true,
usePayload: false,
useQueryString: false,
key: 'Authorization',
value: `Basic ${token}`,
}
}

case AuthenticationTypes.BearerAuth: {

return {
useHeader: true,
usePayload: false,
useQueryString: false,
key: 'Authorization',
value: `Bearer ${auth.authToken}`,
}
}
}

throw new Error('TODO: givem me a meangingful error')
}
}


+ 2
- 28
src/index.ts View File

@@ -1,35 +1,9 @@
import Client from './client'
import PortalClient, { Client, Config } from './client'

import method, { MethodFactory } from './method'
import resrouceGenerator, { ResourceFactory } from './resource'

import { URL } from 'url' // TODO: declare it instead of importing it
import got from 'got'
import { OutgoingHttpHeaders } from 'http'

export enum AuthenticationTypes {
BasicAuth = 'basic',
TokenAuth = 'token',
KeyAuth = 'key',
BearerAuth = 'bearer',
}

export type Seconds = number

export type BaseUrl = string | URL

export interface Authentication {
type: AuthenticationTypes,
}

export interface Config {
baseUrl: BaseUrl,
headers?: OutgoingHttpHeaders,
authentication?: Authentication,
retries?: number,
timeout?: Seconds,
onError?: 'reject' | 'resolve',
}

export interface Portal {
route: MethodFactory,
@@ -38,7 +12,7 @@ export interface Portal {
}

export function createBaseClient (config: Config): Portal {
const client = new Client(got) // TODO:
const client = new PortalClient(got, config)

const portal: Portal = {
route: method(client),

+ 3
- 3
src/method.ts View File

@@ -1,4 +1,4 @@
import { Client } from './client'
import { Client, Response } from './client'

import defaults from 'lodash.defaultsdeep'
import {
@@ -21,7 +21,7 @@ export interface MethodSpec {
// strict?: boolean,
}

export type RouteFunction = (...args: any[]) => Promise<any>
export type RouteFunction = (...args: any[]) => Promise<Response>
export type MethodFactory = (spec: MethodSpec) => RouteFunction

export function method (client: Client): MethodFactory {
@@ -43,7 +43,7 @@ export function method (client: Client): MethodFactory {
}
}

return async function (...args: any[]): Promise<any> {
return async function (...args: any[]): Promise<Response> {
let length = args.length

let query

+ 1
- 1
test/client.spec.ts View File

@@ -4,6 +4,6 @@ describe('Client', () => {
let client

before(() => {
client = new Client()
// client = new Client()
})
})

Loading…
Cancel
Save