如何创建一个“通用包”以共享对流包中的通用逻辑?

时间:2019-08-22 21:08:01

标签: hyperledger-fabric convector

我想创建一个通用包以共享对等链代码中的通用登录名...这在项目不断增长时非常有用,我们希望共享通用代码块,utils和其他有用代码以免使项目变干或硬编码字符串

但是如果对流器当前不支持它怎么办?

1 个答案:

答案 0 :(得分:1)

目前,对流器不能使用常见的香草包(仅),只能使用控制器, 为了工作,我们需要破解一些东西,例如创建一个实现控制器的程序包,例如假控制器。并遵循一些步骤

感谢 Covalent Diego Walter ,并花了几个小时

  

此帖子属于一个拥有nest.js服务器的github项目,但当前没有创建,当我拥有链接时我会更新此帖子

首先,我们开始手动创建用于打字稿的lerna包

创建lerna通用软件包@convector-rest-sample/common

packages/common/tsconfig.json

{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "."
  },
  "include": [
    "./src/**/*"
  ]
}

packages/common/package.json

{
  "name": "@convector-rest-sample/common",
  "version": "0.1.0",
  "main": "dist/src/index",
  "types": "dist/src/index",
  "files": [
    "dist"
  ],
  "scripts": {
    "build": "npm run clean && tsc",
    "clean": "rm -rf ./dist",
    "prepublishOnly": "npm run build"
  },
  "devDependencies": {
    "typescript": "3.4.3"
  }
}
  

注意:路径"main": "dist/src/index""types": "dist/src/index"很重要,必须指向索引文件的位置,如果使用错误的路径,则使用包会出错

创建索引以导出软件包文件

packages/common/src/index.ts

export * from './constants';

packages/common/src/constants.ts

// convector model
const CONVECTOR_MODEL_PATH_PREFIX: string = 'io.worldsibu.examples';
const CONVECTOR_MODEL_PATH_PARTICIPANT: string = `${CONVECTOR_MODEL_PATH_PREFIX}.participant`;
const CONVECTOR_MODEL_PATH_PERSON: string = `${CONVECTOR_MODEL_PATH_PREFIX}.person`;
const CONVECTOR_MODEL_PATH_ATTRIBUTE: string = `${CONVECTOR_MODEL_PATH_PREFIX}.attribute`;
const CONVECTOR_MODEL_PATH_X509IDENTITY: string = `${CONVECTOR_MODEL_PATH_PREFIX}.x509identity`;

export const appConstants = {
  CONVECTOR_MODEL_PATH_PARTICIPANT,
  CONVECTOR_MODEL_PATH_PERSON,
  CONVECTOR_MODEL_PATH_ATTRIBUTE,
  CONVECTOR_MODEL_PATH_X509IDENTITY,
};

现在将通用软件包添加到monorepo的所有软件包中

# add to all packages (without scope)
$ npx lerna add @convector-rest-sample/common@0.1.0
# to prevent some problems always use same version has in local package
# clean and bootstrap
$ npx lerna clean -y && npx lerna bootstrap

可选可以使用--scope仅添加到所需的软件包中

# add to all packages (with scope)
$ npx lerna add @convector-rest-sample/common@0.1.0 --scope server --no-bootstrap
$ npx lerna add @convector-rest-sample/common@0.1.0 --scope participant-cc --no-bootstrap
$ npx lerna add @convector-rest-sample/common@0.1.0 --scope person-cc --no-bootstrap
# clean and bootstrap
$ npx lerna clean -y && npx lerna bootstrap --hoist

现在在服务器中测试@convector-rest-sample/common,将此行添加到packages/server/src/app.ts的顶部 确认一切正常预期

  

注意:如果没有服务器,请直接跳过此步骤,以使用ChainCode中的通用软件包部分

import { appConstants as c } from '@convector-rest-sample/common';
debugger;
Logger.log(JSON.stringify(c, undefined, 2));

现在使用调试器启动服务器,并检查c对象或查看日志结果

$ npx lerna run start:debug --scope server --stream

如果输出appConstant,我们准备好了,并且已经可以进行常见的包装工作

在ChainCode内使用通用软件包

要在chaincode中使用通用程序包,非常棘手,而且我花了几个小时才能使它工作,这要归功于WorldSibu的Walter和Diego。 问题在于,目前,在对流器中,没有简单的方法可以使用不是控制器的软件包,要使其正常工作,我们必须在@convector-rest-sample/common中创建一个伪造的控制器以使其正常工作

