Skip to content

Commit fe8cc18

Browse files
committed
feat: add draft of first utlity functions
1 parent 6b806c1 commit fe8cc18

14 files changed

+340
-8
lines changed

index.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ export * as ID from './src/id.js';
1414
*
1515
* @since 0.0.6
1616
*/
17-
export { BASE58_ALLOWED_CHARS, decodeBase58ToUUID, encodeBase58 } from './src/core/base58.js';
17+
export {
18+
BASE58_ALLOWED_CHARS,
19+
decodeBase58ToUUID,
20+
encodeBase58,
21+
} from './src/core/base58.js';
1822

1923
export {
2024
getAcceptEditorArguments,
@@ -33,7 +37,7 @@ export {
3337
*/
3438
export { Account } from './src/account.js';
3539

36-
export { TextBlock, DataBlock, ImageBlock } from './src/blocks.js';
40+
export { DataBlock, ImageBlock, TextBlock } from './src/blocks.js';
3741

3842
/**
3943
* This module provides utility functions for working with knowledge graph
@@ -69,7 +73,7 @@ export { GraphUrl } from './src/scheme.js';
6973
/**
7074
* Provides ids for commonly used entities across the Knowledge Graph.
7175
*/
72-
export { SYSTEM_IDS, NETWORK_IDS, CONTENT_IDS } from './src/system-ids.js';
76+
export { CONTENT_IDS, NETWORK_IDS, SYSTEM_IDS } from './src/system-ids.js';
7377

7478
export { getChecksumAddress } from './src/core/get-checksum-address.js';
7579

@@ -80,3 +84,10 @@ export { getChecksumAddress } from './src/core/get-checksum-address.js';
8084
* @since 0.1.1
8185
*/
8286
export * as IPFS from './src/ipfs.js';
87+
88+
/**
89+
* This module provides high-level utility functions for working with the Knowledge Graph API.
90+
*
91+
* @since 0.5.0
92+
*/
93+
export * as Graph from './src/graph/index.js';

package.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@
77
"main": "./dist/index.js",
88
"ascMain": "./dist/index.js",
99
"type": "module",
10-
"files": [
11-
"dist"
12-
],
10+
"files": ["dist"],
1311
"exports": {
1412
"./package.json": "./package.json",
1513
".": "./dist/index.js",
@@ -47,6 +45,5 @@
4745
"@bufbuild/buf": "^1.31.0",
4846
"@bufbuild/protoc-gen-es": "^1.9.0",
4947
"typescript": "^5.4.5"
50-
},
51-
"packageManager": "[email protected]"
48+
}
5249
}

src/graph/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const DEFAULT_API_HOST = 'https://api-testnet.grc-20.thegraph.com';

src/graph/create-entity.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { TYPES_ATTRIBUTE } from '../core/ids/system.js';
2+
import { generate } from '../id.js';
3+
import { Relation } from '../relation.js';
4+
import { Triple } from '../triple.js';
5+
import type { CreateRelationOp, Op, SetTripleOp, ValueType } from '../types.js';
6+
7+
type Params = {
8+
attributes?: {
9+
[filedName: string]: string;
10+
};
11+
mapping?: {
12+
[filedName: string]: { id: string; type: ValueType };
13+
};
14+
types?: Array<string>;
15+
relations?: Array<{
16+
relationTypeId: string;
17+
toId: string;
18+
}>;
19+
};
20+
21+
export const createEntity = async ({ attributes, mapping, types, relations }: Params) => {
22+
const id = generate();
23+
const ops: Array<Op> = [];
24+
if (attributes && mapping) {
25+
for (const [fieldName, value] of Object.entries(attributes)) {
26+
const attributeMapping = mapping[fieldName];
27+
if (!attributeMapping) {
28+
throw new Error(`Attribute ID for field ${fieldName} not found`);
29+
}
30+
const setTripleOp: SetTripleOp = Triple.make({
31+
entityId: id,
32+
attributeId: attributeMapping.id,
33+
value: {
34+
type: attributeMapping.type,
35+
value,
36+
},
37+
});
38+
39+
ops.push(setTripleOp);
40+
}
41+
}
42+
43+
if (types) {
44+
// add types
45+
for (const typeId of types) {
46+
const setRelationOp: CreateRelationOp = Relation.make({
47+
fromId: id,
48+
relationTypeId: TYPES_ATTRIBUTE,
49+
toId: typeId,
50+
});
51+
ops.push(setRelationOp);
52+
}
53+
}
54+
55+
if (relations) {
56+
// TODO add relations
57+
}
58+
59+
return { id, ops };
60+
};

