Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update TS types #23

Merged
merged 7 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ jobs:
- run: pnpm install --no-optional
- run: pnpm lint
- run: pnpm test
- run: pnpm build
- run: pnpm typecheck
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"scripts": {
"build": "pnpm --filter '@parallelmarkets/*' build",
"lint": "pnpm -r lint",
"test": "pnpm -r test"
"test": "pnpm -r test",
"typecheck": "pnpm -r typecheck"
},
"keywords": [
"ParallelMarkets"
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/__tests__/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import React from 'react'
import { ParallelProvider, PassportButton } from '../index'

const ParallelMock = {
getProfile: (cb, _eb) => cb({}),
getLoginStatus: (cb) => cb({}),
subscribe: () => null,
unsubscribe: () => null,
Expand Down
25 changes: 3 additions & 22 deletions packages/react/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import React, { PropsWithChildren, createContext, useContext, useEffect, useState } from 'react'
import ButtonImg from './medium-passport-button.svg'

import { ParallelApiRecord, loadParallel } from '@parallelmarkets/vanilla'
import type { AuthCallbackResult, Parallel } from '@parallelmarkets/vanilla'
import { ProfileApiResponse } from './profile_api_types'

export * from './profile_api_types'
import { loadParallel } from '@parallelmarkets/vanilla'
import type { AuthCallbackResult, ProfileApiResponse } from '@parallelmarkets/vanilla'

type LoadParallelPromise = ReturnType<typeof loadParallel>
type LoadParallelResult = Awaited<ReturnType<typeof loadParallel>>
Expand All @@ -29,22 +26,6 @@ const isPromise = (thing: unknown): thing is PromiseLike<unknown> => {
return typeof (thing as PromiseLike<unknown>)?.then === 'function'
}

// The Embed API works with callback functions. This wrapper converts them to promises.
const promisifyApiCall = <ResultType extends ParallelApiRecord>(parallel: Parallel, endpoint: string) => {
return () => {
// This promise resolves with the type of the API's Success Callback function's first Parameter
return new Promise<ResultType>((resolve, reject) => {
parallel.api(
endpoint,
(result) => {
resolve(result as ResultType)
},
reject,
)
})
}
}

export const useParallel = () => {
const { parallel: parallelPromise } = useContext(ParallelContext)
const [parallel, setParallel] = useState<LoadParallelResult>(null)
Expand Down Expand Up @@ -104,7 +85,7 @@ export const useParallel = () => {
parallel,
error,
loginStatus,
getProfile: promisifyApiCall<ProfileApiResponse>(parallel, '/profile'),
getProfile: new Promise<ProfileApiResponse>(parallel.getProfile),
login: parallel.login,
logout: parallel.logout,
}
Expand Down
36 changes: 0 additions & 36 deletions packages/react/src/profile_api_types.ts

This file was deleted.

13 changes: 7 additions & 6 deletions packages/vanilla/src/__tests__/index-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,23 @@ declare global {
}

global.window.Parallel = {
get _config() {
return window.config
},
init: ({ on_init, ...params }: ParallelConfig) => {
window.config = params
on_init?.()
},
api: () => null,
getLoginStatus: () => null,
getProfile: () => null,
login: () => null,
logout: () => null,
unsubscribe: () => null,
subscribe: () => null,
showButton: () => null,
hideButton: () => null,
unsubscribe: () => null,
getLoginStatus: () => null,
subscribeWithButton: () => null,
_appendLoadContext: () => null,
get _config() {
return window.config
},
}

test('Configuration is set correctly', async () => {
Expand Down
29 changes: 0 additions & 29 deletions packages/vanilla/src/common_api_types.ts

This file was deleted.

1 change: 0 additions & 1 deletion packages/vanilla/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Parallel, ParallelConfig } from './types'

export * from './types'
export * from './common_api_types'

const V2_URL = 'https://app.parallelmarkets.com/sdk/v2/parallel.js'
let parallelPromise: Promise<Parallel | null> | undefined
Expand Down
74 changes: 59 additions & 15 deletions packages/vanilla/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
import { type BusinessType } from './common_api_types'
export type EntityKind = 'individual' | 'business'

export type BusinessType =
| 'Public Charity'
| 'Private Foundation'
| 'S Corporation'
| 'C Corporation'
| 'Irrevocable Trust'
| 'Revocable Trust'
| 'Family Office'
| 'Limited Liability Company'
| 'Limited Partnership'

/* eslint-disable @typescript-eslint/no-explicit-any */
type AuthResponse = {
Expand All @@ -16,17 +27,19 @@ export type AuthCallbackResult = {
errorDescription?: string
}

// https://developer.parallelmarkets.com/docs/server/scopes
export type ParallelScope = 'profile' | 'accreditation_status' | 'identity' | 'blockchain'
// https://developer.parallelmarkets.com/docs/javascript/configuration#scopes
export type ParallelScope = 'profile' | 'accreditation_status' | 'identity'

// https://developer.parallelmarkets.com/docs/javascript/configuration
type EmbedParallelConfig = {
flow_type: 'embed'
embed_into_id: string
}

type OverlayRedirectParallelConfig = {
flow_type: 'overlay' | 'redirect'
}

export type ParallelConfig = (EmbedParallelConfig | OverlayRedirectParallelConfig) & {
client_id?: string
environment?: 'production' | 'demo'
Expand All @@ -40,21 +53,47 @@ export type ParallelConfig = (EmbedParallelConfig | OverlayRedirectParallelConfi
raw_config?: Record<string, any>
}

export type IndividualProfile = {
email: string
first_name: string
last_name: string
}

export type BusinessProfile = {
name: string
business_type: BusinessType
primary_contact: IndividualProfile
}

export type ProfileApiResponse = {
id: string
type: EntityKind
profile: IndividualProfile | BusinessProfile
user_id: string
user_profile: IndividualProfile
user_providing_for: 'self' | 'controlled-business' | 'other-individual'
access_expires_at: string | null
access_revoked_by: 'subject' | 'partner' | 'system' | null
available_scopes: Array<ParallelScope>
}

type GetProfileSuccessCallbackFunc = (_result: ProfileApiResponse) => void

type GetProfileFailureCallbackFunc = (_result: { error: unknown }) => void

type AuthSuccessCallbackFunc = (_result: AuthCallbackResult) => void
type AuthFailureCallbackFunc = (_result: { error: unknown }) => void

// TODO: implement this
export type ParallelApiRecord = Record<string, any>
export type ParallelApiSuccessCallback = (_response: ParallelApiRecord) => void
export type ParallelApiErrorCallback = (_reason: any) => void
type AuthFailureCallbackFunc = (_result: { error: unknown }) => void

type SubscribeEvents = 'auth.login' | 'auth.logout' | 'auth.statusChange' | 'auth.authResponseChange'

type OAuthErrorCode =
| 'invalid_request'
| 'invalid_client'
| 'invalid_grant'
| 'unauthorized_client'
| 'unsupported_grant_type'

type SubscriptionEvent = {
status: 'not_authorized' | 'unknown' | 'connected'
error?: OAuthErrorCode
Expand All @@ -67,37 +106,42 @@ type SubscriptionEvent = {
refresh_expires_in: number
}
}

type SubscriptionHandler = (_response: SubscriptionEvent) => void

export interface LoginOptions {
email?: string
first_name?: string
last_name?: string
external_id?: string
expected_entity_id?: string
expected_entity_type?: 'self' | BusinessType
expected_business_name?: string
partner_supporting?: string
ref_code?: string
redirect_uri_signature?: string
required_entity_id?: string
}

export interface Parallel {
init(_options: ParallelConfig): void
_config: ParallelConfig
getLoginStatus: (_callback: AuthSuccessCallbackFunc) => void
getProfile: (_successFunc: GetProfileSuccessCallbackFunc, _errorFunc: GetProfileFailureCallbackFunc) => void
login: (_options?: LoginOptions) => void
logout: () => void
subscribeWithButton: (_successFunc: AuthSuccessCallbackFunc, _errorFunc: AuthFailureCallbackFunc) => void
unsubscribe: (_event: SubscribeEvents, _callback: SubscriptionHandler) => void
subscribe: (_event: SubscribeEvents, _callback: SubscriptionHandler) => void
showButton: () => void
hideButton: () => void
api: (_endpoint: string, _callback: ParallelApiSuccessCallback, _errback: ParallelApiErrorCallback) => void
subscribe: (_event: SubscribeEvents, _callback: SubscriptionHandler) => void
unsubscribe: (_event: SubscribeEvents, _callback: SubscriptionHandler) => void
getLoginStatus: (_callback: AuthSuccessCallbackFunc) => void
subscribeWithButton: (_successFunc: AuthSuccessCallbackFunc, _errorFunc: AuthFailureCallbackFunc) => void
_appendLoadContext: (_context: string) => void
_config: ParallelConfig
}

declare global {
interface Window {
// parallel.js must be loaded directly from app.parallelmarkets.com/sdk/v2/parallel.js
// which places a `Paralell` object at the window level
// which places a `Parallel` object at the window level
Parallel?: Parallel
}
}
Loading