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
+});

Reply via email to