diff --git a/ss-utils/ss-utils-tests.ts b/ss-utils/ss-utils-tests.ts
new file mode 100644
index 000000000..52ac7151b
--- /dev/null
+++ b/ss-utils/ss-utils-tests.ts
@@ -0,0 +1,81 @@
+///
+///
+
+declare var EventSource : sse.IEventSourceStatic;
+
+declare module sse {
+ interface IEventSourceStatic extends EventTarget {
+ new (url: string, eventSourceInitDict?: IEventSourceInit):IEventSourceStatic;
+ url: string;
+ }
+
+ interface IEventSourceInit {
+ withCredentials?: boolean;
+ }
+}
+
+function test_ssutils() {
+ $.ss.eventReceivers = { "document": document };
+
+ var source = new EventSource("/event-stream?channels=home,work");
+ $(source).handleServerEvents({
+ handlers: {
+ onConnect: function(connect:ssutils.SSEConnect) {},
+ onHeartbeat: function(msg:ssutils.SSEHeartbeat, e:MessageEvent){},
+ onJoin: function(msg:ssutils.SSEJoin) {},
+ onLeave: function(msg:ssutils.SSELeave) {}
+ },
+ receivers: {
+ tv: {
+ watch: function(){}
+ }
+ }
+ });
+
+ $(document).bindHandlers({
+ announce: function (msg:string) {}
+ })
+ .on('customEvent', function (e, msg, msgEvent) { });
+
+ $.ss.handlers["changeChannel"]("home");
+}
+
+function test_jQuery_functions(){
+ $("document").setFieldError("name","message");
+ var map = $("form").serializeMap();
+ $("form").applyErrors({errorCode:"",message:"",stackTrace:"",errors:[]});
+ $("form").clearErrors();
+ $("form").bindForm({
+ overrideMessages: true,
+ messages: {"NotFound": "Not Found"},
+ errorFilter: function(errorMsg, errorCode, type){}
+ });
+ $("form").applyValues({
+ "Key": "Value"
+ });
+ $("form").bindHandlers({
+ "test": function() {}
+ });
+}
+
+function test_ssutils_Static(){
+ $.ss.handlers["key"] = () => 0;
+ $.ss.onSubmitDisable = "class";
+ $.ss.validation.messages["Code"] = "Message";
+ $.ss.clearAdjacentError();
+ var date:Date = $.ss.todate("2001-01-01");
+ var dateFmt:String = $.ss.todfmt("2001-01-01");
+ dateFmt = $.ss.dfmt(new Date(2001,1,1));
+ dateFmt = $.ss.dfmthm(new Date(2001,1,1));
+ dateFmt = $.ss.tfmt12(new Date(2001,1,1));
+ var parts:string[] = $.ss.splitOnFirst("A,B,C");
+ parts = $.ss.splitOnLast("A,B,C");
+ var selectedText = $.ss.getSelection();
+ var qs:{ [index: string]: string } = $.ss.queryString("http://google.com?a=b&c=d");
+ var relativePath = $.ss.createUrl("/path/to/{File}", {File:"file.js"});
+ var readableText = $.ss.humanize("TheVariableName");
+
+ $.ss.listenOn = "click onmousedown";
+ $.ss.eventReceivers = { "document": document };
+ $.ss.handlers["changeChannel"]("home");
+}
\ No newline at end of file
diff --git a/ss-utils/ss-utils.d.ts b/ss-utils/ss-utils.d.ts
new file mode 100644
index 000000000..3d6ddfbf4
--- /dev/null
+++ b/ss-utils/ss-utils.d.ts
@@ -0,0 +1,122 @@
+// Type definitions for ServiceStack Utils v0.0.1
+// Project: https://servicestack.net/
+// Definitions by: Demis Bellot
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+
+///
+
+declare namespace ssutils {
+
+ interface Static {
+ handlers: { [index: string]: Function };
+ onSubmitDisable: string;
+ validation: Validation;
+ clearAdjacentError: () => void;
+ todate: (s: string) => Date;
+ todfmt: (s: string) => string;
+ dfmt: (d: Date) => string;
+ dfmthm: (d: Date) => string;
+ tfmt12: (d: Date) => string;
+ splitOnFirst: (s: string) => string[];
+ splitOnLast: (s: string) => string[];
+ getSelection: () => string;
+ queryString: (url: string) => { [index: string]: string };
+ createUrl: (route: string, args?: any) => string;
+ humanize: (s: string) => string;
+
+ listenOn: string;
+ eventReceivers: any;
+ reconnectServerEvents: (opt: ReconnectServerEventsOptions) => any;
+ }
+
+ interface Validation {
+ overrideMessages: boolean;
+ messages: { [index: string]: string };
+ errorFilter: (errorMsg: string, errorCode: string, type: string) => void;
+ }
+
+ interface ValidationOptional {
+ overrideMessages?: boolean;
+ messages?: { [index: string]: string };
+ errorFilter?: (errorMsg: string, errorCode: string, type: string) => void;
+ }
+
+ interface ApplyErrorsOptions extends ValidationOptional {
+ }
+
+ interface BindFormOptions {
+ validation?: ValidationOptional;
+ validate?: (form: HTMLFormElement) => boolean;
+ onSubmitDisable?: string;
+ complete?: (...args: any[]) => void;
+ error?: (...args: any[]) => void;
+ }
+
+ interface HandleServerEventsOptions {
+ handlers?: { [index: string]: Function };
+ validate?: (op?: string, target?: string, msg?: string, json?: string) => boolean;
+ heartbeatUrl?: string;
+ heartbeatIntervalMs?: number;
+ unRegisterUrl?: string;
+ receivers?: { [index: string]: any };
+ success?: (selector: string, msg: string, e: any) => void;
+ }
+
+ interface ResponseStatus {
+ errorCode: string;
+ message: string;
+ stackTrace: string;
+ errors: ResponseError[];
+ }
+ interface ResponseError {
+ errorCode: string;
+ fieldName: string;
+ message: string;
+ }
+
+ interface SSECommand {
+ userId: string;
+ displayName: string;
+ channels: string;
+ profileUrl: string;
+ }
+
+ interface SSEHeartbeat extends SSECommand { }
+ interface SSEJoin extends SSECommand { }
+ interface SSELeave extends SSECommand { }
+
+ interface SSEConnect extends SSECommand {
+ id: string;
+ unRegisterUrl: string;
+ heartbeatUrl: string;
+ heartbeatIntervalMs: number;
+ idleTimeoutMs: number;
+ }
+
+ interface ReconnectServerEventsOptions {
+ url?: string;
+ onerror?: (...args: any[]) => void;
+ onmessage?: (...args: any[]) => void;
+ errorArgs: any[];
+ }
+}
+
+interface JQuery {
+ setFieldError: (name: string, msg: string) => void;
+ serializeMap: () => { [index: string]: any };
+ applyErrors: (status: ssutils.ResponseStatus, opt?: ssutils.ApplyErrorsOptions) => JQuery;
+ clearErrors: () => JQuery;
+ bindForm: (opt?: ssutils.ApplyErrorsOptions) => JQuery;
+ applyValues: (values: { [index: string]: string }) => JQuery;
+ bindHandlers: (handlers: { [index: string]: Function }) => JQuery;
+ setActiveLinks: () => JQuery;
+ handleServerEvents: (opt?: ssutils.HandleServerEventsOptions) => void;
+}
+
+interface JQueryStatic {
+ ss: ssutils.Static;
+}
+
+declare module "ss-utils" {
+ export = ssutils;
+}
\ No newline at end of file