1
Fork 0

typescript(monadic): feat: basic stuff

Signed-off-by: prescientmoon <git@moonythm.dev>
This commit is contained in:
Matei Adriel 2020-04-24 17:00:36 +03:00 committed by prescientmoon
parent 7bdf572b2d
commit fd81cf068e
Signed by: prescientmoon
SSH key fingerprint: SHA256:UUF9JT2s8Xfyv76b8ZuVL7XrmimH4o49p4b+iexbVH4
29 changed files with 2553 additions and 299 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
{"id":"index.html","dependencies":[{"name":"./main.ts","dynamic":true,"resolved":"/home/adrielus/Projects/monadic/demos/basic/main.ts","parent":"/home/adrielus/Projects/monadic/demos/basic/index.html"}],"generated":{"html":"<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Monadic-ui basic</title>\n </head>\n <body>\n <div id=\"app\"></div>\n <script src=\"/6427dc610ec40c788cba04a9c39d6dcf.js\"></script>\n </body>\n</html>\n"},"sourceMaps":null,"error":null,"hash":"0737204c3508dc612eec91e4e9a1165d","cacheData":{}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
{"id":"node_modules/lit-html/lib/part.js","dependencies":[{"name":"/home/adrielus/Projects/monadic/demos/basic/node_modules/lit-html/lib/part.js.map","includedInParent":true,"mtime":499162500000},{"name":"/home/adrielus/Projects/monadic/demos/basic/package.json","includedInParent":true,"mtime":1587734964624},{"name":"/home/adrielus/Projects/monadic/demos/basic/node_modules/lit-html/package.json","includedInParent":true,"mtime":499162500000}],"generated":{"js":"\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.nothing = exports.noChange = void 0;\n\n/**\n * @license\n * Copyright (c) 2018 The Polymer Project Authors. All rights reserved.\n * This code may only be used under the BSD style license found at\n * http://polymer.github.io/LICENSE.txt\n * The complete set of authors may be found at\n * http://polymer.github.io/AUTHORS.txt\n * The complete set of contributors may be found at\n * http://polymer.github.io/CONTRIBUTORS.txt\n * Code distributed by Google as part of the polymer project is also\n * subject to an additional IP rights grant found at\n * http://polymer.github.io/PATENTS.txt\n */\n\n/**\n * A sentinel value that signals that a value was handled by a directive and\n * should not be written to the DOM.\n */\nconst noChange = {};\n/**\n * A sentinel value that signals a NodePart to fully clear its content.\n */\n\nexports.noChange = noChange;\nconst nothing = {};\nexports.nothing = nothing;"},"sourceMaps":{"js":{"mappings":[{"source":"../src/lib/part.ts","name":null,"original":{"line":1,"column":0},"generated":{"line":8,"column":0}},{"source":"../src/lib/part.ts","name":null,"original":{"line":45,"column":0},"generated":{"line":22,"column":0}},{"source":"../src/lib/part.ts","name":null,"original":{"line":49,"column":7},"generated":{"line":26,"column":0}},{"source":"../src/lib/part.ts","name":null,"original":{"line":49,"column":13},"generated":{"line":26,"column":6}},{"source":"../src/lib/part.ts","name":null,"original":{"line":49,"column":21},"generated":{"line":26,"column":14}},{"source":"../src/lib/part.ts","name":null,"original":{"line":49,"column":24},"generated":{"line":26,"column":17}},{"source":"../src/lib/part.ts","name":null,"original":{"line":49,"column":7},"generated":{"line":26,"column":19}},{"source":"../src/lib/part.ts","name":null,"original":{"line":51,"column":0},"generated":{"line":27,"column":0}},{"source":"../src/lib/part.ts","name":null,"original":{"line":54,"column":7},"generated":{"line":32,"column":0}},{"source":"../src/lib/part.ts","name":null,"original":{"line":54,"column":13},"generated":{"line":32,"column":6}},{"source":"../src/lib/part.ts","name":null,"original":{"line":54,"column":20},"generated":{"line":32,"column":13}},{"source":"../src/lib/part.ts","name":null,"original":{"line":54,"column":23},"generated":{"line":32,"column":16}},{"source":"../src/lib/part.ts","name":null,"original":{"line":54,"column":7},"generated":{"line":32,"column":18}}],"sources":{"../src/lib/part.ts":"/**\n * @license\n * Copyright (c) 2018 The Polymer Project Authors. All rights reserved.\n * This code may only be used under the BSD style license found at\n * http://polymer.github.io/LICENSE.txt\n * The complete set of authors may be found at\n * http://polymer.github.io/AUTHORS.txt\n * The complete set of contributors may be found at\n * http://polymer.github.io/CONTRIBUTORS.txt\n * Code distributed by Google as part of the polymer project is also\n * subject to an additional IP rights grant found at\n * http://polymer.github.io/PATENTS.txt\n */\n\n/**\n * @module lit-html\n */\n\n/**\n * The Part interface represents a dynamic part of a template instance rendered\n * by lit-html.\n */\nexport interface Part {\n readonly value: unknown;\n\n /**\n * Sets the current part value, but does not write it to the DOM.\n * @param value The value that will be committed.\n */\n setValue(value: unknown): void;\n\n /**\n * Commits the current part value, causing it to actually be written to the\n * DOM.\n *\n * Directives are run at the start of `commit`, so that if they call\n * `part.setValue(...)` synchronously that value will be used in the current\n * commit, and there's no need to call `part.commit()` within the directive.\n * If directives set a part value asynchronously, then they must call\n * `part.commit()` manually.\n */\n commit(): void;\n}\n\n/**\n * A sentinel value that signals that a value was handled by a directive and\n * should not be written to the DOM.\n */\nexport const noChange = {};\n\n/**\n * A sentinel value that signals a NodePart to fully clear its content.\n */\nexport const nothing = {};\n"},"lineCount":null}},"error":null,"hash":"05fa49157353fce29752c1b0c5b69944","cacheData":{"env":{}}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
{"id":"../../src/index.ts","dependencies":[{"name":"/home/adrielus/Projects/monadic/tsconfig.json","includedInParent":true,"mtime":1587733898427},{"name":"/home/adrielus/Projects/monadic/demos/basic/package.json","includedInParent":true,"mtime":1587734964624},{"name":"./environment","loc":{"line":1,"column":14},"parent":"/home/adrielus/Projects/monadic/src/index.ts","resolved":"/home/adrielus/Projects/monadic/src/environment.ts"}],"generated":{"js":"\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _environment = require(\"./environment\");\n\nObject.keys(_environment).forEach(function (key) {\n if (key === \"default\" || key === \"__esModule\") return;\n Object.defineProperty(exports, key, {\n enumerable: true,\n get: function () {\n return _environment[key];\n }\n });\n});"},"sourceMaps":{"js":{"mappings":[{"source":"../../src/index.ts","name":null,"original":{"line":1,"column":0},"generated":{"line":7,"column":0}},{"source":"../../src/index.ts","name":null,"original":{"line":1,"column":0},"generated":{"line":9,"column":0}},{"source":"../../src/index.ts","name":null,"original":{"line":1,"column":0},"generated":{"line":10,"column":0}},{"source":"../../src/index.ts","name":null,"original":{"line":1,"column":0},"generated":{"line":11,"column":0}},{"source":"../../src/index.ts","name":null,"original":{"line":1,"column":0},"generated":{"line":12,"column":0}},{"source":"../../src/index.ts","name":null,"original":{"line":1,"column":0},"generated":{"line":13,"column":0}},{"source":"../../src/index.ts","name":null,"original":{"line":1,"column":0},"generated":{"line":14,"column":0}},{"source":"../../src/index.ts","name":null,"original":{"line":1,"column":0},"generated":{"line":15,"column":0}},{"source":"../../src/index.ts","name":null,"original":{"line":1,"column":0},"generated":{"line":16,"column":0}},{"source":"../../src/index.ts","name":null,"original":{"line":1,"column":0},"generated":{"line":17,"column":0}}],"sources":{"../../src/index.ts":"export * from './environment';\n"},"lineCount":null}},"error":null,"hash":"4a985b7aa5441bcd69670f6f7e81fde5","cacheData":{"env":{}}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,8 @@
{
"cSpell.words": [
"adriel",
"esnext",
"matei",
"tslib"
]
}

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Monadic-ui basic</title>
</head>
<body>
<div id="app"></div>
<script src="./main.ts"></script>
</body>
</html>

View file

@ -0,0 +1,38 @@
import { runUi } from '../../src';
import { render, html, TemplateResult } from 'lit-html';
type Action = 'increase' | 'decrease';
type State = {
count: number;
};
runUi<TemplateResult, State, Action>({
parent: document.getElementById('app'),
render,
initialState: { count: 0 },
component: {
render: (state, dispatch) => {
return html`
<div>
<div>${state.count}</div>
<button @click=${dispatch('increase')}>Increase</button>
<button @click=${dispatch('decrease')}>Decrease</button>
</div>
`;
},
handleActions: (action: Action, state) => {
if (action === 'increase') {
return {
count: state.count + 1,
};
} else if (action === 'decrease') {
return {
count: state.count - 1,
};
}
return state;
},
},
});

View file

@ -0,0 +1,14 @@
{
"name": "basic",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Matei Adriel",
"license": "ISC",
"dependencies": {
"lit-html": "^1.2.1"
}
}

View file

@ -0,0 +1,10 @@
dependencies:
lit-html: 1.2.1
lockfileVersion: 5.1
packages:
/lit-html/1.2.1:
dev: false
resolution:
integrity: sha512-GSJHHXMGLZDzTRq59IUfL9FCdAlGfqNp/dEa7k7aBaaWD+JKaCjsAk9KYm2V12ItonVaYx2dprN66Zdm1AuBTQ==
specifiers:
lit-html: ^1.2.1

View file

@ -34,6 +34,7 @@
"module": "dist/monadic.esm.js",
"devDependencies": {
"husky": "^4.2.5",
"parcel": "^1.12.4",
"tsdx": "^0.13.2",
"tslib": "^1.11.1",
"typescript": "^3.8.3"

View file

@ -0,0 +1,42 @@
import { IterableEmitter } from './iterableEmitter';
export type EnvConfig<T, S, A> = {
render: (template: T, parent: HTMLElement) => void;
parent: HTMLElement;
component: Component<T, S, A>;
initialState: S;
};
export type Component<T, S, A> = {
render: (state: S, dispatch: (a: A) => () => void) => T;
handleActions: (action: A, state: S) => S;
};
async function* runComponent<T, S, A>(
component: Component<T, S, A>,
initialState: S
): AsyncGenerator<T> {
const emitter = new IterableEmitter(initialState);
const dispatch = (state: S) => (action: A) => {
const newState = component.handleActions(action, state);
return () => {
emitter.next(newState);
};
};
for await (const state of emitter) {
yield component.render(state, dispatch(state));
}
}
export const runUi = async <T, S, A>(
config: EnvConfig<T, S, A>
): Promise<void> => {
const component = runComponent(config.component, config.initialState);
for await (const template of component) {
config.render(template, config.parent);
}
};

View file

@ -0,0 +1,110 @@
declare const index: unique symbol;
/**
* Placeholder representing an indexed type variable.
*/
export interface _<N extends number = 0> {
[index]: N;
}
export type _0 = _<0>;
export type _1 = _<1>;
export type _2 = _<2>;
export type _3 = _<3>;
export type _4 = _<4>;
export type _5 = _<5>;
export type _6 = _<6>;
export type _7 = _<7>;
export type _8 = _<8>;
export type _9 = _<9>;
declare const fixed: unique symbol;
/**
* Marks a type to be ignored by the application operator `$`. This is used to protect
* bound type parameters.
*/
export interface Fixed<T> {
[fixed]: T;
}
/**
* Type application (simultaneously substitutes all placeholders within the target type)
*/
// prettier-ignore
export type $<T, S extends any[]> = (
T extends Fixed<infer U> ? { [indirect]: U } :
T extends _<infer N> ? { [indirect]: S[N] } :
T extends undefined | null | boolean | string | number ? { [indirect]: T } :
T extends (infer A)[] & { length: infer L } ? {
[indirect]: L extends keyof TupleTable
? TupleTable<T, S>[L]
: $<A, S>[]
} :
T extends (...x: infer I) => infer O ? { [indirect]: (...x: $<I, S>) => $<O, S> } :
T extends object ? { [indirect]: { [K in keyof T]: $<T[K], S> } } :
{ [indirect]: T }
)[typeof indirect];
/**
* Used as a level of indirection to avoid circularity errors.
*/
declare const indirect: unique symbol;
/**
* Allows looking up the type for a tuple based on its `length`, instead of trying
* each possibility one by one in a single long conditional.
*/
// prettier-ignore
type TupleTable<T extends any[] = any, S extends any[] = any> = {
0: [];
1: T extends [
infer A0
] ? [
$<A0, S>
] : never
2: T extends [
infer A0, infer A1
] ? [
$<A0, S>, $<A1, S>
] : never
3: T extends [
infer A0, infer A1, infer A2
] ? [
$<A0, S>, $<A1, S>, $<A2, S>
] : never
4: T extends [
infer A0, infer A1, infer A2, infer A3
] ? [
$<A0, S>, $<A1, S>, $<A2, S>, $<A3, S>
] : never
5: T extends [
infer A0, infer A1, infer A2, infer A3, infer A4
] ? [
$<A0, S>, $<A1, S>, $<A2, S>, $<A3, S>, $<A4, S>
] : never
6: T extends [
infer A0, infer A1, infer A2, infer A3, infer A4, infer A5
] ? [
$<A0, S>, $<A1, S>, $<A2, S>, $<A3, S>, $<A4, S>, $<A5, S>
] : never
7: T extends [
infer A0, infer A1, infer A2, infer A3, infer A4, infer A5, infer A6
] ? [
$<A0, S>, $<A1, S>, $<A2, S>, $<A3, S>, $<A4, S>, $<A5, S>, $<A6, S>
] : never
8: T extends [
infer A0, infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, infer A7
] ? [
$<A0, S>, $<A1, S>, $<A2, S>, $<A3, S>, $<A4, S>, $<A5, S>, $<A6, S>, $<A7, S>
] : never
9: T extends [
infer A0, infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, infer A7, infer A8
] ? [
$<A0, S>, $<A1, S>, $<A2, S>, $<A3, S>, $<A4, S>, $<A5, S>, $<A6, S>, $<A7, S>, $<A8, S>
] : never
10: T extends [
infer A0, infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, infer A7, infer A8, infer A9
] ? [
$<A0, S>, $<A1, S>, $<A2, S>, $<A3, S>, $<A4, S>, $<A5, S>, $<A6, S>, $<A7, S>, $<A8, S>, $<A9, S>
] : never
}

View file

@ -1,6 +1 @@
export const sum = (a: number, b: number) => {
if ('development' === process.env.NODE_ENV) {
console.log('boop');
}
return a + b;
};
export * from './environment';

View file

@ -0,0 +1,34 @@
// An event emitter which can be used
// with for of loops
export class IterableEmitter<T> {
// The generation of the emitter
// Used to avoid trying to resolve a promise twice
private generation = 0;
// Set the state
public next = (_: T) => {};
public constructor(private state: T) {}
async *[Symbol.asyncIterator](): AsyncGenerator<T> {
const createPromise = () =>
new Promise<T>(resolve => {
const generation = this.generation;
this.next = (value: T) => {
if (generation !== this.generation) {
throw new Error('Cannot resolve the same generation twice');
}
this.generation++;
resolve(value);
};
});
yield this.state;
while (true) {
yield createPromise();
}
}
}

File diff suppressed because it is too large Load diff