Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/rxdi/ui-registry
IPFS Decentralized Web Components registry
https://github.com/rxdi/ui-registry
components decentralized gapi ipfs lit-html rxdi web-components
Last synced: 24 days ago
JSON representation
IPFS Decentralized Web Components registry
- Host: GitHub
- URL: https://github.com/rxdi/ui-registry
- Owner: rxdi
- Created: 2019-09-14T14:37:42.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2023-01-04T10:24:49.000Z (about 2 years ago)
- Last Synced: 2024-10-30T04:49:16.362Z (2 months ago)
- Topics: components, decentralized, gapi, ipfs, lit-html, rxdi, web-components
- Language: TypeScript
- Homepage:
- Size: 668 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# @rxdi/ui-registry
* Reusability of components
* IPFS Components registry
* Decentralized future## Setup
## Local machine
Install `@rxdi/deploy` global
```bash
npm i -g @rxdi/deploy
```Execute command:
```bash
rxdi-deploy --graphiql-playground --webui --browser --ipfs-api-gateway 8080 --ipfs-api-port 5001
```Current working directory will be used for serving files throught Web user interface
This setup will create following directories inide current user folder `~/` `~/.jsipfs`, `~/.rxdi`, `~/.packages`
### Docker
Create `my-project` directory
```
mkdir my-project
```#### Spawn `ipfs node` for Web and components bundling
```bash
docker run \
-p 8957:8957 \
-p 5001:5001 \
-p 8080:8080 \
-p 9300:9300 \
-v $(pwd)/my-project:/usr/src/app/files \
-v $(pwd)/packages:/usr/src/app/packages \
-v $(pwd)/.rxdi:/root/.rxdi \
-v $(pwd)/.jsipfs:/root/.jsipfs \
-i \
-t \
rxdi/deploy:latest \
--graphiql-playground \
--webui
--browser
```#### Spawn `ipfs node` for Backend bundling
```bash
docker run \
-p 8957:8957 \
-p 5001:5001 \
-p 8080:8080 \
-p 9300:9300 \
-v $(pwd)/my-project:/usr/src/app/files \
-v $(pwd)/packages:/usr/src/app/packages \
-v $(pwd)/.rxdi:/root/.rxdi \
-v $(pwd)/.jsipfs:/root/.jsipfs \
-i \
-t \
rxdi/deploy:latest \
--graphiql-playground \
--webui
```## Open WebUI
Managing your deployment processes
```bash
http://localhost:9300/webui/
```## Creating your first component
```bash
cd my-project && mkdir trello
``````typescript
import { Component, html } from '@rxdi/lit-html';/**
* @customElement inject-tailwind
*/
@Component({
selector: 'inject-tailwind',
template: () => html`
`,
})
export class TailWindComponent extends HTMLElement {}
```## Trigger build for component
```graphql
mutation {
triggerBuild(
buildFolder: "./trello-component/build"
file: "trello.component.ts"
folder: "./trello-component/"
message: "Init trello component"
namespace: "@my-project/trello"
) {
status
file {
hash
}
}
}
```This will give you `ipfs` hash `QmQGKFj9pF8pcdffdnRZJ5rLg1rs8xiNh2D974ZG9FQsgU`
Default provider is `http://127.0.0.1:8080/ipfs/` so we can access our transpiled file at address http://127.0.0.1:8080/ipfs/QmQGKFj9pF8pcdffdnRZJ5rLg1rs8xiNh2D974ZG9FQsgU
## Mapping to `@rxdi/graphqj` configuration
```yml
$views:
home:
components:
- link: http://127.0.0.1:8080/ipfs/QmQGKFj9pF8pcdffdnRZJ5rLg1rs8xiNh2D974ZG9FQsgU
selector: trello-component
html: |
```
#### Modify Authentication logic
Add inside the working directory file with name `interceptor.ts` and add following content;
if using `docker` place `interceptor.ts` inside `my-project` or mount it at with custom folder `-v $(pwd)/files:/usr/src/app/files`
as long as `interceptor.ts` present inside `/usr/src/app/files` it will be loaded.Working with this approach you need to set `--interceptor ./interceptor.ts` argument
```typescript
import { Request } from 'hapi';
import { errorUnauthorized, GenericGapiResolversType } from '@gapi/core';interface Context {
user: { type: string };
}interface Resolver extends GenericGapiResolversType {
scope?: string[];
public?: boolean;
}function canAccess(resolverScope: string[], context: Context) {
return context && context.user && resolverScope.filter(scope => scope === context.user.type).length
? true
: errorUnauthorized();
}
function AuthenticationHooks(resolver: Resolver, context: Context) {
canAccess(resolver.scope, context);
}
function ResolverHooks(resolver: Resolver, root, args, context: Context, info) {
if (resolver && !resolver.public) {
AuthenticationHooks(resolver, context);
}
}export async function OnRequestHook(request: Request) {
return { user: { type: 'ADMIN' } };
}export async function ResolverHook(resolver: Resolver, root, args, context: Context, info) {
return ResolverHooks(resolver, root, args, context, info);
}```
Important part is that we export 2 methods `OnRequestHook` and `ResolverHook`
These are named for convenience the script internally will take UP to 2 methods1. Request handler function - will populate `context` variable for resolver
2. Resolver hook function - on every request apply some authentication logic
3. By default every resolver scope is predefined with `ADMIN` to change it set Environment variable `APP_DEFAULT_SCOPE````typescript
export async function MyMethodWhichWillPopulateContext(request: Request) {
return { user: { type: 'ADMIN' } };
}export async function MyMethodThatWillBeRunnedOnEveryRequest(resolver: Resolver, root, args, context: Context, info) {
console.log(context);
return ResolverHooks(resolver, root, args, context, info);
}
```#### Advanced technique
Create `import.ts` file and pass argument `--import ./import.ts` with the following format
```typescript
import {
Module,
ON_REQUEST_HANDLER,
GRAPHQL_PLUGIN_CONFIG,
Boom,
RESOLVER_HOOK,
GenericGapiResolversType
} from '@gapi/core';
import { ResponseToolkit } from 'hapi';@Module({
providers: [
{
provide: ON_REQUEST_HANDLER,
deps: [GRAPHQL_PLUGIN_CONFIG],
useFactory: (config: GRAPHQL_PLUGIN_CONFIG) => async (
next,
request: Request,
h: ResponseToolkit,
err: Error
) => {
if (request.headers['authorization']) {
try {
config.graphqlOptions.context = {};
} catch (e) {
Boom.unauthorized();
}
} else {
config.graphqlOptions.context = null;
}
return next();
}
},
{
provide: RESOLVER_HOOK,
useFactory: () => (resolver: GenericGapiResolversType) => {
const resolve = resolver.resolve.bind(resolver.target);
resolver.resolve = async function(root, args, context, info, ...a) {
// Do something with resolver
return resolve(root, args, context, info, ...a);
};
return resolver;
}
}
]
})
export class TestImport {}```