首先在我们的@convector-rest-sample/common中安装所需的控制器依赖项,这是使用{ Controller, Invokable }所必需的

# install dependency
$ npx lerna add @worldsibu/convector-core --scope @convector-rest-sample/common

接下来,我们必须在packages/common/src/common.controller.ts中创建一个假控制器

import { Controller, Invokable } from '@worldsibu/convector-core';

@Controller('common')
export class CommonController {
  @Invokable()
  public async greeting() {
    return 'Hello from CommonController';
  }
}

不要忘记将export * from './common.controller';添加到packages/common/src/index.ts以导出控制器

export * from './constants';
export * from './common.controller';

在此之后,我们必须更改chaincode.config.json来添加伪控制器,这真是一个骇客,我们使用伪控制器强制将@convector-rest-sample/common复制到chaincode-person目录中,否则,@convector-rest-sample/common将不会被复制,并且当我们尝试使用cc:startcc:upgrade进行部署时,链代码会断开,它总是显示令人讨厌的错误npm ERR! 404 Not Found: @convector-rest-sample/common@0.1.0

第一个更改chaincode.config.json

  

提示:如果项目中没有此提示,请将org1.person.config.json复制到chaincode.config.json并继续。...

在我的情况下,我只有旧文件org1.participant.config.jsonorg1.person.config.jsonorg2.participant.config.jsonorg2.person.config.json

  

此文件可以删除(迭戈提示)

好,让我们更改chaincode.config.json并在person-cc上方添加另一个控制器

"controllers": [
  {
    "name": "participant-cc",
    "version": "file:./packages/participant-cc",
    "controller": "ParticipantController"
  },
  {
    "name": "person-cc",
    "version": "file:./packages/person-cc",
    "controller": "PersonController"
  },
  // BO : ADD THIS
  {
    "name": "@convector-rest-sample/common",
    "version": "file:./packages/common",
    "controller": "CommonController"
  }
  // EO : ADD THIS
],
  

注意:这是另一个巧妙的技巧部分,name程序包名称,就像我们在导入中使用的一样,version路径位置在我们的构建chaincode-person

在构建链码之前,我们必须更改模型以使用@convector-rest-sample/common ex c.CONVECTOR_MODEL_PATH_X509IDENTITY中的新公共常量,当前,此公共包仅使用简单常量,为了保持简单,关键在于创建了公共逻辑对于所有软件包,其余服务器,前端,packages-cc,cli-tools等

packages/participant-cc/src/participant.model.ts

