Skip to content

Commit

Permalink
Merge pull request #1 from Picolab/dependency-updates
Browse files Browse the repository at this point in the history
Dependency Updates
  • Loading branch information
farskipper authored Nov 12, 2023
2 parents bd490bd + 4f2111e commit 6d702b0
Show file tree
Hide file tree
Showing 20 changed files with 143 additions and 153 deletions.
21 changes: 9 additions & 12 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
name: Test

on: push

on: [push, pull_request]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
node-version:
- lts/* # LTS version
- "17" # latest version
node:
- lts/*
- current
os: [ubuntu-latest, macOS-latest, windows-latest]

steps:
- uses: actions/checkout@v2
- name: Node ${{ matrix.node-version }}
uses: actions/setup-node@v2
- uses: actions/checkout@v3
- name: Node ${{ matrix.node }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}

- run: npm i
node-version: ${{ matrix.node }}
- run: npm install
- run: npm test
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# pico-framework

[![Build Status](https://github.com/Picolab/pico-framework/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/Picolab/pico-framework/actions/workflows/test.yml)

A framework for building actor-based, people-centric systems. (pico = PersIstent Compute Objects)

## Why Picos?
Expand All @@ -19,7 +21,7 @@ It handles the building blocks of a Pico based system.
- Rulesets
- What the ruleset code is allowed to do to a pico i.e. sandboxing

The pico-framework also handles persistence of the pico objects. You can provided the persistance layer via an implementation of [abstract-leveldown](https://github.com/Level/abstract-leveldown)
The pico-framework also handles persistence of the pico objects. You simply provide the persistence layer via an implementation of [abstract-level](https://github.com/Level/abstract-level).

## Contributing

Expand Down
23 changes: 10 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,25 @@
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
"scripts": {
"prepublish": "npm run build",
"prepare": "npm run build",
"build": "rm -rf dist && tsc",
"test": "nyc ava"
"test": "ava reset-cache && nyc ava"
},
"dependencies": {
"charwise": "^3.0.1",
"abstract-level": "^1.0.3",
"cuid": "^2.1.8",
"encoding-down": "^6.3.0",
"level-json-coerce-null": "^1.0.1",
"levelup": "^4.4.0",
"lodash": "^4.17.19",
"memdown": "^5.1.0",
"select-when": "^0.1.4"
"select-when": "^0.1.9"
},
"devDependencies": {
"@types/abstract-leveldown": "^5.0.1",
"@types/levelup": "^4.3.0",
"@types/lodash": "^4.14.157",
"ava": "^4.0.0",
"@types/lodash": "^4.14.201",
"ava": "^5.3.1",
"charwise": "^3.0.1",
"level-json-coerce-null": "^1.0.1",
"memory-level": "^1.0.0",
"nyc": "^15.1.0",
"ts-node": "^10.4.0",
"typescript": "^4.5.4"
"typescript": "^5.2.2"
},
"ava": {
"extensions": [
Expand Down
25 changes: 14 additions & 11 deletions src/Pico.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,17 @@ export class Pico {

private queue: PicoQueue;

constructor(private pf: PicoFramework, id: string) {
constructor(
private pf: PicoFramework,
id: string,
) {
this.id = id;
this.channels[id] = new Channel(this, id, { tags: ["system", "self"] }, id);

this.queue = new PicoQueue(
this.id,
this.doTxn.bind(this),
(ev: PicoFrameworkEvent) => this.pf.emit(ev)
(ev: PicoFrameworkEvent) => this.pf.emit(ev),
);
}

Expand Down Expand Up @@ -152,13 +155,13 @@ export class Pico {
const child = new Pico(this.pf, this.pf.genID());
const parentChannel = this.newChannelBase(
{ tags: ["system", "parent"] },
child.id
child.id,
);
child.parent = parentChannel.id;

const childChannel = child.newChannelBase(
{ tags: ["system", "child"] },
this.id
this.id,
);
child.channels[childChannel.id] = childChannel;
this.children.push(childChannel.id);
Expand Down Expand Up @@ -304,7 +307,7 @@ export class Pico {

async newChannel(
conf?: ChannelConfig,
familyChannelPicoID?: string
familyChannelPicoID?: string,
): Promise<Channel> {
const chann = this.newChannelBase(conf, familyChannelPicoID);
await this.pf.db.batch([chann.toDbPut()]);
Expand All @@ -314,7 +317,7 @@ export class Pico {

private newChannelBase(
conf?: ChannelConfig,
familyChannelPicoID?: string
familyChannelPicoID?: string,
): Channel {
const chann = new Channel(this, this.pf.genID(), conf, familyChannelPicoID);
return chann;
Expand Down Expand Up @@ -364,7 +367,7 @@ export class Pico {

private async installBase(
rs: Ruleset,
config: RulesetConfig = {}
config: RulesetConfig = {},
): Promise<{ instance: RulesetInstance; dbPut: LevelBatch }> {
// even if we already have that rid installed, we need to init again
// b/c the configuration may have changed
Expand Down Expand Up @@ -403,7 +406,7 @@ export class Pico {
key: data.key,
};
return delEnt;
}
},
);
ops.push({
type: "del",
Expand Down Expand Up @@ -454,7 +457,7 @@ export class Pico {
domain: string,
name: string,
attrs: PicoEventPayload["attrs"],
forRid?: string
forRid?: string,
) {
const event = cleanEvent({
eci: (this.current && this.current.event.eci) || "[raise]",
Expand Down Expand Up @@ -515,7 +518,7 @@ export class Pico {
// must process one event at a time to maintain the pico's single-threaded guarantee
const response = await rs.instance.event(
this.current.event,
eid
eid,
);
responses.push(response);
}
Expand All @@ -532,7 +535,7 @@ export class Pico {
const qfn = rs?.instance?.query && rs.instance.query[txn.query.name];
if (!qfn) {
throw new Error(
`Ruleset ${txn.query.rid} does not have query function "${txn.query.name}"`
`Ruleset ${txn.query.rid} does not have query function "${txn.query.name}"`,
);
}
const data = await qfn(txn.query, txn.id);
Expand Down
26 changes: 7 additions & 19 deletions src/PicoFramework.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
import { AbstractLevelDOWN } from "abstract-leveldown";
import * as cuid from "cuid";
import { default as level, LevelUp } from "levelup";
import { PicoDb } from "./utils";
import { Channel } from "./Channel";
import { dbRange } from "./dbRange";
import { Pico } from "./Pico";
import { cleanEvent, PicoEvent } from "./PicoEvent";
import { PicoFrameworkEvent } from "./PicoFrameworkEvent";
import { cleanQuery, PicoQuery } from "./PicoQuery";
import { Ruleset, RulesetConfig } from "./Ruleset";
const charwise = require("charwise");
const encode = require("encoding-down");
const safeJsonCodec = require("level-json-coerce-null");
const memdown = require("memdown");

export type RulesetLoader = (
picoId: string,
rid: string,
config: RulesetConfig
config: RulesetConfig,
) => Ruleset | Promise<Ruleset>;

type OnFrameworkEvent = (event: PicoFrameworkEvent) => void;
Expand All @@ -26,10 +21,8 @@ export interface PicoFrameworkConf {

/**
* Specify how data should be persisted.
*
* By default it uses memdown
*/
leveldown?: AbstractLevelDOWN;
db: PicoDb;