src/graph/create-relation-type.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { ATTRIBUTE, NAME_ATTRIBUTE, SCHEMA_TYPE, TYPES_ATTRIBUTE } from '../core/ids/system.js';
2+
import { generate } from '../id.js';
3+
import { Relation } from '../relation.js';
4+
import { Triple } from '../triple.js';
5+
import type { CreateRelationOp, Op, SetTripleOp } from '../types.js';
6+
7+
type Params = {
8+
from: string;
9+
to: string;
10+
name: string;
11+
};
12+
13+
export const createRelationType = async ({ from, to, name }: Params) => {
14+
const id = generate();
15+
const ops: Op[] = [];
16+
17+
const nameTripleOp: SetTripleOp = Triple.make({
18+
entityId: id,
19+
attributeId: NAME_ATTRIBUTE,
20+
value: {
21+
type: 'TEXT',
22+
value: name,
23+
},
24+
});
25+
ops.push(nameTripleOp);
26+
27+
const setRelationOp: CreateRelationOp = Relation.make({
28+
fromId: id,
29+
relationTypeId: TYPES_ATTRIBUTE,
30+
toId: SCHEMA_TYPE, // this sets the relation type to be a typ type
31+
});
32+
ops.push(setRelationOp);
33+
34+
const setRelationOp2: CreateRelationOp = Relation.make({
35+
fromId: id,
36+
relationTypeId: TYPES_ATTRIBUTE,
37+
toId: ATTRIBUTE, // this sets the relation type to be an "property" type
38+
});
39+
ops.push(setRelationOp2);
40+
41+
// TODO relations
42+
43+
return { id, ops };
44+
};

src/graph/create-relation.ts

Whitespace-only changes.

src/graph/create-space.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { DEFAULT_API_HOST } from './constants.js';
2+
3+
type Params = {
4+
editorAddress: string;
5+
name: string;
6+
options?: {
7+
apiHost?: string;
8+
};
9+
};
10+
11+
export const createSpace = async (params: Params) => {
12+
const apiHost = params.options?.apiHost || DEFAULT_API_HOST;
13+
const result = await fetch(`${apiHost}/deploy`, {
14+
method: 'POST',
15+
body: JSON.stringify({
16+
spaceName: params.name,
17+
initialEditorAddress: params.editorAddress,
18+
}),
19+
headers: {
20+
'Content-Type': 'application/json',
21+
},
22+
});
23+
24+
const { spaceId } = await result.json();
25+
return { id: spaceId };
26+
};

