Skip to content

Commit 243604a

Browse files
committed
clientfirst
1 parent 9c16df6 commit 243604a

3 files changed

Lines changed: 215 additions & 33 deletions

File tree

imports/client.tsx

Lines changed: 125 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ corePckg.data.filter(l => !!l.type).forEach((l, i) => {
2424
corePckgIds[l.id] = i+1;
2525
});
2626

27+
const random = () => Math.random().toString(36).slice(2, 7);
28+
2729
export const _ids = {
2830
'@deep-foundation/core': corePckgIds,
2931
};
@@ -139,9 +141,9 @@ export const pathToWhere = (start: (DeepClientStartItem), ...path: DeepClientPat
139141
return where;
140142
}
141143

142-
export const serializeWhere = (exp: any, env: string = 'links'): any => {
144+
export const serializeWhere = (exp: any, env: string = 'links', unvertualizeId: (id: number) => number = defaultUnvertualizeId): any => {
143145
// if exp is array - map
144-
if (Object.prototype.toString.call(exp) === '[object Array]') return exp.map((e) => serializeWhere(e, env));
146+
if (Object.prototype.toString.call(exp) === '[object Array]') return exp.map((e) => serializeWhere(e, env, unvertualizeId));
145147
else if (typeof(exp) === 'object') {
146148
// if object
147149
const keys = Object.keys(exp);
@@ -162,26 +164,27 @@ export const serializeWhere = (exp: any, env: string = 'links'): any => {
162164
setted = result[type] = { value: { _eq: exp[key] } };
163165
} else {
164166
// else just equal
165-
setted = result[key] = { _eq: exp[key] };
167+
setted = result[key] = { _eq: unvertualizeId(exp[key]) };
166168
}
167169
} else if (!_boolExpFields[key] && Object.prototype.toString.call(exp[key]) === '[object Array]') {
168170
// if field is not boolExp (_and _or _not) but contain array
169171
// @ts-ignore
170-
setted = result[key] = serializeWhere(pathToWhere(...exp[key]));
172+
setted = result[key] = serializeWhere(pathToWhere(...exp[key]), 'links', unvertualizeId);
171173
}
172174
} else if (env === 'tree') {
173175
// if field contain primitive type - string/number
174176
if (type === 'string' || type === 'number') {
175-
setted = result[key] = { _eq: exp[key] };
177+
const isId = key === 'link_id' || key === 'tree_id' || key === 'root_id' || key === 'parent_id';
178+
setted = result[key] = { _eq: isId ? unvertualizeId(exp[key]) : exp[key] };
176179
} else if (!_boolExpFields[key] && Object.prototype.toString.call(exp[key]) === '[object Array]') {
177180
// if field is not boolExp (_and _or _not) but contain array
178181
// @ts-ignore
179-
setted = result[key] = serializeWhere(pathToWhere(...exp[key]));
182+
setted = result[key] = serializeWhere(pathToWhere(...exp[key]), 'links', unvertualizeId);
180183
}
181184
} else if (env === 'value') {
182185
// if this is value
183186
if (type === 'string' || type === 'number') {
184-
setted = result[key] = { _eq: exp[key] };
187+
setted = result[key] = { _eq: key === 'link_id' ? unvertualizeId(exp[key]) : exp[key] };
185188
}
186189
}
187190
if (type === 'object' && exp[key].hasOwnProperty('_type_of') && (
@@ -192,7 +195,7 @@ export const serializeWhere = (exp: any, env: string = 'links'): any => {
192195
(env === 'value' && key === 'link_id')
193196
)) {
194197
// if field is object, and contain _type_od
195-
const _temp = setted = { _by_item: { path_item_id: { _eq: exp[key]._type_of }, group_id: { _eq: 0 } } };
198+
const _temp = setted = { _by_item: { path_item_id: { _eq: unvertualizeId(exp[key]._type_of) }, group_id: { _eq: _ids['@deep-foundation/core'].typesTree } } };
196199
if (key === 'id') {
197200
result._and = result._and ? [...result._and, _temp] : [_temp];
198201
} else {
@@ -205,8 +208,9 @@ export const serializeWhere = (exp: any, env: string = 'links'): any => {
205208
(env === 'tree' && !!~['link_id', 'tree_id', 'root_id', 'parent_id'].indexOf(key)) ||
206209
(env === 'value' && key === 'link_id')
207210
) && Object.prototype.toString.call(exp[key]._id) === '[object Array]' && exp[key]._id.length >= 1) {
208-
// if field is object, and contain _type_od
209-
const _temp = setted = serializeWhere(pathToWhere(exp[key]._id[0], ...exp[key]._id.slice(1)), 'links');
211+
const root = exp[key]._id[0];
212+
// if field is object, and contain _type_of
213+
const _temp = setted = serializeWhere(pathToWhere(typeof(root) === 'number' ? unvertualizeId(root) : root, ...exp[key]._id.slice(1)), 'links', unvertualizeId);
210214
if (key === 'id') {
211215
result._and = result._and ? [...result._and, _temp] : [_temp];
212216
} else {
@@ -220,13 +224,13 @@ export const serializeWhere = (exp: any, env: string = 'links'): any => {
220224
_boolExpFields[key]
221225
) ? (
222226
// just parse each item in array
223-
serializeWhere(exp[key], env)
227+
serializeWhere(exp[key], env, unvertualizeId)
224228
) : (
225229
// if we know context
226230
_serialize?.[env]?.relations?.[key]
227231
) ? (
228232
// go to this context then
229-
serializeWhere(exp[key], _serialize?.[env]?.relations?.[key])
233+
serializeWhere(exp[key], _serialize?.[env]?.relations?.[key], unvertualizeId)
230234
) : (
231235
// else just stop
232236
exp[key]
@@ -242,10 +246,12 @@ export const serializeWhere = (exp: any, env: string = 'links'): any => {
242246
}
243247
};
244248

245-
export const serializeQuery = (exp: any, env: string = 'links'): any => {
249+
const defaultUnvertualizeId = (id) => id;
250+
251+
export const serializeQuery = (exp: any, env: string = 'links', unvertualizeId = defaultUnvertualizeId): any => {
246252
const { limit, order_by, offset, distinct_on, ...where } = exp;
247-
const result: any = { where: typeof(exp) === 'object' ? Object.prototype.toString.call(exp) === '[object Array]' ? { id: { _in: exp } } : serializeWhere(where, env) : { id: { _eq: exp } } };
248-
// const result: any = { where: serializeWhere(where, env) };
253+
const result: any = { where: typeof(exp) === 'object' ? Object.prototype.toString.call(exp) === '[object Array]' ? { id: { _in: exp.map(id => unvertualizeId(id)) } } : serializeWhere(where, env, unvertualizeId) : { id: { _eq: unvertualizeId(exp) } } };
254+
// const result: any = { where: serializeWhere(where, env, unvertualizeId) };
249255
if (limit) result.limit = limit;
250256
if (order_by) result.order_by = order_by;
251257
if (offset) result.offset = offset;
@@ -351,7 +357,8 @@ export interface DeepClientInstance<L = Link<number>> {
351357

352358

353359
serializeWhere(exp: any, env?: string): any;
354-
serializeQuery(exp: any, env?: string): any;
360+
serializeQuery(exp: any, env?: string, unvertualizeId?: (id: number) => number): any;
361+
unvertualizeId(id: number): number;
355362

356363
id(start: DeepClientStartItem | QueryLink, ...path: DeepClientPathItem[]): Promise<number>;
357364
idLocal(start: DeepClientStartItem, ...path: DeepClientPathItem[]): number;
@@ -474,6 +481,69 @@ export function checkAndFillShorts(obj) {
474481
}
475482
}
476483

484+
export function convertDeepInsertToMinilinksApply(deep, objects, table, result: { id?: number; from_id?: number; to_id?: number; type_id?: number; value?: any }[] = []): void {
485+
if (table === 'links') {
486+
for (let i = 0; i < objects.length; i++) {
487+
const o = objects[i];
488+
let id = o.id;
489+
if (!id) {
490+
id = deep.minilinks.virtualCounter--;
491+
// @ts-ignore
492+
deep.minilinks?.byId[id]?._id = apply;
493+
}
494+
result.push({
495+
id: o.id || id, from_id: o.from_id, to_id: o.to_id, type_id: o.type_id,
496+
value: o.string?.data || o.number?.data || o.object?.data,
497+
});
498+
if (o?.from) convertDeepInsertToMinilinksApply(deep, [o?.from?.data], table, result);
499+
if (o?.to) convertDeepInsertToMinilinksApply(deep, [o?.to?.data], table, result);
500+
if (o?.type) convertDeepInsertToMinilinksApply(deep, [o?.type?.data], table, result);
501+
if (o?.out) convertDeepInsertToMinilinksApply(deep, (o?.out?.data?.length ? o?.out?.data : [o?.out?.data]).map(l => ({ ...l, from_id: id })), table, result);
502+
if (o?.in) convertDeepInsertToMinilinksApply(deep, (o?.in?.data?.length ? o?.in?.data : [o?.in?.data]).map(l => ({ ...l, to_id: id })), table, result);
503+
if (o?.types) convertDeepInsertToMinilinksApply(deep, (o?.types?.data?.length ? o?.types?.data : [o?.types?.data]).map(l => ({ ...l, type_id: id })), table, result);
504+
}
505+
}
506+
}
507+
508+
export function convertDeepUpdateToMinilinksApply(ml, _exp, _set, table, toUpdate: { id?: number; from_id?: number; to_id?: number; type_id?: number; value?: any }[] = []): void {
509+
if (table === 'links') {
510+
try {
511+
const founded = ml.query(_exp);
512+
for (let f of founded) {
513+
toUpdate.push({
514+
id: f.id, from_id: f.from_id, to_id: f.to_id, type_id: f.type_id,
515+
value: f.value,
516+
..._set
517+
});
518+
}
519+
} catch(e) {}
520+
} else if (table === 'strings' || table === 'numbers' || table === 'objects') {
521+
const key = table.slice(0, -1);
522+
const founded = ml.query({ [key]: _exp });
523+
for (let f of founded) {
524+
toUpdate.push({
525+
id: f.id, from_id: f.from_id, to_id: f.to_id, type_id: f.type_id,
526+
value: { ...f?.value, value: _set.value },
527+
});
528+
}
529+
}
530+
}
531+
532+
export function convertDeepDeleteToMinilinksApply(ml, _exp, table, toDelete: number[] = [], toUpdate: { id?: number; from_id?: number; to_id?: number; type_id?: number; value?: any }[] = []): void {
533+
if (table === 'links') {
534+
try {
535+
const founded = ml.query(_exp);
536+
toDelete.push(...founded.map(l => l.id));
537+
} catch(e) {}
538+
} else if (table === 'strings' || table === 'numbers' || table === 'objects') {
539+
const key = table.slice(0, -1);
540+
const founded = ml.query({ [key]: _exp });
541+
toUpdate.push(...founded.map(o => ({
542+
id: o.id, from_id: o.from_id, to_id: o.to_id, type_id: o.type_id,
543+
})));
544+
}
545+
}
546+
477547
export class DeepClient<L = Link<number>> implements DeepClientInstance<L> {
478548
static resolveDependency?: (path: string) => Promise<any>
479549

@@ -538,6 +608,10 @@ export class DeepClient<L = Link<number>> implements DeepClientInstance<L> {
538608

539609
// @ts-ignore
540610
this.minilinks = options.minilinks || new MinilinkCollection();
611+
this.unvertualizeId = (id: number): number => {
612+
// @ts-ignore
613+
return this.minilinks.virtual.hasOwnProperty(id) ? this.minilinks.virtual[id] : id;
614+
};
541615
this.table = options.table || 'links';
542616

543617
this.token = options.token;
@@ -589,12 +663,13 @@ export class DeepClient<L = Link<number>> implements DeepClientInstance<L> {
589663

590664
serializeQuery = serializeQuery;
591665
serializeWhere = serializeWhere;
666+
unvertualizeId: (id: number) => number;
592667

593668
async select<TTable extends 'links'|'numbers'|'strings'|'objects'|'can'|'selectors'|'tree'|'handlers', LL = L>(exp: Exp<TTable>, options?: ReadOptions<TTable>): Promise<DeepClientResult<LL[]>> {
594669
if (!exp) {
595670
return { error: { message: '!exp' }, data: undefined, loading: false, networkStatus: undefined };
596671
}
597-
const query = serializeQuery(exp, options?.table || 'links');
672+
const query = serializeQuery(exp, options?.table || 'links', this.unvertualizeId);
598673
const table = options?.table || this.table;
599674
const returning = options?.returning ??
600675
(table === 'links' ? this.linksSelectReturning :
@@ -635,7 +710,13 @@ export class DeepClient<L = Link<number>> implements DeepClientInstance<L> {
635710
const variables = options?.variables;
636711
const name = options?.name || this.defaultInsertName;
637712
let q: any = {};
638-
713+
714+
if (this.minilinks) {
715+
const toApply: any = [];
716+
convertDeepInsertToMinilinksApply(this, _objects, table, toApply);
717+
this.minilinks.add(toApply);
718+
}
719+
639720
try {
640721
q = await this.apolloClient.mutate(generateSerial({
641722
actions: [insertMutation(table, { ...variables, objects: _objects }, { tableName: table, operation: 'insert', returning })],
@@ -646,7 +727,7 @@ export class DeepClient<L = Link<number>> implements DeepClientInstance<L> {
646727
if (sqlError?.message) e.message = sqlError.message;
647728
if (!this._silent(options)) throw new Error(`DeepClient Insert Error: ${e.message}`, { cause: e })
648729
return { ...q, data: (q)?.data?.m0?.returning, error: e };
649-
}
730+
}
650731

651732
// @ts-ignore
652733
return { ...q, data: (q)?.data?.m0?.returning };
@@ -656,8 +737,15 @@ export class DeepClient<L = Link<number>> implements DeepClientInstance<L> {
656737
if (exp === null) return this.insert( [value], options);
657738
if (value === null) return this.delete( exp, options );
658739

659-
const query = serializeQuery(exp, options?.table === this.table || !options?.table ? 'links' : 'value');
740+
const query = serializeQuery(exp, options?.table === this.table || !options?.table ? 'links' : 'value', this.unvertualizeId);
660741
const table = options?.table || this.table;
742+
743+
if (this.minilinks) {
744+
const toUpdate: any = [];
745+
convertDeepUpdateToMinilinksApply(this.minilinks, exp, value, table, toUpdate);
746+
this.minilinks.update(toUpdate);
747+
}
748+
661749
const returning = options?.returning || this.updateReturning;
662750
const variables = options?.variables;
663751
const name = options?.name || this.defaultUpdateName;
@@ -673,18 +761,28 @@ export class DeepClient<L = Link<number>> implements DeepClientInstance<L> {
673761
if (!this._silent(options)) throw new Error(`DeepClient Update Error: ${e.message}`, { cause: e });
674762
return { ...q, data: (q)?.data?.m0?.returning, error: e };
675763
}
764+
676765
// @ts-ignore
677766
return { ...q, data: (q)?.data?.m0?.returning };
678767
};
679768

680769
async delete<TTable extends 'links'|'numbers'|'strings'|'objects'>(exp: Exp<TTable>, options?: WriteOptions<TTable>):Promise<DeepClientResult<{ id }[]>> {
681770
if (!exp) throw new Error('!exp');
682-
const query = serializeQuery(exp, options?.table === this.table || !options?.table ? 'links' : 'value');
771+
const query = serializeQuery(exp, options?.table === this.table || !options?.table ? 'links' : 'value', this.unvertualizeId);
683772
const table = options?.table || this.table;
684773
const returning = options?.returning || this.deleteReturning;
685774
const variables = options?.variables;
686775
const name = options?.name || this.defaultDeleteName;
687776
let q;
777+
778+
if (this.minilinks) {
779+
const toDelete: any = [];
780+
const toUpdate: any = [];
781+
convertDeepDeleteToMinilinksApply(this.minilinks, exp, table, toDelete, toUpdate);
782+
this.minilinks.update(toUpdate);
783+
this.minilinks.remove(toDelete);
784+
}
785+
688786
try {
689787
q = await this.apolloClient.mutate(generateSerial({
690788
actions: [deleteMutation(table, { ...variables, ...query, returning }, { tableName: table, operation: 'delete', returning })],
@@ -697,6 +795,7 @@ export class DeepClient<L = Link<number>> implements DeepClientInstance<L> {
697795
if (!this._silent(options)) throw new Error(`DeepClient Delete Error: ${e.message}`, { cause: e });
698796
return { ...q, data: (q)?.data?.m0?.returning, error: e };
699797
}
798+
700799
return { ...q, data: (q)?.data?.m0?.returning };
701800
};
702801

@@ -730,15 +829,15 @@ export class DeepClient<L = Link<number>> implements DeepClientInstance<L> {
730829
const newSerialActions: IGenerateMutationBuilder[] = updateOperations.map(operation => {
731830
const exp = operation.exp;
732831
const value = operation.value;
733-
const query = serializeQuery(exp, table === this.table || !table ? 'links' : 'value');
832+
const query = serializeQuery(exp, table === this.table || !table ? 'links' : 'value', this.unvertualizeId);
734833
return updateMutation(table, {...query, _set: value }, { tableName: table, operation: operationType ,returning})
735834
})
736835
serialActions = [...serialActions, ...newSerialActions];
737836
} else if (operationType === 'delete') {
738837
const deleteOperations = operations as Array<SerialOperation<'delete', Table<'delete'>>>;;
739838
const newSerialActions: IGenerateMutationBuilder[] = deleteOperations.map(operation => {
740839
const exp = operation.exp;
741-
const query = serializeQuery(exp, table === this.table || !table ? 'links' : 'value');
840+
const query = serializeQuery(exp, table === this.table || !table ? 'links' : 'value', this.unvertualizeId);
742841
return deleteMutation(table, { ...query }, { tableName: table, operation: operationType, returning })
743842
})
744843
serialActions = [...serialActions, ...newSerialActions];
@@ -1070,11 +1169,11 @@ export function useDeepQuery<Table extends 'links'|'numbers'|'strings'|'objects'
10701169
error?: any;
10711170
loading: boolean;
10721171
} {
1073-
const [miniName] = useState(options?.mini || Math.random().toString(36).slice(2, 7));
1172+
const [miniName] = useState(options?.mini || random());
10741173
debug('useDeepQuery', miniName, query, options);
10751174
const deep = useDeep();
10761175
const wq = useMemo(() => {
1077-
const sq = serializeQuery(query);
1176+
const sq = serializeQuery(query, 'links', deep.unvertualizeId);
10781177
return generateQuery({
10791178
operation: 'query',
10801179
queries: [generateQueryData({
@@ -1114,7 +1213,7 @@ export function useDeepSubscription<Table extends 'links'|'numbers'|'strings'|'o
11141213
debug('useDeepSubscription', miniName, query, options);
11151214
const deep = useDeep();
11161215
const wq = useMemo(() => {
1117-
const sq = serializeQuery(query);
1216+
const sq = serializeQuery(query, 'links', deep.unvertualizeId);
11181217
return generateQuery({
11191218
operation: 'subscription',
11201219
queries: [generateQueryData({

imports/minilinks-query.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { _serialize, _boolExpFields, serializeWhere, serializeQuery } from './client.js';
1+
import { _serialize, _boolExpFields, serializeWhere, serializeQuery, useDeep } from './client.js';
22
import { BoolExpLink, ComparasionType, QueryLink } from './client_types.js';
33
import { MinilinkCollection, MinilinksGeneratorOptions, Link } from './minilinks.js';
44

@@ -12,7 +12,7 @@ export const minilinksQuery = <L extends Link<number>>(
1212
): L[] => {
1313
if (typeof(query) === 'number') return [ml.byId[query]];
1414
else {
15-
const q = serializeQuery(query);
15+
const q = serializeQuery(query, 'links');
1616
const result = minilinksQueryHandle<L>(q.where, ml);
1717
return q.limit ? result.slice(q.offset || 0, (q.offset || 0) + (q.limit)) : result;
1818
}
@@ -24,7 +24,7 @@ export const minilinksQueryIs = <L extends Link<number>>(
2424
): boolean => {
2525
if (typeof(query) === 'number') return link.id === query;
2626
else {
27-
const q = serializeQuery(query);
27+
const q = serializeQuery(query, 'links');
2828
return minilinksQueryLevel(
2929
q,
3030
link,

0 commit comments

Comments
 (0)