Projects are bootstrapped with templates, and so before we can talk about evolving project boilerplate, we have to first talk about how templates work.
We can represent the rendering of a template T
into an artifact a
with the equation
a = T(v)
import { createStream } from 'effection'; | |
// create an effection stream out of an array of promises | |
// https://frontside.com/effection/docs/guides/collections | |
export function producer(promises) { | |
return createStream(publish => { | |
for (let promise of promises) { | |
promise.then(publish); | |
} | |
}); |
const { once, spawn, main, on, createChannel } = require('effection'); | |
const { Worker } = require('worker_threads'); | |
main(function* () { | |
const worker1 = yield createWorker('./worker1.js'); | |
const worker2 = yield createWorker('./worker2.js'); | |
yield spawn(function*() { | |
const interval = setInterval(() => { | |
worker2.worker.postMessage({ t: 'getValue' }); // ticker |
/** | |
* Implements an operation to fetch the data as described in https://twitter.com/BenLesh/status/1455597411385098242 | |
* The "winner" is unambiguous. It is the request corresponding to the latest click, guaranteed. | |
* Other important things to note: | |
* | |
* 1. The HTTP request is cancelled every time along with its containing task | |
* 2. click listener is removed automatically at the end of the `clickToLoad` operation | |
* 3. The cancellation logic is explicit here to demonstrate the concept, but it can easily be abstracted into a separate | |
*. function. See the `click-to-load-HOF` example below | |
*/ |
import { Vertex } from '@frontside/graphgen'; | |
export interface PageArgs { | |
first?: number; | |
before?: string; | |
last?: number; | |
after: string; | |
} | |
export interface PageInfo { |
import { createQueue, main, on, Operation, Resource } from 'effection'; | |
import { daemon, exec, Process } from '@effection/process'; | |
import { watch } from 'chokidar'; | |
main(function*() { | |
let watcher = watch('./src/**/*.ts', { ignoreInitial: true, ignored: 'dist' }); | |
try { | |
let build = yield createSpawnPoint(start); |
// pause | |
// -- suspend at the next point | |
// play | |
// -- unsuspend and you are now free to do | |
// step | |
// -- unspend, but suspend at the next point | |
import { main } from './main'; | |
import { once, Operation } from 'effection'; | |
import { EventEmitter } from 'events'; |
Projects are bootstrapped with templates, and so before we can talk about evolving project boilerplate, we have to first talk about how templates work.
We can represent the rendering of a template T
into an artifact a
with the equation
a = T(v)
import { Task, Operation } from 'effection'; | |
interface SupervisorOptions { | |
maxConcurrency?: number; | |
dropMostRecent?: boolean; | |
} | |
const supervisorDefaults = { | |
maxConcurrency: 1, | |
dropMostRecent: true |
export function* map<A>(slice: Slice<Record<string, A>>, operation: (slice: Slice<A>) => Operation<void>): Operation<void> { | |
let contexts = new Map<string,Context>(); | |
function* synchronize(record: Record<string, A>) { | |
let keep = new Set<string>(); | |
for (let key of Object.keys(record)) { | |
if (!contexts.has(key)) { | |
contexts.set(key, yield spawn(operation(slice.slice(key)))) | |
} |
import { Page, TextField, Button, HTML, Heading, including } from '@bigtest/interactor'; | |
import { describe } from '@bigtest/suite/bdd'; //hypothetical bdd syntax entry point | |
import { createUser } from './helpers'; | |
export default describe("login test", function*() { | |
yield createUser("cowboyd", "password"); //=> injects `user` into context | |
yield Page.visit('/sign-in'); | |
yield Heading(including('Sign into app')).exists(); | |
yield describe("with good credentials", function*() { |