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

Rewrite JSONImporter in TypeScript. Closes #30 #43

Merged
merged 23 commits into from
Oct 4, 2022
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6e2c70c
Initial Commit for typescript support
umesh-timalsina Sep 14, 2022
63f382c
WIP- Bring in GME types
umesh-timalsina Sep 14, 2022
0d816fc
WIP- plan library build
umesh-timalsina Sep 28, 2022
cd5006b
WIP- Merge branch main
umesh-timalsina Sep 28, 2022
a4f41cc
Modified changeset;
umesh-timalsina Sep 28, 2022
a38d603
Continue on error
umesh-timalsina Sep 28, 2022
b03d99a
WIP- build fails; test pass
umesh-timalsina Sep 28, 2022
41e57d4
WIP- Fix line endings
umesh-timalsina Sep 28, 2022
29bd2dd
Build using vite; remove changeset dependency
umesh-timalsina Sep 29, 2022
5ef49fd
WIP- commit missing file
umesh-timalsina Sep 29, 2022
4ffbf32
Don't change test/plugin files by uniform export of the library
umesh-timalsina Sep 29, 2022
5774566
Readd test files
umesh-timalsina Sep 29, 2022
17680eb
WIP- Fix ts build errors for except Importer.ts; Formalize GMEJson type
umesh-timalsina Sep 29, 2022
525aacc
Make changeset dev dependency
brollb Sep 30, 2022
45f6bc0
WIP- Prefer composition over inheritance, refactor wierd promise issu…
umesh-timalsina Oct 3, 2022
da0298e
WIP- Rename GMEJson to JSONNode
umesh-timalsina Oct 3, 2022
e3e2322
WIP- export GMEDiff as well
umesh-timalsina Oct 3, 2022
6dce159
Remove changeset diff as export
umesh-timalsina Oct 3, 2022
f9c9cf4
Export changetype
umesh-timalsina Oct 3, 2022
228865f
Rename JSONNode; add missing types to gmeDiff
brollb Oct 4, 2022
c009a45
fix formatting
brollb Oct 4, 2022
87f9851
Promise<any>[] -> Promise<void>[] (rm unnecessary fn)
brollb Oct 4, 2022
ae40697
Promise<any>[] -> Promise<void>[]
brollb Oct 4, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:

- name: "Install Dependencies"
run: npm install -g npm && npm install
continue-on-error: true

- name: "Run Tests"
run: npm test
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ node_modules
tmp/
blob-local-storage/
test-tmp/

build
10 changes: 10 additions & 0 deletions lib/common/JSONImporter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {Importer} from './JSONImporter/Importer';
import {OmittedProperties} from './JSONImporter/OmittedProperties';
import {NodeSelections} from './JSONImporter/NodeSelectors';
import {NodeChangeSet} from './JSONImporter/NodeChangeSet';
import {NodeSelector} from './JSONImporter/NodeSelectors';

import diff from 'changeset';

export default Importer;
export {OmittedProperties, NodeSelections, diff, NodeChangeSet, NodeSelector};
182 changes: 182 additions & 0 deletions lib/common/JSONImporter/Exporter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/// <reference path="./webgme/webgme.d.ts" />
import type {
GMEJson,
GMERelationRuleType
} from './Models';

import {OmittedProperties} from './OmittedProperties';


type Core = GmeClasses.Core;