/**
* Function that is called on a pico framework event
Expand All @@ -55,7 +48,7 @@ export interface PicoFrameworkConf {
}

export class PicoFramework {
db: LevelUp;
db: PicoDb;

private rootPico_?: Pico;
public get rootPico(): Pico {
Expand All @@ -82,12 +75,7 @@ export class PicoFramework {
private onFrameworkEvent?: OnFrameworkEvent;

constructor(conf: PicoFrameworkConf) {
this.db = level(
encode((conf && conf.leveldown) || memdown(), {
keyEncoding: charwise,
valueEncoding: safeJsonCodec,
})
);
this.db = conf.db;
this.rulesetLoader = conf && conf.rulesetLoader;
this.genID = (conf && conf.genID) || cuid;
this.environment = conf && conf.environment;
Expand Down Expand Up @@ -219,7 +207,7 @@ export class PicoFramework {
*/
async eventWait(
event: PicoEvent,
fromPicoId?: string
fromPicoId?: string,
): Promise<{ eid: string; responses: any[] }> {
event = this.cleanEvent(event);

Expand All @@ -239,7 +227,7 @@ export class PicoFramework {
async eventQuery(
event: PicoEvent,
query: PicoQuery,
fromPicoId?: string
fromPicoId?: string,
): Promise<any> {
event = this.cleanEvent(event);
query = cleanQuery(query);
Expand Down
57 changes: 17 additions & 40 deletions src/dbRange.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,21 @@
import { LevelUp } from "levelup";
import * as _ from "lodash";
import { AbstractIteratorOptions } from "abstract-level";
import { PicoDb, PicoDbKey } from "./utils";

export function dbRange<T = any>(
ldb: LevelUp,
opts: any,
onData: (data: any, stop: () => void) => Promise<T> | T
export async function dbRange<T = any>(
db: PicoDb,
opts: { prefix?: PicoDbKey },
onData: (data: any) => Promise<T> | T,
): Promise<T[]> {
return new Promise(function(resolve, reject) {
const promises: Promise<T>[] = [];
const promises: Promise<T>[] = [];

let hasCalledback = false;
function callback(err?: any) {
if (hasCalledback) return;
hasCalledback = true;
if (err) {
return reject(err);
}
Promise.all(promises)
.then(resolve)
.catch(reject);
}

if (_.has(opts, "prefix")) {
opts = _.assign({}, opts, {
gte: opts.prefix,
lte: opts.prefix.concat([undefined]) // bytewise sorts with null at the bottom and undefined at the top
});
delete opts.prefix;
}
const s = ldb.createReadStream(opts);
function stopRange() {
(s as any).destroy();
callback();
}
s.on("error", function(err) {
callback(err);
});
s.on("end", callback);
s.on("data", function(data) {
promises.push(Promise.resolve(onData(data, stopRange)));
});
});
let streamOpts: AbstractIteratorOptions<PicoDbKey, any> = {};
if (opts && Array.isArray(opts.prefix)) {
streamOpts.gte = opts.prefix;
streamOpts.lte = opts.prefix.concat([undefined] as any); // bytewise sorts with null at the bottom and undefined at the top
}
const iter = db.iterator(streamOpts);
for await (const [key, value] of iter) {
promises.push(Promise.resolve(onData({ key, value })));
}
return await Promise.all(promises);
}
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ import {
import { PicoQuery } from "./PicoQuery";
import { Ruleset, RulesetConfig, RulesetInstance } from "./Ruleset";
import { createRulesetContext, RulesetContext } from "./RulesetContext";
import { PicoDb, PicoDbKey } from "./utils";

export {
Pico,
PicoDb,
PicoDbKey,
PicoEvent,
PicoQuery,
PicoReadOnly,
Expand Down
20 changes: 5 additions & 15 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
import { AbstractLevel, AbstractBatchOperation } from "abstract-level";

export function isNotStringOrBlank(val: any) {
return typeof val !== "string" || val.trim().length === 0;
}

/**
* Copied AbstractBatch from "abstract-leveldown"
* b/c typescript module resolution doesn't work very well with lerna (used in pico-engine)
*/
export type LevelBatch = PutBatch | DelBatch;
type LevelKey = (string | number | null | boolean)[];
interface PutBatch {
readonly type: "put";
readonly key: LevelKey;
readonly value: any;
}
interface DelBatch {
readonly type: "del";
readonly key: LevelKey;
}
export type PicoDbKey = (string | number | null | boolean)[];
export type PicoDb = AbstractLevel<any, PicoDbKey, any>;
export type LevelBatch = AbstractBatchOperation<PicoDb, PicoDbKey, any>;
Loading

0 comments on commit 6d702b0

Please sign in to comment.