src/graph/create-type.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { SCHEMA_TYPE, TYPES_ATTRIBUTE } from '../core/ids/system.js';
2+
import { generate } from '../id.js';
3+
import { Relation } from '../relation.js';
4+
import { Triple } from '../triple.js';
5+
import type { CreateRelationOp, Op, SetTripleOp, ValueType } from '../types.js';
6+
7+
type Params = {
8+
attributes: {
9+
[filedName: string]: { id?: string; type: ValueType; name: string };
10+
};
11+
relations?: Array<{
12+
relationTypeId: string;
13+
toId: string;
14+
}>;
15+
};
16+
17+
export const createType = async ({ attributes }: Params) => {
18+
const id = generate();
19+
const ops: Op[] = [];
20+
const mapping: Record<string, { id: string; type: ValueType }> = {};
21+
22+
for (const [fieldName, item] of Object.entries(attributes)) {
23+
const attributeId = item.id || generate();
24+
const setTripleOp: SetTripleOp = Triple.make({
25+
entityId: id,
26+
attributeId,
27+
value: {
28+
type: item.type,
29+
value: fieldName,
30+
},
31+
});
32+
33+
ops.push(setTripleOp);
34+
mapping[fieldName] = { id: attributeId, type: item.type };
35+
}
36+
37+
// add the type relation
38+
const setRelationOp: CreateRelationOp = Relation.make({
39+
fromId: id,
40+
relationTypeId: TYPES_ATTRIBUTE,
41+
toId: SCHEMA_TYPE,
42+
});
43+
ops.push(setRelationOp);
44+
45+
// TODO relations
46+
47+
return { id, ops, mapping };
48+
};

src/graph/graph.test.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { NAME_ATTRIBUTE } from '../core/ids/system.js';
3+
import type { Op } from '../types.js';
4+
import { createEntity } from './create-entity.js';
5+
import { createRelationType } from './create-relation-type.js';
6+
import { createType } from './create-type.js';
7+
8+
describe('Graph', () => {
9+
it('creates multiple types, relation types, entities, relations', async () => {
10+
const operations: Array<Op> = [];
11+
12+
// create person type
13+
const {
14+
id: personTypeId,
15+
ops: createPersonTypeOps,
16+
mapping: personMapping,
17+
} = await createType({
18+
attributes: {
19+
name: {
20+
id: NAME_ATTRIBUTE,
21+
type: 'TEXT',
22+
name: 'Name',
23+
},
24+
age: {
25+
// ID is optional and will be generated automatically
26+
type: 'NUMBER',
27+
name: 'Age',
28+
},
29+
},
30+
});
31+
operations.push(...createPersonTypeOps);
32+
33+
// create restaurant type
34+
const {
35+
id: restaurantTypeId,
36+
ops: createRestaurantTypeOps,
37+
mapping: restaurantMapping,
38+
} = await createType({
39+
attributes: {
40+
name: {
41+
id: NAME_ATTRIBUTE,
42+
type: 'TEXT',
43+
name: 'Name',
44+
},
45+
},
46+
});
47+
operations.push(...createRestaurantTypeOps);
48+
49+
// create loves relation type
50+
const { id: relationTypeId, ops: createRelationTypeOps } = await createRelationType({
51+
from: personTypeId,
52+
to: restaurantTypeId,
53+
name: 'Loves',
54+
});
55+
operations.push(...createRelationTypeOps);
56+
57+
// create restaurant entity
58+
const { id: restaurantId, ops: createRestaurantOps } = await createEntity({
59+
types: [restaurantTypeId],
60+
attributes: {
61+
name: 'Yummy Dining',
62+
},
63+
mapping: restaurantMapping,
64+
});
65+
operations.push(...createRestaurantOps);
66+
67+
// create person entity
68+
const { id: personId, ops: createPersonOps } = await createEntity({
69+
types: [personTypeId],
70+
attributes: {
71+
name: 'John Doe',
72+
},
73+
mapping: personMapping,
74+
relations: [{ relationTypeId, toId: restaurantId }],
75+
});
76+
operations.push(...createPersonOps);
77+
78+
expect(operations.length).toBe(12);
79+
80+
// publish all changes
81+
// const { proposalId } = await publish({
82+
// operations,
83+
// editName: 'Create person, restaurant, and loves relation',
84+
// spaceId: '0x1',
85+
// accountId: '0x2',
86+
// });
87+
});
88+
});

src/graph/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './create-entity.js';
2+
export * from './create-space.js';

0 commit comments

Comments
 (0)