Merge "Simplify aos::Init"
diff --git a/aos/network/www/BUILD b/aos/network/www/BUILD
index ac376db..7ec26cc 100644
--- a/aos/network/www/BUILD
+++ b/aos/network/www/BUILD
@@ -22,6 +22,7 @@
         "//aos:configuration_ts_fbs",
         "//aos/network:connect_ts_fbs",
         "//aos/network:web_proxy_ts_fbs",
+        "@com_github_google_flatbuffers//ts:flatbuffers_ts",
     ],
 )
 
@@ -65,7 +66,10 @@
     ],
     deps = [
         ":reflection_ts",
+        "//aos:configuration_ts_fbs",
+        "//aos:json_to_flatbuffer_flatbuffer_ts",
         "//aos/network/www:proxy",
+        "@com_github_google_flatbuffers//ts:flatbuffers_ts",
     ],
 )
 
@@ -73,11 +77,11 @@
     name = "reflection_ts",
     srcs = ["reflection.ts"],
     visibility = ["//visibility:public"],
-    deps =
-        [
-            "//aos:configuration_ts_fbs",
-            "//aos:json_to_flatbuffer_flatbuffer_ts",
-        ],
+    deps = [
+        "//aos:configuration_ts_fbs",
+        "//aos:json_to_flatbuffer_flatbuffer_ts",
+        "@com_github_google_flatbuffers//ts:flatbuffers_ts",
+    ],
 )
 
 ts_library(
diff --git a/aos/network/www/config_handler.ts b/aos/network/www/config_handler.ts
index 8670c0a..a65d2fa 100644
--- a/aos/network/www/config_handler.ts
+++ b/aos/network/www/config_handler.ts
@@ -1,7 +1,13 @@
-import {aos.Configuration as Configuration, aos.Channel as Channel} from 'aos/configuration_generated';
-import {Connect} from 'aos/network/connect_generated';
+import * as configuration from 'org_frc971/aos/configuration_generated';
+import * as connect from 'org_frc971/aos/network/connect_generated';
+import * as flatbuffers_builder from 'org_frc971/external/com_github_google_flatbuffers/ts/builder';
+
 import {Connection} from './proxy';
 
+import Configuration = configuration.aos.Configuration;
+import Channel = configuration.aos.Channel;
+import Connect = connect.aos.message_bridge.Connect;
+
 export class ConfigHandler {
   private readonly root_div = document.createElement('div');
   private readonly tree_div;
@@ -54,7 +60,8 @@
 
   handleChange() {
     const toggles = this.root_div.getElementsByTagName('input');
-    const builder = new flatbuffers.Builder(512);
+    const builder =
+        new flatbuffers_builder.Builder(512) as unknown as flatbuffers.Builder;
 
     const channels: flatbuffers.Offset[] = [];
     for (const toggle of toggles) {
diff --git a/aos/network/www/graph.html b/aos/network/www/graph.html
index f43f331..0f66bb0 100644
--- a/aos/network/www/graph.html
+++ b/aos/network/www/graph.html
@@ -1,6 +1,5 @@
 <html>
   <head>
-    <script src="flatbuffers.js"></script>
     <script src="graph_main_bundle.min.js" defer></script>
     <link rel="stylesheet" href="styles.css">
   </head>
diff --git a/aos/network/www/graph_main.ts b/aos/network/www/graph_main.ts
index 74fc54b..b2286d1 100644
--- a/aos/network/www/graph_main.ts
+++ b/aos/network/www/graph_main.ts
@@ -8,18 +8,27 @@
 // timer in the the /aos timing report message (this message was chosen because
 // it is already being published by the web proxy process, so the demo requires
 // very little setup).
-import {Line, Plot} from 'aos/network/www/plotter';
-import {aos} from 'aos/configuration_generated';
-import {aos} from 'aos/network/connect_generated';
-import {aos} from 'aos/network/www/proxy';
-import {aos} from 'aos/network/www/reflection'
+import * as configuration from 'org_frc971/aos/configuration_generated';
+import * as connect from 'org_frc971/aos/network/connect_generated';
+import {Line, Plot} from 'org_frc971/aos/network/www/plotter';
+import * as proxy from 'org_frc971/aos/network/www/proxy';
+import * as reflection from 'org_frc971/aos/network/www/reflection'
+import * as flatbuffers_builder from 'org_frc971/external/com_github_google_flatbuffers/ts/builder';
+import {ByteBuffer} from 'org_frc971/external/com_github_google_flatbuffers/ts/byte-buffer';
+
+import Channel = configuration.aos.Channel;
+import Connection = proxy.Connection;
+import Configuration = configuration.aos.Configuration;
+import Parser = reflection.Parser;
+import Table = reflection.Table;
+import Connect = connect.aos.message_bridge.Connect;
 
 const width = 900;
 const height = 400;
 
 const helpDiv = document.createElement('div');
-helpDiv.style.top = 0;
-helpDiv.style.left = 0;
+helpDiv.style.top = '0';
+helpDiv.style.left = '0';
 helpDiv.style.position = 'absolute';
 document.body.appendChild(helpDiv);
 helpDiv.innerHTML =
@@ -28,20 +37,20 @@
     'X-axes of the top two plots are linked together.';
 
 const div = document.createElement('div');
-div.style.top = 40;
-div.style.left = 0;
+div.style.top = '40';
+div.style.left = '0';
 div.style.position = 'absolute';
 document.body.appendChild(div);
 
 const div2 = document.createElement('div');
-div2.style.top = parseFloat(div.style.top) + height;
-div2.style.left = 0;
+div2.style.top = (parseFloat(div.style.top) + height).toString();
+div2.style.left = '0';
 div2.style.position = 'absolute';
 document.body.appendChild(div2);
 
 const benchmarkDiv = document.createElement('div');
-benchmarkDiv.style.top = parseFloat(div2.style.top) + height;
-benchmarkDiv.style.left = 0;
+benchmarkDiv.style.top = (parseFloat(div2.style.top) + height).toString();
+benchmarkDiv.style.left = '0';
 benchmarkDiv.style.position = 'absolute';
 document.body.appendChild(benchmarkDiv);
 
@@ -110,7 +119,7 @@
 
 let reportParser = null;
 
-conn.addConfigHandler((config: aos.Configuration) => {
+conn.addConfigHandler((config: Configuration) => {
   // Locate the timing report schema so that we can read the received messages.
   let reportSchema = null;
   for (let ii = 0; ii < config.channelsLength(); ++ii) {
@@ -124,33 +133,34 @@
   reportParser = new Parser(reportSchema);
 
   // Subscribe to the timing report message.
-  const builder = new flatbuffers.Builder(512);
+  const builder =
+      new flatbuffers_builder.Builder(512) as unknown as flatbuffers.Builder;
   const channels: flatbuffers.Offset[] = [];
   for (const channel of [timingReport]) {
     const nameFb = builder.createString(channel.name);
     const typeFb = builder.createString(channel.type);
-    aos.Channel.startChannel(builder);
-    aos.Channel.addName(builder, nameFb);
-    aos.Channel.addType(builder, typeFb);
-    const channelFb = aos.Channel.endChannel(builder);
+    Channel.startChannel(builder);
+    Channel.addName(builder, nameFb);
+    Channel.addType(builder, typeFb);
+    const channelFb = Channel.endChannel(builder);
     channels.push(channelFb);
   }
 
-  const channelsFb = aos.message_bridge.Connect.createChannelsToTransferVector(builder, channels);
-  aos.message_bridge.Connect.startConnect(builder);
-  aos.message_bridge.Connect.addChannelsToTransfer(builder, channelsFb);
-  const connect = aos.message_bridge.Connect.endConnect(builder);
+  const channelsFb = Connect.createChannelsToTransferVector(builder, channels);
+  Connect.startConnect(builder);
+  Connect.addChannelsToTransfer(builder, channelsFb);
+  const connect = Connect.endConnect(builder);
   builder.finish(connect);
   conn.sendConnectMessage(builder);
 });
 
-const startTime = null;
+let startTime = null;
 conn.addHandler(timingReport.type, (data: Uint8Array, time: number) => {
   if (startTime === null) {
     startTime = time;
   }
   time = time - startTime;
-  const table = Table.getRootTable(new flatbuffers.ByteBuffer(data));
+  const table = Table.getRootTable(new ByteBuffer(data));
 
   const timer = reportParser.readVectorOfTables(table, "timers")[0];
   handlerLines.addPoints(
@@ -176,8 +186,8 @@
 for (let ii = 0; ii < NUM_POINTS; ++ii) {
   points1.push(ii);
   points2.push(ii);
-  points1.push(Math.sin(ii * 10 / NUM_POINTS);
-  points2.push(Math.cos(ii * 10 / NUM_POINTS);
+  points1.push(Math.sin(ii * 10 / NUM_POINTS));
+  points2.push(Math.cos(ii * 10 / NUM_POINTS));
 }
 line1.setPoints(new Float32Array(points1));
 line2.setPoints(new Float32Array(points2));
diff --git a/aos/network/www/index.html b/aos/network/www/index.html
index 97e16d4..b67c63d 100644
--- a/aos/network/www/index.html
+++ b/aos/network/www/index.html
@@ -1,6 +1,5 @@
 <html>
   <head>
-    <script src="flatbuffers.js"></script>
     <script src="main_bundle.min.js" defer></script>
     <link rel="stylesheet" href="styles.css">
   </head>
diff --git a/aos/network/www/ping_handler.ts b/aos/network/www/ping_handler.ts
index a7fb0d4..8d4b3c6 100644
--- a/aos/network/www/ping_handler.ts
+++ b/aos/network/www/ping_handler.ts
@@ -1,4 +1,4 @@
-import {aos} from 'aos/events/ping_generated';
+import {aos} from 'org_frc971/aos/events/ping_generated';
 
 export function HandlePing(data: Uint8Array) {
   const fbBuffer = new flatbuffers.ByteBuffer(data);
diff --git a/aos/network/www/plotter.ts b/aos/network/www/plotter.ts
index 774f3aa..4a51c34 100644
--- a/aos/network/www/plotter.ts
+++ b/aos/network/www/plotter.ts
@@ -39,9 +39,9 @@
   private _maxValues: number[] = [0.0, 0.0];
   private _color: number[] = [1.0, 0.0, 0.0];
   private pointAttribLocation: number;
-  private colorLocation: WebGLUniformLocation;
-  private pointSizeLocation: WebGLUniformLocation;
-  private _label: string;
+  private colorLocation: WebGLUniformLocation | null;
+  private pointSizeLocation: WebGLUniformLocation | null;
+  private _label: string = "";
   constructor(
       private readonly ctx: WebGLRenderingContext,
       private readonly program: WebGLProgram,
diff --git a/aos/network/www/proxy.ts b/aos/network/www/proxy.ts
index ee3ad69..4952a11 100644
--- a/aos/network/www/proxy.ts
+++ b/aos/network/www/proxy.ts
@@ -1,6 +1,16 @@
 import {ConfigHandler} from './config_handler';
-import {aos} from 'aos/configuration_generated';
-import * as WebProxy from 'aos/network/web_proxy_generated';
+import * as configuration from 'org_frc971/aos/configuration_generated';
+import * as web_proxy from 'org_frc971/aos/network/web_proxy_generated';
+import {Builder} from 'org_frc971/external/com_github_google_flatbuffers/ts/builder';
+import {ByteBuffer} from 'org_frc971/external/com_github_google_flatbuffers/ts/byte-buffer';
+
+import Configuration = configuration.aos.Configuration;
+import MessageHeader = web_proxy.aos.web_proxy.MessageHeader;
+import WebSocketIce = web_proxy.aos.web_proxy.WebSocketIce;
+import WebSocketMessage = web_proxy.aos.web_proxy.WebSocketMessage;
+import Payload = web_proxy.aos.web_proxy.Payload;
+import WebSocketSdp = web_proxy.aos.web_proxy.WebSocketSdp;
+import SdpType = web_proxy.aos.web_proxy.SdpType;
 
 // There is one handler for each DataChannel, it maintains the state of
 // multi-part messages and delegates to a callback when the message is fully
@@ -16,9 +26,9 @@
   }
 
   handleMessage(e: MessageEvent): void {
-    const fbBuffer = new flatbuffers.ByteBuffer(new Uint8Array(e.data));
-    const messageHeader =
-        WebProxy.MessageHeader.getRootAsMessageHeader(fbBuffer);
+    const fbBuffer = new ByteBuffer(new Uint8Array(e.data));
+    const messageHeader = MessageHeader.getRootAsMessageHeader(
+        fbBuffer as unknown as flatbuffers.ByteBuffer);
     const time = messageHeader.monotonicSentTime().toFloat64() * 1e-9;
     // Short circuit if only one packet
     if (messageHeader.packetCount() === 1) {
@@ -52,9 +62,9 @@
   private dataChannel: RTCDataChannel|null = null;
   private webSocketUrl: string;
 
-  private configInternal: aos.Configuration|null = null;
+  private configInternal: Configuration|null = null;
   // A set of functions that accept the config to handle.
-  private readonly configHandlers = new Set<(config: aos.Configuration) => void>();
+  private readonly configHandlers = new Set<(config: Configuration) => void>();
 
   private readonly handlerFuncs =
       new Map<string, (data: Uint8Array, sentTime: number) => void>();
@@ -65,7 +75,7 @@
     this.webSocketUrl = `ws://${server}/ws`;
   }
 
-  addConfigHandler(handler: (config: aos.Configuration) => void): void {
+  addConfigHandler(handler: (config: Configuration) => void): void {
     this.configHandlers.add(handler);
   }
 
@@ -74,7 +84,7 @@
    * different channel names with the same type differently, this is good
    * enough.
    */
-  addHandler(id: string, handler: (data: Uint8Array) => void): void {
+  addHandler(id: string, handler: (data: Uint8Array, sentTime: number) => void): void {
     this.handlerFuncs.set(id, handler);
   }
 
@@ -94,8 +104,9 @@
   // Handle messages on the DataChannel. Handles the Configuration message as
   // all other messages are sent on specific DataChannels.
   onConfigMessage(data: Uint8Array): void {
-    const fbBuffer = new flatbuffers.ByteBuffer(data);
-    this.configInternal = aos.Configuration.getRootAsConfiguration(fbBuffer);
+    const fbBuffer = new ByteBuffer(data);
+    this.configInternal = Configuration.getRootAsConfiguration(
+        fbBuffer as unknown as flatbuffers.ByteBuffer);
     for (const handler of Array.from(this.configHandlers)) {
       handler(this.configInternal);
     }
@@ -114,14 +125,15 @@
       return;
     }
     const candidate = e.candidate;
-    const builder = new flatbuffers.Builder(512);
+    const builder = new Builder(512);
     const candidateString = builder.createString(candidate.candidate);
     const sdpMidString = builder.createString(candidate.sdpMid);
 
-    const iceFb = WebProxy.WebSocketIce.createWebSocketIce(
-        builder, candidateString, sdpMidString, candidate.sdpMLineIndex);
-    const messageFb = WebProxy.WebSocketMessage.createWebSocketMessage(
-        builder, WebProxy.Payload.WebSocketIce, iceFb);
+    const iceFb = WebSocketIce.createWebSocketIce(
+        builder as unknown as flatbuffers.Builder, candidateString,
+        sdpMidString, candidate.sdpMLineIndex);
+    const messageFb = WebSocketMessage.createWebSocketMessage(
+        builder as unknown as flatbuffers.Builder, Payload.WebSocketIce, iceFb);
     builder.finish(messageFb);
     const array = builder.asUint8Array();
     this.webSocketConnection.send(array.buffer.slice(array.byteOffset));
@@ -130,13 +142,14 @@
   // Called for new SDPs. Make sure to set it locally and remotely.
   onOfferCreated(description: RTCSessionDescriptionInit): void {
     this.rtcPeerConnection.setLocalDescription(description);
-    const builder = new flatbuffers.Builder(512);
+    const builder = new Builder(512);
     const offerString = builder.createString(description.sdp);
 
-    const webSocketSdp = WebProxy.WebSocketSdp.createWebSocketSdp(
-        builder, WebProxy.SdpType.OFFER, offerString);
-    const message = WebProxy.WebSocketMessage.createWebSocketMessage(
-        builder, WebProxy.Payload.WebSocketSdp, webSocketSdp);
+    const webSocketSdp = WebSocketSdp.createWebSocketSdp(
+        builder as unknown as flatbuffers.Builder, SdpType.OFFER, offerString);
+    const message = WebSocketMessage.createWebSocketMessage(
+        builder as unknown as flatbuffers.Builder, Payload.WebSocketSdp,
+        webSocketSdp);
     builder.finish(message);
     const array = builder.asUint8Array();
     this.webSocketConnection.send(array.buffer.slice(array.byteOffset));
@@ -164,21 +177,21 @@
   // adding the remote ice candidate.
   onWebSocketMessage(e: MessageEvent): void {
     const buffer = new Uint8Array(e.data)
-    const fbBuffer = new flatbuffers.ByteBuffer(buffer);
-    const message =
-        WebProxy.WebSocketMessage.getRootAsWebSocketMessage(fbBuffer);
+    const fbBuffer = new ByteBuffer(buffer);
+    const message = WebSocketMessage.getRootAsWebSocketMessage(
+        fbBuffer as unknown as flatbuffers.ByteBuffer);
     switch (message.payloadType()) {
-      case WebProxy.Payload.WebSocketSdp:
-        const sdpFb = message.payload(new WebProxy.WebSocketSdp());
-        if (sdpFb.type() !== WebProxy.SdpType.ANSWER) {
+      case Payload.WebSocketSdp:
+        const sdpFb = message.payload(new WebSocketSdp());
+        if (sdpFb.type() !== SdpType.ANSWER) {
           console.log('got something other than an answer back');
           break;
         }
         this.rtcPeerConnection.setRemoteDescription(new RTCSessionDescription(
             {'type': 'answer', 'sdp': sdpFb.payload()}));
         break;
-      case WebProxy.Payload.WebSocketIce:
-        const iceFb = message.payload(new WebProxy.WebSocketIce());
+      case Payload.WebSocketIce:
+        const iceFb = message.payload(new WebSocketIce());
         const candidate = {} as RTCIceCandidateInit;
         candidate.candidate = iceFb.candidate();
         candidate.sdpMid = iceFb.sdpMid();
diff --git a/aos/network/www/reflection.ts b/aos/network/www/reflection.ts
index a2fe3e4..9c21a17 100644
--- a/aos/network/www/reflection.ts
+++ b/aos/network/www/reflection.ts
@@ -6,7 +6,8 @@
 // constructed flatbuffers.
 // See reflection_test_main.ts for sample usage.
 
-import {reflection, aos} from 'aos/configuration_generated';
+import {reflection, aos} from 'org_frc971/aos/configuration_generated';
+import {ByteBuffer} from 'org_frc971/external/com_github_google_flatbuffers/ts/byte-buffer';
 
 // Returns the size, in bytes, of the given type. For vectors/strings/etc.
 // returns the size of the offset.
@@ -100,10 +101,6 @@
   return isInteger(baseType) && (typeSize(baseType) > 4);
 }
 
-// TODO(james): Use the actual flatbuffers.ByteBuffer object; this is just
-// to prevent the typescript compiler from complaining.
-class ByteBuffer {}
-
 // Stores the data associated with a Table within a given buffer.
 export class Table {
   // Wrapper to represent an object (Table or Struct) within a ByteBuffer.
@@ -217,7 +214,7 @@
   }
 
   // Returns the Object definition associated with the given type index.
-  getType(typeIndex: number): Object {
+  getType(typeIndex: number): reflection.Object {
     if (typeIndex === -1) {
       return this.schema.rootTable();
     }
@@ -230,7 +227,7 @@
   // Retrieves the Field schema for the given field name within a given
   // type index.
   getField(fieldName: string, typeIndex: number): reflection.Field {
-    const schema: Object = this.getType(typeIndex);
+    const schema: reflection.Object = this.getType(typeIndex);
     const numFields = schema.fieldsLength();
     for (let ii = 0; ii < numFields; ++ii) {
       const field = schema.fields(ii);
@@ -300,7 +297,7 @@
     if (offsetToOffset === table.offset) {
       return null;
     }
-    return table.bb.__string(offsetToOffset);
+    return table.bb.__string(offsetToOffset) as string;
   }
   // Reads a sub-message from the given Table. The sub-message may either be
   // a struct or a Table. Returns null if the sub-message is not set.
diff --git a/aos/network/www/reflection_test.html b/aos/network/www/reflection_test.html
index b9cc6c8..37714e6 100644
--- a/aos/network/www/reflection_test.html
+++ b/aos/network/www/reflection_test.html
@@ -1,6 +1,5 @@
 <html>
   <head>
-    <script src="flatbuffers.js"></script>
     <script src="reflection_test_bundle.min.js" defer></script>
   </head>
   <body>
diff --git a/aos/network/www/reflection_test_main.ts b/aos/network/www/reflection_test_main.ts
index 75cf107..5dead7b 100644
--- a/aos/network/www/reflection_test_main.ts
+++ b/aos/network/www/reflection_test_main.ts
@@ -1,9 +1,20 @@
-import {aos} from 'aos/configuration_generated'
-// TODO(james): Fix all the things imported from here to actually run.
-import {aos} from 'aos/json_to_flatbuffer_generated'
+import * as configuration from 'org_frc971/aos/configuration_generated'
+import * as testing from 'org_frc971/aos/json_to_flatbuffer_generated'
+import * as flatbuffers_builder from 'org_frc971/external/com_github_google_flatbuffers/ts/builder';
+import {ByteBuffer} from 'org_frc971/external/com_github_google_flatbuffers/ts/byte-buffer';
+import {Long} from 'org_frc971/external/com_github_google_flatbuffers/ts/long';
 
 import {Connection} from './proxy';
 import {Parser, Table} from './reflection'
+
+import Configuration = configuration.aos.Configuration;
+import BaseType = testing.aos.testing.BaseType;
+import TestTable = testing.aos.testing.Configuration;
+import FooStruct = testing.aos.testing.FooStruct;
+import Location = testing.aos.testing.Location;
+import Map = testing.aos.testing.Map;
+import VectorOfStrings = testing.aos.testing.VectorOfStrings;
+import VectorOfVectorOfString = testing.aos.testing.VectorOfVectorOfString;
 // This file runs a basic test to confirm that the typescript flatbuffer
 // reflection library is working correctly. It currently is not run
 // automatically--to run it, run the web_proxy_demo sh_binary target, open the
@@ -23,8 +34,9 @@
 // Constructs a flatbuffer and then uses Parser.toObject to parse it and confirm
 // that the start/end results are the same. This is largely meant to ensure
 // that we are exercising most of the logic associated with parsing flatbuffers.
-function DoTest(config: aos.Configuration): void {
-  const builder = new flatbuffers.Builder();
+function DoTest(config: Configuration): void {
+  const builder =
+      new flatbuffers_builder.Builder() as unknown as flatbuffers.Builder;
   {
     TestTable.startVectorFooStructVector(builder, 3);
     const fooStruct0 = FooStruct.createFooStruct(builder, 66, 118);
@@ -37,7 +49,11 @@
         Location.createLocation(builder, nameString, typeString, 100, 200);
     const location1 =
         Location.createLocation(builder, nameString, typeString, 300, 400);
-    const map = Map.createMap(builder, location0, location1);
+    Map.startMap(builder);
+    Map.addMatch(builder, location0);
+    Map.addRename(builder, location1);
+    const map = Map.endMap(builder);
+
     const mapVector = TestTable.createMapsVector(builder, [map]);
 
     const strVector =
@@ -60,15 +76,17 @@
     TestTable.addVectorFooStruct(builder, vectorFooStruct);
     TestTable.addVectorFooDouble(builder, doubleVector);
     TestTable.addFooDouble(builder, 11.14);
-    TestTable.addFooLong(builder, new flatbuffers.Long(100, 1));
+    TestTable.addFooLong(
+        builder, new Long(100, 1) as unknown as flatbuffers.Long);
     TestTable.addFooEnum(builder, BaseType.Array);
   }
 
-  builder.finish(aos.Configuration.endConfiguration(builder));
+  builder.finish(Configuration.endConfiguration(builder));
   const array = builder.asUint8Array();
-  const fbBuffer = new flatbuffers.ByteBuffer(array);
+  const fbBuffer = new ByteBuffer(array);
 
-  const parsedFb = TestTable.getRootAsConfiguration(fbBuffer);
+  const parsedFb = TestTable.getRootAsConfiguration(
+      fbBuffer as unknown as flatbuffers.ByteBuffer);
 
   let testSchema = null;
   for (let ii = 0; ii < config.channelsLength(); ++ii) {
@@ -145,7 +163,7 @@
     throw new Error('Couldn\'t find Configuration schema in config.');
   }
   let configParser = new Parser(configSchema);
-  const configTable = Table.getRootTable(config.bb);
+  const configTable = Table.getRootTable(config.bb as unknown as ByteBuffer);
   console.log('Received config:');
   console.log(configParser.toObject(configTable, true));
 
diff --git a/third_party/flatbuffers/BUILD b/third_party/flatbuffers/BUILD
index 346f9a6..3114495 100644
--- a/third_party/flatbuffers/BUILD
+++ b/third_party/flatbuffers/BUILD
@@ -8,13 +8,14 @@
 
 exports_files([
     "LICENSE",
+    "tsconfig.json",
 ])
 
 # Public flatc library to compile flatbuffer files at runtime.
 cc_library(
     name = "flatbuffers",
-    copts = ["-Wno-cast-align"],
     hdrs = ["//:public_headers"],
+    copts = ["-Wno-cast-align"],
     linkstatic = 1,
     strip_include_prefix = "/include",
     deps = ["//src:flatbuffers"],
@@ -82,6 +83,7 @@
     linkstatic = 1,
     strip_include_prefix = "/include",
 )
+
 py_library(
     name = "flatpy",
     srcs = glob(["python/flatbuffers/*.py"]),
diff --git a/third_party/flatbuffers/ts/BUILD b/third_party/flatbuffers/ts/BUILD
new file mode 100644
index 0000000..ad59551
--- /dev/null
+++ b/third_party/flatbuffers/ts/BUILD
@@ -0,0 +1,16 @@
+load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
+
+ts_library(
+    name = "flatbuffers_ts",
+    srcs = [
+        "builder.ts",
+        "byte-buffer.ts",
+        "constants.ts",
+        "encoding.ts",
+        "flatbuffers.ts",
+        "long.ts",
+        "types.ts",
+        "utils.ts",
+    ],
+    visibility = ["//visibility:public"],
+)
diff --git a/third_party/flatbuffers/ts/builder.ts b/third_party/flatbuffers/ts/builder.ts
index 6be72fb..137031e 100644
--- a/third_party/flatbuffers/ts/builder.ts
+++ b/third_party/flatbuffers/ts/builder.ts
@@ -604,7 +604,7 @@
      * @returns list of offsets of each non null object
      */
     createObjectOffsetList(list: string[]): Offset[] {
-      const ret = [];
+      const ret: number[] = [];
   
       for(let i = 0; i < list.length; ++i) {
         const val = list[i];
@@ -625,4 +625,4 @@
       this.createObjectOffsetList(list);
       return this.endVector();
     }
-  }
\ No newline at end of file
+  }
diff --git a/third_party/flatbuffers/tsconfig.json b/third_party/flatbuffers/tsconfig.json
index 9af4075..d480e1b 100644
--- a/third_party/flatbuffers/tsconfig.json
+++ b/third_party/flatbuffers/tsconfig.json
@@ -1,16 +1,12 @@
 {
   "compilerOptions": {
-    "target": "ES5",
-    "module": "commonjs",
-    "lib": ["ES2015", "ES2020.BigInt", "DOM"],
-    "declaration": true,
-    "outDir": "./js",
+    "experimentalDecorators": true,
     "strict": true,
-    "esModuleInterop": true,
-    "skipLibCheck": true, 
-    "forceConsistentCasingInFileNames": true
+    "noImplicitAny": false,
+    "target": "es6",
+    "lib": ["es6", "dom"]
   },
-  "include": [
-    "ts/**/*.ts"
-  ]
+  "bazelOptions": {
+    "workspaceName": "flatbuffers"
+  }
 }
diff --git a/tools/ruby/BUILD b/tools/ruby/BUILD
deleted file mode 100644
index b8b2543..0000000
--- a/tools/ruby/BUILD
+++ /dev/null
@@ -1,5 +0,0 @@
-py_binary(
-    name = "standalone_ruby",
-    srcs = ["standalone_ruby.py"],
-    visibility = ["//visibility:public"],
-)
diff --git a/tools/ruby/standalone_ruby.py b/tools/ruby/standalone_ruby.py
deleted file mode 100644
index 0c574e0..0000000
--- a/tools/ruby/standalone_ruby.py
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/python
-
-import zlib, sys, os, stat
-
-with file(sys.argv[2], "wb+") as outf:
-  outf.write("""#!/usr/bin/env ruby
-require "zlib"
-
-def zip_file_binding()
-  binding()
-end
-
-module Kernel
-  class ZipRequireRecord
-    attr_accessor :fname, :val
-    def initialize(fname, val)
-      @fname = fname
-      @val = val
-    end
-    def do_require()
-      return false if !@val
-      eval(@val, binding = zip_file_binding(), filename="//@bazel/" + @fname)
-      @val = nil
-      return true
-    end
-  end
-  BAZEL_START_ENTRY = "/@bazel/"
-  ZIP_TEMP_OBJS = {}
-  def require_relative(relative_feature)
-    file = caller.first.split(/:\d/,2).first
-    raise LoadError, "require_relative is called in #{$1}" if /\A\((.*)\)/ =~ file
-    require File.expand_path(relative_feature, File.dirname(file))
-  end
-  def require_zip(moduleName)
-    if moduleName.start_with?(BAZEL_START_ENTRY)
-      moduleName = moduleName[BAZEL_START_ENTRY.length..-1]
-    end
-    zip_obj = ZIP_TEMP_OBJS[moduleName]
-    if not zip_obj and !moduleName.end_with?('.rb')
-      zip_obj = ZIP_TEMP_OBJS[moduleName + '.rb']
-    end
-    return zip_obj.do_require() if (zip_obj)
-    return pre_zip_load_require(moduleName)
-  end
-  alias :pre_zip_load_require :require
-  alias :require :require_zip
-  def init_app(main_fname)
-    $0 = "//@bazel/" + main_fname
-    Kernel.require_zip(main_fname)
-  end
-  def register_inline_file(fname, data)
-    raise if ZIP_TEMP_OBJS.has_key?(fname)
-    ZIP_TEMP_OBJS[fname] = Kernel::ZipRequireRecord.new(fname, data.force_encoding("UTF-8"))
-  end
-end
-
-my_data = Zlib.inflate(DATA.read())
-""")
-
-  blob_data = []
-  offset = 0
-  with file(sys.argv[1], 'r') as infile:
-    for line in infile.xreadlines():
-      file_outname, file_binname = line.strip().split('|')
-      with file(file_binname, 'r') as obj_file:
-        obj = obj_file.read()
-      blob_data.append(obj)
-      new_off = offset + len(obj)
-      outf.write("Kernel.register_inline_file(%s, my_data.slice(%s...%s))\n" %
-                 (repr(file_outname), offset, new_off))
-      offset = new_off
-
-  outf.write("Kernel.init_app(%s)\n" % repr(sys.argv[3]))
-  outf.write("__END__\n")
-  outf.write(zlib.compress("".join(blob_data)))
diff --git a/tsconfig.json b/tsconfig.json
index d330268..bfbeb32 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -4,7 +4,7 @@
     "strict": true,
     "noImplicitAny": false,
     "target": "es6",
-    "lib": ["es6", "dom"]
+    "lib": ["es6", "dom", "dom.iterable"]
   },
   "bazelOptions": {
     "workspaceName": "971-Robot-Code"
diff --git a/y2020/BUILD b/y2020/BUILD
index 208b04a..f54ec84 100644
--- a/y2020/BUILD
+++ b/y2020/BUILD
@@ -243,7 +243,6 @@
         "//y2020/www:camera_main_bundle",
         "//y2020/www:field_main_bundle",
         "//y2020/www:files",
-        "//y2020/www:flatbuffers",
     ],
 )
 
diff --git a/y2020/www/BUILD b/y2020/www/BUILD
index 5e11d7c..bc9c016 100644
--- a/y2020/www/BUILD
+++ b/y2020/www/BUILD
@@ -15,6 +15,7 @@
         "//aos/network/www:proxy",
         "//y2020/vision:vision_ts_fbs",
         "//y2020/vision/sift:sift_ts_fbs",
+        "@com_github_google_flatbuffers//ts:flatbuffers_ts",
     ],
 )
 
@@ -61,25 +62,12 @@
     visibility = ["//visibility:public"],
 )
 
-genrule(
-    name = "flatbuffers",
-    srcs = [
-        "@com_github_google_flatbuffers//:flatjs",
-    ],
-    outs = [
-        "flatbuffers.js",
-    ],
-    cmd = "cp $(location @com_github_google_flatbuffers//:flatjs) $@",
-    visibility = ["//y2020:__subpackages__"],
-)
-
 aos_downloader_dir(
     name = "www_files",
     srcs = [
         ":camera_main_bundle",
         ":field_main_bundle",
         ":files",
-        ":flatbuffers",
     ],
     dir = "www",
     visibility = ["//visibility:public"],
diff --git a/y2020/www/camera_main.ts b/y2020/www/camera_main.ts
index e13452e..8667a8e 100644
--- a/y2020/www/camera_main.ts
+++ b/y2020/www/camera_main.ts
@@ -1,7 +1,7 @@
-import {Connection} from 'aos/network/www/proxy';
+import {Connection} from 'org_frc971/aos/network/www/proxy';
 
 import {ImageHandler} from './image_handler';
-import {ConfigHandler} from 'aos/network/www/config_handler';
+import {ConfigHandler} from 'org_frc971/aos/network/www/config_handler';
 
 const conn = new Connection();
 
diff --git a/y2020/www/camera_viewer.html b/y2020/www/camera_viewer.html
index 4a61d7a..aafec55 100644
--- a/y2020/www/camera_viewer.html
+++ b/y2020/www/camera_viewer.html
@@ -1,6 +1,5 @@
 <html>
   <head>
-    <script src="flatbuffers.js"></script>
     <script src="camera_main_bundle.min.js" defer></script>
     <link rel="stylesheet" href="styles.css">
   </head>
diff --git a/y2020/www/field.html b/y2020/www/field.html
index ad449db..c75e7bf 100644
--- a/y2020/www/field.html
+++ b/y2020/www/field.html
@@ -1,6 +1,5 @@
 <html>
   <head>
-    <script src="flatbuffers.js"></script>
     <script src="field_main_bundle.min.js" defer></script>
     <link rel="stylesheet" href="styles.css">
   </head>
diff --git a/y2020/www/field_handler.ts b/y2020/www/field_handler.ts
index ffb4aee..c0b6c50 100644
--- a/y2020/www/field_handler.ts
+++ b/y2020/www/field_handler.ts
@@ -1,8 +1,15 @@
-import {aos} from 'aos/configuration_generated';
-import {aos} from 'aos/network/connect_generated';
-import {Connection} from 'aos/network/www/proxy';
-import {frc971} from 'frc971/control_loops/drivetrain/drivetrain_status_generated';
-import {frc971} from 'y2020/vision/sift/sift_generated';
+import * as configuration from 'org_frc971/aos/configuration_generated';
+import * as connect from 'org_frc971/aos/network/connect_generated';
+import {Connection} from 'org_frc971/aos/network/www/proxy';
+import * as flatbuffers_builder from 'org_frc971/external/com_github_google_flatbuffers/ts/builder';
+import {ByteBuffer} from 'org_frc971/external/com_github_google_flatbuffers/ts/byte-buffer';
+import * as drivetrain from 'org_frc971/frc971/control_loops/drivetrain/drivetrain_status_generated';
+import * as sift from 'org_frc971/y2020/vision/sift/sift_generated';
+
+import DrivetrainStatus = drivetrain.frc971.control_loops.drivetrain.Status;
+import ImageMatchResult = sift.frc971.vision.sift.ImageMatchResult;
+import Connect = connect.aos.message_bridge.Connect;
+import Channel = configuration.aos.Channel;
 
 import {FIELD_LENGTH, FIELD_WIDTH, FT_TO_M, IN_TO_M} from './constants';
 
@@ -83,7 +90,7 @@
 
 export class FieldHandler {
   private canvas = document.createElement('canvas');
-  private imageMatchResult: frc971.vision.sift.ImageMatchResult|null = null;
+  private imageMatchResult: ImageMatchResult|null = null;
   private drivetrainStatus: DrivetrainStatus|null = null;
 
   constructor(private readonly connection: Connection) {
@@ -93,42 +100,46 @@
       this.sendConnect();
     });
     this.connection.addHandler(
-        frc971.vision.sift.ImageMatchResult.getFullyQualifiedName(), (res) => {
+        ImageMatchResult.getFullyQualifiedName(), (res) => {
           this.handleImageMatchResult(res);
         });
-    this.connection.addHandler(frc971.control_loops.drivetrain.Status.getFullyQualifiedName(), (data) => {
-      this.handleDrivetrainStatus(data);
-    });
+    this.connection.addHandler(
+        DrivetrainStatus.getFullyQualifiedName(), (data) => {
+          this.handleDrivetrainStatus(data);
+        });
   }
 
   private handleImageMatchResult(data: Uint8Array): void {
-    const fbBuffer = new flatbuffers.ByteBuffer(data);
-    this.imageMatchResult =
-        frc971.vision.sift.ImageMatchResult.getRootAsImageMatchResult(fbBuffer);
+    const fbBuffer = new ByteBuffer(data);
+    this.imageMatchResult = ImageMatchResult.getRootAsImageMatchResult(
+        fbBuffer as unknown as flatbuffers.ByteBuffer);
   }
 
   private handleDrivetrainStatus(data: Uint8Array): void {
-    const fbBuffer = new flatbuffers.ByteBuffer(data);
-    this.drivetrainStatus = frc971.control_loops.drivetrain.Status.getRootAsStatus(fbBuffer);
+    const fbBuffer = new ByteBuffer(data);
+    this.drivetrainStatus = DrivetrainStatus.getRootAsStatus(
+        fbBuffer as unknown as flatbuffers.ByteBuffer);
   }
 
   private sendConnect(): void {
-    const builder = new flatbuffers.Builder(512);
+    const builder =
+        new flatbuffers_builder.Builder(512) as unknown as flatbuffers.Builder;
     const channels: flatbuffers.Offset[] = [];
     for (const channel of REQUIRED_CHANNELS) {
       const nameFb = builder.createString(channel.name);
       const typeFb = builder.createString(channel.type);
-      aos.Channel.startChannel(builder);
-      aos.Channel.addName(builder, nameFb);
-      aos.Channel.addType(builder, typeFb);
-      const channelFb = aos.Channel.endChannel(builder);
+      Channel.startChannel(builder);
+      Channel.addName(builder, nameFb);
+      Channel.addType(builder, typeFb);
+      const channelFb = Channel.endChannel(builder);
       channels.push(channelFb);
     }
 
-    const channelsFb = aos.message_bridge.Connect.createChannelsToTransferVector(builder, channels);
-    aos.message_bridge.Connect.startConnect(builder);
-    aos.message_bridge.Connect.addChannelsToTransfer(builder, channelsFb);
-    const connect = aos.message_bridge.Connect.endConnect(builder);
+    const channelsFb =
+        Connect.createChannelsToTransferVector(builder, channels);
+    Connect.startConnect(builder);
+    Connect.addChannelsToTransfer(builder, channelsFb);
+    const connect = Connect.endConnect(builder);
     builder.finish(connect);
     this.connection.sendConnectMessage(builder);
   }
@@ -214,7 +225,7 @@
     ctx.lineTo(0.5, -0.5);
     ctx.stroke();
     ctx.beginPath();
-    ctx.arc(0, 0, 0.25, -Math.PI/4, Math.PI/4);
+    ctx.arc(0, 0, 0.25, -Math.PI / 4, Math.PI / 4);
     ctx.stroke();
     ctx.restore();
   }
@@ -233,10 +244,10 @@
     ctx.restore();
   }
 
-  draw(): void  {
+  draw(): void {
     this.reset();
     this.drawField();
-    //draw cameras
+    // draw cameras
     if (this.imageMatchResult) {
       for (let i = 0; i < this.imageMatchResult.cameraPosesLength(); i++) {
         const pose = this.imageMatchResult.cameraPoses(i);
diff --git a/y2020/www/field_main.ts b/y2020/www/field_main.ts
index 163c817..7e2e392 100644
--- a/y2020/www/field_main.ts
+++ b/y2020/www/field_main.ts
@@ -1,4 +1,4 @@
-import {Connection} from 'aos/network/www/proxy';
+import {Connection} from 'org_frc971/aos/network/www/proxy';
 
 import {FieldHandler} from './field_handler';
 
diff --git a/y2020/www/image_handler.ts b/y2020/www/image_handler.ts
index c84fa23..121ab75 100644
--- a/y2020/www/image_handler.ts
+++ b/y2020/www/image_handler.ts
@@ -1,8 +1,18 @@
-import {aos} from 'aos/configuration_generated';
-import {Connection} from 'aos/network/www/proxy';
-import {aos} from 'aos/network/connect_generated';
-import {frc971} from 'y2020/vision/sift/sift_generated'
-import {frc971} from 'y2020/vision/vision_generated';
+import * as configuration from 'org_frc971/aos/configuration_generated';
+import * as connect from 'org_frc971/aos/network/connect_generated';
+import {Connection} from 'org_frc971/aos/network/www/proxy';
+import * as flatbuffers_builder from 'org_frc971/external/com_github_google_flatbuffers/ts/builder';
+import {ByteBuffer} from 'org_frc971/external/com_github_google_flatbuffers/ts/byte-buffer';
+import {Long} from 'org_frc971/external/com_github_google_flatbuffers/ts/long';
+import * as sift from 'org_frc971/y2020/vision/sift/sift_generated'
+import * as vision from 'org_frc971/y2020/vision/vision_generated';
+
+import Channel = configuration.aos.Channel;
+import Configuration = configuration.aos.Configuration;
+import Connect = connect.aos.message_bridge.Connect;
+import CameraImage = vision.frc971.vision.CameraImage;
+import ImageMatchResult = sift.frc971.vision.sift.ImageMatchResult;
+import Feature = sift.frc971.vision.sift.Feature;
 
 /*
  * All the messages that are required to show an image with metadata.
@@ -11,43 +21,43 @@
 const REQUIRED_CHANNELS = [
   {
     name: '/pi1/camera',
-    type: frc971.vision.CameraImage.getFullyQualifiedName(),
+    type: CameraImage.getFullyQualifiedName(),
   },
   {
     name: '/pi2/camera',
-    type: frc971.vision.CameraImage.getFullyQualifiedName(),
+    type: CameraImage.getFullyQualifiedName(),
   },
   {
     name: '/pi3/camera',
-    type: frc971.vision.CameraImage.getFullyQualifiedName(),
+    type: CameraImage.getFullyQualifiedName(),
   },
   {
     name: '/pi4/camera',
-    type: frc971.vision.CameraImage.getFullyQualifiedName(),
+    type: CameraImage.getFullyQualifiedName(),
   },
   {
     name: '/pi5/camera',
-    type: frc971.vision.CameraImage.getFullyQualifiedName(),
+    type: CameraImage.getFullyQualifiedName(),
   },
   {
     name: '/pi1/camera/detailed',
-    type: frc971.vision.sift.ImageMatchResult.getFullyQualifiedName(),
+    type: ImageMatchResult.getFullyQualifiedName(),
   },
   {
     name: '/pi2/camera/detailed',
-    type: frc971.vision.sift.ImageMatchResult.getFullyQualifiedName(),
+    type: ImageMatchResult.getFullyQualifiedName(),
   },
   {
     name: '/pi3/camera/detailed',
-    type: frc971.vision.sift.ImageMatchResult.getFullyQualifiedName(),
+    type: ImageMatchResult.getFullyQualifiedName(),
   },
   {
     name: '/pi4/camera/detailed',
-    type: frc971.vision.sift.ImageMatchResult.getFullyQualifiedName(),
+    type: ImageMatchResult.getFullyQualifiedName(),
   },
   {
     name: '/pi5/camera/detailed',
-    type: frc971.vision.sift.ImageMatchResult.getFullyQualifiedName(),
+    type: ImageMatchResult.getFullyQualifiedName(),
   },
 ];
 
@@ -56,10 +66,10 @@
   private select = document.createElement('select');
 
   private imageBuffer: Uint8ClampedArray|null = null;
-  private image: frc971.vision.CameraImage|null = null;
-  private imageTimestamp: flatbuffers.Long|null = null;
-  private result: frc971.vision.sift.ImageMatchResult|null = null;
-  private resultTimestamp: flatbuffers.Long|null = null;
+  private image: CameraImage|null = null;
+  private imageTimestamp: Long|null = null;
+  private result: ImageMatchResult|null = null;
+  private resultTimestamp: Long|null = null;
   private width = 0;
   private height = 0;
   private selectedIndex = 0;
@@ -77,32 +87,33 @@
       this.sendConnect();
     });
     this.connection.addHandler(
-        frc971.vision.sift.ImageMatchResult.getFullyQualifiedName(), (data) => {
+        ImageMatchResult.getFullyQualifiedName(), (data) => {
           this.handleImageMetadata(data);
         });
-    this.connection.addHandler(
-      frc971.vision.CameraImage.getFullyQualifiedName(), (data) => {
-        this.handleImage(data);
-      });
+    this.connection.addHandler(CameraImage.getFullyQualifiedName(), (data) => {
+      this.handleImage(data);
+    });
   }
 
   private sendConnect(): void {
-    const builder = new flatbuffers.Builder(512);
+    const builder =
+        new flatbuffers_builder.Builder(512) as unknown as flatbuffers.Builder;
     const channels: flatbuffers.Offset[] = [];
     for (const channel of REQUIRED_CHANNELS) {
       const nameFb = builder.createString(channel.name);
       const typeFb = builder.createString(channel.type);
-      aos.Channel.startChannel(builder);
-      aos.Channel.addName(builder, nameFb);
-      aos.Channel.addType(builder, typeFb);
-      const channelFb = aos.Channel.endChannel(builder);
+      Channel.startChannel(builder);
+      Channel.addName(builder, nameFb);
+      Channel.addType(builder, typeFb);
+      const channelFb = Channel.endChannel(builder);
       channels.push(channelFb);
     }
 
-    const channelsFb = aos.message_bridge.Connect.createChannelsToTransferVector(builder, channels);
-    aos.message_bridge.Connect.startConnect(builder);
-    aos.message_bridge.Connect.addChannelsToTransfer(builder, channelsFb);
-    const connect = aos.message_bridge.Connect.endConnect(builder);
+    const channelsFb =
+        Connect.createChannelsToTransferVector(builder, channels);
+    Connect.startConnect(builder);
+    Connect.addChannelsToTransfer(builder, channelsFb);
+    const connect = Connect.endConnect(builder);
     builder.finish(connect);
     this.connection.sendConnectMessage(builder);
   }
@@ -120,8 +131,9 @@
       this.imageSkipCount = 3;
     }
 
-    const fbBuffer = new flatbuffers.ByteBuffer(data);
-    this.image = frc971.vision.CameraImage.getRootAsCameraImage(fbBuffer);
+    const fbBuffer = new ByteBuffer(data);
+    this.image = CameraImage.getRootAsCameraImage(
+        fbBuffer as unknown as flatbuffers.ByteBuffer);
     this.imageTimestamp = this.image.monotonicTimestampNs();
 
     this.width = this.image.cols();
@@ -134,7 +146,8 @@
   }
 
   convertImage(): void {
-    this.imageBuffer = new Uint8ClampedArray(this.width * this.height * 4); // RGBA
+    this.imageBuffer =
+        new Uint8ClampedArray(this.width * this.height * 4);  // RGBA
     // Read four bytes (YUYV) from the data and transform into two pixels of
     // RGBA for canvas
     for (let j = 0; j < this.height; j++) {
@@ -170,9 +183,9 @@
 
   handleImageMetadata(data: Uint8Array): void {
     console.log('got an image match result to process');
-    const fbBuffer = new flatbuffers.ByteBuffer(data);
-    this.result =
-        frc971.vision.sift.ImageMatchResult.getRootAsImageMatchResult(fbBuffer);
+    const fbBuffer = new ByteBuffer(data);
+    this.result = ImageMatchResult.getRootAsImageMatchResult(
+        fbBuffer as unknown as flatbuffers.ByteBuffer);
     this.resultTimestamp = this.result.imageMonotonicTimestampNs();
     this.draw();
   }