Skip to content

Commit 1ca8aab

Browse files
authored
use typescript, add signed header request using postmessage (#11)
* use typescript, add signed header request using postmessage * add example usage * add example usage * add session id to request * update sign interface * rename to login, add message * fix api * add example react app * add docs * add installation instruction * remove session id * add more options, add signify-extension-client message * move signify-extension-client message to constructor * fix readme
1 parent 697eb6a commit 1ca8aab

20 files changed

+6079
-266
lines changed

.prettierrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"printWidth": 120
3+
}

README.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,27 @@
1-
# polaris-web
1+
# polaris-web
2+
3+
4+
## Getting started
5+
6+
See [web-react](./examples/web-react/src/App.tsx) for an example react web app that uses this library to communicate with a signify browser extension.
7+
8+
To test the example,
9+
10+
- `npm install`
11+
- `npm -w web-react start`
12+
13+
14+
To view generated documentation,
15+
16+
- `npm install`
17+
- `npm run docs:serve`
18+
19+
## Usage
20+
21+
Install the package. At this point in time, the easiest way is to install straight from github.
22+
23+
```
24+
npm install --save github:weboftrust/polaris-web#main
25+
```
26+
27+
Change repository owner and branch as needed.

eslint.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// @ts-check
2+
import eslint from "@eslint/js";
3+
import tseslint from "typescript-eslint";
4+
import prettierConfig from "eslint-config-prettier";
5+
6+
export default tseslint.config(eslint.configs.recommended, ...tseslint.configs.recommended, prettierConfig);

examples/web-react/index.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>Polaris Web Example</title>
5+
</head>
6+
<body>
7+
<div id="root"></div>
8+
<script type="module" src="/src/main.tsx"></script>
9+
</body>
10+
</html>

examples/web-react/package.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"private": true,
3+
"type": "module",
4+
"scripts": {
5+
"start": "vite",
6+
"dev": "vite"
7+
},
8+
"devDependencies": {
9+
"@types/react": "^18.3.3",
10+
"@types/react-dom": "^18.3.0",
11+
"@vitejs/plugin-react": "^4.3.1",
12+
"react": "^18.3.1",
13+
"react-dom": "^18.3.1",
14+
"vite": "^5.3.1",
15+
"signify-polaris-web": "file://../../"
16+
}
17+
}

examples/web-react/src/App.tsx

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { AuthorizeResult, createClient } from "signify-polaris-web";
2+
import { FormEvent, useEffect, useState } from "react";
3+
4+
const client = createClient();
5+
6+
export function App() {
7+
const [extensionId, setExtensionId] = useState<string | false | null>(null);
8+
const [error, setError] = useState<string | null>(null);
9+
const [authorizeResult, setAuthorizeResult] = useState<AuthorizeResult | null>(null);
10+
const [headers, setHeaders] = useState<Record<string, string> | null>(null);
11+
const [pending, setPending] = useState(false);
12+
const [url, setUrl] = useState(window.location.href);
13+
const [method, setMethod] = useState("GET");
14+
15+
useEffect(() => {
16+
client.isExtensionInstalled().then((result) => setExtensionId(result));
17+
}, []);
18+
19+
async function handleAuthorize(ev: FormEvent) {
20+
ev.preventDefault();
21+
setError(null);
22+
setAuthorizeResult(null);
23+
setPending(true);
24+
25+
try {
26+
const result = await client.authorize({ message: `Message ${Date.now()}` });
27+
setAuthorizeResult(result);
28+
} catch (error) {
29+
setError(error.message ?? "Something went wrong");
30+
} finally {
31+
setPending(false);
32+
}
33+
}
34+
35+
async function handleSignHeaders(ev: FormEvent) {
36+
ev.preventDefault();
37+
setError(null);
38+
setPending(true);
39+
setHeaders(null);
40+
41+
try {
42+
const result = await client.signRequest({ url, method });
43+
setHeaders(result.headers);
44+
} catch (error) {
45+
setError(error.message ?? "Something went wrong");
46+
} finally {
47+
setPending(false);
48+
}
49+
}
50+
51+
return (
52+
<div style={{ maxWidth: 800, margin: "auto" }}>
53+
<section>
54+
<h1>Request login</h1>
55+
<form id="login-form" onSubmit={handleAuthorize}>
56+
<button type="submit" disabled={pending}>
57+
Request Credential
58+
</button>
59+
</form>
60+
</section>
61+
<section>
62+
<h1>Request signed headers</h1>
63+
<form id="headers-form" onSubmit={handleSignHeaders}>
64+
<div>
65+
<label htmlFor="url">URL</label>
66+
<input id="url" value={url} onChange={(ev) => setUrl(ev.currentTarget.value)} />
67+
</div>
68+
<div>
69+
<label htmlFor="method">Method</label>
70+
<input id="method" value={method} onChange={(ev) => setMethod(ev.currentTarget.value)} />
71+
</div>
72+
<div>
73+
<button type="submit" disabled={!authorizeResult}>
74+
Request Signed Headers
75+
</button>
76+
</div>
77+
</form>
78+
</section>
79+
<section>
80+
<h1>Current state</h1>
81+
<pre style={{ maxHeight: 400, overflowY: "scroll" }}>
82+
<code>
83+
{JSON.stringify(
84+
{
85+
isInstalled: extensionId,
86+
headers,
87+
error,
88+
},
89+
null,
90+
2,
91+
)}
92+
</code>
93+
</pre>
94+
<h1>Current credential</h1>
95+
<pre style={{ maxHeight: 400, overflowY: "scroll" }}>
96+
<code>
97+
{JSON.stringify(
98+
{
99+
credential: authorizeResult?.credential,
100+
},
101+
null,
102+
2,
103+
)}
104+
</code>
105+
</pre>
106+
</section>
107+
</div>
108+
);
109+
}

examples/web-react/src/main.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { createRoot } from "react-dom/client";
2+
import { App } from "./App.tsx";
3+
4+
const root = document.getElementById("root");
5+
6+
if (root) {
7+
createRoot(root).render(<App />);
8+
}

examples/web-react/tsconfig.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"compilerOptions": {
3+
"jsx": "react-jsx",
4+
"allowImportingTsExtensions": true,
5+
"noEmit": true,
6+
"paths": {
7+
"signify-polaris-web": ["../../"]
8+
}
9+
}
10+
}

examples/web-react/vite.config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { defineConfig } from "vite";
2+
import react from "@vitejs/plugin-react";
3+
4+
export default defineConfig({
5+
plugins: [react()],
6+
});

0 commit comments

Comments
 (0)