From 12d1a4d460ef1ec70cd8a42d6f89faee094687e6 Mon Sep 17 00:00:00 2001 From: Kai Peacock Date: Fri, 2 Aug 2024 13:28:10 -0700 Subject: [PATCH] basic working example and test --- package-lock.json | 4 + packages/use-auth-client/.npmignore | 11 +++ .../packages/use-auth-client/src/index.d.ts | 1 + .../cjs/packages/use-auth-client/src/index.js | 17 ++++ .../use-auth-client/src/use-auth-client.d.ts | 29 ++++++ .../use-auth-client/src/use-auth-client.js | 92 +++++++++++++++++++ .../packages/use-auth-client/src/index.d.ts | 1 + .../esm/packages/use-auth-client/src/index.js | 1 + .../use-auth-client/src/use-auth-client.d.ts | 29 ++++++ .../use-auth-client/src/use-auth-client.js | 65 +++++++++++++ packages/use-auth-client/package.json | 5 + .../use-auth-client/src/use-auth-client.ts | 2 + packages/use-auth-client/tsconfig-cjs.json | 7 ++ packages/use-auth-client/tsconfig.json | 4 +- 14 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 packages/use-auth-client/.npmignore create mode 100644 packages/use-auth-client/lib/cjs/packages/use-auth-client/src/index.d.ts create mode 100644 packages/use-auth-client/lib/cjs/packages/use-auth-client/src/index.js create mode 100644 packages/use-auth-client/lib/cjs/packages/use-auth-client/src/use-auth-client.d.ts create mode 100644 packages/use-auth-client/lib/cjs/packages/use-auth-client/src/use-auth-client.js create mode 100644 packages/use-auth-client/lib/esm/packages/use-auth-client/src/index.d.ts create mode 100644 packages/use-auth-client/lib/esm/packages/use-auth-client/src/index.js create mode 100644 packages/use-auth-client/lib/esm/packages/use-auth-client/src/use-auth-client.d.ts create mode 100644 packages/use-auth-client/lib/esm/packages/use-auth-client/src/use-auth-client.js create mode 100644 packages/use-auth-client/tsconfig-cjs.json diff --git a/package-lock.json b/package-lock.json index 4fa5bfca9..6a224e47e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23088,7 +23088,11 @@ "version": "2.0.0", "license": "ISC", "dependencies": { + "@dfinity/agent": "^2.0.0", "@dfinity/auth-client": "^2.0.0", + "@dfinity/candid": "^2.0.0", + "@dfinity/identity": "^2.0.0", + "@dfinity/principal": "^2.0.0", "react": ">16.8" }, "devDependencies": { diff --git a/packages/use-auth-client/.npmignore b/packages/use-auth-client/.npmignore new file mode 100644 index 000000000..eb725972f --- /dev/null +++ b/packages/use-auth-client/.npmignore @@ -0,0 +1,11 @@ +# We work with a safelist here, so block everything that's not permitted, and add packages +# that are. +** + +!lib/** +!types/**/*.d.ts +!package.json +!README.md + +# The following line further removes all test files (which matches .js and .d.ts). +lib/**/*.test.* diff --git a/packages/use-auth-client/lib/cjs/packages/use-auth-client/src/index.d.ts b/packages/use-auth-client/lib/cjs/packages/use-auth-client/src/index.d.ts new file mode 100644 index 000000000..8f216b2fa --- /dev/null +++ b/packages/use-auth-client/lib/cjs/packages/use-auth-client/src/index.d.ts @@ -0,0 +1 @@ +export * from './use-auth-client'; diff --git a/packages/use-auth-client/lib/cjs/packages/use-auth-client/src/index.js b/packages/use-auth-client/lib/cjs/packages/use-auth-client/src/index.js new file mode 100644 index 000000000..91f9e68e2 --- /dev/null +++ b/packages/use-auth-client/lib/cjs/packages/use-auth-client/src/index.js @@ -0,0 +1,17 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./use-auth-client"), exports); diff --git a/packages/use-auth-client/lib/cjs/packages/use-auth-client/src/use-auth-client.d.ts b/packages/use-auth-client/lib/cjs/packages/use-auth-client/src/use-auth-client.d.ts new file mode 100644 index 000000000..d45bc12ce --- /dev/null +++ b/packages/use-auth-client/lib/cjs/packages/use-auth-client/src/use-auth-client.d.ts @@ -0,0 +1,29 @@ +import { AuthClient, AuthClientCreateOptions, AuthClientLoginOptions, InternetIdentityAuthResponseSuccess } from '@dfinity/auth-client'; +import { Identity } from '@dfinity/agent'; +/** + * Options for the useAuthClient hook + */ +export type UseAuthClientOptions = { + /** + * Options passed during the creation of the auth client + */ + createOptions?: AuthClientCreateOptions; + /** + * Options passed during the login of the auth client + */ + loginOptions?: AuthClientLoginOptions; +}; +/** + * React hook to set up the Internet Computer auth client + * @param {UseAuthClientOptions} options configuration for the hook + * @see {@link UseAuthClientOptions} + * @param {AuthClientCreateOptions} options.createOptions - options passed during the creation of the auth client + * @param {AuthClientLoginOptions} options.loginOptions - + */ +export declare function useAuthClient(options?: UseAuthClientOptions): { + authClient: AuthClient; + identity: Identity; + isAuthenticated: boolean; + login: () => Promise; + logout: () => Promise; +}; diff --git a/packages/use-auth-client/lib/cjs/packages/use-auth-client/src/use-auth-client.js b/packages/use-auth-client/lib/cjs/packages/use-auth-client/src/use-auth-client.js new file mode 100644 index 000000000..09a12038e --- /dev/null +++ b/packages/use-auth-client/lib/cjs/packages/use-auth-client/src/use-auth-client.js @@ -0,0 +1,92 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.useAuthClient = void 0; +const React = __importStar(require("react")); +const auth_client_1 = require("@dfinity/auth-client"); +/** + * React hook to set up the Internet Computer auth client + * @param {UseAuthClientOptions} options configuration for the hook + * @see {@link UseAuthClientOptions} + * @param {AuthClientCreateOptions} options.createOptions - options passed during the creation of the auth client + * @param {AuthClientLoginOptions} options.loginOptions - + */ +function useAuthClient(options) { + const [authClient, setAuthClient] = React.useState(null); + const [identity, setIdentity] = React.useState(null); + const [isAuthenticated, setIsAuthenticated] = React.useState(false); + // load the auth client on mount + React.useEffect(() => { + auth_client_1.AuthClient.create(options?.createOptions).then(async (client) => { + setAuthClient(client); + setIdentity(client.getIdentity()); + setIsAuthenticated(await client.isAuthenticated()); + }); + }, []); + /** + * Login through your configured identity provider + * Wraps the onSuccess and onError callbacks with promises for convenience + * @returns {Promise} - Returns a promise that resolves to the response from the identity provider + */ + function login() { + return new Promise((resolve, reject) => { + if (authClient) { + const callback = options?.loginOptions?.onSuccess; + const errorCb = options?.loginOptions?.onError; + authClient.login({ + ...options?.loginOptions, + onSuccess: (successResponse) => { + if (successResponse !== undefined) { + callback?.(successResponse); + } + else { + callback?.(); + resolve(successResponse); + } + }, + onError: error => { + errorCb?.(error); + reject(error); + }, + }); + } + }); + } + async function logout() { + if (authClient) { + setIsAuthenticated(false); + setIdentity(null); + await authClient.logout(); + } + } + return { + authClient, + identity, + isAuthenticated, + login, + logout, + }; +} +exports.useAuthClient = useAuthClient; diff --git a/packages/use-auth-client/lib/esm/packages/use-auth-client/src/index.d.ts b/packages/use-auth-client/lib/esm/packages/use-auth-client/src/index.d.ts new file mode 100644 index 000000000..8f216b2fa --- /dev/null +++ b/packages/use-auth-client/lib/esm/packages/use-auth-client/src/index.d.ts @@ -0,0 +1 @@ +export * from './use-auth-client'; diff --git a/packages/use-auth-client/lib/esm/packages/use-auth-client/src/index.js b/packages/use-auth-client/lib/esm/packages/use-auth-client/src/index.js new file mode 100644 index 000000000..8f216b2fa --- /dev/null +++ b/packages/use-auth-client/lib/esm/packages/use-auth-client/src/index.js @@ -0,0 +1 @@ +export * from './use-auth-client'; diff --git a/packages/use-auth-client/lib/esm/packages/use-auth-client/src/use-auth-client.d.ts b/packages/use-auth-client/lib/esm/packages/use-auth-client/src/use-auth-client.d.ts new file mode 100644 index 000000000..d45bc12ce --- /dev/null +++ b/packages/use-auth-client/lib/esm/packages/use-auth-client/src/use-auth-client.d.ts @@ -0,0 +1,29 @@ +import { AuthClient, AuthClientCreateOptions, AuthClientLoginOptions, InternetIdentityAuthResponseSuccess } from '@dfinity/auth-client'; +import { Identity } from '@dfinity/agent'; +/** + * Options for the useAuthClient hook + */ +export type UseAuthClientOptions = { + /** + * Options passed during the creation of the auth client + */ + createOptions?: AuthClientCreateOptions; + /** + * Options passed during the login of the auth client + */ + loginOptions?: AuthClientLoginOptions; +}; +/** + * React hook to set up the Internet Computer auth client + * @param {UseAuthClientOptions} options configuration for the hook + * @see {@link UseAuthClientOptions} + * @param {AuthClientCreateOptions} options.createOptions - options passed during the creation of the auth client + * @param {AuthClientLoginOptions} options.loginOptions - + */ +export declare function useAuthClient(options?: UseAuthClientOptions): { + authClient: AuthClient; + identity: Identity; + isAuthenticated: boolean; + login: () => Promise; + logout: () => Promise; +}; diff --git a/packages/use-auth-client/lib/esm/packages/use-auth-client/src/use-auth-client.js b/packages/use-auth-client/lib/esm/packages/use-auth-client/src/use-auth-client.js new file mode 100644 index 000000000..fc8dad488 --- /dev/null +++ b/packages/use-auth-client/lib/esm/packages/use-auth-client/src/use-auth-client.js @@ -0,0 +1,65 @@ +import * as React from 'react'; +import { AuthClient, } from '@dfinity/auth-client'; +/** + * React hook to set up the Internet Computer auth client + * @param {UseAuthClientOptions} options configuration for the hook + * @see {@link UseAuthClientOptions} + * @param {AuthClientCreateOptions} options.createOptions - options passed during the creation of the auth client + * @param {AuthClientLoginOptions} options.loginOptions - + */ +export function useAuthClient(options) { + const [authClient, setAuthClient] = React.useState(null); + const [identity, setIdentity] = React.useState(null); + const [isAuthenticated, setIsAuthenticated] = React.useState(false); + // load the auth client on mount + React.useEffect(() => { + AuthClient.create(options?.createOptions).then(async (client) => { + setAuthClient(client); + setIdentity(client.getIdentity()); + setIsAuthenticated(await client.isAuthenticated()); + }); + }, []); + /** + * Login through your configured identity provider + * Wraps the onSuccess and onError callbacks with promises for convenience + * @returns {Promise} - Returns a promise that resolves to the response from the identity provider + */ + function login() { + return new Promise((resolve, reject) => { + if (authClient) { + const callback = options?.loginOptions?.onSuccess; + const errorCb = options?.loginOptions?.onError; + authClient.login({ + ...options?.loginOptions, + onSuccess: (successResponse) => { + if (successResponse !== undefined) { + callback?.(successResponse); + } + else { + callback?.(); + resolve(successResponse); + } + }, + onError: error => { + errorCb?.(error); + reject(error); + }, + }); + } + }); + } + async function logout() { + if (authClient) { + setIsAuthenticated(false); + setIdentity(null); + await authClient.logout(); + } + } + return { + authClient, + identity, + isAuthenticated, + login, + logout, + }; +} diff --git a/packages/use-auth-client/package.json b/packages/use-auth-client/package.json index 147c380f6..ca9480ab2 100644 --- a/packages/use-auth-client/package.json +++ b/packages/use-auth-client/package.json @@ -6,13 +6,18 @@ "module": "./lib/esm/index.js", "unpkg": "./lib/esm/index", "scripts": { + "build": "tsc -b && tsc -p tsconfig-cjs.json", "test": "vitest" }, "keywords": [], "author": "Kai Peacock", "license": "ISC", "dependencies": { + "@dfinity/agent": "^2.0.0", "@dfinity/auth-client": "^2.0.0", + "@dfinity/candid": "^2.0.0", + "@dfinity/identity": "^2.0.0", + "@dfinity/principal": "^2.0.0", "react": ">16.8" }, "devDependencies": { diff --git a/packages/use-auth-client/src/use-auth-client.ts b/packages/use-auth-client/src/use-auth-client.ts index 55a002478..05d0d238f 100644 --- a/packages/use-auth-client/src/use-auth-client.ts +++ b/packages/use-auth-client/src/use-auth-client.ts @@ -55,6 +55,8 @@ export function useAuthClient(options?: UseAuthClientOptions) { authClient.login({ ...options?.loginOptions, onSuccess: (successResponse?: InternetIdentityAuthResponseSuccess) => { + setIsAuthenticated(true); + setIdentity(authClient.getIdentity()); if (successResponse !== undefined) { callback?.(successResponse); } else { diff --git a/packages/use-auth-client/tsconfig-cjs.json b/packages/use-auth-client/tsconfig-cjs.json new file mode 100644 index 000000000..945c51f27 --- /dev/null +++ b/packages/use-auth-client/tsconfig-cjs.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "CommonJS", + "outDir": "./lib/cjs" + } +} diff --git a/packages/use-auth-client/tsconfig.json b/packages/use-auth-client/tsconfig.json index 47759aa14..d0abbac23 100644 --- a/packages/use-auth-client/tsconfig.json +++ b/packages/use-auth-client/tsconfig.json @@ -1,4 +1,5 @@ { + "extends": "../../tsconfig.json", "compilerOptions": { "allowJs": true, "esModuleInterop": true, @@ -7,7 +8,8 @@ "moduleResolution": "node", "lib": ["es5", "es2015", "dom"], "jsx": "react", - "declaration": true + "declaration": true, + "outDir": "lib/esm" }, "include": ["src/**/*"], "exclude": ["node_modules", "test"]