Decentralized @Module example for Reactive extension dependency injection (@rxdi) with Inter planetary file system(IPFS)
This module is created to provide example for future ipfs decentralized node modules using pure nodejs In this repository you will find one module from rxdi infrastructure with included service. Reading above you will understand how to create and deploy your own module using ipfs network and rxdi infrastructure
npm install
npm run build
Before we proceed install ipfs npm i ipfs -g
and run daemon jsipfs daemon
npm run deploy
This will print something like this
added QmW1vAT4oy8w1iB8YoZMvmHoVF4GUHT1eE7h49UqViWawW index.d.ts
added QmfCbYHggmJ5ZdnTRZ9X56iV6KR1REqxKmbX6GjspamH5w index.js
Add these hashes inside index.json
JSON
{
"name":"@test",
"typings": "QmW1vAT4oy8w1iB8YoZMvmHoVF4GUHT1eE7h49UqViWawW",
"module": "QmfCbYHggmJ5ZdnTRZ9X56iV6KR1REqxKmbX6GjspamH5w",
"dependencies": [""]
}
npm run deploy-config
This will print our deployed module
added QmWtJLqyokMZE37DgncpY5HhFvtFQieBzMPDQ318aJeTw6 index.json
Install module inside @rxdi infrastructure:
rxdi install QmWtJLqyokMZE37DgncpY5HhFvtFQieBzMPDQ318aJeTw6
Purpose of this is to put documentation for current module and the same hash can be used to download module
Instead creating index.json
file create index.html
When requesting this page rxdi will parse content between <!--meta-rxdi-ipfs-module-->
meta tags
<div style="visibility:hidden;z-index:-10000;position:absolute;">
<!--meta-rxdi-ipfs-module-->
{
"name":"@test",
"typings": "QmW1vAT4oy8w1iB8YoZMvmHoVF4GUHT1eE7h49UqViWawW",
"module": "QmfCbYHggmJ5ZdnTRZ9X56iV6KR1REqxKmbX6GjspamH5w",
"dependencies": [""]
}
<!--meta-rxdi-ipfs-module-->
</div>
Example index.html
module: Link
(Optional) Can be installed ParcelJS Bundler globally npm i -g parcel-bundler
Inside this repository devDependencies
, parce-bundler
is included
Inside gapi-cli.conf.yml
there is a command called gapi module build
or npm run build
commands:
testing:
browser: jest --env jsdom --testPathPattern="/src/.*\\.browser.spec.(ts|tsx|js)$"
node: jest --env node --testPathPattern="/src/.*\\.spec.(ts|tsx|js)$"
module:
build:
- ./node_modules/.bin/parcel build --target node development/index.ts
- ./node_modules/.bin/rxdi-merge --name @test --project . --out dist/index.d.ts
- find . -not -path "./node_modules/*" -type f -iname \*.map -delete
- cp -r dist/* .
- ./node_modules/.bin/gapi module clean
clean:
- rm -rf dist
- rm -rf .cache
deploy:
- jsipfs add index.js
- jsipfs add index.d.ts
deploy-config:
- jsipfs add index.json
Lets take a closer look command by command
This will take index.ts
inside development folder will bundle it to single js file inside dist/index.js
with mapping dist/index.map
You should export everything like export * from ''
inside this index.ts
because parcel needs to know what this module includes.
Else you will end up not having all your files bundled.
parcel build --target node development/index.ts
This command will search for *.ts files from them will generate index.d.ts file representing all your Typescript Module Definitions
You can install this Globally by typing: npm i @rxdi/dts-merge -g
Inside this repository devDependencies
@rxdi/dts-merge is included
rxdi-merge --name @test --project . --out dist/index.d.ts
If you want to change exported namespace aka @test
just pass different name inside parameter --name @yourName
Remember to change index.json file and redeploy your module.
{
"name":"@yourName",
"typings": "hash",
"module": "hash",
"dependencies": [""]
}
Then use new generated hash to install your module rxdi i hash
This command will search for all *.map files inside your project generated from parcel and will delete it since we don't need them when module is builded for deployment
find . -not -path "./node_modules/*" -type f -iname \*.map -delete
Copy all generated files to root index.js
, index.d.ts
these two files represent our module
cp -r dist/* .
gapi module clean
Now we need to deploy our module to ipfs network
1.Create file called index.json
2.Add this content
{
"name":"@test",
"typings": "QmW1vAT4oy8w1iB8YoZMvmHoVF4GUHT1eE7h49UqViWawW",
"module": "QmfCbYHggmJ5ZdnTRZ9X56iV6KR1REqxKmbX6GjspamH5w",
"dependencies": [""],
}
Where:
name
- Module namespace is important and in the end will be used as follow import { TestModule } from '@test'
in this case
typings
- Hash from ipfs network leading to our generated types index.d.ts
Download folder: 'node_modules/@types/@test
module
- Hash from ipfs network leading to our generated module via ParcelJS index.js
Download folder: 'node_modules/@test
dependencies
- Every module can have many dependencies from the same type pass hash
['QmeFUenbAy4kxKj6hA4kP662nwm11dGUTG8HZowBuapbFv']
To use typings you need to set typeRoots
to "node_modules/@types"
inside tsconfig.json
The system will automatically download typings to @types folder
"typeRoots": [
"node_modules/@types"
]
Example @test module: https://ipfs.io/ipfs/QmWtJLqyokMZE37DgncpY5HhFvtFQieBzMPDQ318aJeTw6
Now you should know what to do! We need to deploy index.js and index.d.ts files from where we will get Hash key
We need ipfs
module to deploy our modules or you can deploy them manually with Desktop application provided from
Ipfs Shipyard Desktop https://github.com/ipfs-shipyard/ipfs-desktop
Documentation for ipfs CLI can be found here: https://github.com/ipfs/js-ipfs
npm install ipfs -g
To add our modules to ipfs:
jsipfs add index.js && jsipfs add index.d.ts
This will print something like this
added QmW1vAT4oy8w1iB8YoZMvmHoVF4GUHT1eE7h49UqViWawW index.d.ts
added QmfCbYHggmJ5ZdnTRZ9X56iV6KR1REqxKmbX6GjspamH5w index.js
Lets prepare our configuration inside index.json
{
"name":"@test",
"typings": "QmW1vAT4oy8w1iB8YoZMvmHoVF4GUHT1eE7h49UqViWawW",
"module": "QmfCbYHggmJ5ZdnTRZ9X56iV6KR1REqxKmbX6GjspamH5w"
}
Deploy index.json
to ipfs network
jsipfs add index.json
This will print something like this
added QmWtJLqyokMZE37DgncpY5HhFvtFQieBzMPDQ318aJeTw6 index.json
Voila!!!! You are ready!!! now lets install this module inside rxdi
infrastructure
Lets take simple server side example
Inside package.json
add the following configuration
"ipfs": [
{
"provider": "https://ipfs.io/ipfs/",
"dependencies": [
"QmWtJLqyokMZE37DgncpY5HhFvtFQieBzMPDQ318aJeTw6"
]
}
],
where:
provider
- This is public gateway from where we will download our modules you can try also with your private gateway http://127.0.0.1:8080/ipfs/
dependencies
- This Array from hashes represents our modules with hash aka index.json which we deploy to ipfs network
{
"name":"@test",
"typings": "QmW1vAT4oy8w1iB8YoZMvmHoVF4GUHT1eE7h49UqViWawW",
"module": "QmfCbYHggmJ5ZdnTRZ9X56iV6KR1REqxKmbX6GjspamH5w"
}
Now we need to run our rxdi install command:
This will take configuration from package.json > ipfs and will download all modules representing Hashes inside dependencies
See real world example: https://ipfs.io/ipfs/QmWtJLqyokMZE37DgncpY5HhFvtFQieBzMPDQ318aJeTw6
Running from local node_modules installation
node ./node_modules/@rxdi/core/bin/root.js install
or
./node_modules/.bin/rxdi install
or Global
npm i -g @rxdi/core
Now you should have rxdi install
command globally for all rxdi
projects this will read package.json
> "ipfs" object
Command will look for package.json
inside current working directory where it is executed
Now when we execute:
rxdi install
You should see something like this:
[
{
"hash": "QmWtJLqyokMZE37DgncpY5HhFvtFQieBzMPDQ318aJeTw6",
"provider": "https://ipfs.io/ipfs/"
}
]
Modules installed!
If you want to install single dependency type:
Short version it will default to https://ipfs.io/ipfs/
provider
rxdi install QmWtJLqyokMZE37DgncpY5HhFvtFQieBzMPDQ318aJeTw6
Long version
rxdi install --hash=QmWtJLqyokMZE37DgncpY5HhFvtFQieBzMPDQ318aJeTw6 --provider=https://ipfs.io/ipfs/
import { Module, Bootstrap } from '@gapi/core';
import { TestModule, TestService } from '@test';
@Module({
imports: [
TestModule
]
})
export class AppModule { }
Bootstrap(AppModule)
.subscribe(
() => console.log('Started!'),
(e) => console.error(e)
);
This is it !
You can Enjoy decentralized rxdi module system!
There is a platform which will be created representing all your private and public modules
Purpose is when you copy QmWtJLqyokMZE37DgncpY5HhFvtFQieBzMPDQ318aJeTw6
and paste it inside search it should show you the package with README.md and everything like regular repository.
Njoy!