i am working towards creating the fundamental es module package structure before pulling out behavior from the ionic-gib project into this lib. so this is just a shell right now.
I have created a working MVP for ibgib that shows some of the potential for the architecture:
- try it out
- pre-refactored MVP codebase on GitHub
-
ionic-gib
: https://github.com/wraiford/ibgib/tree/v0.2.729/ionic-gib - "pre-refactored" = doesn't use this core-gib lib, but rather is the springboard/"carcass" for it.
-
- base ibgib protocol graphing substrate lib on GitLab
core-gib
is the intermediate ibgib substrate that provides functionality for basic ibgib interactions.
This includes plumbing for the following primary areas:
- witnesses
- spaces
- apps
- robbots
note: many of these could technically be its own library, but at the very least for now these will stay within this core library until it seems they should be broken out.
This sits on top of the lowest level ts-gib
library, which provides the very basic
primitives used in the mechanics of ibgib graphing.
An ibgib "witness" is the lowest level of ibgib in code that provides behavior that is associated with its ibgib data. It is so called because it's meant to convey to us that an ibgib is not some impartial, absolute function but rather always has a POV. It is like if you take a function and abstract away specifics of how it gets its information (be it on a stack, heap, at a local RAM location address, etc.)
So in short, a witness is a distributed computation metaversal function, but personified in order to remind each of us of anything's fallibility (including computer functions).
With this in mind, let's look at the witness interface definitions in TypeScript, with generic types and comments removed for clarity.
export interface IbGib {
ib: Ib; // string
gib?: Gib; // string
}
export interface IbGibWithDataAndRel8ns<...> extends IbGib {
data?: TData; // object/map of string->any
rel8ns?: TRel8ns; // map of string->string[]
}
export interface Witness<...> extends IbGibWithDataAndRel8ns<...> {
witness(arg: TIbGibIn): Promise<TIbGibOut | undefined>;
}
This last Witness
interface has a single member: the witness
function. This
accepts a single ibgib arg and returns a single ibgib arg. Since each ibgib is
content addressed (*1), this allows for a function addressing scheme that
effectively works in an infinite addressing space.
Considering this, the ibgib + witness design can be thought of as a superset of
all programming languages with witness
ibgib acting similar to how we think of
functions. So inter-witness communications are at the extreme of functional
programming. Or said another way it can describe any programming language. But
when it comes to execution, adding the isomorphic transformation into the ibgib
description space would necessarily add overhead and most likely create
unfeasible execution times (until computation power vastly improves relative to
our current POV in time). Or in short, it would be NECESSARILY SLOWER, to the
point of local impracticality.
Still, it's important to think each witness as a universally addressed function, and each space as a special case witness whose job is colocation.
[*1] primitives and other ibgibs without a gib hash, like "6^gib" or "hello^gib", are still "content addressed", it's simply the value is the address itself.
So a "witness" is an ibgib with behavior, i.e. doesn't just have data. A "space" is one kind of witness. Its primary job is to collocate ibgib.
nuance: The implementation of "collocation" is not concrete and can be decided by - and vary wildly by - the implementing class.
Ideally all spaces are to be considered equally, with the idea being that you
"simply" treat them as buckets of data. As such, we can think of them like a
bucket or a repo with just a couple capabilities: get
, put
, etc.
But when dealing with the process of living, temporal data dynamics, we must consider one key aspect of data: perspective, i.e. POV. As such, there are necessarily(?) three "types" of space with respect to POV:
- local space
- outer space
- inner space
These are currently implemented in the ionic-gib MVP as follows:
- local space
- implemented with
IonicSpace_V1
- uses capacitor filesystem api (v4) as indexeddb substrate
- outer space
- implemented with
AWSDynamoSpace_V1
- this is implemented as a "merge" space, in that when ibgibs are "put" into the space, timelines are dynamically merged using a CRDT-like merging algorithm that applies unapplied DNA transforms
- uses DynamoDB for most ibgib data stored as four string fields (max string size of 400 KB)
- uses S3 for larger ibgibs with DynamoDB entries that indicate S3 storage
- inner space
- the InnerSpace_V1 is not used or tested
- it is only sketched
- better composeability will be required for inner spaces to be utilized
If you think of a function in a programming language, it has a couple of characteristics:
- has an address
- has at least one parameter, which ultimately has an an address (either in the stack/heap or a pointer to memory)
- returns 0-1+ data structures
as a workaround for bleeding edge ES module consumption (let alone testing
frameworks for them), I have kluged a workaround by editing
/node_modules/jasmine-browser-runner/run.html.ejs
to include an import map
section. So atow paste the following code before any other script
tags in the
head
section. (the versions may need to change):
note: atow I am copy/pasting this text whenever I reinstall node_modules folder
<script type="importmap">
{
"imports": {
"ts-gib": "https://unpkg.com/ts-gib@0.4.8/dist/index.mjs",
"ts-gib/": "https://unpkg.com/ts-gib@0.4.8/"
}
}
</script>