From ff5e5dec14186daa4be1bd81e9d0bf2e683164c1 Mon Sep 17 00:00:00 2001 From: Derrick Hammer Date: Tue, 19 Mar 2024 07:20:11 -0400 Subject: [PATCH] refactor: major refactor of the providers and resources to be more dynamic and flexible --- app/data/account-provider.ts | 11 ++ app/data/auth-provider.ts | 216 ++++++++++++++--------------------- app/data/file-provider.ts | 5 +- app/data/providers.ts | 31 +++++ app/data/resources.ts | 18 +++ app/data/sdk-provider.ts | 6 + app/root.tsx | 29 ++--- vite-env.d.ts | 9 ++ 8 files changed, 177 insertions(+), 148 deletions(-) create mode 100644 app/data/account-provider.ts create mode 100644 app/data/providers.ts create mode 100644 app/data/resources.ts create mode 100644 app/data/sdk-provider.ts create mode 100644 vite-env.d.ts diff --git a/app/data/account-provider.ts b/app/data/account-provider.ts new file mode 100644 index 0000000..5028718 --- /dev/null +++ b/app/data/account-provider.ts @@ -0,0 +1,11 @@ +import type { DataProvider } from "@refinedev/core"; +import {SdkProvider} from "~/data/sdk-provider.js"; + +export const accountProvider: SdkProvider = { + getList: () => { throw Error("Not Implemented") }, + getOne: () => { throw Error("Not Implemented") }, + update: () => { throw Error("Not Implemented") }, + create: () => { throw Error("Not Implemented") }, + deleteOne: () => { throw Error("Not Implemented") }, + getApiUrl: () => "", +} diff --git a/app/data/auth-provider.ts b/app/data/auth-provider.ts index 7a96734..f7c211d 100644 --- a/app/data/auth-provider.ts +++ b/app/data/auth-provider.ts @@ -31,134 +31,94 @@ export type Identity = { email: string; } -export class PortalAuthProvider implements RequiredAuthProvider { - constructor(apiUrl: string) { - this._sdk = Sdk.create(apiUrl); - - const methods: Array = [ - 'login', - 'logout', - 'check', - 'onError', - 'register', - 'forgotPassword', - 'updatePassword', - 'getPermissions', - 'getIdentity', - ]; - - methods.forEach((method) => { - this[method] = this[method]?.bind(this) as any; - }); - } - - private _sdk: Sdk; - - get sdk(): Sdk { - return this._sdk; - } - - public static create(apiUrl: string): AuthProvider { - return new PortalAuthProvider(apiUrl); - } - - async login(params: AuthFormRequest): Promise { - const ret = await this._sdk.account().login({ - email: params.email, - password: params.password, - }) - - let redirectTo: string | undefined; - - if (ret) { - redirectTo = params.redirectTo; - if (!redirectTo) { - redirectTo = ret ? "/dashboard" : "/login"; - } - this._sdk.setAuthToken(this._sdk.account().jwtToken); - } - - return { - success: ret, - redirectTo, - }; - } - - async logout(params: any): Promise { - let ret = await this._sdk.account().logout(); - return {success: ret, redirectTo: "/login"}; - } - - async check(params?: any): Promise { - const ret = await this._sdk.account().ping(); - - if(ret){ - this.maybeSetupAuth(); - } - - return {authenticated: ret, redirectTo: ret ? undefined : "/login"}; - } - - async onError(error: any): Promise { - return {logout: true}; - } - - async register(params: RegisterFormRequest): Promise { - const ret = await this._sdk.account().register({ - email: params.email, - password: params.password, - first_name: params.firstName, - last_name: params.lastName, - }); - return {success: ret, redirectTo: ret ? "/dashboard" : undefined}; - } - - async forgotPassword(params: any): Promise { - return {success: true}; - } - - async updatePassword(params: any): Promise { - return {success: true}; - } - - async getPermissions(params?: Record): Promise { - return {success: true}; - } - - async getIdentity(params?: Identity): Promise { - this.maybeSetupAuth(); - const ret = await this._sdk.account().info(); - - if (!ret) { - return {identity: null}; - } - - const acct = ret as AccountInfoResponse; - - return { - id: acct.id, - firstName: acct.first_name, - lastName: acct.last_name, - email: acct.email, - }; - } - - maybeSetupAuth(): void { - const jwt = this._sdk.account().jwtToken +export const createPortalAuthProvider = (sdk: Sdk): AuthProvider => { + const maybeSetupAuth = (): void => { + const jwt = sdk.account().jwtToken; if (jwt) { - this._sdk.setAuthToken(jwt); + sdk.setAuthToken(jwt); } - } -} + }; -export interface RequiredAuthProvider extends AuthProvider { - login: AuthProvider['login']; - logout: AuthProvider['logout']; - check: AuthProvider['check']; - onError: AuthProvider['onError']; - register: AuthProvider['register']; - forgotPassword: AuthProvider['forgotPassword']; - updatePassword: AuthProvider['updatePassword']; - getPermissions: AuthProvider['getPermissions']; - getIdentity: AuthProvider['getIdentity']; -} + return { + async login(params: AuthFormRequest): Promise { + const ret = await sdk.account().login({ + email: params.email, + password: params.password, + }); + + let redirectTo: string | undefined; + + if (ret) { + redirectTo = params.redirectTo; + if (!redirectTo) { + redirectTo = ret ? "/dashboard" : "/login"; + } + sdk.setAuthToken(sdk.account().jwtToken); + } + + return { + success: ret, + redirectTo, + }; + }, + + async logout(params: any): Promise { + let ret = await sdk.account().logout(); + return { success: ret, redirectTo: "/login" }; + }, + + async check(params?: any): Promise { + const ret = await sdk.account().ping(); + + if (ret) { + maybeSetupAuth(); + } + + return { authenticated: ret, redirectTo: ret ? undefined : "/login" }; + }, + + async onError(error: any): Promise { + return { logout: true }; + }, + + async register(params: RegisterFormRequest): Promise { + const ret = await sdk.account().register({ + email: params.email, + password: params.password, + first_name: params.firstName, + last_name: params.lastName, + }); + return { success: ret, redirectTo: ret ? "/dashboard" : undefined }; + }, + + async forgotPassword(params: any): Promise { + return { success: true }; + }, + + async updatePassword(params: any): Promise { + return { success: true }; + }, + + async getPermissions(params?: Record): Promise { + return { success: true }; + }, + + async getIdentity(params?: Identity): Promise { + maybeSetupAuth(); + const ret = await sdk.account().info(); + + if (!ret) { + return { identity: null }; + } + + const acct = ret as AccountInfoResponse; + + return { + id: acct.id, + firstName: acct.first_name, + lastName: acct.last_name, + email: acct.email, + }; + }, + }; +}; diff --git a/app/data/file-provider.ts b/app/data/file-provider.ts index 004d6b1..4d89673 100644 --- a/app/data/file-provider.ts +++ b/app/data/file-provider.ts @@ -1,10 +1,11 @@ import type { DataProvider } from "@refinedev/core"; +import {SdkProvider} from "~/data/sdk-provider.js"; -export const defaultProvider: DataProvider = { +export const fileProvider: SdkProvider = { getList: () => { throw Error("Not Implemented") }, getOne: () => { throw Error("Not Implemented") }, update: () => { throw Error("Not Implemented") }, create: () => { throw Error("Not Implemented") }, deleteOne: () => { throw Error("Not Implemented") }, getApiUrl: () => "", -} \ No newline at end of file +} diff --git a/app/data/providers.ts b/app/data/providers.ts new file mode 100644 index 0000000..ee47b55 --- /dev/null +++ b/app/data/providers.ts @@ -0,0 +1,31 @@ +import type {AuthProvider, DataProvider} from "@refinedev/core"; +import {fileProvider} from "~/data/file-provider.js"; +import {Sdk} from "@lumeweb/portal-sdk"; +import {accountProvider} from "~/data/account-provider.js"; +import type {SdkProvider} from "~/data/sdk-provider.js"; +import {createPortalAuthProvider} from "~/data/auth-provider.js"; + +interface DataProviders { + default: SdkProvider; + auth: AuthProvider; + + [key: string]: SdkProvider | AuthProvider; +} + +let providers: DataProviders; + +export function getProviders(sdk: Sdk) { + if (providers) { + return providers; + } + + accountProvider.sdk = sdk; + fileProvider.sdk = sdk; + providers = { + default: accountProvider, + auth: createPortalAuthProvider(sdk), + files: fileProvider, + }; + + return providers; +} diff --git a/app/data/resources.ts b/app/data/resources.ts new file mode 100644 index 0000000..d36d69e --- /dev/null +++ b/app/data/resources.ts @@ -0,0 +1,18 @@ +import type {ResourceProps} from "@refinedev/core"; + +const resources: ResourceProps[] = [ + { + name: 'account', + meta: { + dataProviderName: 'default', + } + }, + { + name: 'file', + meta: { + dataProviderName: 'files', + } + } +]; + +export default resources; diff --git a/app/data/sdk-provider.ts b/app/data/sdk-provider.ts new file mode 100644 index 0000000..c5fbcea --- /dev/null +++ b/app/data/sdk-provider.ts @@ -0,0 +1,6 @@ +import {DataProvider} from "@refinedev/core"; +import {Sdk} from "@lumeweb/portal-sdk"; + +export interface SdkProvider extends DataProvider { + sdk?: Sdk; +} diff --git a/app/root.tsx b/app/root.tsx index a825abd..f44d8b2 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -1,21 +1,16 @@ -import { - Links, - Meta, - Outlet, - Scripts, - ScrollRestoration, -} from "@remix-run/react"; +import {Links, Meta, Outlet, Scripts, ScrollRestoration,} from "@remix-run/react"; import stylesheet from "./tailwind.css?url"; -import type { LinksFunction } from "@remix-run/node"; +import type {LinksFunction} from "@remix-run/node"; // Supports weights 200-800 import '@fontsource-variable/manrope'; import {Refine} from "@refinedev/core"; -import {PortalAuthProvider} from "~/data/auth-provider.js"; import routerProvider from "@refinedev/remix-router"; -import { defaultProvider } from "./data/file-provider"; import {SdkContextProvider} from "~/components/lib/sdk-context.js"; +import {getProviders} from "~/data/providers.js"; +import {Sdk} from "@lumeweb/portal-sdk"; +import resources from "~/data/resources.js"; export const links: LinksFunction = () => [ { rel: "stylesheet", href: stylesheet }, @@ -40,19 +35,17 @@ export function Layout({children}: { children: React.ReactNode }) { } export default function App() { - const auth = PortalAuthProvider.create("https://alpha.pinner.xyz") + const sdk = Sdk.create(import.meta.env.VITE_PORTAL_URL) + const providers = getProviders(sdk); return ( - + diff --git a/vite-env.d.ts b/vite-env.d.ts new file mode 100644 index 0000000..5f868a8 --- /dev/null +++ b/vite-env.d.ts @@ -0,0 +1,9 @@ +/// + +interface ImportMetaEnv { + readonly VITE_PORTAL_API_URL: string +} + +interface ImportMeta { + readonly env: ImportMetaEnv +}