This is an automated email from the ASF dual-hosted git repository.
igal pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink-statefun.git
The following commit(s) were added to refs/heads/master by this push:
new 197738f [FLINK-24322][js] Various improvements to the consistency and
style
197738f is described below
commit 197738fe6940d9501fd579b227f0876772d97392
Author: Ingo Bürk <[email protected]>
AuthorDate: Fri Sep 17 10:42:37 2021 +0200
[FLINK-24322][js] Various improvements to the consistency and style
* Improve imports/exports and minor TS improvements
* Use Protobuf types where possible
* Seperate public api to a separate file
* Add jest explicitly
---
statefun-sdk-js/package.json | 4 +-
statefun-sdk-js/src/context.ts | 59 +++---------
statefun-sdk-js/src/core.ts | 166 ++++++++--------------------------
statefun-sdk-js/src/egress.ts | 44 ++++-----
statefun-sdk-js/src/handler.ts | 91 +++++++++++--------
statefun-sdk-js/src/message.ts | 61 ++++---------
statefun-sdk-js/src/public_api.ts | 5 +
statefun-sdk-js/src/statefun.ts | 35 ++-----
statefun-sdk-js/src/storage.ts | 75 +++++++--------
statefun-sdk-js/src/types.ts | 68 ++++++--------
statefun-sdk-js/test/core.test.ts | 2 +-
statefun-sdk-js/test/egress.test.ts | 3 +-
statefun-sdk-js/test/message.test.ts | 12 +--
statefun-sdk-js/test/statefun.test.ts | 1 +
statefun-sdk-js/test/storage.test.ts | 56 +++++-------
statefun-sdk-js/test/types.test.ts | 8 +-
16 files changed, 253 insertions(+), 437 deletions(-)
diff --git a/statefun-sdk-js/package.json b/statefun-sdk-js/package.json
index ac0706b..d83591a 100644
--- a/statefun-sdk-js/package.json
+++ b/statefun-sdk-js/package.json
@@ -2,8 +2,8 @@
"name": "apache-flink-statefun",
"version": "3.2-SNAPSHOT",
"description": "JavaScript SDK for Apache Flink Stateful functions",
- "main": "dist/statefun.js",
- "types": "dist/statefun.d.ts",
+ "main": "dist/public_api.js",
+ "types": "dist/public_api.d.ts",
"scripts": {
"build": "tsc --noEmitOnError",
"test": "jest"
diff --git a/statefun-sdk-js/src/context.ts b/statefun-sdk-js/src/context.ts
index ac5acfb..cc0f234 100644
--- a/statefun-sdk-js/src/context.ts
+++ b/statefun-sdk-js/src/context.ts
@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-'use strict';
+"use strict";
import {isEmptyOrNull} from "./core";
import {Message} from "./message";
@@ -23,58 +23,23 @@ import {EgressMessage} from "./message";
import {Address} from "./core";
export class DelayedMessage {
- readonly delay: number;
- readonly message: Message;
- readonly token: string | undefined;
-
- constructor(delay: number, message: Message, cancellationToken: string |
undefined) {
- this.delay = delay;
- this.message = message;
- this.token = cancellationToken;
-
- }
+ constructor(
+ readonly delay: number,
+ readonly message: Message,
+ readonly token: string | undefined
+ ) {}
}
export class CancellationRequest {
- readonly token: string;
-
- constructor(cancellationToken: string) {
- this.token = cancellationToken;
+ constructor(readonly token: string) {
}
}
export class InternalContext {
- #caller: null | Address;
- readonly #sent: Message[];
- readonly #delayed: (DelayedMessage | CancellationRequest)[];
- readonly #egress: EgressMessage[];
-
- constructor() {
- this.#caller = null;
- this.#sent = [];
- this.#delayed = [];
- this.#egress = [];
- }
-
- get sent() {
- return this.#sent;
- }
-
- get delayed() {
- return this.#delayed;
- }
-
- get egress() {
- return this.#egress;
- }
-
- set caller(newCaller: null | Address) {
- this.#caller = newCaller;
- }
-
- get caller(): null | Address {
- return this.#caller;
- }
+ caller: Address | null = null;
+ readonly sent: Message[] = [];
+ readonly delayed: (DelayedMessage | CancellationRequest)[] = [];
+ readonly egress: EgressMessage[] = [];
}
// noinspection SuspiciousTypeOfGuard
@@ -100,7 +65,7 @@ export class Context {
* This property represents a storage that is scoped for the currently
executing function.
* The returned object contains, as properties, the values of each
registered state spec.
*
- * @returns {any} the address scoped storage that is associated with this
function.
+ * @returns {*} the address scoped storage that is associated with this
function.
*/
get storage() {
return this.#storage;
diff --git a/statefun-sdk-js/src/core.ts b/statefun-sdk-js/src/core.ts
index d5c6c4d..aa5436a 100644
--- a/statefun-sdk-js/src/core.ts
+++ b/statefun-sdk-js/src/core.ts
@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-'use strict';
+"use strict";
import {Context} from "./context";
import {Message} from "./message";
@@ -24,7 +24,7 @@ import {Message} from "./message";
* Type - represents the base class for every StateFun type.
* each type is globally and uniquely (across languages) defined by it's
Typename string (of the form <namespace>/<name>).
*/
-abstract class Type<T> {
+export abstract class Type<T> {
readonly #typename: string;
protected constructor(typename: string) {
@@ -62,17 +62,8 @@ abstract class Type<T> {
/**
* A Stateful Function's Address.
*/
-class Address {
- readonly #namespace: string;
- readonly #name: string;
- readonly #id: string;
- readonly #typename: string;
-
- constructor(namespace: string, name: string, id: string, typename: string)
{
- this.#namespace = namespace;
- this.#name = name
- this.#id = id;
- this.#typename = typename;
+export class Address {
+ constructor(readonly namespace: string, readonly name: string, readonly
id: string, readonly typename: string) {
}
/**
@@ -98,42 +89,10 @@ class Address {
throw new Error("id must be a defined string");
}
const {namespace, name} = parseTypeName(typename);
- return new Address(namespace, name, id, typename)
- }
-
-
- /**
- * @returns {string} returns the type name string (typename) of this
function.
- */
- get typename() {
- return this.#typename;
- }
-
- /**
- * @returns {string} the id part of the address.
- */
- get id() {
- return this.#id;
- }
-
- /**
- *
- * @returns {string} returns the namespace part of this address
- */
- get namespace() {
- return this.#namespace;
- }
-
- /**
- *
- * @returns {string} returns the typename's name part of this address.
- */
- get name() {
- return this.#name;
+ return new Address(namespace, name, id, typename);
}
}
-
/**
* A representation of a single state value specification.
* This is created from the following object:
@@ -147,16 +106,15 @@ export interface ValueSpecOpts {
name: string;
type: Type<any>;
expireAfterCall?: number;
- expireAfterWrite?: number
+ expireAfterWrite?: number;
}
/**
- * A Stateful function instance is a two argument function that accepts a
Context to preforme various side-effects with,
+ * A Stateful function instance is a two argument function that accepts a
Context to preform various side-effects with,
* and an input message.
*/
export type JsStatefulFunction = (context: Context, message: Message) => void
| Promise<void>;
-
/**
* A representation of a single function.
* This can be created with the following object:
@@ -171,23 +129,19 @@ export type JsStatefulFunction = (context: Context,
message: Message) => void |
export interface FunctionOpts {
typename: string;
fn: JsStatefulFunction;
- specs?: ValueSpecOpts[]
+ specs?: ValueSpecOpts[];
}
/**
* an internal representation of a value spec
*/
-class ValueSpec implements ValueSpecOpts {
- readonly #name: string;
- readonly #type: Type<any>;
- readonly #expireAfterCall: number;
- readonly #expireAfterWrite: number;
-
- constructor(name: string, type: Type<any>, expireAfterCall?: number,
expireAfterWrite?: number) {
- this.#name = name;
- this.#type = type;
- this.#expireAfterCall = expireAfterCall || -1;
- this.#expireAfterWrite = expireAfterWrite || -1;
+export class ValueSpec implements ValueSpecOpts {
+ constructor(
+ readonly name: string,
+ readonly type: Type<any>,
+ readonly expireAfterCall: number = -1,
+ readonly expireAfterWrite: number = -1
+ ) {
}
/**
@@ -209,37 +163,14 @@ class ValueSpec implements ValueSpecOpts {
if (type === undefined || type === null) {
throw new Error("missing type");
}
- if (!Number.isInteger(expireAfterCall || -1)) {
+ if (expireAfterCall != null && !Number.isInteger(expireAfterCall)) {
throw new Error("expireAfterCall is not an integer");
}
- if (!Number.isInteger(expireAfterWrite || -1)) {
+ if (expireAfterWrite != null && !Number.isInteger(expireAfterWrite)) {
throw new Error("expireAfterWrite is not an integer");
}
return new ValueSpec(name, type, expireAfterCall, expireAfterWrite);
}
-
- /**
- *
- * @returns {string} the name of the this spec
- */
- get name() {
- return this.#name;
- }
-
- /**
- * @returns {Type} this StateFun type.
- */
- get type() {
- return this.#type;
- }
-
- get expireAfterWrite() {
- return this.#expireAfterWrite;
- }
-
- get expireAfterCall() {
- return this.#expireAfterCall;
- }
}
@@ -247,19 +178,16 @@ class ValueSpec implements ValueSpecOpts {
* An internal representation of a function spec.
* A function specification has a typename, a list of zero or more declared
states, and an instance of a function to invoke.
*/
-class FunctionSpec implements FunctionOpts {
- readonly #typename: string;
- readonly #fn: JsStatefulFunction;
- readonly #valueSpecs: ValueSpec[];
-
- constructor(typename: string, fn: JsStatefulFunction, specs: ValueSpec[]) {
+export class FunctionSpec implements FunctionOpts {
+ constructor(
+ readonly typename: string,
+ readonly fn: JsStatefulFunction,
+ readonly valueSpecs: ValueSpec[]
+ ) {
validateTypeName(typename);
if (fn === undefined) {
throw new Error(`input function must be defined.`);
}
- this.#typename = typename;
- this.#fn = fn;
- this.#valueSpecs = specs;
}
static fromOpts({fn, specs, typename}: FunctionOpts): FunctionSpec {
@@ -267,29 +195,19 @@ class FunctionSpec implements FunctionOpts {
if (fn === undefined || fn === null) {
throw new Error(`missing function instance for ${typename}`);
}
- let validatedSpecs = [];
- let seen: Record<string, ValueSpec> = {};
- for (let spec of (specs || [])) {
- const valueSpec = ValueSpec.fromOpts(spec);
- if (seen.hasOwnProperty(valueSpec.name)) {
- throw new Error(`${valueSpec.name} is already defined.`);
- }
- seen[valueSpec.name] = valueSpec;
- validatedSpecs.push(valueSpec);
- }
- return new FunctionSpec(typename, fn, validatedSpecs);
- }
- get valueSpecs() {
- return this.#valueSpecs;
- }
+ const valueSpecs = (specs ?? []).map(spec => ValueSpec.fromOpts(spec));
- get fn() {
- return this.#fn;
- }
+ const seen = new Set<String>();
+ for (const valueSpec of valueSpecs) {
+ if (seen.has(valueSpec.name)) {
+ throw new Error(`{valueSpec.name} is already defined.`);
+ }
- get typename() {
- return this.#typename;
+ seen.add(valueSpec.name);
+ }
+
+ return new FunctionSpec(typename, fn, valueSpecs);
}
}
@@ -297,7 +215,7 @@ class FunctionSpec implements FunctionOpts {
*
* @param {string} typename a namespace/name string
*/
-function validateTypeName(typename: string) {
+export function validateTypeName(typename: string) {
parseTypeName(typename);
}
@@ -305,7 +223,7 @@ function validateTypeName(typename: string) {
* @param {string} typename a string of <namespace>/<name>
* @returns {{namespace: string, name: string}}
*/
-function parseTypeName(typename: string) {
+export function parseTypeName(typename: string): {namespace: string, name:
string} {
if (isEmptyOrNull(typename)) {
throw new Error(`typename must be provided and of the form
<namespace>/<name>`);
}
@@ -321,15 +239,7 @@ function parseTypeName(typename: string) {
return {namespace, name};
}
-function isEmptyOrNull(s: string | undefined | null): boolean {
- // noinspection SuspiciousTypeOfGuard
- return (s === null || s === undefined || (typeof s !== 'string') ||
s.length === 0);
+export function isEmptyOrNull(str: string | undefined | null): boolean {
+ return (str === null || str === undefined
+ || (typeof (str as unknown) !== 'string') || str.length === 0);
}
-
-export {FunctionSpec}
-export {ValueSpec}
-export {Address}
-export {Type}
-export {validateTypeName}
-export {parseTypeName}
-export {isEmptyOrNull}
diff --git a/statefun-sdk-js/src/egress.ts b/statefun-sdk-js/src/egress.ts
index 7f307c3..4467f56 100644
--- a/statefun-sdk-js/src/egress.ts
+++ b/statefun-sdk-js/src/egress.ts
@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-'use strict';
+"use strict";
import "./generated/kafka-egress_pb";
import "./generated/kinesis-egress_pb";
@@ -26,17 +26,11 @@ import {isEmptyOrNull} from "./core";
import {TypedValueSupport} from "./types";
import {EgressMessage} from "./message";
-// noinspection JSUnresolvedVariable
-const PB_KAFKA = global.proto.io.statefun.sdk.egress.KafkaProducerRecord;
-
-// noinspection JSUnresolvedVariable
-const PB_KINESIS = global.proto.io.statefun.sdk.egress.KinesisEgressRecord;
-
-function serialize(type: Type<any> | undefined, value: any): Buffer {
+export function trySerializerForEgress(type: Type<any> | undefined | null,
value: any): Buffer {
if (!(type === undefined || type === null)) {
return type.serialize(value);
}
- if (typeof value === 'string') {
+ if (typeof value === "string") {
return Buffer.from(value);
}
if (Number.isSafeInteger(value)) {
@@ -52,11 +46,11 @@ function serialize(type: Type<any> | undefined, value:
any): Buffer {
}
export interface KafkaEgressOpts {
- typename: string,
- topic: string,
- key?: string,
- value: any,
- valueType?: Type<any>
+ typename: string;
+ topic: string;
+ key?: string;
+ value: any;
+ valueType?: Type<any>;
}
/**
@@ -65,11 +59,11 @@ export interface KafkaEgressOpts {
* @param {string} typename the target egress.
* @param {string} topic the target topic
* @param {string} key the key part of the produced kafka record
- * @param {any} value the value part of the produced kafka record.
+ * @param {*} value the value part of the produced kafka record.
* @param {Type} valueType a custom Type to use to deserialize the given value.
* @returns {EgressMessage} a message to be sent to an egress
*/
-function kafkaEgressMessage({typename = "", topic = "", key = "", value =
null, valueType}: KafkaEgressOpts) {
+export function kafkaEgressMessage({typename = "", topic = "", key = "", value
= null, valueType}: KafkaEgressOpts) {
if (isEmptyOrNull(typename)) {
throw new Error("typename is missing");
}
@@ -80,9 +74,9 @@ function kafkaEgressMessage({typename = "", topic = "", key =
"", value = null,
if (value === undefined || value === null) {
throw new Error("value is missing");
}
- let pbKafka = new PB_KAFKA()
+ const pbKafka = new proto.io.statefun.sdk.egress.KafkaProducerRecord();
pbKafka.setTopic(topic);
- pbKafka.setValueBytes(serialize(valueType, value));
+ pbKafka.setValueBytes(trySerializerForEgress(valueType, value));
if (!isEmptyOrNull(key)) {
pbKafka.setKey(key);
}
@@ -97,7 +91,7 @@ export interface KinesisEgressOpts {
partitionKey: string,
hashKey?: string;
value: any;
- valueType?: Type<any>
+ valueType?: Type<any>;
}
/**
@@ -106,10 +100,10 @@ export interface KinesisEgressOpts {
* @param {string} stream the name of the stream to produce to
* @param {string} partitionKey the partition key to use
* @param {string} hashKey an explicit hash key
- * @param {any} value the value to produce
+ * @param {*} value the value to produce
* @param {Type} valueType a custom Type to use to deserialize the provided
value to bytes
*/
-function kinesisEgressMessage({typename = "", stream = "", partitionKey = "",
hashKey = "", value = null, valueType}: KinesisEgressOpts) {
+export function kinesisEgressMessage({typename = "", stream = "", partitionKey
= "", hashKey = "", value = null, valueType}: KinesisEgressOpts) {
if (isEmptyOrNull(typename)) {
throw new Error("typename is missing");
}
@@ -123,10 +117,10 @@ function kinesisEgressMessage({typename = "", stream =
"", partitionKey = "", ha
if (value === undefined || value === null) {
throw new Error("value is missing");
}
- let record = new PB_KINESIS();
+ const record = new proto.io.statefun.sdk.egress.KinesisEgressRecord();
record.setStream(stream);
record.setPartitionKey(partitionKey);
- record.setValueBytes(serialize(valueType, value))
+ record.setValueBytes(trySerializerForEgress(valueType, value))
if (!isEmptyOrNull(hashKey)) {
record.setExplicitHashKey(hashKey);
}
@@ -134,7 +128,3 @@ function kinesisEgressMessage({typename = "", stream = "",
partitionKey = "", ha
const box =
TypedValueSupport.toTypedValueRaw("type.googleapis.com/io.statefun.sdk.egress.KinesisEgressRecord",
bytes);
return new EgressMessage(typename, box);
}
-
-export {kafkaEgressMessage}
-export {kinesisEgressMessage}
-export {serialize as trySerializerForEgress}
\ No newline at end of file
diff --git a/statefun-sdk-js/src/handler.ts b/statefun-sdk-js/src/handler.ts
index 42dbd43..8d778c6 100644
--- a/statefun-sdk-js/src/handler.ts
+++ b/statefun-sdk-js/src/handler.ts
@@ -15,8 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-'use strict';
-
+"use strict";
import {EgressMessage, Message} from "./message";
@@ -27,11 +26,6 @@ import {Address, FunctionSpec, JsStatefulFunction,
parseTypeName, ValueSpec} fro
import {CancellationRequest, Context, DelayedMessage, InternalContext} from
"./context";
import {AddressScopedStorageFactory, Value} from "./storage";
-const PB_ToFn = global.proto.io.statefun.sdk.reqreply.ToFunction;
-const PB_FromFn = global.proto.io.statefun.sdk.reqreply.FromFunction
-const PB_InvocationResponse =
global.proto.io.statefun.sdk.reqreply.FromFunction.InvocationResponse;
-const PB_Address = global.proto.io.statefun.sdk.reqreply.Address;
-
//
----------------------------------------------------------------------------------------------------
// Missing context handling
//
----------------------------------------------------------------------------------------------------
@@ -42,7 +36,7 @@ const PB_Address =
global.proto.io.statefun.sdk.reqreply.Address;
*/
function respondImmediatelyWithMissingContext(missing: ValueSpec[]):
Uint8Array {
const ctx = valueSpecsToIncompleteInvocationContext(missing);
- const pbFromFn = new PB_FromFn();
+ const pbFromFn = new proto.io.statefun.sdk.reqreply.FromFunction();
pbFromFn.setIncompleteInvocationContext(ctx);
return pbFromFn.serializeBinary();
}
@@ -54,17 +48,17 @@ function respondImmediatelyWithMissingContext(missing:
ValueSpec[]): Uint8Array
*/
function expirationSpecFromValueSpec(valueSpec: ValueSpec) {
if (valueSpec.expireAfterWrite !== -1) {
- const pbSpec = new PB_FromFn.ExpirationSpec();
+ const pbSpec = new
proto.io.statefun.sdk.reqreply.FromFunction.ExpirationSpec();
pbSpec.setExpireAfterMillis(valueSpec.expireAfterWrite);
// noinspection JSCheckFunctionSignatures,TypeScriptValidateJSTypes
- pbSpec.setMode(1) // AFTER_WRITE
+ pbSpec.setMode(1); // AFTER_WRITE
return pbSpec;
}
if (valueSpec.expireAfterCall !== -1) {
- const pbSpec = new PB_FromFn.ExpirationSpec();
+ const pbSpec = new
proto.io.statefun.sdk.reqreply.FromFunction.ExpirationSpec();
pbSpec.setExpireAfterMillis(valueSpec.expireAfterCall);
// noinspection JSCheckFunctionSignatures,TypeScriptValidateJSTypes
- pbSpec.setMode(2) // AFTER_CALL
+ pbSpec.setMode(2); // AFTER_CALL
return pbSpec;
}
return null;
@@ -75,7 +69,7 @@ function expirationSpecFromValueSpec(valueSpec: ValueSpec) {
*/
function valueSpecsToIncompleteInvocationContext(missing: ValueSpec[]) {
const pbValueSpecs = missing.map(missingValueSpec => {
- let pbPersistedValueSpec = new PB_FromFn.PersistedValueSpec();
+ const pbPersistedValueSpec = new
proto.io.statefun.sdk.reqreply.FromFunction.PersistedValueSpec();
pbPersistedValueSpec.setStateName(missingValueSpec.name);
pbPersistedValueSpec.setTypeTypename(missingValueSpec.type.typename);
@@ -88,7 +82,7 @@ function valueSpecsToIncompleteInvocationContext(missing:
ValueSpec[]) {
return pbPersistedValueSpec;
});
- const res = new PB_FromFn.IncompleteInvocationContext();
+ const res = new
proto.io.statefun.sdk.reqreply.FromFunction.IncompleteInvocationContext();
pbValueSpecs.forEach(pbSpec => res.addMissingValues(pbSpec));
return res;
}
@@ -97,11 +91,14 @@ function valueSpecsToIncompleteInvocationContext(missing:
ValueSpec[]) {
// Handler
//
----------------------------------------------------------------------------------------------------
-async function tryHandle(toFunctionBytes: Buffer | Uint8Array, fns: any):
Promise<Buffer | Uint8Array> {
+export async function handle(
+ toFunctionBytes: Buffer | Uint8Array,
+ fns: Record<string, FunctionSpec>
+): Promise<Buffer | Uint8Array> {
//
// setup
//
- const toFn = PB_ToFn.deserializeBinary(toFunctionBytes);
+ const toFn =
proto.io.statefun.sdk.reqreply.ToFunction.deserializeBinary(toFunctionBytes);
const pbInvocationBatchRequest = toFn.getInvocation();
if (pbInvocationBatchRequest === null) {
throw new Error("An empty invocation request");
@@ -121,20 +118,20 @@ async function tryHandle(toFunctionBytes: Buffer |
Uint8Array, fns: any): Promis
//
// apply the batch
//
- const internalContext = new InternalContext()
+ const internalContext = new InternalContext();
const context = new Context(targetAddress, storage, internalContext);
await applyBatch(pbInvocationBatchRequest, context, internalContext,
fnSpec.fn);
//
// collect the side effects
//
- let pbInvocationResponse = new PB_InvocationResponse();
+ const pbInvocationResponse = new
proto.io.statefun.sdk.reqreply.FromFunction.InvocationResponse();
collectStateMutations(values, pbInvocationResponse);
collectOutgoingMessages(internalContext.sent, pbInvocationResponse);
collectEgress(internalContext.egress, pbInvocationResponse);
collectDelayedMessage(internalContext.delayed, pbInvocationResponse);
- let fromFn = new PB_FromFn();
- fromFn.setInvocationResult(pbInvocationResponse)
+ const fromFn = new proto.io.statefun.sdk.reqreply.FromFunction();
+ fromFn.setInvocationResult(pbInvocationResponse);
return fromFn.serializeBinary();
}
@@ -145,10 +142,15 @@ async function tryHandle(toFunctionBytes: Buffer |
Uint8Array, fns: any): Promis
* @param {InternalContext} internalContext
* @param {*} fn the function to apply
*/
-async function applyBatch(pbInvocationBatchRequest: any, context: Context,
internalContext: InternalContext, fn: JsStatefulFunction) {
- for (let invocation of pbInvocationBatchRequest.getInvocationsList()) {
+async function applyBatch(
+ pbInvocationBatchRequest:
proto.io.statefun.sdk.reqreply.ToFunction.InvocationBatchRequest,
+ context: Context,
+ internalContext: InternalContext,
+ fn: JsStatefulFunction
+) {
+ for (const invocation of pbInvocationBatchRequest.getInvocationsList()) {
internalContext.caller = pbAddressToSdkAddress(invocation.getCaller());
- const message = new Message(context.self, invocation.getArgument());
+ const message = new Message(context.self, invocation.getArgument()!);
const maybePromise = fn(context, message);
if (maybePromise instanceof Promise) {
await maybePromise;
@@ -160,18 +162,24 @@ async function applyBatch(pbInvocationBatchRequest: any,
context: Context, inter
// Side Effect Collection
//
----------------------------------------------------------------------------------------------------
-function collectStateMutations(values: Value<unknown>[], pbInvocationResponse:
any) {
- for (let mutation of AddressScopedStorageFactory.collectMutations(values))
{
+function collectStateMutations(
+ values: Value<unknown>[],
+ pbInvocationResponse:
proto.io.statefun.sdk.reqreply.FromFunction.InvocationResponse
+) {
+ for (const mutation of
AddressScopedStorageFactory.collectMutations(values)) {
pbInvocationResponse.addStateMutations(mutation);
}
}
-function collectOutgoingMessages(sent: Message[], pbInvocationResponse: any) {
- for (let message of sent) {
+function collectOutgoingMessages(
+ sent: Message[],
+ pbInvocationResponse:
proto.io.statefun.sdk.reqreply.FromFunction.InvocationResponse
+) {
+ for (const message of sent) {
const pbAddr = sdkAddressToPbAddress(message.targetAddress);
const pbArg = message.typedValue;
- let pbMessage = new PB_FromFn.Invocation();
+ const pbMessage = new
proto.io.statefun.sdk.reqreply.FromFunction.Invocation();
pbMessage.setTarget(pbAddr);
pbMessage.setArgument(pbArg);
@@ -179,9 +187,12 @@ function collectOutgoingMessages(sent: Message[],
pbInvocationResponse: any) {
}
}
-function collectEgress(egresses: EgressMessage[], pbInvocationResponse: any) {
- for (let egress of egresses) {
- let outEgress = new PB_FromFn.EgressMessage();
+function collectEgress(
+ egresses: EgressMessage[],
+ pbInvocationResponse:
proto.io.statefun.sdk.reqreply.FromFunction.InvocationResponse
+) {
+ for (const egress of egresses) {
+ const outEgress = new
proto.io.statefun.sdk.reqreply.FromFunction.EgressMessage();
const {namespace, name} = parseTypeName(egress.typename);
outEgress.setEgressNamespace(namespace);
@@ -192,9 +203,12 @@ function collectEgress(egresses: EgressMessage[],
pbInvocationResponse: any) {
}
}
-function collectDelayedMessage(delayed: (DelayedMessage |
CancellationRequest)[], pbInvocationResponse: any) {
- for (let delayedOr of delayed) {
- let pb = new PB_FromFn.DelayedInvocation();
+function collectDelayedMessage(
+ delayed: (DelayedMessage | CancellationRequest)[],
+ pbInvocationResponse:
proto.io.statefun.sdk.reqreply.FromFunction.InvocationResponse
+) {
+ for (const delayedOr of delayed) {
+ const pb = new
proto.io.statefun.sdk.reqreply.FromFunction.DelayedInvocation();
if (delayedOr instanceof CancellationRequest) {
pb.setIsCancellationRequest(true);
pb.setCancellationToken(delayedOr.token);
@@ -216,14 +230,14 @@ function collectDelayedMessage(delayed: (DelayedMessage |
CancellationRequest)[]
//
----------------------------------------------------------------------------------------------------
function sdkAddressToPbAddress(sdkAddress: Address) {
- let pbAddr = new PB_Address();
+ const pbAddr = new proto.io.statefun.sdk.reqreply.Address();
pbAddr.setNamespace(sdkAddress.namespace);
pbAddr.setType(sdkAddress.name);
pbAddr.setId(sdkAddress.id);
return pbAddr;
}
-function pbAddressToSdkAddress(pbAddress: any) {
+function pbAddressToSdkAddress(pbAddress:
proto.io.statefun.sdk.reqreply.Address | null | undefined) {
if (pbAddress === undefined || pbAddress === null) {
return null;
}
@@ -236,12 +250,9 @@ function pbAddressToSdkAddress(pbAddress: any) {
* @param {Address} targetAddress the target function address which we need to
invoke.
* @returns {FunctionSpec} the function spec that this batch is addressed to.
*/
-function findTargetFunctionSpec(fns: any, targetAddress: Address):
FunctionSpec {
+function findTargetFunctionSpec(fns: Record<string, FunctionSpec>,
targetAddress: Address): FunctionSpec {
if (!fns.hasOwnProperty(targetAddress.typename)) {
throw new Error(`unknown function type ${targetAddress.typename}`);
}
return fns[targetAddress.typename];
}
-
-
-export {tryHandle as handle}
\ No newline at end of file
diff --git a/statefun-sdk-js/src/message.ts b/statefun-sdk-js/src/message.ts
index ab6ed80..90b0990 100644
--- a/statefun-sdk-js/src/message.ts
+++ b/statefun-sdk-js/src/message.ts
@@ -15,29 +15,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-'use strict';
+"use strict";
import * as types from "./types";
import {validateTypeName, Address, isEmptyOrNull, Type} from "./core";
-class Message {
- readonly #targetAddress: Address;
- readonly #typedValue: any;
+export class Message {
+ /** This message's target address. */
+ readonly targetAddress: Address;
+ readonly #typedValue: proto.io.statefun.sdk.reqreply.TypedValue;
- constructor(targetAddress: Address, typedValue: any) {
- this.#targetAddress = targetAddress;
+ constructor(targetAddress: Address, typedValue:
proto.io.statefun.sdk.reqreply.TypedValue) {
+ this.targetAddress = targetAddress;
this.#typedValue = typedValue;
}
/**
- * Return this message's target address.
- */
- get targetAddress() {
- return this.#targetAddress;
- }
-
- /**
* @returns {string} This message value's type name.
*/
get valueTypeName(): string {
@@ -106,26 +99,15 @@ class Message {
return this.as(types.INT_TYPE);
}
- get typedValue() {
+ get typedValue(): proto.io.statefun.sdk.reqreply.TypedValue {
return this.#typedValue;
}
}
-class EgressMessage {
- readonly #typename;
- readonly #box;
-
- constructor(typename: string, box: any) {
- this.#typename = typename;
- this.#box = box;
- }
-
- get typename() {
- return this.#typename;
- }
-
- get typedValue() {
- return this.#box;
+export class EgressMessage {
+ constructor(
+ public readonly typename: string,
+ public readonly typedValue: proto.io.statefun.sdk.reqreply.TypedValue)
{
}
}
@@ -136,20 +118,19 @@ export interface MessageOpts {
typename: string;
id: string;
value: any;
- valueType?: Type<any> | undefined
+ valueType?: Type<any> | undefined;
}
-
/**
* Constructs a Message to be sent.
*
* @param {string} typename a target address function type of the form
<namespace>/<name> (typename).
* @param {string} id the target address id.
- * @param {any} value a value to send.
+ * @param {*} value a value to send.
* @param {Type} valueType the StateFun's type of the value to send.
* @returns {Message} an message object to be sent.
*/
-function messageBuilder({typename = "", id = "", value = null, valueType}:
MessageOpts) {
+export function messageBuilder({typename = "", id = "", value = null,
valueType}: MessageOpts) {
validateTypeName(typename);
if (isEmptyOrNull(id)) {
throw new Error("Target id (id) can not missing");
@@ -180,24 +161,18 @@ export interface EgressOpts {
* Constructs an egress message to be sent.
*
* @param {string} typename a target address typename.
- * @param {any} value a value to send.
+ * @param {*} value a value to send.
* @param {Type} valueType the StateFun's type of the value to send.
* @returns {EgressMessage} an message object to be sent.
*/
-function egressMessageBuilder({typename, value, valueType}: EgressOpts) {
+export function egressMessageBuilder({typename, value, valueType}: EgressOpts)
{
validateTypeName(typename);
if (value === undefined || value === null) {
throw new Error("Missing value");
}
if (valueType === null || valueType === undefined) {
- throw new Error("Missing type.");
+ throw new Error("Missing type");
}
const box = types.TypedValueSupport.toTypedValue(value, valueType);
return new EgressMessage(typename, box);
}
-
-
-export {Message}
-export {EgressMessage}
-export {messageBuilder}
-export {egressMessageBuilder}
\ No newline at end of file
diff --git a/statefun-sdk-js/src/public_api.ts
b/statefun-sdk-js/src/public_api.ts
new file mode 100644
index 0000000..7c53ccd
--- /dev/null
+++ b/statefun-sdk-js/src/public_api.ts
@@ -0,0 +1,5 @@
+export {Context} from "./context";
+export {FunctionOpts, ValueSpecOpts, Address, Type} from "./core";
+export {kafkaEgressMessage, kinesisEgressMessage} from "./egress";
+export {Message, messageBuilder, egressMessageBuilder} from "./message";
+export {StateFun} from "./statefun";
diff --git a/statefun-sdk-js/src/statefun.ts b/statefun-sdk-js/src/statefun.ts
index f50cc3a..9a30caa 100644
--- a/statefun-sdk-js/src/statefun.ts
+++ b/statefun-sdk-js/src/statefun.ts
@@ -17,20 +17,13 @@
*/
"use strict";
-import {FunctionSpec, ValueSpec, Address, Type, FunctionOpts} from "./core";
-import {Context} from "./context";
-import {Message, messageBuilder, egressMessageBuilder} from "./message";
-import {kafkaEgressMessage, kinesisEgressMessage} from "./egress";
+import {FunctionSpec, Type, FunctionOpts} from "./core";
import {handle} from "./handler";
import {BOOL_TYPE, CustomType, FLOAT_TYPE, INT_TYPE, JsonType, ProtobufType,
STRING_TYPE} from "./types";
-class StateFun {
- readonly #fns: Record<string, FunctionSpec>;
-
- constructor() {
- this.#fns = {};
- }
+export class StateFun {
+ readonly #fns: Record<string, FunctionSpec> = {};
/**
* Bind a single function.
@@ -98,9 +91,9 @@ class StateFun {
* Creates a Type that can marshal/unmarshal Protobuf generated JavaScript
classes.
*
* @param {string} typename typename a string of the form
<namespace>/<name> that represents this Type's name.
- * @param {any} googleProtobufGeneratedType a JavaScript class that was
generated using the protoc compiler.
+ * @param {*} googleProtobufGeneratedType a JavaScript class that was
generated using the protoc compiler.
*/
- static protoType<T>(typename: string, googleProtobufGeneratedType: any):
Type<T> {
+ static protoType<T>(typename: string, googleProtobufGeneratedType:
unknown): Type<T> {
return new ProtobufType(typename, googleProtobufGeneratedType);
}
@@ -130,13 +123,13 @@ class StateFun {
*/
handler() {
const self = this;
- return async (req: any, res: any) => {
+ return async (req: unknown, res: unknown) => {
await self.handle(req, res);
}
}
- async handle(req: any, res: any) {
- let outBuf;
+ async handle(req: any, res: any): Promise<void> {
+ let outBuf: Buffer | Uint8Array;
try {
const chunks = [];
for await (const chunk of req) {
@@ -145,7 +138,6 @@ class StateFun {
const inBuf = Buffer.concat(chunks);
outBuf = await handle(inBuf, this.#fns);
} catch (e) {
- console.log(e);
res.writeHead(500, {'Content-Type': 'application/octet-stream'});
res.end();
return;
@@ -154,14 +146,3 @@ class StateFun {
res.end(outBuf);
}
}
-
-export {StateFun}
-export {FunctionSpec}
-export {ValueSpec}
-export {Address}
-export {Message}
-export {Context}
-export {messageBuilder}
-export {egressMessageBuilder}
-export {kafkaEgressMessage}
-export {kinesisEgressMessage}
\ No newline at end of file
diff --git a/statefun-sdk-js/src/storage.ts b/statefun-sdk-js/src/storage.ts
index 9fb258e..8ca76b4 100644
--- a/statefun-sdk-js/src/storage.ts
+++ b/statefun-sdk-js/src/storage.ts
@@ -15,24 +15,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-'use strict';
+"use strict";
import "./generated/request-reply_pb";
import {TypedValueSupport} from "./types";
import {Type, ValueSpec} from "./core";
-const M =
global.proto.io.statefun.sdk.reqreply.FromFunction.PersistedValueMutation;
-
-const DEL =
global.proto.io.statefun.sdk.reqreply.FromFunction.PersistedValueMutation.MutationType['DELETE'];
-
-// noinspection JSUnresolvedVariable
-const MOD =
global.proto.io.statefun.sdk.reqreply.FromFunction.PersistedValueMutation.MutationType['MODIFY'];
+const MutationType =
proto.io.statefun.sdk.reqreply.FromFunction.PersistedValueMutation.MutationType;
// noinspection JSValidateJSDoc
-class Value<T> {
- readonly #name: string;
+export class Value<T> {
+ readonly name: string;
readonly #type: Type<T>;
- #box;
+ #box: proto.io.statefun.sdk.reqreply.TypedValue | null;
#mutated: boolean;
#deleted: boolean;
@@ -42,8 +37,8 @@ class Value<T> {
* @param {Type} type
* @param {proto.io.statefun.sdk.reqreply.TypedValue} box
*/
- constructor(name: string, type: Type<T>, box: any) {
- this.#name = name;
+ constructor(name: string, type: Type<T>, box:
proto.io.statefun.sdk.reqreply.TypedValue | null) {
+ this.name = name;
this.#type = type;
this.#box = box;
this.#mutated = false;
@@ -69,35 +64,31 @@ class Value<T> {
}
}
- get name() {
- return this.#name;
- }
-
// internal helpers
- asMutation(): any {
+ asMutation():
proto.io.statefun.sdk.reqreply.FromFunction.PersistedValueMutation | null {
if (!this.#mutated) {
return null;
}
- let mutation = new M();
- mutation.setStateName(this.#name);
+ const mutation = new
proto.io.statefun.sdk.reqreply.FromFunction.PersistedValueMutation();
+ mutation.setStateName(this.name);
if (this.#deleted) {
- mutation.setMutationType(DEL);
+ mutation.setMutationType(MutationType['DELETE']);
} else {
- mutation.setMutationType(MOD);
+ mutation.setMutationType(MutationType['MODIFY']);
mutation.setStateValue(this.#box);
}
return mutation;
}
- static fromState<U>(persistedValue: any, type: Type<U>) {
+ static fromState<U>(persistedValue:
proto.io.statefun.sdk.reqreply.ToFunction.PersistedValue, type: Type<U>) {
const name = persistedValue.getStateName();
return new Value<U>(name, type, persistedValue.getStateValue());
}
}
// noinspection JSValidateJSDoc
-class AddressScopedStorageFactory {
+export class AddressScopedStorageFactory {
/**
* Tries to create an AddressScopedStorage. An object that contains each
known state as a property on that object.
@@ -106,7 +97,10 @@ class AddressScopedStorageFactory {
* @param { [ValueSpec] } knownStates
* @returns either a list of missing ValueSpecs or a list of Values and an
AddressScopedStorage.
*/
- static tryCreateAddressScopedStorage(invocationBatchRequest: any,
knownStates: ValueSpec[]) {
+ static tryCreateAddressScopedStorage(
+ invocationBatchRequest:
proto.io.statefun.sdk.reqreply.ToFunction.InvocationBatchRequest,
+ knownStates: ValueSpec[]
+ ) {
const receivedState =
AddressScopedStorageFactory.indexActualState(invocationBatchRequest);
const {found, missing} =
AddressScopedStorageFactory.extractKnownStates(knownStates, receivedState);
if (missing.length > 0) {
@@ -127,10 +121,10 @@ class AddressScopedStorageFactory {
};
}
- static extractKnownStates(knownStates: ValueSpec[], receivedState: any) {
- let found = [];
- let missing = [];
- for (let spec of knownStates) {
+ static extractKnownStates(knownStates: ValueSpec[], receivedState:
Record<string, any>) {
+ const found = [];
+ const missing = [];
+ for (const spec of knownStates) {
if (!receivedState.hasOwnProperty(spec.name)) {
missing.push(spec);
continue;
@@ -141,10 +135,12 @@ class AddressScopedStorageFactory {
return {found, missing};
}
- static indexActualState(batch: any): Record<string, any> {
- const states = batch.getStateList();
- let gotState: Record<string, any> = {};
- for (let state of states) {
+ static indexActualState(
+ batchRequest:
proto.io.statefun.sdk.reqreply.ToFunction.InvocationBatchRequest
+ ): Record<string, any> {
+ const states = batchRequest.getStateList();
+ const gotState: Record<string, any> = {};
+ for (const state of states) {
gotState[state.getStateName()] = state;
}
return gotState;
@@ -154,8 +150,8 @@ class AddressScopedStorageFactory {
* @param {[Value]} values a list of initialize values
*/
static create(values: Value<unknown>[]) {
- let storage = Object.create(null);
- for (let v of values) {
+ const storage = Object.create(null);
+ for (const v of values) {
Object.defineProperty(storage, v.name, {
get: () => v.getValue(),
set: (newValue) => v.setValue(newValue)
@@ -164,12 +160,9 @@ class AddressScopedStorageFactory {
return Object.seal(storage);
}
- static collectMutations(values: Value<unknown>[]) {
- return values
- .map(v => v.asMutation())
- .filter(m => m !== null);
+ static collectMutations(values: Value<unknown>[]):
proto.io.statefun.sdk.reqreply.FromFunction.PersistedValueMutation[] {
+ return
<proto.io.statefun.sdk.reqreply.FromFunction.PersistedValueMutation[]>values
+ .map(value => value.asMutation())
+ .filter(mutation => mutation !== null);
}
}
-
-export {Value}
-export {AddressScopedStorageFactory}
\ No newline at end of file
diff --git a/statefun-sdk-js/src/types.ts b/statefun-sdk-js/src/types.ts
index 38acd08..443b782 100644
--- a/statefun-sdk-js/src/types.ts
+++ b/statefun-sdk-js/src/types.ts
@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-'use strict';
+"use strict";
import {Type} from "./core";
@@ -35,9 +35,7 @@ const STRING_TYPENAME = "io.statefun.types/string";
// const DOUBLE_TYPENAME = "io.statefun.types/double";
// noinspection JSValidateJSDoc
-class TypedValueSupport {
-
- static TV: any = global.proto.io.statefun.sdk.reqreply.TypedValue;
+export class TypedValueSupport {
/**
* Parse an instance of a TypedValue via the given type to a JS Object.
@@ -46,7 +44,10 @@ class TypedValueSupport {
* @param {Type} type an StateFun type
* @returns {null|any} a JsObject that was via type or NULL if the typed
value was empty.
*/
- static parseTypedValue<T>(box: any, type: Type<T>): T | null {
+ static parseTypedValue<T>(
+ box: proto.io.statefun.sdk.reqreply.TypedValue | undefined | null,
+ type: Type<T>
+ ): T | null {
if (type === undefined || type === null) {
throw new Error("Type can not be missing");
}
@@ -63,11 +64,11 @@ class TypedValueSupport {
return type.deserialize(buf);
}
- static toTypedValue<T>(obj: T, type: Type<T>): any {
+ static toTypedValue<T>(obj: T, type: Type<T>):
proto.io.statefun.sdk.reqreply.TypedValue {
if (type === undefined || type === null) {
throw new Error("Type can not be missing");
}
- let ret = new TypedValueSupport.TV();
+ const ret = new proto.io.statefun.sdk.reqreply.TypedValue();
ret.setTypename(type.typename);
if (obj === undefined || obj === null) {
@@ -81,8 +82,8 @@ class TypedValueSupport {
return ret;
}
- static toTypedValueRaw(typename: string, bytes: Buffer | Uint8Array) {
- let box = new TypedValueSupport.TV();
+ static toTypedValueRaw(typename: string, bytes: Buffer | Uint8Array):
proto.io.statefun.sdk.reqreply.TypedValue {
+ const box = new proto.io.statefun.sdk.reqreply.TypedValue();
box.setHasValue(true);
box.setTypename(typename);
box.setValue(bytes);
@@ -94,7 +95,7 @@ class TypedValueSupport {
// primitive types
class ProtobufWrapperType<T> extends Type<T> {
- readonly #wrapper
+ readonly #wrapper: any;
constructor(typename: string, wrapper: any) {
super(typename);
@@ -102,19 +103,19 @@ class ProtobufWrapperType<T> extends Type<T> {
}
serialize(value: T) {
- let w = new this.#wrapper();
- w.setValue(value);
- return w.serializeBinary();
+ const wrapper = new this.#wrapper();
+ wrapper.setValue(value);
+ return wrapper.serializeBinary();
}
deserialize(bytes: Buffer): T {
- let w = this.#wrapper.deserializeBinary(bytes);
- return w.getValue();
+ const wrapper = this.#wrapper.deserializeBinary(bytes);
+ return wrapper.getValue();
}
}
class BoolType extends ProtobufWrapperType<boolean> {
- static INSTANCE = new BoolType();
+ static readonly INSTANCE = new BoolType();
constructor() {
super(BOOLEAN_TYPENAME,
global.proto.io.statefun.sdk.types.BooleanWrapper);
@@ -122,8 +123,7 @@ class BoolType extends ProtobufWrapperType<boolean> {
}
class IntType extends ProtobufWrapperType<number> {
- static INSTANCE = new IntType();
-
+ static readonly INSTANCE = new IntType();
constructor() {
super(INTEGER_TYPENAME, proto.io.statefun.sdk.types.IntWrapper);
@@ -132,7 +132,7 @@ class IntType extends ProtobufWrapperType<number> {
// noinspection JSUnresolvedVariable
class FloatType extends ProtobufWrapperType<number> {
- static INSTANCE = new FloatType();
+ static readonly INSTANCE = new FloatType();
constructor() {
super(FLOAT_TYPENAME, proto.io.statefun.sdk.types.FloatWrapper);
@@ -140,34 +140,33 @@ class FloatType extends ProtobufWrapperType<number> {
}
class StringType extends ProtobufWrapperType<string> {
- static INSTANCE = new StringType();
+ static readonly INSTANCE = new StringType();
constructor() {
super(STRING_TYPENAME, proto.io.statefun.sdk.types.StringWrapper);
}
}
-
-class CustomType<T> extends Type<T> {
- readonly #ser;
- readonly #desr;
+export class CustomType<T> extends Type<T> {
+ readonly #serializer: (a: T) => Buffer;
+ readonly #deserializer: (buf: Buffer) => T;
constructor(typename: string, serialize: (a: T) => Buffer, deserializer:
(buf: Buffer) => T) {
super(typename);
- this.#ser = serialize;
- this.#desr = deserializer;
+ this.#serializer = serialize;
+ this.#deserializer = deserializer;
}
- serialize(value: T): Buffer {
- return this.#ser(value);
+ serialize(value: T) {
+ return this.#serializer(value);
}
deserialize(bytes: Buffer) {
- return this.#desr(bytes);
+ return this.#deserializer(bytes);
}
}
-class JsonType<T> extends Type<T> {
+export class JsonType<T> extends Type<T> {
constructor(typename: string) {
super(typename);
@@ -182,7 +181,7 @@ class JsonType<T> extends Type<T> {
}
}
-class ProtobufType<T> extends Type<T> {
+export class ProtobufType<T> extends Type<T> {
#wrapper: any;
constructor(typename: string, wrapper: any) {
@@ -199,14 +198,7 @@ class ProtobufType<T> extends Type<T> {
}
}
-export {Type}
-
export const BOOL_TYPE = BoolType.INSTANCE;
export const INT_TYPE = IntType.INSTANCE;
export const FLOAT_TYPE = FloatType.INSTANCE;
export const STRING_TYPE = StringType.INSTANCE;
-
-export {CustomType}
-export {JsonType}
-export {ProtobufType}
-export {TypedValueSupport}
\ No newline at end of file
diff --git a/statefun-sdk-js/test/core.test.ts
b/statefun-sdk-js/test/core.test.ts
index 3786460..25728eb 100644
--- a/statefun-sdk-js/test/core.test.ts
+++ b/statefun-sdk-js/test/core.test.ts
@@ -40,4 +40,4 @@ describe('ValueSpec', () => {
expect(spec.expireAfterWrite).toStrictEqual(123);
});
-});
\ No newline at end of file
+});
diff --git a/statefun-sdk-js/test/egress.test.ts
b/statefun-sdk-js/test/egress.test.ts
index bac093e..4432619 100644
--- a/statefun-sdk-js/test/egress.test.ts
+++ b/statefun-sdk-js/test/egress.test.ts
@@ -17,6 +17,7 @@
*/
'use strict';
+import {describe, expect} from '@jest/globals'
import {StateFun} from "../src/statefun";
import {kinesisEgressMessage, kafkaEgressMessage} from "../src/egress";
@@ -96,4 +97,4 @@ describe('Egress', () => {
expect(actual).toStrictEqual(aUser);
});
-});
\ No newline at end of file
+});
diff --git a/statefun-sdk-js/test/message.test.ts
b/statefun-sdk-js/test/message.test.ts
index 345371f..7ccb705 100644
--- a/statefun-sdk-js/test/message.test.ts
+++ b/statefun-sdk-js/test/message.test.ts
@@ -16,11 +16,11 @@
* limitations under the License.
*/
-import {Address, Message, messageBuilder, StateFun} from "../src/statefun";
-
+import {describe, expect} from '@jest/globals'
+import {StateFun} from "../src/statefun";
import {TypedValueSupport} from "../src/types";
-
-import {egressMessageBuilder} from "../src/message";
+import {egressMessageBuilder, Message, messageBuilder} from "../src/message";
+import {Address} from "../src/core";
// test constants
const UserType = StateFun.jsonType("io.foo.bar/User");
@@ -88,7 +88,7 @@ describe('Message Test', () => {
value: 2,
});
-
expect(msg.targetAddress).toStrictEqual(Address.fromTypeNameId("foo/bar",
"id"));
+
expect(msg.targetAddress).toStrictEqual(Address.fromTypeNameId("foo/bar", "1"));
expect(msg.isInt()).toStrictEqual(true);
expect(msg.asInt()).toStrictEqual(2);
});
@@ -100,4 +100,4 @@ describe('Message Test', () => {
const actual = TypedValueSupport.parseTypedValue(msg.typedValue,
StateFun.floatType());
expect(actual).toStrictEqual(123);
});
-});
\ No newline at end of file
+});
diff --git a/statefun-sdk-js/test/statefun.test.ts
b/statefun-sdk-js/test/statefun.test.ts
index f3f2be1..169ef07 100644
--- a/statefun-sdk-js/test/statefun.test.ts
+++ b/statefun-sdk-js/test/statefun.test.ts
@@ -16,6 +16,7 @@
* limitations under the License.
*/
+import {describe, expect} from '@jest/globals'
import {StateFun} from '../src/statefun';
function assertThrows(ex: any, fn: () => any) {
diff --git a/statefun-sdk-js/test/storage.test.ts
b/statefun-sdk-js/test/storage.test.ts
index f8258db..c3d4f1f 100644
--- a/statefun-sdk-js/test/storage.test.ts
+++ b/statefun-sdk-js/test/storage.test.ts
@@ -15,9 +15,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+import {describe, expect} from '@jest/globals'
import {StateFun} from '../src/statefun';
import {Value, AddressScopedStorageFactory} from '../src/storage';
-import {Type, TypedValueSupport} from "../src/types";
+import {TypedValueSupport} from "../src/types";
+import {Type} from "../src/core";
import "../src/generated/request-reply_pb";
function stateFrom<T>(name: string, tpe: Type<T>, obj: T): any {
@@ -51,17 +54,14 @@ describe('Value Test', () => {
const incomingType = StateFun.intType();
let incomingState = stateFrom("seen", incomingType, 123);
- let mutation;
- {
- let v = Value.fromState(incomingState, incomingType);
- v.setValue(v.getValue()! + 1) // value should be 124
- mutation = v.asMutation();
- }
+ let v = Value.fromState(incomingState, incomingType);
+ v.setValue(v.getValue()! + 1) // value should be 124
+ const mutation = v.asMutation();
- expect(mutation.getStateName()).toStrictEqual("seen");
- expect(mutation.getMutationType()).toStrictEqual(1);
+ expect(mutation).not.toBeNull();
+ expect(mutation!.getMutationType()).toStrictEqual(1);
- const actual =
TypedValueSupport.parseTypedValue(mutation.getStateValue(), incomingType);
+ const actual =
TypedValueSupport.parseTypedValue(mutation!.getStateValue(), incomingType);
expect(actual).toStrictEqual(124);
});
@@ -70,12 +70,9 @@ describe('Value Test', () => {
const incomingType = StateFun.intType();
let incomingState = stateFrom("seen", incomingType, 123);
- let mutation;
- {
- let v = Value.fromState(incomingState, incomingType);
- // do nothing
- mutation = v.asMutation();
- }
+ let v = Value.fromState(incomingState, incomingType);
+ // do nothing
+ const mutation = v.asMutation();
expect(mutation).toStrictEqual(null);
});
@@ -84,16 +81,13 @@ describe('Value Test', () => {
const incomingType = StateFun.intType();
let incomingState = stateFrom("seen", incomingType, 123);
- let mutation;
- {
- let v = Value.fromState(incomingState, incomingType);
- v.setValue(null); // acts as delete.
-
- mutation = v.asMutation();
- }
+ let v = Value.fromState(incomingState, incomingType);
+ v.setValue(null); // acts as delete.
+ const mutation = v.asMutation();
- expect(mutation.getMutationType()).toStrictEqual(0);
+ expect(mutation).not.toBeNull();
+ expect(mutation!.getMutationType()).toStrictEqual(0);
});
@@ -105,16 +99,12 @@ describe('Value Test', () => {
let v1 = Value.fromState(incomingState1, incomingType);
let v2 = Value.fromState(incomingState2, incomingType);
- let mutations;
- {
- let storage = AddressScopedStorageFactory.create([v1, v2]);
-
- storage.seen += 1;
- storage.idle += 1;
+ let storage = AddressScopedStorageFactory.create([v1, v2]);
- mutations = AddressScopedStorageFactory.collectMutations([v1, v2]);
- }
+ storage.seen += 1;
+ storage.idle += 1;
+ const mutations = AddressScopedStorageFactory.collectMutations([v1,
v2]);
expect(mutations.length).toStrictEqual(2);
});
-});
\ No newline at end of file
+});
diff --git a/statefun-sdk-js/test/types.test.ts
b/statefun-sdk-js/test/types.test.ts
index 043f01f..6e943d8 100644
--- a/statefun-sdk-js/test/types.test.ts
+++ b/statefun-sdk-js/test/types.test.ts
@@ -15,9 +15,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import {StateFun} from '../src/statefun';
-import {Type, TypedValueSupport} from "../src/types";
+import {describe, expect} from '@jest/globals'
+import {StateFun} from '../src/statefun';
+import {TypedValueSupport} from "../src/types";
+import {Type} from "../src/core";
function roundTrip<T>(tpe: Type<T>, value: T): T {
const bytes = tpe.serialize(value);
@@ -90,4 +92,4 @@ describe('Simple Serialization Test', () => {
}
expect(failed).toStrictEqual(true);
})
-});
\ No newline at end of file
+});