only-cliches / Reach-Web-Service-Engine

The core engine and runtime for the Reach web service.
1 stars 0 forks source link

Development Server #1

Open only-cliches opened 4 years ago

only-cliches commented 4 years ago

The development server does live compilation and live reload of apps in development.

The development server needs to have the following features:

1. Dynamic Deploy

It can be started (including the file watching) and stopped dynamically in the runtime. We should be able to point the server to a given directory, start file watching/live compilation on that directory, and spin up the dev server on a given set of ports. At a later time, the runtime should be able to stop the dev server (and it's file watching and everything else it was doing).

2. Simple Typescript Compilation

Looking at the example_app directory, there should be a separate server/port for each html_X folder. One port for the html_public directory, one for the html_doc directory and one for the html_admin directory. The compilation and other steps will largely look the same for these folders. All typescript compilation should output a .d.ts file and a .js file with mappings. Absolutely zero module bundeling or minification should be performed.

3. Directory Specifics

Inside each html_* directory is a set of default subdirectories, they should be treated as follows:

views

This contains all the react/vue/angular code for the app. The typescript files in this directory should be compiled into the target/client directory and the target/server directory. For example, a /html_public/index.tsx should be compiled and placed in /target/server/html_public/index.js AND /target/client/html_public/index.js.

views/services

This folder contains the services (controller in MVC) that anything in the views can call to perform actions on the server. The server should expect a single file, index.ts in the root that has a format like this:

export default {
    service_name: async (args) => {

    },
    service_name_2: async (args) => {

    },
    user_services: {
        add_user: async (ags) => {

        }
    }
    ...
}

We should expect that different kinds of services will be split up into seperate files or subdirectories in this export, and it should be handled gracefully. For example, a developer might do something like this:

import * as user_services from "./user";

export default {
    user_services: user_services
}

Services will have a unique compile process. For every file in the services directory, there will be two seperate compilations, one for the client side and the other for the server side.

Client Side Compile For the client side compilation, the files should be loaded into Deno and mutated so that all of the functions are removed and replaced with a single async function (that will be created later, so just use a placeholder for now) and then copied into the target folder. For example /html_public/services/index.ts should be compiled to /target/client/html_public/services/index.js. Here's an example of the mutation:

Source file:

export default {
    service_name: async (args) => {
        /* ... real service code **/
    },
    user_services: {
        make_user: async (args) => {
            /* .. real service code **/
        }
    }
}

Target:

export default {
    service_name: call_server("service_name", 123),
    user_services: {
        make_user: call_server("user_services.make_user", 123)
    }
}

The call_server function will be implemented later on, it will be shaped like this:

const call_server = (service_name, app_id) => {
    return async (args) => {
        /* send message to server with websockets or POST */
    }
}

Server Side Compile The server side compile should be a direct compilation of the files in the /services directory. For example /html_public/services/index.ts will be compiled to /target/server/html_public/services/index.js. Unlike the client side code, there should be no mutation.

node_modules

Contains library dependencies of the views and services

static

Static files for CSS and other styling like background images.

4. Bin Directory

The files inside the /bin directory should be watched and compiled into /target/bin. Like the other compilations, the file layout should be identical between the source and target. For example /bin/some_dir/index.ts should compile to /target/bin/some_dir/index.js and /target/bin/some_dir/index.d.ts.

5. File & App Hosting

Each server should provide static file hosting for the following directories:

only-cliches commented 4 years ago
OtterCode commented 4 years ago

Needs a simple JSON Key/Value store backing the admin api.

Needs an abstract interface. CRUD for tables and keys.

Make sure that you don't exceed the capabilities of etcd.

Scanning for tables. Get all records.

OtterCode commented 4 years ago

/admin should always redirect to control panel

only-cliches commented 4 years ago

Production server layout (notes for later)

1. Forum App
2. Designer
3. Chat Room App
4...
5...

localhost:80
localhost:443

|
|  example.com        |   whatever.com     |
|  database           |   database         |
|  filesystem         |   filesystem       |
|                     |
|  / (Designer)       |   / (Designer)
|  /forum (Forum)     |   /chat  (Chat App)
|  /about (Designer)  |   /about (Designer)
OtterCode commented 4 years ago

Static app assets mount at: specificDomain.com/static-assets/org/example-app/html_public/views

API: specificDomain.com/api/org/example-app/delete_prod

OtterCode commented 4 years ago

A domain requires three servers each.

Filter out manifest.json, views/services, and bin/

OtterCode commented 4 years ago

Append the static files to admin server.

OtterCode commented 4 years ago

On the admin database, add a table of enabled/disabled domains, and add a table keyed per domain with a json config that must contain an "apps" and "routes" property. Config must be loaded into each HTML page.

only-cliches commented 4 years ago

Get services file compiling correctly.

Max 4 hours on this (compiling source code)

// source code written by app developer

// services.ts
export const services = {
     user: {
         fnOne: async () => {
           db.request....
         }
     },
     profile: require("profile.js")
};

// profile.js
export const profileServices = {
    fnOne: await fn()...
}

// client side API fn

const rwsRequest = function(section: string, fnName: string) {
    return (...args) => {
       return fetch(JSON.stringfy(args).then(())
    }
}

// client output

export const services = {
     user: {
         fnOne: rwsRequest("user", "fnOne");
     },
     profile: {
         fnOne: rwsRequest("profile", "fnOne");
     }
}
``

// developer can do this in the client side app
```ts
const mydata = await services.user.fnOne(..args);