From b2b6f6f95f0124c96a9ba067c02feaa325ba6de8 Mon Sep 17 00:00:00 2001
From: Felipe Guizar Diaz <felipegaiacharly@gmail.com>
Date: Wed, 4 Sep 2019 00:20:32 -0500
Subject: [PATCH 1/7] Separate server and browser scripts, and add nova
 directive loaders

---
 package.json  |  2 +-
 server.js     |  1 +
 src/index.js  | 73 ++++++++++++++++++++-------------------------------
 src/server.js | 53 +++++++++++++++++++++++++++++++++++++
 4 files changed, 84 insertions(+), 45 deletions(-)
 create mode 100644 server.js
 create mode 100644 src/server.js

diff --git a/package.json b/package.json
index 47e9c30..0cb826c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "hypernova-vue",
-  "version": "2.1.0",
+  "version": "3.0.0-alpha.0",
   "description": "Vue bindings for Hypernova",
   "main": "lib/index.js",
   "author": "Felipe Guizar Diaz <felipegaiacharly@gmail.com>",
diff --git a/server.js b/server.js
new file mode 100644
index 0000000..429f220
--- /dev/null
+++ b/server.js
@@ -0,0 +1 @@
+module.exports = require('./lib/server.js');
diff --git a/src/index.js b/src/index.js
index 5cac0dd..0a2dc3c 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,11 +1,14 @@
 import vue from 'vue';
-import { createRenderer } from 'vue-server-renderer';
-import hypernova, { serialize, load } from 'hypernova';
+import hypernova, { load } from 'hypernova';
 import { findNode, getData } from 'nova-helpers';
 
 const { document } = global;
 
-const mountComponent = (Component, node, data) => {
+export const Vue = vue;
+
+export { load } from 'hypernova';
+
+export const mountComponent = (Component, node, data) => {
   const vm = new Component({
     propsData: data,
   });
@@ -15,32 +18,38 @@ const mountComponent = (Component, node, data) => {
   }
 
   vm.$mount(node.children[0]);
-};
 
-export const Vue = vue;
+  return vm;
+};
 
 export const renderInPlaceholder = (name, Component, id) => {
   const node = findNode(name, id);
   const data = getData(name, id);
 
   if (node && data) {
-    mountComponent(Component, node, data);
+    return mountComponent(Component, node, data);
   }
+
+  return null;
 };
 