import { appConstants as c } from '@convector-rest-sample/common';
...
export class x509Identities extends ConvectorModel<x509Identities>{
  @ReadOnly()
  public readonly type = c.CONVECTOR_MODEL_PATH_X509IDENTITY;
  ...
export class Participant extends ConvectorModel<Participant> {
  @ReadOnly()
  public readonly type = c.CONVECTOR_MODEL_PATH_PARTICIPANT;
  ...

packages/person-cc/src/person.model.ts

import { appConstants as c } from '@convector-rest-sample/common';
...
export class Attribute extends ConvectorModel<Attribute>{
  @ReadOnly()
  @Required()
  public readonly type = c.CONVECTOR_MODEL_PATH_ATTRIBUTE;
  ...
export class Person extends ConvectorModel<Person> {
  @ReadOnly()
  @Required()
  public readonly type = 'io.worldsibu.example.person';
  ...

现在我们可以cc:package链码chaincode-person,这将使用我们的{{将@convector-rest-sample/common和链person-ccparticipant-cc一起包装在链码中1}}常量

@convector-rest-sample/common

打包后,建议我们的链码检查是否将通用包复制到正确路径的# first remove chaincode (optional) $ rm chaincode-person -r # now manually invoke package command $ npm run cc:package -- person org1 文件夹中

chaincode-person

另一个好的做法是检查是否在$ ls -la chaincode-person/packages chaincode-person/packages/@convector-rest-sample chaincode-person/packages/participant-cc chaincode-person/packages/person-cc 文件夹中的文件chaincode-person中,是否将我们的chaincode-person/package.json添加到@convector-rest-sample/common中,在上面的json块中,我们可以看到{{ 1}}脚本添加行dependencies,这是根据我们在添加虚假控制器时cc:package记住的更改而创建的

"@convector-rest-sample/common": "file:./package/@convector-rest-sample/common"

现在完成,我们可以使用chaincode.config.json"dependencies": { "@theledger/fabric-chaincode-utils": "^4.0.1", "@worldsibu/convector-core": "^1.3.3", "@worldsibu/convector-storage-stub": "^1.3.3", "reflect-metadata": "^0.1.12", "tslib": "^1.9.0", "participant-cc": "file:./packages/participant-cc", "person-cc": "file:./packages/person-cc", // BO: magic line here "@convector-rest-sample/common": "file:./packages/@convector-rest-sample/common" // EO: magic line here },

来部署我们的链码。
  

提示:如果是第一次使用cc:start,如果不是第一次使用cc:upgrade

要从一开始就检查一切是否正常,我们重新启动超级账本堆栈,然后从头开始,警告它会破坏所有数据,如果不想破坏数据,请不要执行{ {1}},并使用cc:start,更多信息

cc:package

完成,一切正常,我们已经实施了npm run env:restart软件包。

如果我们检查ouchdb cc:upgrade人,我们可以检查使用的是# this recreate environment and destroy all data $ npm run env:restart $ npm run cc:start -- person # seed ledger $ npm run seed # create couchdb views $ ./views/install.sh # invoke person_create $ npx hurl invoke person person_create "{ \"id\": \"1-100-103\", \"firstname\": \"Pete\", \"lastname\": \"Doe\", \"username\": \"pete\", \"password\": \"12345678\", \"email\": \"pete.doe@example.com\"}" -u admin # invoke some stuff (wait for first invoke finish) $ npx hurl invoke person person_getAll 类型的@convector-rest-sample/common类型,证明它是从{{1}获取值的},相信我,如果找不到1-100-103,它就会崩溃.....简单

为了将来更改链码,请使用上述命令对其进行升级

"type": "io.worldsibu.examples.person"

我们完成了........

使用脚本将其他文件复制到链码

在找到解决方案之前,我尝试破解的另一件事是使用@convector-rest-sample/common,但是它不起作用,因为我们需要在{{1}中使用@convector-rest-sample/common@convector-rest-sample/common来修改# upgrade chaincode $ npm run cc:upgrade -- person 1.1 },但我尝试了……

将其保留在此处,可能对其他类型的东西有用,例如复制其他类型的东西

npm scripts
  

chaincode-person/package.json中的"@convector-rest-sample/common": "file:./packages/@convector-rest-sample/common"dependencies中的{ "scripts": { ... "cc:package": "f() { npm run lerna:build; chaincode-manager --update --config ./$2.$1.config.json --output ./chaincode-$1 package; npm run copy:indexes -- $1; npm run copy:package:common -- $1; }; f", ... "copy:package:common": "f () { mkdir -p ./chaincode-$1/node_modules/@convector-rest-sample/; cp -r ./packages/common/ ./chaincode-$1/node_modules/@convector-rest-sample/; }; f" ... 的注释,可以使用,但是不会用行修改npm run copy:package:common -- $1;

"cc:package"

清理

最后,我们可以删除旧文件cp -r ./packages/common/ ./chaincode-$1/node_modules/@convector-rest-sample/; };,现在我们使用配置文件"copy:package:common"(感谢迭戈的提示)

chaincode-person/package.json

注意:不要忘记用新的"dependencies": { "@theledger/fabric-chaincode-utils": "^4.0.1", "@worldsibu/convector-core": "^1.3.3", "@worldsibu/convector-storage-stub": "^1.3.3", "reflect-metadata": "^0.1.12", "tslib": "^1.9.0", "participant-cc": "file:./packages/participant-cc", "person-cc": "file:./packages/person-cc", // BO: magic line here "@convector-rest-sample/common": "file:./packages/@convector-rest-sample/common" // EO: magic line here } 文件更新org1.participant.config.json org1.person.config.json org2.person.config.json org2.participant.config.json chaincode.config.json

# remove legacy files rm org1.participant.config.json org1.person.config.json org2.person.config.json org2.participant.config.json

packages.json

感谢Covalent的所有好心人

更新:如果尝试"cc:package",则在新的项目/克隆中出现以下错误

./chaincode.config.json

这是因为该软件包在使用之前需要先构建

package.json

现在可以使用

"cc:package": "f() { npm run lerna:build; chaincode-manager --update --config ./chaincode.config.json --output ./chaincode-$1 package; npm run copy:indexes -- $1; }; f",