Skip to content

Commit

Permalink
deepclient and minilinsk support nested return
Browse files Browse the repository at this point in the history
  • Loading branch information
ivansglazunov committed Feb 13, 2024
1 parent 386f491 commit 1d4fb80
Show file tree
Hide file tree
Showing 9 changed files with 421 additions and 122 deletions.
115 changes: 63 additions & 52 deletions imports/client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@ export const serializeWhere = (exp: any, env: string = 'links'): any => {
// if this is link
if (env === 'links') {
// if field contain primitive type - string/number
if (type === 'string' || type === 'number') {
if (key === 'relation') {
setted = result[key] = exp[key];
} else if (type === 'string' || type === 'number') {
if (key === 'value' || key === type) {
// if field id link.value
setted = result[type] = { value: { _eq: exp[key] } };
Expand All @@ -169,6 +171,11 @@ export const serializeWhere = (exp: any, env: string = 'links'): any => {
// if field is not boolExp (_and _or _not) but contain array
// @ts-ignore
setted = result[key] = serializeWhere(pathToWhere(...exp[key]));
} else if (key === 'return') {
setted = result[key] = {};
for (let r in exp[key]) {
result[key][r] = serializeWhere(exp[key][r], env);
}
}
} else if (env === 'tree') {
// if field contain primitive type - string/number
Expand Down Expand Up @@ -283,6 +290,8 @@ export interface Observer<T> {
};

export interface DeepClientOptions<L extends Link<Id> = Link<Id>> {
needConnection?: boolean;

linkId?: Id;
token?: string;
handleAuth?: (linkId?: Id, token?: string) => any;
Expand Down Expand Up @@ -548,65 +557,67 @@ export class DeepClient<L extends Link<Id> = Link<Id>> implements DeepClientInst
}

constructor(options: DeepClientOptions<L>) {
this.deep = options?.deep;
this.apolloClient = options?.apolloClient;
this.token = options?.token;

if (this.deep && !this.apolloClient) {
const token = this.token ?? this.deep.token;
if (!token) {
throw new Error('token for apolloClient is invalid or not provided');
if (options?.needConnection != false) {
this.deep = options?.deep;
this.apolloClient = options?.apolloClient;
this.token = options?.token;

if (this.deep && !this.apolloClient) {
const token = this.token ?? this.deep.token;
if (!token) {
throw new Error('token for apolloClient is invalid or not provided');
}
this.apolloClient = generateApolloClient({
// @ts-ignore
path: this.deep.apolloClient?.path,
// @ts-ignore
ssl: this.deep.apolloClient?.ssl,
token: token,
});
}
this.apolloClient = generateApolloClient({
// @ts-ignore
path: this.deep.apolloClient?.path,
// @ts-ignore
ssl: this.deep.apolloClient?.ssl,
token: token,
});
}

if (!this.apolloClient) throw new Error('apolloClient is invalid or not provided');
if (!this.apolloClient) throw new Error('apolloClient is invalid or not provided');

this.client = this.apolloClient;
this.client = this.apolloClient;

// @ts-ignore
this.minilinks = options.minilinks || new MinilinkCollection();
this.table = options.table || 'links';

if (this.token) {
const decoded = parseJwt(this.token);
const linkId = decoded?.userId;
if (!linkId){
throw new Error(`Unable to parse linkId from jwt token.`);
}
if (options.linkId && options.linkId !== linkId){
throw new Error(`linkId (${linkId}) parsed from jwt token is not the same as linkId passed via options (${options.linkId}).`);
this.table = options.table || 'links';

if (this.token) {
const decoded = parseJwt(this.token);
const linkId = decoded?.userId;
if (!linkId){
throw new Error(`Unable to parse linkId from jwt token.`);
}
if (options.linkId && options.linkId !== linkId){
throw new Error(`linkId (${linkId}) parsed from jwt token is not the same as linkId passed via options (${options.linkId}).`);
}
this.linkId = linkId;
} else {
this.linkId = options.linkId;
}
this.linkId = linkId;
} else {
this.linkId = options.linkId;
}

this.handleAuth = options?.handleAuth || options?.deep?.handleAuth;
this.linksSelectReturning = options.linksSelectReturning || options.selectReturning || 'id type_id from_id to_id value';
this.selectReturning = options.selectReturning || this.linksSelectReturning;
this.valuesSelectReturning = options.valuesSelectReturning || 'id link_id value';
this.selectorsSelectReturning = options.selectorsSelectReturning ||'item_id selector_id';
this.filesSelectReturning = options.filesSelectReturning ||'id link_id name mimeType';
this.insertReturning = options.insertReturning || 'id';
this.updateReturning = options.updateReturning || 'id';
this.deleteReturning = options.deleteReturning || 'id';

this.defaultSelectName = options.defaultSelectName || 'SELECT';
this.defaultInsertName = options.defaultInsertName || 'INSERT';
this.defaultUpdateName = options.defaultUpdateName || 'UPDATE';
this.defaultDeleteName = options.defaultDeleteName || 'DELETE';

this.silent = options.silent || false;

this.linksSelectReturning = options.linksSelectReturning || options.selectReturning || 'id type_id from_id to_id value';
this.selectReturning = options.selectReturning || this.linksSelectReturning;
this.valuesSelectReturning = options.valuesSelectReturning || 'id link_id value';
this.selectorsSelectReturning = options.selectorsSelectReturning ||'item_id selector_id';
this.filesSelectReturning = options.filesSelectReturning ||'id link_id name mimeType';
this.insertReturning = options.insertReturning || 'id';
this.updateReturning = options.updateReturning || 'id';
this.deleteReturning = options.deleteReturning || 'id';

this.defaultSelectName = options.defaultSelectName || 'SELECT';
this.defaultInsertName = options.defaultInsertName || 'INSERT';
this.defaultUpdateName = options.defaultUpdateName || 'UPDATE';
this.defaultDeleteName = options.defaultDeleteName || 'DELETE';

this.silent = options.silent || false;
this.unsafe = options.unsafe || {};
}

this.unsafe = options.unsafe || {};
this.handleAuth = options?.handleAuth || options?.deep?.handleAuth;
// @ts-ignore
this.minilinks = options.minilinks || new MinilinkCollection();
}

stringify(any?: any): string {
Expand Down
7 changes: 7 additions & 0 deletions imports/client_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@ import { Id } from "./minilinks";

export type Query = BoolExpLink | number;

export type LinkToLinksRelations = 'from' | 'to' | 'type' | 'in' | 'out' | 'typed';

export interface QueryLink extends BoolExpLink {
limit?: number;
order_by?: { [key: string]: 'asc'|'desc' };
offset?: number;
distinct_on?: [string];
return?: QueryLinkReturn;
}

export interface QueryLinkReturn extends QueryLink {
relation: LinkToLinksRelations;
}

export interface BoolExp<T> {
Expand Down
176 changes: 168 additions & 8 deletions imports/cyber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import {
DeepClient, DeepClientAuthResult, DeepClientGuestOptions, DeepClientInstance,
DeepClientJWTOptions, Exp, GUEST, InsertObjects, JWT, ReadOptions, UpdateValue, WHOISME, WriteOptions,
} from './client.js';
import { CyberClient } from '@cybercongress/cyber-js';
import _m0 from "protobufjs/minimal";

const log = debug.extend('log');
const error = debug.extend('error');
Expand All @@ -34,24 +36,182 @@ corePckg.data.filter(l => !!l.type).forEach((l, i) => {
corePckgIds[l.id] = i+1;
});

export async function generateCyberInDeepClient(options: any): Promise<CyberDeepClient<Link<Id>>> {
return new CyberDeepClient(options);
export interface Models {
[model: string]: {
out: { [field: string]: string };
in: { [model: string]: { [field: string]: true } };
};
};
export const model = (
name: string,
fields: { [field: string]: string },
models: Models = {},
) => {
const th = models[name] = {
out: fields,
in: {},
};
for (const f in fields) {
if (models[fields[f]]) {
models[fields[f]].in[name] = models[fields[f]].in[name] || {};
models[fields[f]].in[name][f] = true;
}
}
for (const m in models) {
for (const f in models[m].out) {
if (models[m].out[f] === name) {
th.in[m] = th.in[m] || {};
th.in[m][f] = true;
}
}
}
};

export interface Schemas {
byType?: { [type: string]: {
from: string;
to: string;
get?: (deep, id) => Promise<any>;
} };
byFrom?: { [type: string]: string[] };
byTo?: { [type: string]: string[] };
}

export const schema = (type, from = '', to = '', schemas: Schemas = {}) => {
if (!schemas.byType) schemas.byType = {};
if (!schemas.byFrom) schemas.byFrom = {};
if (!schemas.byTo) schemas.byTo = {};
schemas.byType[type] = { from, to };
if (from) {
schemas.byFrom[from] = schemas.byFrom[from] || [];
schemas.byFrom[from].push(type);
}
if (to) {
schemas.byTo[to] = schemas.byTo[to] || [];
schemas.byTo[to].push(type);
}
};

// model('account', {});
// model('tx', {
// 'coin_received.receiver': 'account',
// 'coin_spent.spender': 'account',
// 'message.sender': 'account',
// 'transfer.recipient': 'account',
// 'transfer.sender': 'account',
// });
// schema('tx', '', '');
// schema('txReceiver', 'tx', 'account');
// schema('txSender', 'tx', 'account');

export interface CONFIG {
"CYBER_CONGRESS_ADDRESS": string;
"DIVISOR_CYBER_G": number;
"HYDROGEN": string;
"CHAIN_ID": string;
"DENOM_CYBER": string;
"DENOM_LIQUID_TOKEN": string;
"DENOM_CYBER_G": string;
"CYBER_NODE_URL_API": string;
"CYBER_WEBSOCKET_URL": string;
"CYBER_NODE_URL_LCD": string;
"CYBER_INDEX_HTTPS": string;
"CYBER_INDEX_WEBSOCKET": string;
"BECH32_PREFIX_ACC_ADDR_CYBER": string;
"BECH32_PREFIX_ACC_ADDR_CYBERVALOPER": string;
"MEMO_KEPLR": string;
"CYBER_GATEWAY": string;
};

export async function generateCyberDeepClient(options: {
config: CONFIG;
}): Promise<CyberDeepClient<Link<string>>> {
const cyberClient = await CyberClient.connect(options.config.CYBER_NODE_URL_API);
const schemas = {};
const models = {};
model('account', {}, models);
model('tx', {
'coin_received.receiver': 'account',
'coin_spent.spender': 'account',
'message.sender': 'account',
'transfer.recipient': 'account',
'transfer.sender': 'account',
}, models);
schema('tx', '', '', schemas);
schema('txReceiver', 'tx', 'account', schemas);
schema('txSender', 'tx', 'account', schemas);
return new CyberDeepClient({
cyberClient,
config: options.config,
schemas, models,
});
}

export interface CyberDeepClientInstance<L extends Link<Id> = Link<Id>> extends DeepClientInstance<L> {
}

export class CyberDeepClient<L extends Link<Id> = Link<Id>> extends DeepClient<L> implements CyberDeepClientInstance<L> {
export interface CyberDeepClientOptions<L extends Link<Id>> extends DeepClientOptions<L> {
cyberClient: CyberClient;
config: CONFIG;

schemas?: Schemas;
models?: Models;
}

export class CyberDeepClient<L extends Link<string> = Link<string>> extends DeepClient<L> implements CyberDeepClientInstance<L> {
static resolveDependency?: (path: string) => Promise<any>

cyberClient: CyberClient;
config: CONFIG;

accountPrefix: string;

_byId: { [id: string]: any } = {};

schemas: Schemas;
models: Models;

// @ts-ignore
constructor(options: DeepClientOptions<L>) {
super(options);
constructor(options: CyberDeepClientOptions<L>) {
super({
apolloClient: generateApolloClient({
path: options.config.CYBER_INDEX_HTTPS.slice(8),
ssl: true,
token: ''
}),
});
this.cyberClient = options.cyberClient;
this.config = options.config;

this.accountPrefix = this.config.BECH32_PREFIX_ACC_ADDR_CYBER;
this.schemas = options.schemas;
this.models = options.models;
}

async select<TTable extends 'links'|'numbers'|'strings'|'objects'|'can'|'selectors'|'tree'|'handlers', LL = L>(exp: Exp<TTable>, options?: ReadOptions<TTable>): Promise<DeepClientResult<LL[]>> {
throw new Error('not implemented');
};
// async select<TTable extends 'links'|'numbers'|'strings'|'objects'|'can'|'selectors'|'tree'|'handlers', LL = L>(exp: Exp<TTable>, options?: ReadOptions<TTable>): Promise<DeepClientResult<LL[]>> {
// let q = {};
// if (typeof(exp) === 'string') {
// if (exp.slice(0, this.accountPrefix.length) === this.accountPrefix) {
// return {
// data: [{ id: exp, type_id: 'account' } as LL],
// loading: false,
// networkStatus: 7,
// };
// }
// } else if (typeof(exp) === 'number') {
// throw new Error('not implemented');
// } else q = exp;
// const level = async (prev, exp) => {
// if (!exp.type_id) {
// throw new Error('!type_id');
// }
// if (exp.to_id && exp.type_id === 'tx') {
// await this.cyberClient.getTx(exp.to_id);
// }
// };
// await level(undefined, exp);
// throw new Error('not implemented');
// };

/**
* deep.subscribe
Expand Down
Loading

0 comments on commit 1d4fb80

Please sign in to comment.