-export const renderVue = (name, Component) => hypernova({
-  server() {
-    return async (propsData) => {
-      const vm = new Component({
-        propsData,
-      });
+export const loadById = (name, id) => {
+  const node = findNode(name, id);
+  const data = getData(name, id);
 
-      const renderer = createRenderer();
+  if (node && data) {
+    return {
+      node,
+      data,
+    };
+  }
 
-      const contents = await renderer.renderToString(vm);
+  return null;
+};
 
-      return serialize(name, contents, propsData);
-    };
+export const renderVue = (name, Component) => hypernova({
+  server() {
+    throw new Error('Use hypernova-vue/server instead');
   },
 
   client() {
@@ -49,11 +58,7 @@ export const renderVue = (name, Component) => hypernova({
       payloads.forEach((payload) => {
         const { node, data: propsData } = payload;
 
-        const vm = new Component({
-          propsData,
-        });
-
-        vm.$mount(node.children[0]);
+        mountComponent(Component, node, propsData);
       });
     }
 
@@ -64,24 +69,7 @@ export const renderVue = (name, Component) => hypernova({
 
 export const renderVuex = (name, ComponentDefinition, createStore) => hypernova({
   server() {
-    return async (propsData) => {
-      const store = createStore();
-
-      const Component = Vue.extend({
-        ...ComponentDefinition,
-        store,
-      });
-
-      const vm = new Component({
-        propsData,
-      });
-
-      const renderer = createRenderer();
-
-      const contents = await renderer.renderToString(vm);
-
-      return serialize(name, contents, { propsData, state: vm.$store.state });
-    };
+    throw new Error('Use hypernova-vue/server instead');
   },
 
   client() {
@@ -90,6 +78,7 @@ export const renderVuex = (name, ComponentDefinition, createStore) => hypernova(
       payloads.forEach((payload) => {
         const { node, data } = payload;
         const { propsData, state } = data;
+
         const store = createStore();
 
         const Component = Vue.extend({
@@ -97,13 +86,9 @@ export const renderVuex = (name, ComponentDefinition, createStore) => hypernova(
           store,
         });
 
-        const vm = new Component({
-          propsData,
-        });
+        const vm = mountComponent(Component, node, propsData);
 
         vm.$store.replaceState(state);
-
-        vm.$mount(node.children[0]);
       });
     }
 
diff --git a/src/server.js b/src/server.js
new file mode 100644
index 0000000..731ad17
--- /dev/null
+++ b/src/server.js
@@ -0,0 +1,53 @@
+import vue from 'vue';
+import { createRenderer } from 'vue-server-renderer';
+import hypernova, { serialize } from 'hypernova';
+
+export const Vue = vue;
+
+export const renderVue = (name, Component) => hypernova({
+  server() {
+    return async (propsData) => {
+      const vm = new Component({
+        propsData,
+      });
+
+      const renderer = createRenderer();
+
+      const contents = await renderer.renderToString(vm);
+
+      return serialize(name, contents, propsData);
+    };
+  },
+
+  client() {
+    throw new Error('Use hypernova-vue instead');
+  },
+});
+
+
+export const renderVuex = (name, ComponentDefinition, createStore) => hypernova({
+  server() {
+    return async (propsData) => {
+      const store = createStore();
+
+      const Component = Vue.extend({
+        ...ComponentDefinition,
+        store,
+      });
+
+      const vm = new Component({
+        propsData,
+      });
+
+      const renderer = createRenderer();
+
+      const contents = await renderer.renderToString(vm);
+
+      return serialize(name, contents, { propsData, state: vm.$store.state });
+    };
+  },
+
+  client() {
+    throw new Error('Use hypernova-vue instead');
+  },
+});

From 57d2d2ab67c4bf7d1a7021cba7ebb3c13a0a178b Mon Sep 17 00:00:00 2001
From: Felipe Guizar Diaz <felipegaiacharly@gmail.com>
Date: Sun, 8 Sep 2019 20:26:07 -0500
Subject: [PATCH 2/7] Migrate to typescript

---
 .eslintignore                |   2 +
 .eslintrc                    |   7 +--
 package.json                 |  18 +++---
 src/index.js                 |  97 ---------------------------------
 src/index.ts                 | 103 +++++++++++++++++++++++++++++++++++
 src/{server.js => server.ts} |  23 +++++---
 tsconfig.json                |  11 ++++
 7 files changed, 140 insertions(+), 121 deletions(-)
 create mode 100644 .eslintignore
 delete mode 100644 src/index.js
 create mode 100644 src/index.ts
 rename src/{server.js => server.ts} (53%)
 create mode 100644 tsconfig.json

diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..a9f4ed5
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,2 @@
+lib
+node_modules
\ No newline at end of file
diff --git a/.eslintrc b/.eslintrc
index b8e390a..50e3f0c 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,8 +1,3 @@
 {
-  "extends": [
-    "airbnb-base"
-  ],
-  "rules": {
-    "import/no-unresolved": 0
-  }
+  "extends": ["plugin:@typescript-eslint/recommended"]
 }
\ No newline at end of file
diff --git a/package.json b/package.json
index 0cb826c..dff0da1 100644
--- a/package.json
+++ b/package.json
@@ -3,11 +3,12 @@
   "version": "3.0.0-alpha.0",
   "description": "Vue bindings for Hypernova",
   "main": "lib/index.js",
+  "types": "lib/index.d.ts",
   "author": "Felipe Guizar Diaz <felipegaiacharly@gmail.com>",
   "scripts": {
     "prepublish": "npm run build",
-    "lint": "eslint src",
-    "build": "babel src -d lib"
+    "lint": "eslint src/**/*.ts",
+    "build": "tsc"
   },
   "keywords": [
     "vuew",
@@ -21,13 +22,12 @@
     "url": "git@github.com:marconi1992/hypernova-vue.git"
   },
   "devDependencies": {
-    "@babel/cli": "^7.5.5",
-    "@babel/core": "^7.5.5",
-    "@babel/runtime": "^7.5.5",
-    "babel-preset-airbnb": "^4.0.1",
-    "eslint": "^5.14.1",
-    "eslint-config-airbnb-base": "^13.1.0",
-    "eslint-plugin-import": "^2.16.0"
+    "@babel/runtime": "^7.6.0",
+    "@types/node": "^12.7.4",
+    "@typescript-eslint/eslint-plugin": "^2.1.0",
+    "@typescript-eslint/parser": "^2.1.0",
+    "eslint": "^6.3.0",
+    "typescript": "^3.6.0"
   },
   "dependencies": {
     "hypernova": "^2.5.0",
diff --git a/src/index.js b/src/index.js
deleted file mode 100644
index 0a2dc3c..0000000
--- a/src/index.js
+++ /dev/null
@@ -1,97 +0,0 @@
-import vue from 'vue';
-import hypernova, { load } from 'hypernova';
-import { findNode, getData } from 'nova-helpers';
-
-const { document } = global;
-
-export const Vue = vue;
-
-export { load } from 'hypernova';
-
-export const mountComponent = (Component, node, data) => {
-  const vm = new Component({
-    propsData: data,
-  });
-
-  if (!node.firstChild) {
-    node.appendChild(document.createElement('div'));
-  }
-
-  vm.$mount(node.children[0]);
-
-  return vm;
-};
-
-export const renderInPlaceholder = (name, Component, id) => {
-  const node = findNode(name, id);
-  const data = getData(name, id);
-
-  if (node && data) {
-    return mountComponent(Component, node, data);
-  }
-
-  return null;
-};
-
-export const loadById = (name, id) => {
-  const node = findNode(name, id);
-  const data = getData(name, id);
-
-  if (node && data) {
-    return {
-      node,
-      data,
-    };
-  }
-
-  return null;
-};
-
-export const renderVue = (name, Component) => hypernova({
-  server() {
-    throw new Error('Use hypernova-vue/server instead');
-  },
-
-  client() {
-    const payloads = load(name);
-    if (payloads) {
-      payloads.forEach((payload) => {
-        const { node, data: propsData } = payload;
-
-        mountComponent(Component, node, propsData);
-      });
-    }
-
-    return Component;
-  },
-});
-
-
-export const renderVuex = (name, ComponentDefinition, createStore) => hypernova({
-  server() {
-    throw new Error('Use hypernova-vue/server instead');
-  },
-
-  client() {
-    const payloads = load(name);
-    if (payloads) {
-      payloads.forEach((payload) => {
-        const { node, data } = payload;
-        const { propsData, state } = data;
-
-        const store = createStore();
-
-        const Component = Vue.extend({
-          ...ComponentDefinition,
-          store,
-        });
-
-        const vm = mountComponent(Component, node, propsData);
-
-        vm.$store.replaceState(state);
-      });
-    }
-
-    return ComponentDefinition;
-  },
-});
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 0000000..7d5d93a
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1,103 @@
+import Vue, { VueConstructor } from 'vue';
+import { load } from 'hypernova';
+import * as hypernova from 'hypernova';
+import { findNode, getData } from 'nova-helpers';
+import { CombinedVueInstance } from 'vue/types/vue';
+
+type HypernovaPayload = {
+  node: HTMLElement;
+  data: any;
+}
+
+type VueWithStoreInstance = CombinedVueInstance<Vue, object, object, object, object> & { $store: any };
+
+export { default as Vue }  from 'vue';
+
+export { load } from 'hypernova';
+
+export const mountComponent = (Component: VueConstructor, node: HTMLElement, data: any): CombinedVueInstance<Vue, object, object, object, object> => {
+  const vm = new Component({
+    propsData: data,
+  });
+
+  if (!node.firstChild) {
+    node.appendChild(document.createElement('div'));
+  }
+
+  vm.$mount(node.children[0]);
+
+  return vm;
+};
+
+export const renderInPlaceholder = (name: string, Component: VueConstructor, id: string): CombinedVueInstance<Vue, object, object, object, object> => {
+  const node: HTMLElement = findNode(name, id);
+  const data: any = getData(name, id);
+
+  if (node && data) {
+    return mountComponent(Component, node, data);
+  }
+
+  return null;
+};
+
+export const loadById = (name: string, id: string): HypernovaPayload => {
+  const node = findNode(name, id);
+  const data = getData(name, id);
+
+  if (node && data) {
+    return {
+      node,
+      data,
+    };
+  }
+
+  return null;
+};
+
+export const renderVue = (name: string, Component: VueConstructor): void => hypernova({
+  server() {
+    throw new Error('Use hypernova-vue/server instead');
+  },
+
+  client() {
+    const payloads = load(name);
+    if (payloads) {
+      payloads.forEach((payload: HypernovaPayload) => {
+        const { node, data: propsData } = payload;
+
+        mountComponent(Component, node, propsData);
+      });
+    }
+
+    return Component;
+  },
+});
+
+export const renderVuex = (name: string, ComponentDefinition: any, createStore: Function): void => hypernova({
+  server() {
+    throw new Error('Use hypernova-vue/server instead');
+  },
+
+  client() {
+    const payloads = load(name);
+    if (payloads) {
+      payloads.forEach((payload: HypernovaPayload) => {
+        const { node, data } = payload;
+        const { propsData, state } = data;
+
+        const store = createStore();
+
+        const Component: VueConstructor = Vue.extend({
+          ...ComponentDefinition,
+          store,
+        });
+
+        const vm = mountComponent(Component, node, propsData) as VueWithStoreInstance;
+
+        vm.$store.replaceState(state);
+      });
+    }
+
+    return ComponentDefinition;
+  },
+});
diff --git a/src/server.js b/src/server.ts
similarity index 53%
rename from src/server.js
rename to src/server.ts
index 731ad17..ce52b58 100644
--- a/src/server.js
+++ b/src/server.ts
@@ -1,12 +1,17 @@
-import vue from 'vue';
+import Vue, { VueConstructor } from 'vue';
 import { createRenderer } from 'vue-server-renderer';
-import hypernova, { serialize } from 'hypernova';
+import { serialize } from 'hypernova';
+import * as hypernova from 'hypernova';
+import { CombinedVueInstance } from 'vue/types/vue';
 
-export const Vue = vue;
 
-export const renderVue = (name, Component) => hypernova({
+type VueWithStoreInstance = CombinedVueInstance<Vue, object, object, object, object> & { $store: any };
+
+export { default as Vue } from 'vue';
+
+export const renderVue = (name: string, Component: VueConstructor): void => hypernova({
   server() {
-    return async (propsData) => {
+    return async (propsData: object): Promise<string> => {
       const vm = new Component({
         propsData,
       });
@@ -25,9 +30,9 @@ export const renderVue = (name, Component) => hypernova({
 });
 
 
-export const renderVuex = (name, ComponentDefinition, createStore) => hypernova({
+export const renderVuex = (name: string, ComponentDefinition: any, createStore: Function): void => hypernova({
   server() {
-    return async (propsData) => {
+    return async (propsData: object): Promise<string> => {
       const store = createStore();
 
       const Component = Vue.extend({
@@ -35,9 +40,9 @@ export const renderVuex = (name, ComponentDefinition, createStore) => hypernova(
         store,
       });
 
-      const vm = new Component({
+      const vm = (new Component({
         propsData,
-      });
+      })) as VueWithStoreInstance;
 
       const renderer = createRenderer();
 
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..df7e99a
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,11 @@
+{
+  "compilerOptions": {
+    "module": "commonjs",
+    "target": "esnext",
+    "declaration": true,
+    "outDir": "./lib"
+  },
+  "include": [
+    "src/**/*"
+  ]
+}
\ No newline at end of file

From b068471d9ce5241b6c05953c2ca49e30a8792d1d Mon Sep 17 00:00:00 2001
From: Felipe Guizar Diaz <felipegaiacharly@gmail.com>
Date: Sun, 8 Sep 2019 21:34:07 -0500
Subject: [PATCH 3/7] Add unit tests for client side helpers using jest

---
 .eslintrc                  |  13 +++-
 jest.config.js             |   8 +++
 package.json               |   9 ++-
 src/__test__/index.spec.ts | 120 +++++++++++++++++++++++++++++++++++++
 src/index.ts               |  28 ++++++---
 src/server.ts              |  12 ++--
 tsconfig.json              |   6 +-
 7 files changed, 180 insertions(+), 16 deletions(-)
 create mode 100644 jest.config.js
 create mode 100644 src/__test__/index.spec.ts

diff --git a/.eslintrc b/.eslintrc
index 50e3f0c..be789b4 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,3 +1,14 @@
 {
-  "extends": ["plugin:@typescript-eslint/recommended"]
+  "env": {
+    "browser": true,
+    "node": true,
+    "jest": true
+  },
+  "extends": [
+    "plugin:@typescript-eslint/recommended",
+    "airbnb-base"
+  ],
+  "rules": {
+    "import/no-unresolved": 0
+  }
 }
\ No newline at end of file
diff --git a/jest.config.js b/jest.config.js
new file mode 100644
index 0000000..4317c53
--- /dev/null
+++ b/jest.config.js
@@ -0,0 +1,8 @@
+module.exports = {
+  roots: ['<rootDir>/src'],
+  transform: {
+    '^.+\\.tsx?$': 'ts-jest',
+  },
+  testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
+  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index dff0da1..1b0a1f9 100644
--- a/package.json
+++ b/package.json
@@ -6,9 +6,9 @@
   "types": "lib/index.d.ts",
   "author": "Felipe Guizar Diaz <felipegaiacharly@gmail.com>",
   "scripts": {
-    "prepublish": "npm run build",
     "lint": "eslint src/**/*.ts",
-    "build": "tsc"
+    "build": "tsc",
+    "test": "jest"
   },
   "keywords": [
     "vuew",
@@ -23,10 +23,15 @@
   },
   "devDependencies": {
     "@babel/runtime": "^7.6.0",
+    "@types/jest": "^24.0.18",
     "@types/node": "^12.7.4",
     "@typescript-eslint/eslint-plugin": "^2.1.0",
     "@typescript-eslint/parser": "^2.1.0",
     "eslint": "^6.3.0",
+    "eslint-config-airbnb-base": "^14.0.0",
+    "eslint-plugin-import": "^2.18.2",
+    "jest": "^24.9.0",
+    "ts-jest": "^24.0.2",
     "typescript": "^3.6.0"
   },
   "dependencies": {
diff --git a/src/__test__/index.spec.ts b/src/__test__/index.spec.ts
new file mode 100644
index 0000000..e6b52d3
--- /dev/null
+++ b/src/__test__/index.spec.ts
@@ -0,0 +1,120 @@
+import Vue, { VNode } from 'vue';
+import {
+  loadById,
+  mountComponent,
+  renderInPlaceholder,
+  renderVue,
+} from '..';
+
+describe('loadById', () => {
+  beforeEach(() => {
+    document.body.innerHTML = '';
+  });
+
+  test('should load payload by id', () => {
+    document.body.innerHTML = `
+      <div data-hypernova-key="Example" data-hypernova-id="d0a0b082-dad0-4bf2-ae4f-08eff16575b4"></div>
+      <script type="application/json" data-hypernova-key="Example" data-hypernova-id="d0a0b082-dad0-4bf2-ae4f-08eff16575b4"><!--{"title":"Ara Framework"}--></script>
+    `;
+
+    const payload = loadById('Example', 'd0a0b082-dad0-4bf2-ae4f-08eff16575b4');
+
+    const { node, data } = payload;
+
+    expect(node.getAttribute('data-hypernova-key')).toEqual('Example');
+    expect(node.getAttribute('data-hypernova-id')).toEqual('d0a0b082-dad0-4bf2-ae4f-08eff16575b4');
+    expect(data).toEqual({
+      title: 'Ara Framework',
+    });
+  });
+
+  test('should not load payload by id', () => {
+    const payload = loadById('Example', 'd0a0b082-dad0-4bf2-ae4f-08eff16575b4');
+
+    expect(payload).toBeNull();
+  });
+});
+
+describe('mountComponent', () => {
+  beforeEach(() => {
+    document.body.innerHTML = '';
+  });
+
+  test('should mount component correctly', () => {
+    document.body.innerHTML = '<div id="app"><div>';
+
+    const app = Vue.extend({
+      props: ['title'],
+      render(h): VNode {
+        return h('h1', {}, this.title);
+      },
+    });
+
+    const node = document.getElementById('app');
+
+    mountComponent(app, node, { title: 'Ara Framework' });
+
+    expect(node.innerHTML).toEqual('<h1>Ara Framework</h1>');
+  });
+});
+
+describe('renderInPlaceholder', () => {
+  beforeEach(() => {
+    document.body.innerHTML = '';
+  });
+
+  test('should render component in placeholder correctly', () => {
+    document.body.innerHTML = `
+      <div data-hypernova-key="Example" data-hypernova-id="d0a0b082-dad0-4bf2-ae4f-08eff16575b4"></div>
+      <script type="application/json" data-hypernova-key="Example" data-hypernova-id="d0a0b082-dad0-4bf2-ae4f-08eff16575b4"><!--{"title":"Ara Framework"}--></script>
+    `;
+
+    const app = Vue.extend({
+      props: ['title'],
+      render(h): VNode {
+        return h('h1', {}, this.title);
+      },
+    });
+
+    renderInPlaceholder('Example', app, 'd0a0b082-dad0-4bf2-ae4f-08eff16575b4');
+
+    const expectedHTML = `
+      <div data-hypernova-key="Example" data-hypernova-id="d0a0b082-dad0-4bf2-ae4f-08eff16575b4"><h1>Ara Framework</h1></div>
+      <script type="application/json" data-hypernova-key="Example" data-hypernova-id="d0a0b082-dad0-4bf2-ae4f-08eff16575b4"><!--{"title":"Ara Framework"}--></script>
+    `;
+    expect(document.body.innerHTML).toEqual(expectedHTML);
+  });
+});
+
+describe('renderVue', () => {
+  beforeEach(() => {
+    document.body.innerHTML = '';
+  });
+
+  test('should render all the components in the body', () => {
+    document.body.innerHTML = `
+      <div data-hypernova-key="Example" data-hypernova-id="d0a0b082-dad0-4bf2-ae4f-08eff16575b4"></div>
+      <script type="application/json" data-hypernova-key="Example" data-hypernova-id="d0a0b082-dad0-4bf2-ae4f-08eff16575b4"><!--{"title":"Ara Framework"}--></script>
+      <div data-hypernova-key="Example" data-hypernova-id="d0a0b082-dad0-4bf2-ae4f-08eff16575b5"></div>
+      <script type="application/json" data-hypernova-key="Example" data-hypernova-id="d0a0b082-dad0-4bf2-ae4f-08eff16575b5"><!--{"title":"Ara Framework 2"}--></script>
+    `;
+
+    const app = Vue.extend({
+      props: ['title'],
+      render(h): VNode {
+        return h('h1', {}, this.title);
+      },
+    });
+
+    renderVue('Example', app);
+
+    const expectedHTML = `
+      <div data-hypernova-key="Example" data-hypernova-id="d0a0b082-dad0-4bf2-ae4f-08eff16575b4"><h1>Ara Framework</h1></div>
+      <script type="application/json" data-hypernova-key="Example" data-hypernova-id="d0a0b082-dad0-4bf2-ae4f-08eff16575b4"><!--{"title":"Ara Framework"}--></script>
+      <div data-hypernova-key="Example" data-hypernova-id="d0a0b082-dad0-4bf2-ae4f-08eff16575b5"><h1>Ara Framework 2</h1></div>
+      <script type="application/json" data-hypernova-key="Example" data-hypernova-id="d0a0b082-dad0-4bf2-ae4f-08eff16575b5"><!--{"title":"Ara Framework 2"}--></script>
+    `;
+
+    expect(document.body.innerHTML).toEqual(expectedHTML);
+  });
+});
diff --git a/src/index.ts b/src/index.ts
index 7d5d93a..d4950bd 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,6 +1,5 @@
 import Vue, { VueConstructor } from 'vue';
-import { load } from 'hypernova';
-import * as hypernova from 'hypernova';
+import hypernova, { load } from 'hypernova';
 import { findNode, getData } from 'nova-helpers';
 import { CombinedVueInstance } from 'vue/types/vue';
 
@@ -9,13 +8,20 @@ type HypernovaPayload = {
   data: any;
 }
 
-type VueWithStoreInstance = CombinedVueInstance<Vue, object, object, object, object> & { $store: any };
+type VueInstance = CombinedVueInstance<Vue, object, object, object, object>
 
-export { default as Vue }  from 'vue';
+type VueWithStoreInstance =
+  CombinedVueInstance<Vue, object, object, object, object> & { $store: any };
+
+export { default as Vue } from 'vue';
 
 export { load } from 'hypernova';
 
-export const mountComponent = (Component: VueConstructor, node: HTMLElement, data: any): CombinedVueInstance<Vue, object, object, object, object> => {
+export const mountComponent = (
+  Component: VueConstructor,
+  node: HTMLElement,
+  data: any,
+): VueInstance => {
   const vm = new Component({
     propsData: data,
   });
@@ -29,7 +35,11 @@ export const mountComponent = (Component: VueConstructor, node: HTMLElement, dat
   return vm;
 };
 
-export const renderInPlaceholder = (name: string, Component: VueConstructor, id: string): CombinedVueInstance<Vue, object, object, object, object> => {
+export const renderInPlaceholder = (
+  name: string,
+  Component: VueConstructor,
+  id: string,
+): VueInstance => {
   const node: HTMLElement = findNode(name, id);
   const data: any = getData(name, id);
 
@@ -73,7 +83,11 @@ export const renderVue = (name: string, Component: VueConstructor): void => hype
   },
 });
 
-export const renderVuex = (name: string, ComponentDefinition: any, createStore: Function): void => hypernova({
+export const renderVuex = (
+  name: string,
+  ComponentDefinition: any,
+  createStore: Function,
+): void => hypernova({
   server() {
     throw new Error('Use hypernova-vue/server instead');
   },
diff --git a/src/server.ts b/src/server.ts
index ce52b58..2e93ce0 100644
--- a/src/server.ts
+++ b/src/server.ts
@@ -1,11 +1,11 @@
 import Vue, { VueConstructor } from 'vue';
 import { createRenderer } from 'vue-server-renderer';
-import { serialize } from 'hypernova';
-import * as hypernova from 'hypernova';
+import hypernova, { serialize } from 'hypernova';
 import { CombinedVueInstance } from 'vue/types/vue';
 
 
-type VueWithStoreInstance = CombinedVueInstance<Vue, object, object, object, object> & { $store: any };
+type VueWithStoreInstance =
+  CombinedVueInstance<Vue, object, object, object, object> & { $store: any };
 
 export { default as Vue } from 'vue';
 
@@ -30,7 +30,11 @@ export const renderVue = (name: string, Component: VueConstructor): void => hype
 });
 
 
-export const renderVuex = (name: string, ComponentDefinition: any, createStore: Function): void => hypernova({
+export const renderVuex = (
+  name: string,
+  ComponentDefinition: any,
+  createStore: Function,
+): void => hypernova({
   server() {
     return async (propsData: object): Promise<string> => {
       const store = createStore();
diff --git a/tsconfig.json b/tsconfig.json
index df7e99a..43cddb9 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -3,9 +3,11 @@
     "module": "commonjs",
     "target": "esnext",
     "declaration": true,
-    "outDir": "./lib"
+    "outDir": "./lib",
+    "esModuleInterop": true
   },
   "include": [
     "src/**/*"
-  ]
+  ],
+  "exclude": ["node_modules", "**/*.spec.ts"]
 }
\ No newline at end of file

From b171e655a0c12d377a3ca68f9034628fc7a3f449 Mon Sep 17 00:00:00 2001
From: Felipe Guizar Diaz <felipegaiacharly@gmail.com>
Date: Sun, 8 Sep 2019 21:40:05 -0500
Subject: [PATCH 4/7] Add circle ci configuration

---
 .circleci/config.yml | 35 +++++++++++++++++++++++++++++++++++
 jest.config.js       |  2 +-
 2 files changed, 36 insertions(+), 1 deletion(-)
 create mode 100644 .circleci/config.yml

diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000..8e31b71
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,35 @@
+# Javascript Node CircleCI 2.0 configuration file
+#
+# Check https://circleci.com/docs/2.0/language-javascript/ for more details
+#
+version: 2
+jobs:
+  build:
+    docker:
+      # specify the version you desire here
+      - image: circleci/node:10.16
+
+    working_directory: ~/hypernova-vue
+
+    steps:
+      - checkout
+
+      # Download and cache dependencies
+      - restore_cache:
+          keys:
+            - v1-dependencies-{{ checksum "package.json" }}
+            # fallback to using the latest cache if no exact match is found
+            - v1-dependencies-
+
+      - run: yarn install
+
+      - save_cache:
+          paths:
+            - node_modules
+          key: v1-dependencies-{{ checksum "package.json" }}
+
+      # run linter
+      - run: yarn lint
+
+      # run tests
+      - run: yarn test
\ No newline at end of file
diff --git a/jest.config.js b/jest.config.js
index 4317c53..6d7b8ae 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -5,4 +5,4 @@ module.exports = {
   },
   testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
   moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
-}
\ No newline at end of file
+};

From 39a76a3d3cdedc3aef1d3907f5bc3dfd7033cf70 Mon Sep 17 00:00:00 2001
From: Felipe Guizar Diaz <felipegaiacharly@gmail.com>
Date: Sun, 8 Sep 2019 21:44:31 -0500
Subject: [PATCH 5/7] Add circle ci workflow

---
 .circleci/config.yml | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/.circleci/config.yml b/.circleci/config.yml
index 8e31b71..c945a6e 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -32,4 +32,10 @@ jobs:
       - run: yarn lint
 
       # run tests
-      - run: yarn test
\ No newline at end of file
+      - run: yarn test
+
+workflows:
+  version: 2
+  main:
+    jobs:
+    - build
\ No newline at end of file

From 9cde6f3053342f04c2f246b13b1308fd891ba539 Mon Sep 17 00:00:00 2001
From: Felipe Guizar Diaz <felipegaiacharly@gmail.com>
Date: Sun, 8 Sep 2019 22:08:49 -0500
Subject: [PATCH 6/7] feat(pencil): Add semantic release

---
 package.json | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index 1b0a1f9..4fa9dea 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,8 @@
   "scripts": {
     "lint": "eslint src/**/*.ts",
     "build": "tsc",
-    "test": "jest"
+    "test": "jest",
+    "semantic-release": "semantic-release"
   },
   "keywords": [
     "vuew",
@@ -19,7 +20,7 @@
   "license": "MIT",
   "repository": {
     "type": "git",
-    "url": "git@github.com:marconi1992/hypernova-vue.git"
+    "url": "https://github.com/ara-framework/hypernova-vue.git"
   },
   "devDependencies": {
     "@babel/runtime": "^7.6.0",
@@ -32,7 +33,8 @@
     "eslint-plugin-import": "^2.18.2",
     "jest": "^24.9.0",
     "ts-jest": "^24.0.2",
-    "typescript": "^3.6.0"
+    "typescript": "^3.6.0",
+    "semantic-release": "^15.13.24"
   },
   "dependencies": {
     "hypernova": "^2.5.0",

From 868b4568085d90c6042f30fd7c2825c76de41e4c Mon Sep 17 00:00:00 2001
From: Felipe Guizar Diaz <felipegaiacharly@gmail.com>
Date: Sun, 8 Sep 2019 22:18:21 -0500
Subject: [PATCH 7/7] feat(pencil): Add publish job in circle ci

---
 .circleci/config.yml | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/.circleci/config.yml b/.circleci/config.yml
index c945a6e..e258e18 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -33,9 +33,42 @@ jobs:
 
       # run tests
       - run: yarn test
+  
+  publish:
+    docker:
+      # specify the version you desire here
+      - image: circleci/node:10.16
+    
+    working_directory: ~/hypernova-vue
+
+    steps:
+      - checkout
+
+      # Download and cache dependencies
+      - restore_cache:
+          keys:
+            - v1-dependencies-{{ checksum "package.json" }}
+            # fallback to using the latest cache if no exact match is found
+            - v1-dependencies-
+
+      - run: yarn install
+
+      - save_cache:
+          paths:
+            - node_modules
+          key: v1-dependencies-{{ checksum "package.json" }}
+
+      # run linter
+      - run: yarn semantic-release -d
 
 workflows:
   version: 2
   main:
     jobs:
-    - build
\ No newline at end of file
+    - build
+    - publish:
+        requires:
+            - build
+        filters:
+          branches:
+            only: master
\ No newline at end of file