export class Exporter {
core: Core;
rootNode: Core.Node;
omitted: OmittedProperties;
promiseQueue: Promise<any>[];

constructor(core: Core, rootNode: Core.Node) {
this.core = core
this.rootNode = rootNode;
this.omitted = new OmittedProperties();
this.promiseQueue = [];
brollb marked this conversation as resolved.
Show resolved Hide resolved
}

async _metaDictToGuids(meta_dict: Core.RelationRule | null): Promise<GMERelationRuleType> {
if (meta_dict === null) return meta_dict;
return Object.fromEntries(
await Promise.all(Object.entries(meta_dict).map(async ([key, value]) => {
if (key === 'min' || key === 'max') return [key, value];
const node = await this.core.loadByPath(this.rootNode, key);
return [this.core.getGuid(node), value];
}))
);
}

clearPromiseQueue(): void {
this.promiseQueue = [];
}

setOmittedProperties(omitted: OmittedProperties): void {
this.omitted = omitted;
}

async toJSON(node: Core.Node, omit: OmittedProperties | boolean = new OmittedProperties()): Promise<Partial<GMEJson>> {
if (typeof omit === 'boolean') {
const omitList = omit ? ['children'] : [];
omit = new OmittedProperties(omitList);
} // Backwards compatible with shallow

this.setOmittedProperties(omit);
brollb marked this conversation as resolved.
Show resolved Hide resolved
return await this._toJSON(node);
}

async _toJSON(node: Core.Node): Promise<Partial<GMEJson>> {
const json = {
id: this.core.getGuid(node),
path: this.core.getPath(node),
guid: this.core.getGuid(node),
attributes: {},
attribute_meta: {},
pointers: {},
pointer_meta: {},
mixins: [],
registry: {},
sets: {},
member_registry: {},
member_attributes: {},
children: [],
children_meta: {},
}

this.omitted.forEach(toOmit => delete json[toOmit]);

this.clearPromiseQueue();
Object.keys(json).forEach(key => {
if (this[key]) {
this[key](node, json);
}
});
await Promise.all(this.promiseQueue);

this.clearPromiseQueue();
brollb marked this conversation as resolved.
Show resolved Hide resolved
return json;
}

attributes(node: Core.Node, json: Pick<GMEJson, 'attributes'>) {
this.core.getOwnAttributeNames(node).forEach(name => {
json.attributes[name] = this.core.getAttribute(node, name);
});
}

attribute_meta(node: Core.Node, json: Pick<GMEJson, 'attribute_meta'>) {
this.core.getOwnValidAttributeNames(node).forEach(name => {
json.attribute_meta[name] = this.core.getAttributeMeta(node, name);
});
}

sets(node: Core.Node, json: Pick<GMEJson, 'sets' | 'member_attributes' | 'member_registry'>) {
this.promiseQueue.push(...this.core.getOwnSetNames(node)
.filter(name => name !== '_mixins')
.map(async name => {
const paths = this.core.getMemberPaths(node, name);
const members = await Promise.all(paths.map(path => this.core.loadByPath(this.rootNode, path)));
const memberGuids = members.map(member => this.core.getGuid(member));
json.sets[name] = memberGuids;

if (!this.omitted.has('member_attributes')) { // Alternatives to this closure variable?
members.forEach(member => {
let guid = this.core.getGuid(member);
let memberPath = this.core.getPath(member);

json.member_attributes[name] = {};
json.member_attributes[name][guid] = {};
this.core.getMemberAttributeNames(node, name, memberPath).forEach(attrName => {
const value = this.core.getMemberAttribute(node, name, memberPath, attrName);
json.member_attributes[name][guid][attrName] = value;
});
});
}
if (!this.omitted.has('member_registry')) {
members.forEach(member => {
let guid = this.core.getGuid(member);
let memberPath = this.core.getPath(member);

json.member_registry[name] = {};
json.member_registry[name][guid] = {};
this.core.getMemberRegistryNames(node, name, memberPath).forEach(regName => {
const value = this.core.getMemberRegistry(node, name, memberPath, regName);
json.member_registry[name][guid][regName] = value;
});
});
}
}));
}

pointers(node: Core.Node, json: Pick<GMEJson, 'pointers'>) {
this.promiseQueue.push(...this.core.getOwnPointerNames(node).map(async name => {
const path = this.core.getPointerPath(node, name);
if (path) {
const target = await this.core.loadByPath(this.rootNode, path);
json.pointers[name] = this.core.getGuid(target);
} else {
json.pointers[name] = path;
}
}));
const baseNode = this.core.getBase(node);
json.pointers.base = baseNode && this.core.getGuid(baseNode);
}

registry(node: Core.Node, json: Pick<GMEJson, 'registry'>) {
this.core.getOwnRegistryNames(node).forEach(name => {
json.registry[name] = this.core.getRegistry(node, name);
});
}

children(node: Core.Node, json: Pick<GMEJson, 'children'>) {
this.promiseQueue.push((async () => {
const children = await this.core.loadChildren(node);
json.children = await Promise.all(
children.map(child => this._toJSON(child))
);
})());
}

children_meta(node: Core.Node, json: Pick<GMEJson, 'children_meta'>) {
this.promiseQueue.push(
this._metaDictToGuids(this.core.getChildrenMeta(node))
.then((children_meta) => json.children_meta = children_meta)
);
}

pointer_meta(node: Core.Node, json: Pick<GMEJson, 'pointer_meta'>) {
this.promiseQueue.push(...this.core.getOwnValidPointerNames(node).map(async name => {
const ptr_meta = this.core.getPointerMeta(node, name);
json.pointer_meta[name] = await this._metaDictToGuids(ptr_meta);
}));
}

mixins(node: Core.Node, json: Pick<GMEJson, 'mixins'>) {
json.mixins = Object.values(this.core.getMixinNodes(node)).map(node => this.core.getGuid(node));
}
}
Loading