Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document ORM API #18

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
28 changes: 28 additions & 0 deletions debug.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { initWebAssembly, Session, KeyPair } from './lib/node/index.cjs';

const ENDPOINT = 'http://127.0.0.1:2020/graphql';
const SCHEMA_ID =
'chat_002009a6721c3015eb87a7b941e5d54183b7bd209c72dec05af234ede47dd4772f35';

async function run() {
await initWebAssembly();

const keyPair = new KeyPair();
const session = new Session(ENDPOINT).setKeyPair(keyPair);

const Chat = session.addSchema(SCHEMA_ID);

const message = await Chat.create({
message: '1',
});

await message.update({
message: '2',
});

await message.update({
message: '3',
});
}

run();
25 changes: 25 additions & 0 deletions src/cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: AGPL-3.0-or-later

export class Cache<T> {
private storage: { [key: string]: T };

constructor() {
this.storage = {};
}

insert(key: string, value: T) {
this.storage[key] = value;
}

get(key: string): T | null {
if (key in this.storage) {
return this.storage[key];
}

return null;
}

remove(key: string) {
delete this.storage[key];
}
}
21 changes: 21 additions & 0 deletions src/collection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: AGPL-3.0-or-later

import { Document } from './document';

import type { DocumentFields } from './types';

export class Collection extends Array {
#documents: Document[];

constructor(documents: Document[], values: DocumentFields[]) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
super(...values);

this.#documents = documents;
}

getDocuments(): Document[] {
return this.#documents;
}
}
107 changes: 107 additions & 0 deletions src/document.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// SPDX-License-Identifier: AGPL-3.0-or-later

import { Session } from './session';
import { marshallFields } from './utils';

import type {
DocumentFields,
DocumentId,
DocumentValue,
DocumentViewId,
SchemaFields,
SchemaId,
} from './types';

export class Document {
#session: Session;

#fields: DocumentFields;

#schemaFields: SchemaFields;

readonly schemaId: SchemaId;

readonly documentId: DocumentId;

viewId: DocumentViewId;

constructor(
args: {
fields: DocumentFields;
schemaId: SchemaId;
schemaFields: SchemaFields;
documentId: DocumentId;
viewId: DocumentViewId;
},
session: Session,
) {
const { fields, schemaId, schemaFields, documentId, viewId } = args;

this.#session = session;

this.#fields = fields;
this.#schemaFields = schemaFields;

this.schemaId = schemaId;
this.documentId = documentId;
this.viewId = viewId;

return new Proxy(this, {
get(target, prop, receiver) {
if (Object.keys(fields).includes(prop as string) && !(prop in target)) {
return target.get.apply(target, [prop as string]);
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const value = target[prop];
if (value instanceof Function) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return function (...args) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return value.apply(this === receiver ? target : this, args);
};
}

return value;
},
});
}

get(name: string): DocumentValue {
if (!(name in this.#fields)) {
throw new Error(`'${name}' field not given in document`);
}

return this.#fields[name];
}

async update(fields: DocumentFields): Promise<DocumentViewId> {
const operationFields = marshallFields(fields, this.#schemaFields);

const viewId = await this.#session.update(operationFields, this.viewId, {
schemaId: this.schemaId,
documentId: this.documentId,
});

Object.keys(fields).forEach((fieldName) => {
this.#fields[fieldName] = fields[fieldName];
});

this.viewId = viewId;

return viewId;
}

async delete(): Promise<DocumentViewId> {
const viewId = await this.#session.delete(this.viewId, {
schemaId: this.schemaId,
documentId: this.documentId,
});

this.viewId = viewId;
return viewId;
}
}
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

import { KeyPair, initWebAssembly } from 'p2panda-js';

import { FieldType } from './schema';
import { Session } from './session';

export { Session, KeyPair, initWebAssembly };
export { Session, KeyPair, initWebAssembly, FieldType };

export type { Options } from './session';
export type { SchemaId, NextArgs, DocumentViewId, Fields } from './types';
Loading