Skip to content

Commit

Permalink
feat(js-sdk): add Node.js SDK Client
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 committed Oct 28, 2021
1 parent 75902ff commit 1441f4e
Show file tree
Hide file tree
Showing 27 changed files with 14,157 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ logs/
/cover.out
vendor/
demo/state/redis/client
sdk/js-sdk/node_modules
sdk/js-sdk/dist
46 changes: 46 additions & 0 deletions sdk/js-sdk/.github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: Node.js CI

on:
push:
branches:
- main
- master
pull_request:
branches:
- main
- master
schedule:
- cron: '0 2 * * *'

jobs:
build:
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
node-version: [14, 16]
os: [ubuntu-latest, macos-latest]

steps:
- name: Checkout Git Source
uses: actions/checkout@v2

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}

- name: Install Dependencies
run: npm i -g npminstall && npminstall

- name: Continuous Integration
run: npm run ci

- name: Code Coverage
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
56 changes: 56 additions & 0 deletions sdk/js-sdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Layotto Node.js SDK

The Layotto Node.js SDK to build your application.

## Usage

### State

`demo/state.ts`

```ts
import { Client } from 'layotto';

const storeName = 'redis';
const key = 'foo-js-sdk';
const value = `bar, from js-sdk, ${Date()}`;

await client.state.save(storeName, { key, value });
console.log('saveState success, key: %j, value: %j', key, value);

const resValue = await client.state.get(storeName, key);
console.log('getState success, key: %j, value: %j, toString: %j', key, resValue, Buffer.from(resValue).toString('utf8'));
```

## Development

### Install dependencies

```bash
npm install
```

### Generate gRPC files

```bash
npm run build:grpc
```

### Run Tests

run the unit tests in your local env:

- Start Layotto first, see [How to run layotto](https://mosn.io/layotto/#/zh/start/state/start?id=%e7%ac%ac%e4%ba%8c%e6%ad%a5%ef%bc%9a%e8%bf%90%e8%a1%8clayotto)

```bash
cd ${projectpath}/cmd/layotto
go build

./layotto start -c ../../configs/config_state_redis.json
```

- Then, run unit tests script by npm

```bash
npm run test:unit
```
12 changes: 12 additions & 0 deletions sdk/js-sdk/demo/helloworld.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { strict as assert } from 'assert';
import { Client } from 'layotto';

const client = new Client();
assert(client);

async function main() {
const hello = await client.hello.sayHello('helloworld', 'js-sdk');
console.log('%s', hello);
}

main();
12 changes: 12 additions & 0 deletions sdk/js-sdk/demo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "layotto-demo",
"version": "0.0.0",
"description": "Layotto Node.js SDK Demo",
"private": true,
"scripts": {
"test:all": "npm run test:cjs && npm run test:esm && npm run test:ts",
"test:cjs": "node ./state.js",
"test:esm": "node ./state.mjs",
"test:ts": "ts-node ./state.ts"
}
}
21 changes: 21 additions & 0 deletions sdk/js-sdk/demo/state.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const { strict: assert } = require('assert');
const { Client } = require('layotto');

const client = new Client();
assert(client);

async function main() {
const storeName = 'redis';
const key = 'foo-js-sdk';
const value = `bar, from js-sdk, ${Date()}`;

await client.state.save(storeName, [
{ key, value },
]);
console.log('saveState success, key: %j, value: %j', key, value);

const resValue = await client.state.get(storeName, key);
console.log('getState success, key: %j, value: %j, toString: %j', key, resValue, Buffer.from(resValue).toString('utf8'));
}

main();
21 changes: 21 additions & 0 deletions sdk/js-sdk/demo/state.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { strict as assert } from 'assert';
import { Client } from 'layotto';

const client = new Client();
assert(client);

async function main() {
const storeName = 'redis';
const key = 'foo-js-sdk';
const value = `bar, from js-sdk, ${Date()}`;

await client.state.save(storeName, [
{ key, value },
]);
console.log('saveState success, key: %j, value: %j', key, value);

const resValue = await client.state.get(storeName, key);
console.log('getState success, key: %j, value: %j, toString: %j', key, resValue, Buffer.from(resValue).toString('utf8'));
}

