parent
2f9a2d8668
commit
9c1165653b
@ -0,0 +1,24 @@ |
|||||||
|
# Logs |
||||||
|
logs |
||||||
|
*.log |
||||||
|
npm-debug.log* |
||||||
|
yarn-debug.log* |
||||||
|
yarn-error.log* |
||||||
|
pnpm-debug.log* |
||||||
|
lerna-debug.log* |
||||||
|
|
||||||
|
node_modules |
||||||
|
dist |
||||||
|
dist-ssr |
||||||
|
*.local |
||||||
|
|
||||||
|
# Editor directories and files |
||||||
|
.vscode/* |
||||||
|
!.vscode/extensions.json |
||||||
|
.idea |
||||||
|
.DS_Store |
||||||
|
*.suo |
||||||
|
*.ntvs* |
||||||
|
*.njsproj |
||||||
|
*.sln |
||||||
|
*.sw? |
@ -0,0 +1,88 @@ |
|||||||
|
<!-- |
||||||
|
// Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers |
||||||
|
// All rights reserved. |
||||||
|
// Licensed under the Apache License, Version 2.0 |
||||||
|
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0> |
||||||
|
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>, |
||||||
|
// at your option. All files in the project carrying such |
||||||
|
// notice may not be copied, modified, or distributed except |
||||||
|
// according to those terms. |
||||||
|
--> |
||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8" /> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||||
|
<title>NextGraph Auth</title> |
||||||
|
<style> |
||||||
|
.splashing { |
||||||
|
height: 95vh; |
||||||
|
width:100%; |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
.noshow { |
||||||
|
display: none !important; |
||||||
|
} |
||||||
|
.nextgraph-app-auth-iframe { |
||||||
|
visibility: hidden; |
||||||
|
} |
||||||
|
.nextgraph-app-auth-iframe.nextgraph-app-auth-iframe--active { |
||||||
|
visibility: visible; |
||||||
|
} |
||||||
|
#banner { |
||||||
|
padding-right: 36px !important; |
||||||
|
width: 100%; position: fixed; left:0; top:0; min-height:36px; background-color: rgb(73, 114, 165); color: white; text-align:center ;z-index:10; padding:3px; font-size: 1.25rem; |
||||||
|
line-height: 1.75rem; overflow-wrap: break-word; |
||||||
|
} |
||||||
|
#close-auth { |
||||||
|
position: fixed; right:0; top:0; width: 36px; height: 36px; background-color: rgb(73, 114, 165);z-index:11; |
||||||
|
cursor:pointer; |
||||||
|
} |
||||||
|
</style> |
||||||
|
</head> |
||||||
|
|
||||||
|
<body> |
||||||
|
<iframe id="nextgraph-app-auth-iframe" class="nextgraph-app-auth-iframe" scrolling="auto" frameborder="0" |
||||||
|
style="position: fixed; left: 0; top: 0; height: 100%; width: 100%; overflow:auto;"> |
||||||
|
</iframe> |
||||||
|
<div id="banner"> |
||||||
|
</div> |
||||||
|
<div id="close-auth"> |
||||||
|
<svg data-slot="icon" fill="none" stroke-width="1.5" stroke="white" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> |
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"></path> |
||||||
|
</svg> |
||||||
|
</div> |
||||||
|
<script> |
||||||
|
document.getElementById("close-auth").onclick = (e)=> { |
||||||
|
window.ng_status_callback.write({status:"cancelled"}); |
||||||
|
}; |
||||||
|
</script> |
||||||
|
<div id="splash" class="splashing"> |
||||||
|
<div style="flex-direction: column;justify-content: center;color:#4972a5;width:100%;text-align:center;font-family: Inter, Avenir, Helvetica, Arial, sans-serif;"> |
||||||
|
<svg |
||||||
|
style="width:100px;height:100px;margin: 0 auto 20px ;display:flex;" |
||||||
|
xmlns="http://www.w3.org/2000/svg" |
||||||
|
viewBox="0 0 225 225" |
||||||
|
> |
||||||
|
<g> |
||||||
|
<circle |
||||||
|
r="106.98013" |
||||||
|
cy="112.90476" |
||||||
|
cx="109.88096" |
||||||
|
style="fill:#ffffff;stroke:none;stroke-width:0.268375" /> |
||||||
|
<path |
||||||
|
d="M 98.343352,190.26108 C 80.403778,187.53354 65.011938,179.57839 52.608228,166.62327 38.602093,151.99448 31.178059,133.41381 31.178059,112.98841 c 0,-10.21889 1.700058,-19.44396 5.221234,-28.332119 4.28678,-10.820699 10.037295,-19.39063 18.535095,-27.62263 4.72982,-4.58187 6.60687,-6.10643 11.28099,-9.16256 11.89869,-7.779841 24.173884,-11.879991 38.095802,-12.724761 19.80437,-1.2017 39.11165,5.11306 54.60284,17.858751 1.50718,1.24006 2.72951,2.35934 2.71628,2.48729 -0.0132,0.12795 -3.85821,3.63443 -8.54442,7.79217 -4.6862,4.157729 -10.04724,8.96276 -11.91342,10.677819 -1.86617,1.715071 -3.54094,3.11831 -3.7217,3.11831 -0.18075,0 -1.39985,-0.745188 -2.70911,-1.655969 -7.53011,-5.23834 -15.99428,-7.82188 -25.62597,-7.82188 -12.731628,0 -23.249192,4.3379 -32.143882,13.257541 -6.39594,6.413868 -10.70387,14.555268 -12.50018,23.623578 -0.69099,3.48832 -0.68968,13.53072 0.002,17.00893 3.70508,18.62577 18.31886,33.10194 36.642322,36.29729 4.16439,0.72621 11.98099,0.71223 15.98975,-0.0286 14.03187,-2.59311 25.86047,-11.36806 32.26533,-23.93578 0.77379,-1.51834 1.26018,-2.88461 1.08086,-3.03616 -0.17934,-0.15156 -6.87448,-1.1779 -14.87813,-2.28078 -9.7795,-1.34758 -14.92353,-2.21379 -15.68471,-2.64117 -1.52067,-0.85379 -2.83611,-2.88806 -2.83611,-4.3859 0,-1.1732 2.02687,-15.86876 2.49085,-18.05962 0.29676,-1.40127 2.42559,-3.4934 3.84317,-3.77691 0.62227,-0.12445 8.82712,0.85555 18.28065,2.18348 9.43343,1.32511 17.26269,2.29453 17.39833,2.15427 0.13566,-0.14026 1.11808,-6.54833 2.18313,-14.24014 1.10778,-8.000208 2.20407,-14.60184 2.56177,-15.426229 0.34392,-0.792599 1.11019,-1.849131 1.70287,-2.34782 2.06321,-1.736079 3.1433,-1.785011 12.20439,-0.55291 9.63637,1.310309 10.70873,1.56224 12.28077,2.88503 1.64359,1.382979 2.2732,2.810909 2.25906,5.123309 -0.007,1.10173 -0.92172,8.29645 -2.03332,15.98826 -1.11158,7.69182 -1.97159,14.04091 -1.91113,14.1091 0.0605,0.0682 7.16644,1.11143 15.79109,2.31832 11.10566,1.55407 16.00827,2.38757 16.80223,2.85657 1.53015,0.90389 2.48023,2.64785 2.45017,4.49756 -0.0462,2.84349 -2.41252,18.12279 -2.97521,19.21089 -0.66164,1.27949 -2.60244,2.54696 -3.92109,2.56074 -0.51973,0.005 -7.87449,-0.95937 -16.34391,-2.144 -8.46944,-1.18464 -15.47588,-2.077 -15.56986,-1.98301 -0.094,0.094 -1.18792,7.34163 -2.43097,16.10589 -1.44004,10.15311 -2.49792,16.43621 -2.91556,17.31631 -0.72531,1.52848 -2.76261,3.06291 -4.53817,3.41802 -0.95688,0.19138 -10.90014,-0.92798 -13.59859,-1.53084 -0.5471,-0.12223 -1.89146,0.67252 -4.50941,2.66588 -11.2627,8.57562 -24.34195,13.90917 -38.35741,15.64164 -4.40038,0.54395 -15.72658,0.43298 -19.853658,-0.19451 z" |
||||||
|
style="fill:#4972a5;fill-opacity:1;stroke:#4972a5;stroke-width:0.377976;stroke-opacity:1" /> |
||||||
|
</g> |
||||||
|
</svg> |
||||||
|
<div> Loading ...</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div id="app" class="noshow"> |
||||||
|
</div> |
||||||
|
<!-- # INSERT SCRIPT HERE --> |
||||||
|
<script type="module" src="/src/main.ts"></script> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,32 @@ |
|||||||
|
{ |
||||||
|
"compilerOptions": { |
||||||
|
"moduleResolution": "bundler", |
||||||
|
"target": "ESNext", |
||||||
|
"module": "ESNext", |
||||||
|
/** |
||||||
|
* svelte-preprocess cannot figure out whether you have |
||||||
|
* a value or a type, so tell TypeScript to enforce using |
||||||
|
* `import type` instead of `import` for Types. |
||||||
|
*/ |
||||||
|
"verbatimModuleSyntax": true, |
||||||
|
"isolatedModules": true, |
||||||
|
"resolveJsonModule": true, |
||||||
|
/** |
||||||
|
* To have warnings / errors of the Svelte compiler at the |
||||||
|
* correct position, enable source maps by default. |
||||||
|
*/ |
||||||
|
"sourceMap": true, |
||||||
|
"esModuleInterop": true, |
||||||
|
"skipLibCheck": true, |
||||||
|
/** |
||||||
|
* Typecheck JS in `.svelte` and `.js` files by default. |
||||||
|
* Disable this if you'd like to use dynamic types. |
||||||
|
*/ |
||||||
|
"checkJs": true |
||||||
|
}, |
||||||
|
/** |
||||||
|
* Use global.d.ts instead of compilerOptions.types |
||||||
|
* to avoid limiting type declarations. |
||||||
|
*/ |
||||||
|
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] |
||||||
|
} |
@ -0,0 +1,40 @@ |
|||||||
|
{ |
||||||
|
"name": "@ng-org/ngnet-auth", |
||||||
|
"private": true, |
||||||
|
"version": "0.1.2", |
||||||
|
"type": "module", |
||||||
|
"scripts": { |
||||||
|
"dev": "vite", |
||||||
|
"build": "vite build --base=./ && shx rm -rf ./dist/assets", |
||||||
|
"builddev": "cross-env NG_DEV=1 vite build --base=./ && shx rm -rf ./dist/assets && shx mkdir -p ../../../app/nextgraph/public_dev && cp ./dist/index.html ../../../app/nextrgaph/public_dev/auth.html", |
||||||
|
"preview": "vite preview" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"flowbite": "^1.6.5", |
||||||
|
"flowbite-svelte": "^0.37.1", |
||||||
|
"svelte-spa-router": "^3.3.0", |
||||||
|
"@tailwindcss/typography": "^0.5.13", |
||||||
|
"svelte-i18n": "^4.0.0", |
||||||
|
"@ng-org/ui-common": "workspace:*", |
||||||
|
"async-proxy": "^0.4.1", |
||||||
|
"remote-web-streams": "^0.2.0" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"shx": "^0.3.4", |
||||||
|
"cross-env": "^7.0.3", |
||||||
|
"node-gzip": "^1.1.2", |
||||||
|
"@sveltejs/vite-plugin-svelte": "^2.0.4", |
||||||
|
"svelte": "^3.58.0", |
||||||
|
"vite": "^4.3.9", |
||||||
|
"postcss": "^8.4.23", |
||||||
|
"postcss-load-config": "^4.0.1", |
||||||
|
"svelte-heros-v2": "^0.10.12", |
||||||
|
"svelte-preprocess": "^5.0.3", |
||||||
|
"tailwindcss": "^3.3.1", |
||||||
|
"autoprefixer": "^10.4.14", |
||||||
|
"vite-plugin-svelte-svg": "^2.2.1", |
||||||
|
"vite-plugin-top-level-await": "1.3.1", |
||||||
|
"vite-plugin-singlefile": "0.13.5", |
||||||
|
"vite-plugin-wasm": "3.2.2" |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,13 @@ |
|||||||
|
const tailwindcss = require("tailwindcss"); |
||||||
|
const autoprefixer = require("autoprefixer"); |
||||||
|
|
||||||
|
const config = { |
||||||
|
plugins: [ |
||||||
|
//Some plugins, like tailwindcss/nesting, need to run before Tailwind, |
||||||
|
tailwindcss(), |
||||||
|
//But others, like autoprefixer, need to run after, |
||||||
|
autoprefixer, |
||||||
|
], |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports = config; |
@ -0,0 +1,32 @@ |
|||||||
|
var crypto = require('crypto') |
||||||
|
, fs = require('fs') |
||||||
|
const {gzip, } = require('node-gzip'); |
||||||
|
|
||||||
|
var algorithm = 'sha256' |
||||||
|
, shasum = crypto.createHash(algorithm) |
||||||
|
|
||||||
|
const sha_file = './dist/index.sha256'; |
||||||
|
const gzip_file = './dist/index.gzip'; |
||||||
|
var filename = './dist/index.html' |
||||||
|
, s = fs.ReadStream(filename) |
||||||
|
|
||||||
|
var bufs = []; |
||||||
|
s.on('data', function(data) { |
||||||
|
shasum.update(data) |
||||||
|
bufs.push(data); |
||||||
|
}) |
||||||
|
|
||||||
|
s.on('end', function() { |
||||||
|
var hash = shasum.digest('hex') |
||||||
|
console.log(hash + ' ' + filename) |
||||||
|
|
||||||
|
fs.writeFileSync(sha_file, hash, 'utf8'); |
||||||
|
|
||||||
|
var buf = Buffer.concat(bufs); |
||||||
|
gzip(buf).then((compressed) => {fs.writeFileSync(gzip_file, compressed);}); |
||||||
|
|
||||||
|
fs.rm(filename,()=>{}); |
||||||
|
|
||||||
|
}) |
||||||
|
|
||||||
|
|
@ -0,0 +1,180 @@ |
|||||||
|
<!-- |
||||||
|
// Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers |
||||||
|
// All rights reserved. |
||||||
|
// Licensed under the Apache License, Version 2.0 |
||||||
|
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0> |
||||||
|
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>, |
||||||
|
// at your option. All files in the project carrying such |
||||||
|
// notice may not be copied, modified, or distributed except |
||||||
|
// according to those terms. |
||||||
|
--> |
||||||
|
|
||||||
|
<script lang="ts"> |
||||||
|
import { push, default as Router } from "svelte-spa-router"; |
||||||
|
import { isLoading } from "svelte-i18n"; |
||||||
|
|
||||||
|
import { onMount, tick, onDestroy } from "svelte"; |
||||||
|
import { ng, brokers_info } from "./store"; |
||||||
|
import { |
||||||
|
NotFound, |
||||||
|
Test, |
||||||
|
WalletCreate, |
||||||
|
Invitation, |
||||||
|
WalletLogin, |
||||||
|
WalletInfo, |
||||||
|
User, |
||||||
|
UserRegistered, |
||||||
|
Install, |
||||||
|
ScanQRWeb, |
||||||
|
AccountInfo, |
||||||
|
WalletLoginUsername, |
||||||
|
WalletLoginQr, |
||||||
|
WalletLoginTextCode |
||||||
|
} from "@ng-org/ui-common/routes"; |
||||||
|
import { Bowser } from "../../../../sdk/js/lib-wasm/jsland/bowser.js"; |
||||||
|
|
||||||
|
import Home from "./routes/Home.svelte"; |
||||||
|
|
||||||
|
const routes = new Map(); |
||||||
|
routes.set("/", Home); |
||||||
|
// routes.set("/test", Test); |
||||||
|
// routes.set("/wallet/login", WalletLogin); |
||||||
|
// routes.set("/wallet/username", WalletLoginUsername); |
||||||
|
// routes.set("/wallet/login-qr", WalletLoginQr); |
||||||
|
// routes.set("/wallet/login-text-code", WalletLoginTextCode); |
||||||
|
// routes.set("/wallet/create", WalletCreate); |
||||||
|
// routes.set("/i/:invitation", Invitation); |
||||||
|
// routes.set("/user", User); |
||||||
|
// routes.set("/user/registered", UserRegistered); |
||||||
|
// routes.set("/wallet", WalletInfo); |
||||||
|
// routes.set("/user/accounts", AccountInfo); |
||||||
|
// routes.set("/scanqr", ScanQRWeb); |
||||||
|
// routes.set("/install", Install); |
||||||
|
routes.set("*", NotFound); |
||||||
|
|
||||||
|
// window.refresh_wallets = async () => { |
||||||
|
// let walls = await ng.get_wallets(); |
||||||
|
// wallets.set(walls); |
||||||
|
// }; |
||||||
|
|
||||||
|
let no_local_storage = false; |
||||||
|
let is_safari = false; |
||||||
|
|
||||||
|
function load_bootstraps(bs: string | null) { |
||||||
|
if (bs) { |
||||||
|
let bootstrap_map = JSON.parse(bs); |
||||||
|
brokers_info.set(bootstrap_map); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
onMount(async () => { |
||||||
|
|
||||||
|
window.document.getElementById("splash").className="noshow"; |
||||||
|
window.document.getElementById("app").className=""; |
||||||
|
|
||||||
|
let info = Bowser.parse(window.navigator.userAgent); |
||||||
|
//console.log(info); |
||||||
|
is_safari = info.browser.name == "Safari"; |
||||||
|
if (is_safari) return; |
||||||
|
|
||||||
|
window.addEventListener("storage", (event) => { |
||||||
|
//console.log("localStorage event", event); |
||||||
|
if (event.storageArea != localStorage) return; |
||||||
|
if (event.key === "ng_bootstrap") { |
||||||
|
load_bootstraps(event.newValue); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
let ls; |
||||||
|
try { |
||||||
|
ls = localStorage; |
||||||
|
|
||||||
|
try { |
||||||
|
let ret = await document.requestStorageAccess({ localStorage: true }); |
||||||
|
ls = ret.localStorage; |
||||||
|
console.log("REQUEST STORAGE ACCESS GRANTED by chrome"); |
||||||
|
} |
||||||
|
catch(e) { |
||||||
|
console.warn("requestStorageAccess of chrome failed. falling back to previous api", e) |
||||||
|
try { |
||||||
|
await document.requestStorageAccess(); |
||||||
|
localStorage; |
||||||
|
console.log("REQUEST STORAGE ACCESS GRANTED"); |
||||||
|
} catch (e) { |
||||||
|
console.error("REQUEST STORAGE ACCESS DENIED",e); |
||||||
|
no_local_storage = true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} catch (e) { |
||||||
|
no_local_storage = true; |
||||||
|
console.log("no access to localStorage",e) |
||||||
|
} |
||||||
|
|
||||||
|
if (!no_local_storage) { |
||||||
|
try { |
||||||
|
load_bootstraps(ls.getItem("ng_bootstrap")); |
||||||
|
} catch (e) { |
||||||
|
console.log("load_bootstraps failed") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
}); |
||||||
|
|
||||||
|
</script> |
||||||
|
{#if is_safari} |
||||||
|
|
||||||
|
<div class="text-center max-w-6xl lg:px-8 mx-auto px-4 text-red-800"> |
||||||
|
<svg |
||||||
|
class="animate-bounce mt-10 h-16 w-16 mx-auto" |
||||||
|
fill="none" |
||||||
|
stroke="currentColor" |
||||||
|
stroke-width="1.5" |
||||||
|
viewBox="0 0 24 24" |
||||||
|
xmlns="http://www.w3.org/2000/svg" |
||||||
|
aria-hidden="true" |
||||||
|
> |
||||||
|
<path |
||||||
|
stroke-linecap="round" |
||||||
|
stroke-linejoin="round" |
||||||
|
d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" |
||||||
|
/> |
||||||
|
</svg> |
||||||
|
<p class="mb-5"> |
||||||
|
We are sorry but Safari is not supported yet<br/>for WebApps authentication with your Wallet.<br/>Please use another browser. |
||||||
|
</p> |
||||||
|
</div> |
||||||
|
|
||||||
|
{:else if no_local_storage} |
||||||
|
|
||||||
|
<div class="text-center max-w-6xl lg:px-8 mx-auto px-4 text-red-800"> |
||||||
|
<svg |
||||||
|
class="animate-bounce mt-10 h-16 w-16 mx-auto" |
||||||
|
fill="none" |
||||||
|
stroke="currentColor" |
||||||
|
stroke-width="1.5" |
||||||
|
viewBox="0 0 24 24" |
||||||
|
xmlns="http://www.w3.org/2000/svg" |
||||||
|
aria-hidden="true" |
||||||
|
> |
||||||
|
<path |
||||||
|
stroke-linecap="round" |
||||||
|
stroke-linejoin="round" |
||||||
|
d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" |
||||||
|
/> |
||||||
|
</svg> |
||||||
|
<p class="mb-5"> |
||||||
|
Please give access to localStorage for the website<br/> |
||||||
|
{location.origin} |
||||||
|
</p> |
||||||
|
</div> |
||||||
|
|
||||||
|
{:else} |
||||||
|
|
||||||
|
{#if $isLoading} |
||||||
|
<p class="text-center">Loading translations...</p> |
||||||
|
{:else} |
||||||
|
<Router {routes} /> |
||||||
|
{/if} |
||||||
|
|
||||||
|
{/if} |
@ -0,0 +1,4 @@ |
|||||||
|
/* Write your global styles here, in PostCSS syntax */ |
||||||
|
@tailwind base; |
||||||
|
@tailwind components; |
||||||
|
@tailwind utilities; |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.9 KiB |
@ -0,0 +1,160 @@ |
|||||||
|
<!-- |
||||||
|
// Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers |
||||||
|
// All rights reserved. |
||||||
|
// Licensed under the Apache License, Version 2.0 |
||||||
|
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0> |
||||||
|
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>, |
||||||
|
// at your option. All files in the project carrying such |
||||||
|
// notice may not be copied, modified, or distributed except |
||||||
|
// according to those terms. |
||||||
|
--> |
||||||
|
<script lang="ts"> |
||||||
|
import { onMount } from "svelte"; |
||||||
|
import { t, locale } from "svelte-i18n"; |
||||||
|
import { CenteredLayout } from "@ng-org/ui-common/lib"; |
||||||
|
import { LogoSimple } from "@ng-org/ui-common/components"; |
||||||
|
import { |
||||||
|
Sidebar, |
||||||
|
SidebarGroup, |
||||||
|
SidebarItem, |
||||||
|
SidebarWrapper, |
||||||
|
} from "flowbite-svelte"; |
||||||
|
import { |
||||||
|
ComputerDesktop, |
||||||
|
GlobeAlt, |
||||||
|
ServerStack |
||||||
|
} from "svelte-heros-v2"; |
||||||
|
|
||||||
|
import { web_origin, brokers_info, selected_broker } from '../store'; |
||||||
|
import { fromWritablePort, RemoteReadableStream } from 'remote-web-streams'; |
||||||
|
|
||||||
|
let top; |
||||||
|
let nonActiveClass = |
||||||
|
"flex items-center p-2 text-base font-normal text-gray-900 rounded-lg dark:text-white hover:bg-gray-200 dark:hover:bg-gray-700"; |
||||||
|
|
||||||
|
const AUTH_HOME = "#/"; |
||||||
|
|
||||||
|
function select(broker: Object) { |
||||||
|
|
||||||
|
let url; |
||||||
|
if (import.meta.env.NG_DEV && broker.localhost === 14400) { |
||||||
|
// dev mode |
||||||
|
url = "http://localhost:1421/appauth.html"; |
||||||
|
} else if (broker.localhost) { |
||||||
|
url = `http://localhost:${broker.localhost}/auth/`; |
||||||
|
} else if (broker.private) { |
||||||
|
//TODO |
||||||
|
url = `http://unimplemented/auth/`; |
||||||
|
} else if (broker.domain) { |
||||||
|
url = `https://${broker.domain}/auth/`; |
||||||
|
} else if (broker.ngbox) { |
||||||
|
url = `https://nextgraph.app/auth/`; |
||||||
|
} else return; |
||||||
|
|
||||||
|
selected_broker.set(broker); |
||||||
|
let iframe = window.document.getElementById("nextgraph-app-auth-iframe"); |
||||||
|
iframe?.classList.add('nextgraph-app-auth-iframe--active'); |
||||||
|
window.document.getElementById("app").style["display"] = "none"; |
||||||
|
|
||||||
|
(<any>window).ng_iframe_origin = new URL(url).origin; |
||||||
|
|
||||||
|
iframe.addEventListener("load", function() { |
||||||
|
|
||||||
|
(<any>window).ng_broker_selected = this.contentWindow; |
||||||
|
const ready_handler = async function(m) { |
||||||
|
if (m.data.ready && m.origin === (<any>window).ng_iframe_origin) { |
||||||
|
//console.log("got ready message",m); |
||||||
|
//remove this listener |
||||||
|
window.removeEventListener("message",ready_handler); |
||||||
|
const { readable, writablePort } = new RemoteReadableStream(); |
||||||
|
//console.log("sending init message to app-auth"); |
||||||
|
(<any>window).ng_broker_selected.postMessage({ method: "init", manifest:window.ng_manifest, port: writablePort }, (<any>window).ng_iframe_origin, [writablePort]); |
||||||
|
const reader = readable.getReader(); |
||||||
|
for (var msg; msg = await reader.read(); ) { |
||||||
|
if (msg.done) { |
||||||
|
(<any>window).ng_status_callback.close(); |
||||||
|
break; |
||||||
|
} else { |
||||||
|
//console.log("forwarding upstream",msg.value); |
||||||
|
(<any>window).ng_status_callback.write(msg.value); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
window.addEventListener("message",ready_handler); |
||||||
|
}); |
||||||
|
|
||||||
|
iframe.src = url+"?o="+location.search.substring(3)+AUTH_HOME; |
||||||
|
} |
||||||
|
|
||||||
|
onMount(() => { |
||||||
|
if (Object.keys($brokers_info).length == 1) { |
||||||
|
select(Object.values($brokers_info)[0]); |
||||||
|
} |
||||||
|
}); |
||||||
|
</script> |
||||||
|
|
||||||
|
{#if Object.keys($brokers_info).length > 1} |
||||||
|
<CenteredLayout> |
||||||
|
<div class="container3" bind:this={top}> |
||||||
|
<div class="row"> |
||||||
|
<LogoSimple/> |
||||||
|
</div> |
||||||
|
<div class="row mb-20"> |
||||||
|
<Sidebar {nonActiveClass}> |
||||||
|
<SidebarWrapper |
||||||
|
divClass="bg-gray-60 overflow-y-auto py-4 px-3 rounded dark:bg-gray-800" |
||||||
|
> |
||||||
|
<SidebarGroup ulClass="space-y-2" role="menu"> |
||||||
|
<li> |
||||||
|
<h2 class="text-xl mb-6">{@html $t("auth.select_broker", {values: { origin:$web_origin }})}</h2> |
||||||
|
</li> |
||||||
|
{#each Object.entries($brokers_info) as broker} |
||||||
|
<li |
||||||
|
tabindex="0" |
||||||
|
role="menuitem" |
||||||
|
class="flex items-center p-2 text-base font-normal text-gray-900 clickable rounded-lg dark:text-white hover:bg-gray-200 dark:hover:bg-gray-700" |
||||||
|
on:keypress={()=>select(broker[1])} |
||||||
|
on:click={()=>select(broker[1])} |
||||||
|
> |
||||||
|
{#if broker[1].localhost} |
||||||
|
<ComputerDesktop tabindex="-1" |
||||||
|
class="w-10 h-10 mr-4 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"/> |
||||||
|
{:else if broker[1].domain} |
||||||
|
<GlobeAlt tabindex="-1" |
||||||
|
class="w-10 min-w-10 h-10 mr-4 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"/> |
||||||
|
{:else if broker[1].private} |
||||||
|
<ServerStack tabindex="-1" |
||||||
|
class="w-10 h-10 mr-4 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"/> |
||||||
|
{:else if broker[1].ngbox} |
||||||
|
<svg |
||||||
|
xmlns="http://www.w3.org/2000/svg" |
||||||
|
version="1.1" |
||||||
|
viewBox="0 0 225 225" |
||||||
|
class="mr-4 block h-10 w-10" |
||||||
|
stroke="currentColor" |
||||||
|
stroke-width="12" |
||||||
|
fill="none" |
||||||
|
> |
||||||
|
<path |
||||||
|
d="M 88.332599,179.77884 C 72.858008,177.42608 59.581081,170.564 48.8817,159.38898 36.800075,146.77026 30.396139,130.74266 30.396139,113.12381 c 0,-8.81477 1.466462,-16.772273 4.503812,-24.439156 3.697755,-9.333883 8.658122,-16.726264 15.988284,-23.827148 4.07992,-3.952299 5.699054,-5.267377 9.730928,-7.903581 10.263753,-6.710853 20.852276,-10.247623 32.861256,-10.976317 17.083161,-1.036581 33.737521,4.410501 47.100151,15.404873 1.30009,1.069669 2.35446,2.035155 2.34305,2.145524 -0.0114,0.110369 -3.32807,3.135042 -7.37038,6.721489 -4.04229,3.586437 -8.6667,7.731233 -10.27646,9.210635 -1.60975,1.479412 -3.05439,2.689839 -3.21032,2.689839 -0.15591,0 -1.2075,-0.642795 -2.33686,-1.428431 -6.49544,-4.518567 -13.79659,-6.747116 -22.104843,-6.747116 -10.982241,0 -20.054641,3.741852 -27.727158,11.435891 -5.517107,5.532575 -9.233107,12.555305 -10.782595,20.377588 -0.596045,3.00901 -0.594915,11.67153 0.0017,14.67182 3.195984,16.0665 15.801761,28.55358 31.607491,31.30987 3.592183,0.62643 10.334745,0.61437 13.792675,-0.0247 12.10383,-2.2368 22.30712,-9.80603 27.83192,-20.64689 0.66747,-1.30971 1.08703,-2.48825 0.93235,-2.61898 -0.1547,-0.13073 -5.9299,-1.01605 -12.83381,-1.96739 -8.43575,-1.16241 -12.87296,-1.9096 -13.52955,-2.27826 -1.31171,-0.73647 -2.44642,-2.49122 -2.44642,-3.78325 0,-1.012 1.74837,-13.68832 2.1486,-15.57814 0.25598,-1.20873 2.0923,-3.01339 3.3151,-3.25795 0.53677,-0.10735 7.61424,0.73799 15.7688,1.88346 8.13723,1.14303 14.89071,1.97925 15.00772,1.85826 0.11702,-0.12098 0.96445,-5.648553 1.88315,-12.283473 0.95557,-6.900944 1.90122,-12.59548 2.20977,-13.306594 0.29667,-0.683692 0.95765,-1.595052 1.46889,-2.025218 1.77972,-1.497534 2.7114,-1.539742 10.52745,-0.476938 8.31229,1.130266 9.2373,1.347581 10.59333,2.488613 1.41776,1.192951 1.96085,2.424677 1.94866,4.419342 -0.006,0.950347 -0.79507,7.156475 -1.75393,13.791395 -0.95885,6.634933 -1.70069,12.111623 -1.64854,12.170443 0.0522,0.0588 6.18174,0.95872 13.62132,1.99978 9.57969,1.34053 13.80866,2.0595 14.49353,2.46406 1.3199,0.77969 2.13943,2.28402 2.1135,3.87957 -0.0399,2.45278 -2.08103,15.63263 -2.5664,16.57122 -0.57073,1.10369 -2.24485,2.197 -3.38232,2.20889 -0.44831,0.004 -6.79249,-0.82755 -14.09817,-1.84941 -7.3057,-1.02186 -13.34942,-1.79161 -13.43049,-1.71053 -0.0811,0.0811 -1.02469,6.33285 -2.09694,13.89286 -1.24218,8.75802 -2.1547,14.1778 -2.51495,14.93697 -0.62565,1.31846 -2.38302,2.64205 -3.91461,2.94836 -0.8254,0.16509 -9.4024,-0.80047 -11.73007,-1.32049 -0.47193,-0.10544 -1.63157,0.58011 -3.8898,2.29957 -9.71515,7.39729 -20.99725,11.99799 -33.08692,13.49241 -3.79574,0.46921 -13.565667,0.37348 -17.125664,-0.16779 z" |
||||||
|
/> |
||||||
|
<rect |
||||||
|
ry="37.596001" |
||||||
|
y="10.583322" |
||||||
|
x="14.363095" |
||||||
|
height="204.86308" |
||||||
|
width="195.79167" |
||||||
|
/> |
||||||
|
</svg> |
||||||
|
{/if} |
||||||
|
<span class="text-left text-xl ml-3" style="overflow-wrap: anywhere;">{broker[0]}</span> |
||||||
|
</li> |
||||||
|
{/each} |
||||||
|
</SidebarGroup> |
||||||
|
</SidebarWrapper> |
||||||
|
</Sidebar> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</CenteredLayout> |
||||||
|
{/if} |
@ -0,0 +1,120 @@ |
|||||||
|
// Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers
|
||||||
|
// All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0
|
||||||
|
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
|
||||||
|
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
|
||||||
|
// at your option. All files in the project carrying such
|
||||||
|
// notice may not be copied, modified, or distributed except
|
||||||
|
// according to those terms.
|
||||||
|
|
||||||
|
import "./app.postcss"; |
||||||
|
import "../../../../app/ui-common/src/styles.css"; |
||||||
|
import { link, push } from "svelte-spa-router"; |
||||||
|
import App from "./App.svelte"; |
||||||
|
import { fromWritablePort, RemoteReadableStream } from 'remote-web-streams'; |
||||||
|
import { web_origin } from './store'; |
||||||
|
|
||||||
|
import { select_default_lang } from "@ng-org/ui-common/lang"; |
||||||
|
select_default_lang(()=>{return window.navigator.languages;}).then(() => {}); |
||||||
|
|
||||||
|
//let status_callback : WritableStreamDefaultWriter<any> | undefined = undefined;
|
||||||
|
|
||||||
|
const origin = decodeURIComponent(location.search.substring(3)); |
||||||
|
|
||||||
|
document.getElementById("banner").innerText = "Opening Wallet for "+ new URL(origin).host; |
||||||
|
|
||||||
|
async function rpc( method:string, args?: any) : Promise<any> { |
||||||
|
const { readable, writablePort } = new RemoteReadableStream(); |
||||||
|
(<any>window).ng_broker_selected.postMessage({ method, args, port: writablePort }, (<any>window).ng_iframe_origin, [writablePort]); |
||||||
|
const reader = readable.getReader(); |
||||||
|
let ret = await reader.read(); |
||||||
|
await reader.read(); // the close
|
||||||
|
return ret.value; |
||||||
|
} |
||||||
|
|
||||||
|
async function rpc_stream( method:string, args: any, writer:WritableStreamDefaultWriter<any>) { |
||||||
|
const { readable, writablePort } = new RemoteReadableStream(); |
||||||
|
(<any>window).ng_broker_selected.postMessage({ method, args, port: writablePort }, (<any>window).ng_iframe_origin, [writablePort]); |
||||||
|
const reader = readable.getReader(); |
||||||
|
for (var msg; msg = await reader.read(); ) { |
||||||
|
if (msg.done) { |
||||||
|
writer.close(); |
||||||
|
break; |
||||||
|
} |
||||||
|
if (msg.value.error) { |
||||||
|
writer.write(msg.value); |
||||||
|
writer.close(); |
||||||
|
break; |
||||||
|
} else if (msg.value.stream) { |
||||||
|
writer.write(msg.value); |
||||||
|
} |
||||||
|
// TODO: deal with end of stream
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const AUTH_HOME = "#/"; |
||||||
|
// const AUTH_USER_PANEL = "#/user";
|
||||||
|
// const AUTH_USER_ACCOUNTS = "#/user/accounts";
|
||||||
|
// const AUTH_WALLET = "#/wallet";
|
||||||
|
|
||||||
|
window.addEventListener("message", async (event)=>{ |
||||||
|
if (event.data.ready) return; |
||||||
|
const { method, port } = event.data; |
||||||
|
const writable = fromWritablePort(port); |
||||||
|
const writer = writable.getWriter(); |
||||||
|
if (event.origin !== origin) { |
||||||
|
console.error("invalid origin",event.origin,origin) |
||||||
|
writer.write({status:'error', error:'invalid origin'}); |
||||||
|
writer.close(); |
||||||
|
} else if ( method === "init" ) { |
||||||
|
|
||||||
|
(<any>window).ng_status_callback = writer; |
||||||
|
web_origin.set(new URL(origin).host); |
||||||
|
|
||||||
|
// make API call with origin, event.data.singleton and event.data.access_requests
|
||||||
|
// in order to get full manifest (including security info)
|
||||||
|
|
||||||
|
(<any>window).ng_manifest = { |
||||||
|
origin: origin, |
||||||
|
singleton: event.data.singleton, |
||||||
|
access_request: event.data.access_requests, |
||||||
|
name: "", |
||||||
|
title: "", |
||||||
|
description: "", // etc...
|
||||||
|
security_info: {} |
||||||
|
}; |
||||||
|
|
||||||
|
} else if ( method === "login" ) { |
||||||
|
|
||||||
|
if (!(<any>window).ng_broker_selected) { |
||||||
|
push(AUTH_HOME); |
||||||
|
writer.write({ok:true, ret: false}); |
||||||
|
writer.close(); |
||||||
|
} else { |
||||||
|
writer.write(await rpc("login")); |
||||||
|
writer.close(); |
||||||
|
} |
||||||
|
} else if ( method === "doc_subscribe" ) { |
||||||
|
|
||||||
|
//console.log("net forward doc_subscribe to app", method, event.data.args)
|
||||||
|
await rpc_stream(method, event.data.args, writer); |
||||||
|
|
||||||
|
} else { |
||||||
|
//console.log("net forward to app", method, event.data.args)
|
||||||
|
// forward to app auth iframe
|
||||||
|
writer.write(await rpc(method, event.data.args)); |
||||||
|
writer.close(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
}, false); |
||||||
|
|
||||||
|
/// for test purposes only, when testing with http://localhost:14402/?o=http://localhost:14402
|
||||||
|
// const { readable, writablePort } = new RemoteReadableStream();
|
||||||
|
// window.postMessage({method:"init", port: writablePort }, location.origin, [writablePort]);
|
||||||
|
|
||||||
|
const app = new App({ |
||||||
|
target: document.getElementById("app"), |
||||||
|
}); |
||||||
|
|
||||||
|
export default app; |
@ -0,0 +1,99 @@ |
|||||||
|
<!-- |
||||||
|
// Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers |
||||||
|
// All rights reserved. |
||||||
|
// Licensed under the Apache License, Version 2.0 |
||||||
|
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0> |
||||||
|
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>, |
||||||
|
// at your option. All files in the project carrying such |
||||||
|
// notice may not be copied, modified, or distributed except |
||||||
|
// according to those terms. |
||||||
|
--> |
||||||
|
|
||||||
|
<!-- |
||||||
|
Home page to display for logged in users. |
||||||
|
Redirects to no-wallet or login page, if not logged in. |
||||||
|
--> |
||||||
|
|
||||||
|
<script> |
||||||
|
import Home from "../lib/Home.svelte"; |
||||||
|
import { t, locale } from "svelte-i18n"; |
||||||
|
import { NoWallet } from "@ng-org/ui-common/lib"; |
||||||
|
import { push } from "svelte-spa-router"; |
||||||
|
import { onMount, onDestroy } from "svelte"; |
||||||
|
import { brokers_info, web_origin } from "../store"; |
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
|
{#if Object.keys($brokers_info).length == 0} |
||||||
|
<!-- <NoWallet /> --> |
||||||
|
{#if import.meta.env.NG_DEV} |
||||||
|
<div class="text-center max-w-6xl lg:px-8 mx-auto px-4 text-red-800"> |
||||||
|
<svg |
||||||
|
class="animate-bounce mt-10 h-16 w-16 mx-auto" |
||||||
|
fill="none" |
||||||
|
stroke="currentColor" |
||||||
|
stroke-width="1.5" |
||||||
|
viewBox="0 0 24 24" |
||||||
|
xmlns="http://www.w3.org/2000/svg" |
||||||
|
aria-hidden="true" |
||||||
|
> |
||||||
|
<path |
||||||
|
stroke-linecap="round" |
||||||
|
stroke-linejoin="round" |
||||||
|
d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" |
||||||
|
/> |
||||||
|
</svg> |
||||||
|
<p class="mb-5"> |
||||||
|
We could not find a wallet in your browser.<br/> |
||||||
|
This is probably due to the recent changes made to the framework.<br/> |
||||||
|
Please create a new wallet from this browser and try again, |
||||||
|
</p> |
||||||
|
</div> |
||||||
|
{:else} |
||||||
|
<div class="text-center max-w-6xl lg:px-8 mx-auto px-4 text-blue-600"> |
||||||
|
|
||||||
|
<svg |
||||||
|
class="y-10 h-16 w-16 mx-auto mb-3" |
||||||
|
fill="none" |
||||||
|
stroke="currentColor" |
||||||
|
stroke-width="1.5" |
||||||
|
viewBox="0 0 24 24" |
||||||
|
xmlns="http://www.w3.org/2000/svg" |
||||||
|
aria-hidden="true" |
||||||
|
> |
||||||
|
<path |
||||||
|
stroke-linecap="round" |
||||||
|
stroke-linejoin="round" |
||||||
|
d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" |
||||||
|
/> |
||||||
|
</svg> |
||||||
|
We could not find a wallet in your browser.<br/> |
||||||
|
For now, creating a new wallet while a Web App<br/> |
||||||
|
is authenticating, is not implemented. Please<br/> |
||||||
|
create or import your wallet in a new tab by<br/><a href="https://nextgraph.eu" target="_blank">clicking here</a> |
||||||
|
</div> |
||||||
|
{/if} |
||||||
|
{:else if $web_origin} |
||||||
|
<Home /> |
||||||
|
{:else} |
||||||
|
<div class="text-center max-w-6xl lg:px-8 mx-auto px-4 text-red-800"> |
||||||
|
<svg |
||||||
|
class="animate-bounce mt-10 h-16 w-16 mx-auto" |
||||||
|
fill="none" |
||||||
|
stroke="currentColor" |
||||||
|
stroke-width="1.5" |
||||||
|
viewBox="0 0 24 24" |
||||||
|
xmlns="http://www.w3.org/2000/svg" |
||||||
|
aria-hidden="true" |
||||||
|
> |
||||||
|
<path |
||||||
|
stroke-linecap="round" |
||||||
|
stroke-linejoin="round" |
||||||
|
d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" |
||||||
|
/> |
||||||
|
</svg> |
||||||
|
<p class="mb-5"> |
||||||
|
{@html $t("auth.unexpected_error")} |
||||||
|
</p> |
||||||
|
</div> |
||||||
|
{/if} |
@ -0,0 +1,53 @@ |
|||||||
|
// Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers
|
||||||
|
// All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0
|
||||||
|
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
|
||||||
|
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
|
||||||
|
// at your option. All files in the project carrying such
|
||||||
|
// notice may not be copied, modified, or distributed except
|
||||||
|
// according to those terms.
|
||||||
|
|
||||||
|
import { |
||||||
|
writable, |
||||||
|
readable, |
||||||
|
readonly, |
||||||
|
derived, |
||||||
|
get, |
||||||
|
type Writable, |
||||||
|
} from "svelte/store"; |
||||||
|
|
||||||
|
import { createAsyncProxy } from "async-proxy"; |
||||||
|
import { RemoteReadableStream } from 'remote-web-streams'; |
||||||
|
|
||||||
|
export const selected_broker = writable<undefined | Object>( undefined ); |
||||||
|
|
||||||
|
export const brokers_info = writable( {} ); |
||||||
|
|
||||||
|
export const unlocked_wallet = writable(undefined); |
||||||
|
|
||||||
|
export const web_origin = writable(""); |
||||||
|
|
||||||
|
import worker_ from "./worker.js?worker&inline"; |
||||||
|
const worker = new worker_(); |
||||||
|
|
||||||
|
async function rpc( method:string, args?: any) : Promise<any> { |
||||||
|
const { readable, writablePort } = new RemoteReadableStream(); |
||||||
|
worker.postMessage({ method, args, port: writablePort }, [writablePort]); |
||||||
|
const reader = readable.getReader(); |
||||||
|
let ret = await reader.read(); |
||||||
|
await reader.read(); // the close.
|
||||||
|
return ret.value; |
||||||
|
} |
||||||
|
|
||||||
|
const handler = { |
||||||
|
async apply(_target: object, path: PropertyKey[], _caller: any, args?: any) :Promise<any> { |
||||||
|
|
||||||
|
if (path[0] === "login") { |
||||||
|
|
||||||
|
} else { |
||||||
|
return await rpc(<string>path[0], args); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
export const ng = createAsyncProxy({}, handler); |
@ -0,0 +1,2 @@ |
|||||||
|
/// <reference types="svelte" />
|
||||||
|
/// <reference types="vite/client" />
|
@ -0,0 +1,26 @@ |
|||||||
|
// Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers
|
||||||
|
// All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0
|
||||||
|
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
|
||||||
|
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
|
||||||
|
// at your option. All files in the project carrying such
|
||||||
|
// notice may not be copied, modified, or distributed except
|
||||||
|
// according to those terms.
|
||||||
|
|
||||||
|
//import * as sdk from "@ng-org/wasm-tools-auth";
|
||||||
|
import { fromWritablePort } from 'remote-web-streams'; |
||||||
|
|
||||||
|
self.onmessage = (event) => { |
||||||
|
(async function() { |
||||||
|
const { method, args, port } = event.data; |
||||||
|
const writable = fromWritablePort(port); |
||||||
|
const writer = writable.getWriter(); |
||||||
|
console.log("Message received by worker", method, args); |
||||||
|
|
||||||
|
let ret = await Reflect.apply(sdk[method], null, args); |
||||||
|
writer.write(ret); |
||||||
|
writer.close(); |
||||||
|
})(); |
||||||
|
} |
||||||
|
|
||||||
|
console.log("worker loaded"); |
@ -0,0 +1,13 @@ |
|||||||
|
import preprocess from "svelte-preprocess"; |
||||||
|
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; |
||||||
|
|
||||||
|
const config = { |
||||||
|
// preprocess: [
|
||||||
|
// vitePreprocess(),
|
||||||
|
// preprocess({
|
||||||
|
// postcss: true,
|
||||||
|
// }),
|
||||||
|
// ],
|
||||||
|
}; |
||||||
|
|
||||||
|
export default config; |
@ -0,0 +1,38 @@ |
|||||||
|
/** @type {import('tailwindcss').Config}*/ |
||||||
|
const defaultTheme = require('tailwindcss/defaultTheme') |
||||||
|
const config = { |
||||||
|
content: [ |
||||||
|
"./src/**/*.{html,js,svelte,ts}", |
||||||
|
"./node_modules/flowbite-svelte/**/*.{html,js,svelte,ts}", |
||||||
|
"./node_modules/@nng-org/ui-common/src/**/*.{html,js,svelte,ts}", |
||||||
|
], |
||||||
|
theme: { |
||||||
|
extend: { |
||||||
|
colors: { |
||||||
|
primary: { "50": "#eff6ff", "100": "#dbeafe", "200": "#bfdbfe", "300": "#93c5fd", "400": "#60a5fa", "500": "#3b82f6", "600": "#1E88E5", "700": "#4972A5", "800": "#1e40af", "900": "#1e3a8a" } |
||||||
|
}, |
||||||
|
}, |
||||||
|
screens: { |
||||||
|
'xxs': '400px', |
||||||
|
'xs': '500px', |
||||||
|
...defaultTheme.screens, |
||||||
|
|
||||||
|
'tall': { 'raw': '(min-height: 450px)' }, |
||||||
|
'tall-xxs': { 'raw': '(min-height: 360px)' }, |
||||||
|
'tall-xs': { 'raw': '(min-height: 480px)' }, |
||||||
|
'tall-sm': { 'raw': '(min-height: 640px)' }, |
||||||
|
'tall-md': { 'raw': '(min-height: 800px)' }, |
||||||
|
'tall-l': { 'raw': '(min-height: 1000px)' }, |
||||||
|
'tall-xl': { 'raw': '(min-height: 1200px)' }, |
||||||
|
'tall-xxl': { 'raw': '(min-height: 1400px)' }, |
||||||
|
}, |
||||||
|
}, |
||||||
|
|
||||||
|
plugins: [ |
||||||
|
require('flowbite/plugin'), |
||||||
|
require('@tailwindcss/typography') |
||||||
|
], |
||||||
|
darkMode: 'selector', |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports = config; |
@ -0,0 +1,70 @@ |
|||||||
|
import { defineConfig } from 'vite' |
||||||
|
import { svelte, vitePreprocess } from '@sveltejs/vite-plugin-svelte' |
||||||
|
import sveltePreprocess from "svelte-preprocess"; |
||||||
|
import svelteSVG from "vite-plugin-svelte-svg"; |
||||||
|
import wasm from "vite-plugin-wasm"; |
||||||
|
import topLevelAwait from "vite-plugin-top-level-await"; |
||||||
|
import { viteSingleFile } from "vite-plugin-singlefile" |
||||||
|
|
||||||
|
const jsToBottom = () => { |
||||||
|
return { |
||||||
|
name: "script-at-end-of-body", |
||||||
|
transformIndexHtml(html) { |
||||||
|
let scriptTag = html.match(/<script type[^>]*>(.*?)<\/script[^>]*>/)[0] |
||||||
|
//console.log("\n SCRIPT TAG", scriptTag, "\n")
|
||||||
|
html = html.replace(scriptTag, "") |
||||||
|
html = html.replace("<!-- # INSERT SCRIPT HERE -->", scriptTag) |
||||||
|
return html; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({ |
||||||
|
envPrefix: ["VITE_", "NG_"], |
||||||
|
server: { |
||||||
|
port: 14402 |
||||||
|
}, |
||||||
|
worker: { |
||||||
|
format: 'es', |
||||||
|
plugins : [ |
||||||
|
topLevelAwait(), |
||||||
|
wasm(), |
||||||
|
viteSingleFile() |
||||||
|
] |
||||||
|
}, |
||||||
|
plugins: [ |
||||||
|
topLevelAwait(), |
||||||
|
wasm(), |
||||||
|
svelte({ |
||||||
|
preprocess: [ |
||||||
|
vitePreprocess(), |
||||||
|
sveltePreprocess({ |
||||||
|
typescript: false, |
||||||
|
postcss: true, |
||||||
|
}), |
||||||
|
], |
||||||
|
}), |
||||||
|
svelteSVG({ |
||||||
|
svgoConfig: { |
||||||
|
plugins: [ |
||||||
|
{ |
||||||
|
name: 'preset-default', |
||||||
|
params: { |
||||||
|
overrides: { |
||||||
|
// disable plugins
|
||||||
|
removeViewBox: false, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'prefixIds', |
||||||
|
} |
||||||
|
], |
||||||
|
}, // See https://github.com/svg/svgo#configuration
|
||||||
|
requireSuffix: true, // Set false to accept '.svg' without the '?component'
|
||||||
|
}), |
||||||
|
viteSingleFile(), |
||||||
|
jsToBottom(), |
||||||
|
] |
||||||
|
}) |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,24 @@ |
|||||||
|
# Logs |
||||||
|
logs |
||||||
|
*.log |
||||||
|
npm-debug.log* |
||||||
|
yarn-debug.log* |
||||||
|
yarn-error.log* |
||||||
|
pnpm-debug.log* |
||||||
|
lerna-debug.log* |
||||||
|
|
||||||
|
node_modules |
||||||
|
dist |
||||||
|
dist-ssr |
||||||
|
*.local |
||||||
|
|
||||||
|
# Editor directories and files |
||||||
|
.vscode/* |
||||||
|
!.vscode/extensions.json |
||||||
|
.idea |
||||||
|
.DS_Store |
||||||
|
*.suo |
||||||
|
*.ntvs* |
||||||
|
*.njsproj |
||||||
|
*.sln |
||||||
|
*.sw? |
@ -0,0 +1,16 @@ |
|||||||
|
Apache 2.0 License |
||||||
|
|
||||||
|
Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers |
||||||
|
All rights reserved. |
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
you may not use this file except in compliance with the License. |
||||||
|
You may obtain a copy of the License at |
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software |
||||||
|
distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
See the License for the specific language governing permissions and |
||||||
|
limitations under the License. |
@ -0,0 +1,22 @@ |
|||||||
|
MIT License |
||||||
|
|
||||||
|
Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers |
||||||
|
All rights reserved. |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
of this software and associated documentation files (the "Software"), to deal |
||||||
|
in the Software without restriction, including without limitation the rights |
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
copies of the Software, and to permit persons to whom the Software is |
||||||
|
furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all |
||||||
|
copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
SOFTWARE. |
@ -0,0 +1,165 @@ |
|||||||
|
# @ng-org/web |
||||||
|
|
||||||
|
[![Apache 2.0 Licensed][license-image]][license-link] |
||||||
|
[![MIT Licensed][license-image2]][license-link2] |
||||||
|
[](https://forum.nextgraph.org) |
||||||
|
|
||||||
|
JavaScript/TypeScript package containing the SDK of NextGraph for developing third-party Web Apps |
||||||
|
|
||||||
|
## NextGraph |
||||||
|
|
||||||
|
> NextGraph brings about the convergence of P2P and Semantic Web technologies, towards a decentralized, secure and privacy-preserving cloud, based on CRDTs. |
||||||
|
> |
||||||
|
> This open source ecosystem provides solutions for end-users (a platform) and software developers (a framework), wishing to use or create **decentralized** apps featuring: **live collaboration** on rich-text documents, peer to peer communication with **end-to-end encryption**, offline-first, **local-first**, portable and interoperable data, total ownership of data and software, security and privacy. Centered on repositories containing **semantic data** (RDF), **rich text**, and structured data formats like **JSON**, synced between peers belonging to permissioned groups of users, it offers strong eventual consistency, thanks to the use of **CRDTs**. Documents can be linked together, signed, shared securely, queried using the **SPARQL** language and organized into sites and containers. |
||||||
|
> |
||||||
|
> More info here [https://nextgraph.org](https://nextgraph.org) |
||||||
|
|
||||||
|
## Support |
||||||
|
|
||||||
|
Documentation can be found here [https://docs.nextgraph.org](https://docs.nextgraph.org) |
||||||
|
|
||||||
|
And our community forum where you can ask questions is here [https://forum.nextgraph.org](https://forum.nextgraph.org) |
||||||
|
|
||||||
|
## For developers |
||||||
|
|
||||||
|
Read our [getting started guide](https://docs.nextgraph.org/en/getting-started/). |
||||||
|
|
||||||
|
You need to create a Wallet for yourself, on one of our Public Broker Service Provider. Alternatively, you can do everything locally, as [described below](#local-development) |
||||||
|
|
||||||
|
``` |
||||||
|
npm i nextgraphweb |
||||||
|
``` |
||||||
|
|
||||||
|
Additionally, you can use [LDO (Linked Data Object) library](https://ldo.js.org/latest/guides/nextgraph/) to help you with RDF handling in the client side. |
||||||
|
|
||||||
|
``` |
||||||
|
npm i @ldo/connected-nextgraph |
||||||
|
``` |
||||||
|
|
||||||
|
More documentation on LDO can be found [here](https://www.npmjs.com/package/@ldo/connected-nextgraph). |
||||||
|
|
||||||
|
The LDO library also offers a React plugin that will be demonstrated in another example. |
||||||
|
|
||||||
|
You will find a full example web app [here](https://git.nextgraph.org/NextGraph/nextgraph-rs/src/branch/master/ng-sdk-js/example-webapp-vite). |
||||||
|
Specially you will find there instructions for setting up your local dev env. |
||||||
|
|
||||||
|
You have to first call the `init()` and `ng.login()`, then once you receive the status `loggedin` in the callback, you can start using the whole API. |
||||||
|
|
||||||
|
## APIs |
||||||
|
|
||||||
|
All the functions are async. you must use them with `await` (or `.then()`). |
||||||
|
|
||||||
|
They all can throw errors. You must enclose them in `try {} catch(e) {}` |
||||||
|
|
||||||
|
- `ng.doc_create()` |
||||||
|
- `ng.sparql_query(session_id, "[SPARQL query]", base, nuri)` returns or: |
||||||
|
- for SELECT queries: a JSON Sparql Query Result as a Javascript object. [SPARQL Query Results JSON Format](https://www.w3.org/TR/sparql11-results-json/) |
||||||
|
- for CONSTRUCT queries: a list of quads in the format [RDF-JS data model](http://rdf.js.org/data-model-spec/) that can be used as ingress to RDFjs lib. |
||||||
|
- for ASK queries: a boolean |
||||||
|
- `ng.sparql_update(session_id, "[SPARQL update]")` returns nothing, but can throw an error. |
||||||
|
|
||||||
|
Here is the format of the config object to be supplied in the calls to `init_headless` and `admin_create_user`: |
||||||
|
|
||||||
|
## Local development |
||||||
|
|
||||||
|
you need to have a running local ngd server and a local ng-app frontend too. See those [instructions first](https://git.nextgraph.org/NextGraph/nextgraph-rs/src/branch/master/DEV.md#first-run). |
||||||
|
|
||||||
|
You will need to create an admin wallet on the local ngd instance, as explained in the above link. |
||||||
|
|
||||||
|
Then you can use that wallet to log in inside your webapp. |
||||||
|
|
||||||
|
Then compile the nextgraphweb package in dev mode: |
||||||
|
|
||||||
|
``` |
||||||
|
pnpm run -C ../../helpers/nextgraphweb builddev |
||||||
|
``` |
||||||
|
|
||||||
|
Then create your app, by example, with the command: |
||||||
|
|
||||||
|
``` |
||||||
|
npm create vite@latest |
||||||
|
``` |
||||||
|
|
||||||
|
change directory to where our app is located. and install dependencies, then run the dev server. |
||||||
|
|
||||||
|
``` |
||||||
|
npm install |
||||||
|
npm link ../../helpers/nextgraphweb |
||||||
|
npm run dev |
||||||
|
``` |
||||||
|
|
||||||
|
Due to the way `npm link` works, you will have to run this command again, after every time you use `npm install`. |
||||||
|
|
||||||
|
See the example code in [src/main.js](./src/main.js) |
||||||
|
|
||||||
|
## Example usage |
||||||
|
|
||||||
|
call : |
||||||
|
|
||||||
|
```javascript |
||||||
|
import { default as ng, init } from "nextgraphweb"; |
||||||
|
|
||||||
|
await init( |
||||||
|
(event) => { |
||||||
|
// callback |
||||||
|
// once you receive event.status == "loggedin" |
||||||
|
// you can use the full API |
||||||
|
}, |
||||||
|
true, // singleton: boolean (will your app create many docs in the system, or should it be launched as a unique instance) |
||||||
|
[] |
||||||
|
); //list of AccessRequests (for now, leave this empty) |
||||||
|
|
||||||
|
await ng.login(); // this will return false at the first attempt. but it will open the wallet login page so the user can login. |
||||||
|
// if you call it again later once the user has logged in already, it will return true, and nothing more will happen |
||||||
|
``` |
||||||
|
|
||||||
|
You can alternatively wrap the callback inside a Promise in order to wait for the "loggedin" event. |
||||||
|
|
||||||
|
```javascript |
||||||
|
import {default as ng, init} from "nextgraphweb"; |
||||||
|
|
||||||
|
let loggedin = new Promise( async (resolve) => { |
||||||
|
await init( (event) => { |
||||||
|
// callback |
||||||
|
// once you receive event.status == "loggedin" |
||||||
|
// you can use the full API |
||||||
|
if (event.status == "loggedin") resolve(event.session); |
||||||
|
else if (event.status == "cancelled" || event.status == "error") resolve(false); |
||||||
|
} |
||||||
|
, true // singleton: boolean (will your app create many docs in the system, or should it be launched as a unique instance) |
||||||
|
, []); //list of AccessRequests (for now, leave this empty) |
||||||
|
}); |
||||||
|
|
||||||
|
await ng.login(); // this will return false at the first attempt. but it will open the wallet login page so the user can login. |
||||||
|
// if you call it again later once the user has logged in already, it will return true, and nothing more will happen |
||||||
|
|
||||||
|
let session = await loggedin; |
||||||
|
if (session) { |
||||||
|
|
||||||
|
await ng.doc_create(session.session_id,...); |
||||||
|
|
||||||
|
await ng.sparql_query(session.session_id,...); |
||||||
|
|
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
Licensed under either of |
||||||
|
|
||||||
|
- Apache License, Version 2.0 ([LICENSE-APACHE2](LICENSE-APACHE2) or http://www.apache.org/licenses/LICENSE-2.0) |
||||||
|
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) |
||||||
|
at your option. |
||||||
|
|
||||||
|
`SPDX-License-Identifier: Apache-2.0 OR MIT` |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
NextGraph received funding through the [NGI Assure Fund](https://nlnet.nl/assure) and the [NGI Zero Commons Fund](https://nlnet.nl/commonsfund/), both funds established by [NLnet](https://nlnet.nl/) Foundation with financial support from the European Commission's [Next Generation Internet](https://ngi.eu/) programme, under the aegis of DG Communications Networks, Content and Technology under grant agreements No 957073 and No 101092990, respectively. |
||||||
|
|
||||||
|
[license-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg |
||||||
|
[license-link]: https://git.nextgraph.org/NextGraph/nextgraph-rs/raw/branch/master/LICENSE-APACHE2 |
||||||
|
[license-image2]: https://img.shields.io/badge/license-MIT-blue.svg |
||||||
|
[license-link2]: https://git.nextgraph.org/NextGraph/nextgraph-rs/src/branch/master/LICENSE-MIT |
@ -0,0 +1,75 @@ |
|||||||
|
{ |
||||||
|
"name": "@ng-org/web", |
||||||
|
"collaborators": [ |
||||||
|
"Niko PLP <niko@nextgraph.org>" |
||||||
|
], |
||||||
|
"description": "JS/TS SDK of NextGraph for third-party web apps", |
||||||
|
"version": "0.1.2", |
||||||
|
"license": "MIT/Apache-2.0", |
||||||
|
"repository": { |
||||||
|
"type": "git", |
||||||
|
"url": "https://git.nextgraph.org/NextGraph/nextgraph-rs" |
||||||
|
}, |
||||||
|
"type": "module", |
||||||
|
"files": ["dist"], |
||||||
|
"main": "./dist/ngweb.umd.cjs", |
||||||
|
"module": "./dist/ngweb.js", |
||||||
|
"types": "./dist/index.d.ts", |
||||||
|
"exports": { |
||||||
|
".": { |
||||||
|
"import":{ |
||||||
|
"types": "./dist/index.d.ts", |
||||||
|
"default": "./dist/ngweb.js" |
||||||
|
}, |
||||||
|
"require": { |
||||||
|
"types": "./dist/index.d.ts", |
||||||
|
"default": "./dist/ngweb.umd.cjs" |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"dev": "vite", |
||||||
|
"build": "tsc && vite build", |
||||||
|
"builddev": "tsc && cross-env NG_DEV=1 vite build", |
||||||
|
"preview": "vite preview" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"async-proxy": "^0.4.1", |
||||||
|
"remote-web-streams": "^0.2.0" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"@types/node": "^18.7.10", |
||||||
|
"typescript": "~5.7.2", |
||||||
|
"vite": "^6.2.0", |
||||||
|
"vite-plugin-dts": "^4.5.3", |
||||||
|
"cross-env": "^7.0.3" |
||||||
|
}, |
||||||
|
"keywords": [ |
||||||
|
"crdt", |
||||||
|
"dapp", |
||||||
|
"decentralized", |
||||||
|
"e2ee", |
||||||
|
"local-first", |
||||||
|
"p2p", |
||||||
|
"semantic-web", |
||||||
|
"eventual-consistency", |
||||||
|
"json-ld", |
||||||
|
"markdown", |
||||||
|
"ocap", |
||||||
|
"vc", |
||||||
|
"offline-first", |
||||||
|
"p2p-network", |
||||||
|
"collaboration", |
||||||
|
"privacy-protection", |
||||||
|
"rdf", |
||||||
|
"rich-text-editor", |
||||||
|
"self-hosted", |
||||||
|
"sparql", |
||||||
|
"byzantine-fault-tolerance", |
||||||
|
"web3", |
||||||
|
"graph-database", |
||||||
|
"database", |
||||||
|
"triplestore" |
||||||
|
], |
||||||
|
"homepage": "https://nextgraph.org" |
||||||
|
} |
@ -0,0 +1,194 @@ |
|||||||
|
// Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers
|
||||||
|
// All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0
|
||||||
|
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
|
||||||
|
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
|
||||||
|
// at your option. All files in the project carrying such
|
||||||
|
// notice may not be copied, modified, or distributed except
|
||||||
|
// according to those terms.
|
||||||
|
|
||||||
|
import { createAsyncProxy } from "async-proxy"; |
||||||
|
import { RemoteReadableStream } from 'remote-web-streams'; |
||||||
|
|
||||||
|
let initialized: null | Window = null; |
||||||
|
|
||||||
|
const css = `.nextgraph-auth-modal {
|
||||||
|
visibility: hidden; |
||||||
|
background-color: rgba(0, 0, 0, 0.4); |
||||||
|
|
||||||
|
display: grid; |
||||||
|
place-items: center; |
||||||
|
|
||||||
|
height: 100vh; |
||||||
|
width: 100vw; |
||||||
|
|
||||||
|
position: fixed; |
||||||
|
left: 0; |
||||||
|
top: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.nextgraph-auth-modal.nextgraph-auth-modal--fade { |
||||||
|
opacity: 0; |
||||||
|
transition: 0.2s; |
||||||
|
} |
||||||
|
|
||||||
|
.nextgraph-auth-modal.nextgraph-auth-modal--active { |
||||||
|
visibility: visible; |
||||||
|
z-index: 9999; |
||||||
|
opacity: 1; |
||||||
|
} |
||||||
|
|
||||||
|
.nextgraph-auth-modal__content { |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
background-color: #fff; |
||||||
|
} |
||||||
|
|
||||||
|
.nextgraph-auth-modal.nextgraph-auth-modal--active.nextgraph-auth-modal--fade { |
||||||
|
opacity: 1; |
||||||
|
animation-name: fadeInOpacity; |
||||||
|
animation-iteration-count: 1; |
||||||
|
animation-timing-function: ease-in; |
||||||
|
animation-duration: 0.5s; |
||||||
|
} |
||||||
|
|
||||||
|
@keyframes fadeInOpacity { |
||||||
|
0% { |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
100% { |
||||||
|
opacity: 1; |
||||||
|
} |
||||||
|
}`;
|
||||||
|
|
||||||
|
const html = ` |
||||||
|
<div id="nextgraph-auth" class="nextgraph-auth-modal nextgraph-auth-modal--fade"> |
||||||
|
<div class="nextgraph-auth-modal__content"> |
||||||
|
<iframe id="nextgraph-auth-iframe" scrolling="auto" frameborder="0" |
||||||
|
style="position: relative; height: 100%; width: 100%; overflow:auto;"> |
||||||
|
</iframe> |
||||||
|
</div> |
||||||
|
</div>`;
|
||||||
|
|
||||||
|
// const javascript = `
|
||||||
|
// `;
|
||||||
|
|
||||||
|
function addTags() { |
||||||
|
const style = window.document.createElement('style'); |
||||||
|
style.textContent = css; |
||||||
|
window.document.head.append(style); |
||||||
|
|
||||||
|
let body = document.getElementsByTagName("body")[0]; |
||||||
|
body.insertAdjacentHTML("afterbegin", html); |
||||||
|
|
||||||
|
// const js = window.document.createElement('script');
|
||||||
|
// js.type = "text/javascript";
|
||||||
|
// js.textContent = javascript;
|
||||||
|
// body.append(js);
|
||||||
|
} |
||||||
|
|
||||||
|
const iframe_config = import.meta.env.NG_DEV ? {src:"http://localhost:1421/auth.html?o=", origin: "http://localhost:1421"} : {src:"https://nextgraph.net/auth/?o=", origin: "https://nextgraph.net"} ; |
||||||
|
// when developing net-auth
|
||||||
|
//const iframe_config = {src:"http://localhost:14402/?o=", origin: "http://localhost:14402"};
|
||||||
|
// to test ngnet
|
||||||
|
//const iframe_config = {src:"http://127.0.0.1:3033/auth/?o=", origin: "http://127.0.0.1:3033"};
|
||||||
|
|
||||||
|
export const init = async function(callback:Function, singleton:boolean, access_requests:any) { |
||||||
|
if (initialized === null) { |
||||||
|
if (!window) throw new Error("init(callback,..) can only be called from a browser's window"); |
||||||
|
let origin = location.origin; |
||||||
|
let encoded_origin = encodeURIComponent(origin); |
||||||
|
addTags(); |
||||||
|
let iframe: HTMLIFrameElement = <HTMLIFrameElement>window.document.getElementById('nextgraph-auth-iframe'); |
||||||
|
if (iframe) { |
||||||
|
return new Promise(async (resolve) => { |
||||||
|
iframe.addEventListener("load", async function() { |
||||||
|
initialized = this.contentWindow; |
||||||
|
const { readable, writablePort } = new RemoteReadableStream(); |
||||||
|
initialized?.postMessage({ method: "init", singleton, access_requests, port: writablePort }, iframe_config.origin, [writablePort]); |
||||||
|
const reader = readable.getReader(); |
||||||
|
resolve(true); |
||||||
|
for (var msg; msg = await reader.read(); ) { |
||||||
|
if (msg.done) break; |
||||||
|
if (msg.value.status == "error") { |
||||||
|
console.error(msg.value.error); |
||||||
|
} else if ( msg.value.status == "cancelled") { |
||||||
|
hide_nextgraph_auth(); |
||||||
|
} else if (msg.value.status == "loggedin") { |
||||||
|
hide_nextgraph_auth(); |
||||||
|
} |
||||||
|
await (callback)(msg.value); |
||||||
|
} |
||||||
|
}); |
||||||
|
iframe.src = `${iframe_config.src}${encoded_origin}`; |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function show_nextgraph_auth() { |
||||||
|
window.document.getElementById("nextgraph-auth")?.classList.add('nextgraph-auth-modal--active'); |
||||||
|
} |
||||||
|
|
||||||
|
function hide_nextgraph_auth() { |
||||||
|
window.document.getElementById("nextgraph-auth")?.classList.remove('nextgraph-auth-modal--active'); |
||||||
|
}
|
||||||
|
|
||||||
|
async function rpc( method:string, args?: any) : Promise<any> { |
||||||
|
const { readable, writablePort } = new RemoteReadableStream(); |
||||||
|
//console.log("POSTING",method, args);
|
||||||
|
if (method==="doc_subscribe") { |
||||||
|
let callback = args[2]; |
||||||
|
let new_args = [args[0],args[1]]; |
||||||
|
initialized?.postMessage({ method, args:new_args, port: writablePort }, iframe_config.origin, [writablePort]); |
||||||
|
const reader = readable.getReader(); |
||||||
|
let unsub = new Promise(async (resolve)=> { |
||||||
|
resolve(()=>{
|
||||||
|
// unsub function that does nothing.
|
||||||
|
//TODO: implement it
|
||||||
|
}); |
||||||
|
for (var msg; msg = await reader.read(); ) { |
||||||
|
if (msg.done) break; |
||||||
|
if (msg.value.error) { |
||||||
|
throw new Error(msg.value.ret); |
||||||
|
} else if (msg.value.stream) { |
||||||
|
(callback)(msg.value.ret); |
||||||
|
} |
||||||
|
// TODO: deal with end of stream
|
||||||
|
} |
||||||
|
}); |
||||||
|
return unsub; |
||||||
|
|
||||||
|
} else { |
||||||
|
initialized?.postMessage({ method, args, port: writablePort }, iframe_config.origin, [writablePort]); |
||||||
|
const reader = readable.getReader(); |
||||||
|
let ret = await reader.read(); |
||||||
|
//console.log(ret)
|
||||||
|
await reader.read(); // the close
|
||||||
|
if (ret.value.ok)
|
||||||
|
return ret.value.ret; |
||||||
|
else |
||||||
|
throw new Error(ret.value.ret); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
const handler = { |
||||||
|
async apply(_target: object, path: PropertyKey[], _caller: any, args?: any) :Promise<any> { |
||||||
|
if (initialized === null) { |
||||||
|
throw new Error("you must call init() first (and once)"); |
||||||
|
} |
||||||
|
if (path[0] === "login") { |
||||||
|
if (await rpc("login") !== true) { |
||||||
|
show_nextgraph_auth(); |
||||||
|
return false; |
||||||
|
} else { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} else { |
||||||
|
return await rpc(<string>path[0], args); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
export const ng = createAsyncProxy({}, handler); |
@ -0,0 +1 @@ |
|||||||
|
/// <reference types="vite/client" />
|
@ -0,0 +1,24 @@ |
|||||||
|
{ |
||||||
|
"compilerOptions": { |
||||||
|
"target": "ES2020", |
||||||
|
"useDefineForClassFields": true, |
||||||
|
"module": "ESNext", |
||||||
|
"lib": ["ES2020", "DOM", "DOM.Iterable"], |
||||||
|
"skipLibCheck": true, |
||||||
|
|
||||||
|
/* Bundler mode */ |
||||||
|
"moduleResolution": "bundler", |
||||||
|
"allowImportingTsExtensions": true, |
||||||
|
"isolatedModules": true, |
||||||
|
"moduleDetection": "force", |
||||||
|
"noEmit": true, |
||||||
|
|
||||||
|
/* Linting */ |
||||||
|
"strict": true, |
||||||
|
"noUnusedLocals": true, |
||||||
|
"noUnusedParameters": true, |
||||||
|
"noFallthroughCasesInSwitch": true, |
||||||
|
"noUncheckedSideEffectImports": true |
||||||
|
}, |
||||||
|
"include": ["src"] |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
import { resolve } from 'path'; |
||||||
|
import { defineConfig } from 'vite'; |
||||||
|
import dts from 'vite-plugin-dts'; |
||||||
|
|
||||||
|
// https://vitejs.dev/guide/build.html#library-mode
|
||||||
|
export default defineConfig({ |
||||||
|
build: { |
||||||
|
lib: { |
||||||
|
entry: resolve(__dirname, 'src/index.ts'), |
||||||
|
name: 'ngweb', |
||||||
|
fileName: 'ngweb', |
||||||
|
}, |
||||||
|
}, |
||||||
|
envPrefix: ["VITE_", "NG_"], |
||||||
|
plugins: [dts()], |
||||||
|
}); |
Loading…
Reference in new issue