Skip to content

Commit 1d4fb80

Browse files
committed
deepclient and minilinsk support nested return
1 parent 386f491 commit 1d4fb80

9 files changed

+421
-122
lines changed

imports/client.tsx

+63-52
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,9 @@ export const serializeWhere = (exp: any, env: string = 'links'): any => {
157157
// if this is link
158158
if (env === 'links') {
159159
// if field contain primitive type - string/number
160-
if (type === 'string' || type === 'number') {
160+
if (key === 'relation') {
161+
setted = result[key] = exp[key];
162+
} else if (type === 'string' || type === 'number') {
161163
if (key === 'value' || key === type) {
162164
// if field id link.value
163165
setted = result[type] = { value: { _eq: exp[key] } };
@@ -169,6 +171,11 @@ export const serializeWhere = (exp: any, env: string = 'links'): any => {
169171
// if field is not boolExp (_and _or _not) but contain array
170172
// @ts-ignore
171173
setted = result[key] = serializeWhere(pathToWhere(...exp[key]));
174+
} else if (key === 'return') {
175+
setted = result[key] = {};
176+
for (let r in exp[key]) {
177+
result[key][r] = serializeWhere(exp[key][r], env);
178+
}
172179
}
173180
} else if (env === 'tree') {
174181
// if field contain primitive type - string/number
@@ -283,6 +290,8 @@ export interface Observer<T> {
283290
};
284291

285292
export interface DeepClientOptions<L extends Link<Id> = Link<Id>> {
293+
needConnection?: boolean;
294+
286295
linkId?: Id;
287296
token?: string;
288297
handleAuth?: (linkId?: Id, token?: string) => any;
@@ -548,65 +557,67 @@ export class DeepClient<L extends Link<Id> = Link<Id>> implements DeepClientInst
548557
}
549558

550559
constructor(options: DeepClientOptions<L>) {
551-
this.deep = options?.deep;
552-
this.apolloClient = options?.apolloClient;
553-
this.token = options?.token;
554-
555-
if (this.deep && !this.apolloClient) {
556-
const token = this.token ?? this.deep.token;
557-
if (!token) {
558-
throw new Error('token for apolloClient is invalid or not provided');
560+
if (options?.needConnection != false) {
561+
this.deep = options?.deep;
562+
this.apolloClient = options?.apolloClient;
563+
this.token = options?.token;
564+
565+
if (this.deep && !this.apolloClient) {
566+
const token = this.token ?? this.deep.token;
567+
if (!token) {
568+
throw new Error('token for apolloClient is invalid or not provided');
569+
}
570+
this.apolloClient = generateApolloClient({
571+
// @ts-ignore
572+
path: this.deep.apolloClient?.path,
573+
// @ts-ignore
574+
ssl: this.deep.apolloClient?.ssl,
575+
token: token,
576+
});
559577
}
560-
this.apolloClient = generateApolloClient({
561-
// @ts-ignore
562-
path: this.deep.apolloClient?.path,
563-
// @ts-ignore
564-
ssl: this.deep.apolloClient?.ssl,
565-
token: token,
566-
});
567-
}
568578

569-
if (!this.apolloClient) throw new Error('apolloClient is invalid or not provided');
579+
if (!this.apolloClient) throw new Error('apolloClient is invalid or not provided');
570580

571-
this.client = this.apolloClient;
581+
this.client = this.apolloClient;
572582

573-
// @ts-ignore
574-
this.minilinks = options.minilinks || new MinilinkCollection();
575-
this.table = options.table || 'links';
576-
577-
if (this.token) {
578-
const decoded = parseJwt(this.token);
579-
const linkId = decoded?.userId;
580-
if (!linkId){
581-
throw new Error(`Unable to parse linkId from jwt token.`);
582-
}
583-
if (options.linkId && options.linkId !== linkId){
584-
throw new Error(`linkId (${linkId}) parsed from jwt token is not the same as linkId passed via options (${options.linkId}).`);
583+
this.table = options.table || 'links';
584+
585+
if (this.token) {
586+
const decoded = parseJwt(this.token);
587+
const linkId = decoded?.userId;
588+
if (!linkId){
589+
throw new Error(`Unable to parse linkId from jwt token.`);
590+
}
591+
if (options.linkId && options.linkId !== linkId){
592+
throw new Error(`linkId (${linkId}) parsed from jwt token is not the same as linkId passed via options (${options.linkId}).`);
593+
}
594+
this.linkId = linkId;
595+
} else {
596+
this.linkId = options.linkId;
585597
}
586-
this.linkId = linkId;
587-
} else {
588-
this.linkId = options.linkId;
589-
}
590598

591-
this.handleAuth = options?.handleAuth || options?.deep?.handleAuth;
599+
this.linksSelectReturning = options.linksSelectReturning || options.selectReturning || 'id type_id from_id to_id value';
600+
this.selectReturning = options.selectReturning || this.linksSelectReturning;
601+
this.valuesSelectReturning = options.valuesSelectReturning || 'id link_id value';
602+
this.selectorsSelectReturning = options.selectorsSelectReturning ||'item_id selector_id';
603+
this.filesSelectReturning = options.filesSelectReturning ||'id link_id name mimeType';
604+
this.insertReturning = options.insertReturning || 'id';
605+
this.updateReturning = options.updateReturning || 'id';
606+
this.deleteReturning = options.deleteReturning || 'id';
607+
608+
this.defaultSelectName = options.defaultSelectName || 'SELECT';
609+
this.defaultInsertName = options.defaultInsertName || 'INSERT';
610+
this.defaultUpdateName = options.defaultUpdateName || 'UPDATE';
611+
this.defaultDeleteName = options.defaultDeleteName || 'DELETE';
612+
613+
this.silent = options.silent || false;
592614

593-
this.linksSelectReturning = options.linksSelectReturning || options.selectReturning || 'id type_id from_id to_id value';
594-
this.selectReturning = options.selectReturning || this.linksSelectReturning;
595-
this.valuesSelectReturning = options.valuesSelectReturning || 'id link_id value';
596-
this.selectorsSelectReturning = options.selectorsSelectReturning ||'item_id selector_id';
597-
this.filesSelectReturning = options.filesSelectReturning ||'id link_id name mimeType';
598-
this.insertReturning = options.insertReturning || 'id';
599-
this.updateReturning = options.updateReturning || 'id';
600-
this.deleteReturning = options.deleteReturning || 'id';
601-
602-
this.defaultSelectName = options.defaultSelectName || 'SELECT';
603-
this.defaultInsertName = options.defaultInsertName || 'INSERT';
604-
this.defaultUpdateName = options.defaultUpdateName || 'UPDATE';
605-
this.defaultDeleteName = options.defaultDeleteName || 'DELETE';
606-
607-
this.silent = options.silent || false;
615+
this.unsafe = options.unsafe || {};
616+
}
608617

609-
this.unsafe = options.unsafe || {};
618+
this.handleAuth = options?.handleAuth || options?.deep?.handleAuth;
619+
// @ts-ignore
620+
this.minilinks = options.minilinks || new MinilinkCollection();
610621
}
611622

612623
stringify(any?: any): string {

imports/client_types.ts

+7
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@ import { Id } from "./minilinks";
22

33
export type Query = BoolExpLink | number;
44

5+
export type LinkToLinksRelations = 'from' | 'to' | 'type' | 'in' | 'out' | 'typed';
6+
57
export interface QueryLink extends BoolExpLink {
68
limit?: number;
79
order_by?: { [key: string]: 'asc'|'desc' };
810
offset?: number;
911
distinct_on?: [string];
12+
return?: QueryLinkReturn;
13+
}
14+
15+
export interface QueryLinkReturn extends QueryLink {
16+
relation: LinkToLinksRelations;
1017
}
1118

1219
export interface BoolExp<T> {

imports/cyber.tsx

+168-8
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import {
2525
DeepClient, DeepClientAuthResult, DeepClientGuestOptions, DeepClientInstance,
2626
DeepClientJWTOptions, Exp, GUEST, InsertObjects, JWT, ReadOptions, UpdateValue, WHOISME, WriteOptions,
2727
} from './client.js';
28+
import { CyberClient } from '@cybercongress/cyber-js';
29+
import _m0 from "protobufjs/minimal";
2830

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

37-
export async function generateCyberInDeepClient(options: any): Promise<CyberDeepClient<Link<Id>>> {
38-
return new CyberDeepClient(options);
39+
export interface Models {
40+
[model: string]: {
41+
out: { [field: string]: string };
42+
in: { [model: string]: { [field: string]: true } };
43+
};
44+
};
45+
export const model = (
46+
name: string,
47+
fields: { [field: string]: string },
48+
models: Models = {},
49+
) => {
50+
const th = models[name] = {
51+
out: fields,
52+
in: {},
53+
};
54+
for (const f in fields) {
55+
if (models[fields[f]]) {
56+
models[fields[f]].in[name] = models[fields[f]].in[name] || {};
57+
models[fields[f]].in[name][f] = true;
58+
}
59+
}
60+
for (const m in models) {
61+
for (const f in models[m].out) {
62+
if (models[m].out[f] === name) {
63+
th.in[m] = th.in[m] || {};
64+
th.in[m][f] = true;
65+
}
66+
}
67+
}
68+
};
69+
70+
export interface Schemas {
71+
byType?: { [type: string]: {
72+
from: string;
73+
to: string;
74+
get?: (deep, id) => Promise<any>;
75+
} };
76+
byFrom?: { [type: string]: string[] };
77+
byTo?: { [type: string]: string[] };
78+
}
79+
80+
export const schema = (type, from = '', to = '', schemas: Schemas = {}) => {
81+
if (!schemas.byType) schemas.byType = {};
82+
if (!schemas.byFrom) schemas.byFrom = {};
83+
if (!schemas.byTo) schemas.byTo = {};
84+
schemas.byType[type] = { from, to };
85+
if (from) {
86+
schemas.byFrom[from] = schemas.byFrom[from] || [];
87+
schemas.byFrom[from].push(type);
88+
}
89+
if (to) {
90+
schemas.byTo[to] = schemas.byTo[to] || [];
91+
schemas.byTo[to].push(type);
92+
}
93+
};
94+
95+
// model('account', {});
96+
// model('tx', {
97+
// 'coin_received.receiver': 'account',
98+
// 'coin_spent.spender': 'account',
99+
// 'message.sender': 'account',
100+
// 'transfer.recipient': 'account',
101+
// 'transfer.sender': 'account',
102+
// });
103+
// schema('tx', '', '');
104+
// schema('txReceiver', 'tx', 'account');
105+
// schema('txSender', 'tx', 'account');
106+
107+
export interface CONFIG {
108+
"CYBER_CONGRESS_ADDRESS": string;
109+
"DIVISOR_CYBER_G": number;
110+
"HYDROGEN": string;
111+
"CHAIN_ID": string;
112+
"DENOM_CYBER": string;
113+
"DENOM_LIQUID_TOKEN": string;
114+
"DENOM_CYBER_G": string;
115+
"CYBER_NODE_URL_API": string;
116+
"CYBER_WEBSOCKET_URL": string;
117+
"CYBER_NODE_URL_LCD": string;
118+
"CYBER_INDEX_HTTPS": string;
119+
"CYBER_INDEX_WEBSOCKET": string;
120+
"BECH32_PREFIX_ACC_ADDR_CYBER": string;
121+
"BECH32_PREFIX_ACC_ADDR_CYBERVALOPER": string;
122+
"MEMO_KEPLR": string;
123+
"CYBER_GATEWAY": string;
124+
};
125+
126+
export async function generateCyberDeepClient(options: {
127+
config: CONFIG;
128+
}): Promise<CyberDeepClient<Link<string>>> {
129+
const cyberClient = await CyberClient.connect(options.config.CYBER_NODE_URL_API);
130+
const schemas = {};
131+
const models = {};
132+
model('account', {}, models);
133+
model('tx', {
134+
'coin_received.receiver': 'account',
135+
'coin_spent.spender': 'account',
136+
'message.sender': 'account',
137+
'transfer.recipient': 'account',
138+
'transfer.sender': 'account',
139+
}, models);
140+
schema('tx', '', '', schemas);
141+
schema('txReceiver', 'tx', 'account', schemas);
142+
schema('txSender', 'tx', 'account', schemas);
143+
return new CyberDeepClient({
144+
cyberClient,
145+
config: options.config,
146+
schemas, models,
147+
});
39148
}
40149

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

44-
export class CyberDeepClient<L extends Link<Id> = Link<Id>> extends DeepClient<L> implements CyberDeepClientInstance<L> {
153+
export interface CyberDeepClientOptions<L extends Link<Id>> extends DeepClientOptions<L> {
154+
cyberClient: CyberClient;
155+
config: CONFIG;
156+
157+
schemas?: Schemas;
158+
models?: Models;
159+
}
160+
161+
export class CyberDeepClient<L extends Link<string> = Link<string>> extends DeepClient<L> implements CyberDeepClientInstance<L> {
45162
static resolveDependency?: (path: string) => Promise<any>
46163

164+
cyberClient: CyberClient;
165+
config: CONFIG;
166+
167+
accountPrefix: string;
168+
169+
_byId: { [id: string]: any } = {};
170+
171+
schemas: Schemas;
172+
models: Models;
173+
47174
// @ts-ignore
48-
constructor(options: DeepClientOptions<L>) {
49-
super(options);
175+
constructor(options: CyberDeepClientOptions<L>) {
176+
super({
177+
apolloClient: generateApolloClient({
178+
path: options.config.CYBER_INDEX_HTTPS.slice(8),
179+
ssl: true,
180+
token: ''
181+
}),
182+
});
183+
this.cyberClient = options.cyberClient;
184+
this.config = options.config;
185+
186+
this.accountPrefix = this.config.BECH32_PREFIX_ACC_ADDR_CYBER;
187+
this.schemas = options.schemas;
188+
this.models = options.models;
50189
}
51190

52-
async select<TTable extends 'links'|'numbers'|'strings'|'objects'|'can'|'selectors'|'tree'|'handlers', LL = L>(exp: Exp<TTable>, options?: ReadOptions<TTable>): Promise<DeepClientResult<LL[]>> {
53-
throw new Error('not implemented');
54-
};
191+
// async select<TTable extends 'links'|'numbers'|'strings'|'objects'|'can'|'selectors'|'tree'|'handlers', LL = L>(exp: Exp<TTable>, options?: ReadOptions<TTable>): Promise<DeepClientResult<LL[]>> {
192+
// let q = {};
193+
// if (typeof(exp) === 'string') {
194+
// if (exp.slice(0, this.accountPrefix.length) === this.accountPrefix) {
195+
// return {
196+
// data: [{ id: exp, type_id: 'account' } as LL],
197+
// loading: false,
198+
// networkStatus: 7,
199+
// };
200+
// }
201+
// } else if (typeof(exp) === 'number') {
202+
// throw new Error('not implemented');
203+
// } else q = exp;
204+
// const level = async (prev, exp) => {
205+
// if (!exp.type_id) {
206+
// throw new Error('!type_id');
207+
// }
208+
// if (exp.to_id && exp.type_id === 'tx') {
209+
// await this.cyberClient.getTx(exp.to_id);
210+
// }
211+
// };
212+
// await level(undefined, exp);
213+
// throw new Error('not implemented');
214+
// };
55215

56216
/**
57217
* deep.subscribe

0 commit comments

Comments
 (0)