main();
24 changes: 24 additions & 0 deletions sdk/js-sdk/demo/state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { strict as assert } from 'assert'
import { Client } from 'layotto';

const client = new Client();
assert(client);

async function main() {
const storeName = 'redis';
const key = 'foo-js-sdk';
const value = `bar, from js-sdk, ${Date()}`;

await client.state.save(storeName, [
{ key, value },
]);
console.log('saveState success, key: %j, value: %j', key, value);

await client.state.save(storeName, { key, value });
console.log('saveState success, key: %j, value: %j', key, value);

const resValue = await client.state.get(storeName, key);
console.log('getState success, key: %j, value: %j, toString: %j', key, resValue, Buffer.from(resValue).toString('utf8'));
}

main();
5 changes: 5 additions & 0 deletions sdk/js-sdk/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};
65 changes: 65 additions & 0 deletions sdk/js-sdk/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"name": "layotto",
"version": "0.0.0",
"description": "Layotto Node.js SDK",
"main": "dist/index.js",
"files": [
"dist",
"proto",
"package.json",
"README.md"
],
"scripts": {
"ci": "npm run lint && npm run build && npm run test:unit && npm run test:demo",
"test": "jest --runInBand --detectOpenHandles",
"test:unit": "NODE_ENV=test npm run test 'test/unit/.*\\.test\\.ts'",
"test:demo": "cd demo && npm run test:all",
"lint": "tslint -p tsconfig.json",
"build:grpc": "scripts/build-grpc.sh",
"tsc:clean": "rm -rf dist",
"tsc:cjs": "tsc -p tsconfig.json",
"build": "npm run tsc:clean && npm run tsc:cjs",
"rename:cjs": "for f in cjs/*.js; do mv -- \"$f\" \"${f/.js/.cjs}\"; done",
"prepublishOnly": "npm run build"
},
"repository": {
"type": "git",
"url": "git+https://github.com/mosn/layotto.git"
},
"keywords": [
"layotto",
"mosn"
],
"author": "fengmk2",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/mosn/layotto/issues"
},
"homepage": "https://github.com/mosn/layotto#readme",
"devDependencies": {
"@eggjs/tsconfig": "^1.0.0",
"@types/jest": "^27.0.2",
"egg-ci": "^1.19.0",
"grpc-tools": "^1.11.2",
"grpc_tools_node_protoc_ts": "^5.3.2",
"jest": "^27.2.5",
"ts-jest": "^27.0.7",
"ts-node": "^10.3.0",
"tslint": "^6.1.3",
"typescript": "^4.4.4"
},
"dependencies": {
"@grpc/grpc-js": "^1.4.1",
"google-protobuf": "^3.19.0-rc.1"
},
"engines": {
"node": ">=14.0.0"
},
"ci": {
"version": "14, 16",
"type": "github",
"os": {
"github": "linux, macos"
}
}
}
59 changes: 59 additions & 0 deletions sdk/js-sdk/proto/appcallback_grpc_pb.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// package: spec.proto.runtime.v1
// file: appcallback.proto

/* tslint:disable */
/* eslint-disable */

import * as grpc from "@grpc/grpc-js";
import * as appcallback_pb from "./appcallback_pb";
import * as google_protobuf_empty_pb from "google-protobuf/google/protobuf/empty_pb";

interface IAppCallbackService extends grpc.ServiceDefinition<grpc.UntypedServiceImplementation> {
listTopicSubscriptions: IAppCallbackService_IListTopicSubscriptions;
onTopicEvent: IAppCallbackService_IOnTopicEvent;
}

interface IAppCallbackService_IListTopicSubscriptions extends grpc.MethodDefinition<google_protobuf_empty_pb.Empty, appcallback_pb.ListTopicSubscriptionsResponse> {
path: "/spec.proto.runtime.v1.AppCallback/ListTopicSubscriptions";
requestStream: false;
responseStream: false;
requestSerialize: grpc.serialize<google_protobuf_empty_pb.Empty>;
requestDeserialize: grpc.deserialize<google_protobuf_empty_pb.Empty>;
responseSerialize: grpc.serialize<appcallback_pb.ListTopicSubscriptionsResponse>;
responseDeserialize: grpc.deserialize<appcallback_pb.ListTopicSubscriptionsResponse>;
}
interface IAppCallbackService_IOnTopicEvent extends grpc.MethodDefinition<appcallback_pb.TopicEventRequest, appcallback_pb.TopicEventResponse> {
path: "/spec.proto.runtime.v1.AppCallback/OnTopicEvent";
requestStream: false;
responseStream: false;
requestSerialize: grpc.serialize<appcallback_pb.TopicEventRequest>;
requestDeserialize: grpc.deserialize<appcallback_pb.TopicEventRequest>;
responseSerialize: grpc.serialize<appcallback_pb.TopicEventResponse>;
responseDeserialize: grpc.deserialize<appcallback_pb.TopicEventResponse>;
}

export const AppCallbackService: IAppCallbackService;

export interface IAppCallbackServer extends grpc.UntypedServiceImplementation {
listTopicSubscriptions: grpc.handleUnaryCall<google_protobuf_empty_pb.Empty, appcallback_pb.ListTopicSubscriptionsResponse>;
onTopicEvent: grpc.handleUnaryCall<appcallback_pb.TopicEventRequest, appcallback_pb.TopicEventResponse>;
}

export interface IAppCallbackClient {
listTopicSubscriptions(request: google_protobuf_empty_pb.Empty, callback: (error: grpc.ServiceError | null, response: appcallback_pb.ListTopicSubscriptionsResponse) => void): grpc.ClientUnaryCall;
listTopicSubscriptions(request: google_protobuf_empty_pb.Empty, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: appcallback_pb.ListTopicSubscriptionsResponse) => void): grpc.ClientUnaryCall;
listTopicSubscriptions(request: google_protobuf_empty_pb.Empty, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: appcallback_pb.ListTopicSubscriptionsResponse) => void): grpc.ClientUnaryCall;
onTopicEvent(request: appcallback_pb.TopicEventRequest, callback: (error: grpc.ServiceError | null, response: appcallback_pb.TopicEventResponse) => void): grpc.ClientUnaryCall;
onTopicEvent(request: appcallback_pb.TopicEventRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: appcallback_pb.TopicEventResponse) => void): grpc.ClientUnaryCall;
onTopicEvent(request: appcallback_pb.TopicEventRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: appcallback_pb.TopicEventResponse) => void): grpc.ClientUnaryCall;
}

export class AppCallbackClient extends grpc.Client implements IAppCallbackClient {
constructor(address: string, credentials: grpc.ChannelCredentials, options?: Partial<grpc.ClientOptions>);
public listTopicSubscriptions(request: google_protobuf_empty_pb.Empty, callback: (error: grpc.ServiceError | null, response: appcallback_pb.ListTopicSubscriptionsResponse) => void): grpc.ClientUnaryCall;
public listTopicSubscriptions(request: google_protobuf_empty_pb.Empty, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: appcallback_pb.ListTopicSubscriptionsResponse) => void): grpc.ClientUnaryCall;
public listTopicSubscriptions(request: google_protobuf_empty_pb.Empty, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: appcallback_pb.ListTopicSubscriptionsResponse) => void): grpc.ClientUnaryCall;
public onTopicEvent(request: appcallback_pb.TopicEventRequest, callback: (error: grpc.ServiceError | null, response: appcallback_pb.TopicEventResponse) => void): grpc.ClientUnaryCall;
public onTopicEvent(request: appcallback_pb.TopicEventRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: appcallback_pb.TopicEventResponse) => void): grpc.ClientUnaryCall;
public onTopicEvent(request: appcallback_pb.TopicEventRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: appcallback_pb.TopicEventResponse) => void): grpc.ClientUnaryCall;
}
Loading

0 comments on commit 1441f4e

Please sign in to comment.