goby-database 2.0.12 → 2.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/sandbox.js +94 -0
- package/package.json +4 -1
- package/src/index.ts +0 -1256
- package/src/sandbox.ts +0 -107
- package/src/types.ts +0 -222
- package/src/unit-tests.ts +0 -117
- package/src/utils.ts +0 -133
- package/tsconfig.json +0 -111
package/src/sandbox.ts
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { readable_junctionlist } from './utils.js';
|
|
2
|
-
|
|
3
|
-
console.log('--------------------------------------------------------')
|
|
4
|
-
console.log('SANDBOX: running test...\n')
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import Project from './index.js';
|
|
8
|
-
const project=new Project(':memory:');
|
|
9
|
-
|
|
10
|
-
console.log('--------------------------------------------------------')
|
|
11
|
-
console.log('SANDBOX: setting up book-author-script schema\n')
|
|
12
|
-
project.action_edit_class_schema({
|
|
13
|
-
class_edits:[
|
|
14
|
-
{type:'create',class_name:'author'},
|
|
15
|
-
{type:'create',class_name:'book'},
|
|
16
|
-
{type:'create',class_name:'script'}
|
|
17
|
-
],
|
|
18
|
-
property_edits:[
|
|
19
|
-
{type:'create',class_name:'author',prop_name:'age',config:{type:'data',data_type:'number',max_values:1}},
|
|
20
|
-
{type:'create',class_name:'author',prop_name:'works',config:{type:'relation',max_values:null}},
|
|
21
|
-
{type:'create',class_name:'author',prop_name:'books read',config:{type:'relation',max_values:null}},
|
|
22
|
-
{type:'create',class_name:'book',prop_name:'author',config:{type:'relation',max_values:1}}
|
|
23
|
-
],
|
|
24
|
-
relationship_edits:[
|
|
25
|
-
{ type:'create', sides:[{class_name:'author',prop_name:'works'}, {class_name:'book',prop_name:'author'}] },
|
|
26
|
-
{ type:'create', sides:[{class_name:'author',prop_name:'works'}, {class_name:'script'}] },
|
|
27
|
-
{ type:'create',sides:[{class_name:'author',prop_name:'books read'},{class_name:'book'}]}
|
|
28
|
-
]
|
|
29
|
-
})
|
|
30
|
-
console.log(project.junction_cache.map(a=>a.sides));
|
|
31
|
-
|
|
32
|
-
console.log('--------------------------------------------------------')
|
|
33
|
-
console.log('SANDBOX: adding items to classes\n')
|
|
34
|
-
project.action_add_row(1);
|
|
35
|
-
project.action_add_row(2);
|
|
36
|
-
project.action_add_row(2);
|
|
37
|
-
project.action_add_row(3);
|
|
38
|
-
|
|
39
|
-
console.log('--------------------------------------------------------')
|
|
40
|
-
console.log('SANDBOX: making connections between items in classes\n')
|
|
41
|
-
project.action_make_relation({
|
|
42
|
-
class_id:1,
|
|
43
|
-
prop_id:3,
|
|
44
|
-
item_id:1
|
|
45
|
-
},{
|
|
46
|
-
class_id:2,
|
|
47
|
-
prop_id:2,
|
|
48
|
-
item_id:2
|
|
49
|
-
})
|
|
50
|
-
project.action_make_relation({
|
|
51
|
-
class_id:1,
|
|
52
|
-
prop_id:3,
|
|
53
|
-
item_id:1
|
|
54
|
-
},{
|
|
55
|
-
class_id:2,
|
|
56
|
-
prop_id:2,
|
|
57
|
-
item_id:3
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
project.action_make_relation({
|
|
61
|
-
class_id:1,
|
|
62
|
-
prop_id:3,
|
|
63
|
-
item_id:1
|
|
64
|
-
},{
|
|
65
|
-
class_id:3,
|
|
66
|
-
item_id:4
|
|
67
|
-
})
|
|
68
|
-
project.action_make_relation({
|
|
69
|
-
class_id:1,
|
|
70
|
-
prop_id:4,
|
|
71
|
-
item_id:1
|
|
72
|
-
},{
|
|
73
|
-
class_id:2,
|
|
74
|
-
item_id:2
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
project.refresh_caches(['classlist','items','junctions']);
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
console.log('--------------------------------------------------------')
|
|
81
|
-
console.log('SANDBOX: deleting author property in books\n')
|
|
82
|
-
|
|
83
|
-
project.action_edit_class_schema(
|
|
84
|
-
{
|
|
85
|
-
property_edits:[
|
|
86
|
-
{
|
|
87
|
-
type:'delete',
|
|
88
|
-
class_id:2,
|
|
89
|
-
prop_id:2
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
type:'create',
|
|
93
|
-
class_id:2,
|
|
94
|
-
prop_name:'author2',
|
|
95
|
-
config:{
|
|
96
|
-
type:'relation',
|
|
97
|
-
max_values:1
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
],
|
|
101
|
-
relationship_edits:[
|
|
102
|
-
{type:'create',sides:[{class_id:1,prop_id:3},{class_id:2,prop_name:'author2'}]}
|
|
103
|
-
]
|
|
104
|
-
}
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
console.log(readable_junctionlist(project.junction_cache,project.class_cache));
|
package/src/types.ts
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
export type SQLTableType = 'system' | 'class' | 'properties' | 'junction' | 'workspace';
|
|
2
|
-
|
|
3
|
-
export type SQLClassListRow = {
|
|
4
|
-
id: number;
|
|
5
|
-
name: string;
|
|
6
|
-
metadata: string; // JSON string
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export type SQLJunctonListRow = {
|
|
10
|
-
id: number;
|
|
11
|
-
sides: string; //JSON string
|
|
12
|
-
metadata: string; // JSON string
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export type RelationshipSideBase = {
|
|
16
|
-
class_id?:number;
|
|
17
|
-
prop_id?:number;
|
|
18
|
-
class_name?:string;
|
|
19
|
-
prop_name?:string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type RelationshipSide = RelationshipSideBase & {
|
|
23
|
-
class_id:number;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export type RelationTarget = {
|
|
27
|
-
class_id:number;
|
|
28
|
-
prop_id?:number | null;
|
|
29
|
-
junction_id:number;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
export type ItemRelationSide = RelationshipSide & {
|
|
34
|
-
item_id:number;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
type RelationCreate = {
|
|
39
|
-
type:'create',
|
|
40
|
-
sides:[
|
|
41
|
-
RelationshipSideBase,
|
|
42
|
-
RelationshipSideBase
|
|
43
|
-
]
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
type RelationDelete = {
|
|
47
|
-
type:'delete',
|
|
48
|
-
id:number
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
type RelationTransfer = {
|
|
52
|
-
type:'transfer',
|
|
53
|
-
id:number,
|
|
54
|
-
sides:[
|
|
55
|
-
RelationshipSide,
|
|
56
|
-
RelationshipSide
|
|
57
|
-
],
|
|
58
|
-
// ; to allow conversion from two-way to one-way relation (and one way to two-way?)
|
|
59
|
-
new_sides:[
|
|
60
|
-
RelationshipSideBase,
|
|
61
|
-
RelationshipSideBase
|
|
62
|
-
]
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
export type RelationEdit = RelationCreate | RelationDelete | RelationTransfer;
|
|
67
|
-
|
|
68
|
-
export type RelationEditValidSides = (RelationCreate & {sides:JunctionSides})| (RelationTransfer & {sides:JunctionSides, new_sides:JunctionSides}) | RelationDelete;
|
|
69
|
-
|
|
70
|
-
type PropertyCreate ={
|
|
71
|
-
type:'create',
|
|
72
|
-
prop_name:string
|
|
73
|
-
class_id?:number,
|
|
74
|
-
class_name?:string,
|
|
75
|
-
config:PropertyDefinition
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
type PropertyDelete = {
|
|
79
|
-
type:'delete',
|
|
80
|
-
class_id:number
|
|
81
|
-
prop_id:number
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
type PropertyModify ={
|
|
85
|
-
type:'modify',
|
|
86
|
-
prop_id:number,
|
|
87
|
-
class_id:number
|
|
88
|
-
config:PropertyDefinition
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export type PropertyEdit = PropertyCreate | PropertyDelete | PropertyModify
|
|
92
|
-
|
|
93
|
-
type ClassCreate = {
|
|
94
|
-
type:'create',
|
|
95
|
-
class_name:string
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
type ClassDelete = {
|
|
99
|
-
type:'delete',
|
|
100
|
-
class_id:number
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
type ClassModify = {
|
|
104
|
-
type:'modify_attribute';
|
|
105
|
-
class_id:number;
|
|
106
|
-
attribute:{
|
|
107
|
-
// NOTE: for future defining, this should be one of a list of possible values
|
|
108
|
-
name:string;
|
|
109
|
-
// ... and this should be conditioned by the name
|
|
110
|
-
value:any;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export type ClassEdit = ClassCreate | ClassDelete | ClassModify;
|
|
115
|
-
|
|
116
|
-
export type ClassMetadata ={
|
|
117
|
-
style:{
|
|
118
|
-
color?:string
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export type PropertyType = 'data' | 'relation';
|
|
123
|
-
|
|
124
|
-
export type BinaryBoolean = 0 | 1;
|
|
125
|
-
|
|
126
|
-
// null if no max value
|
|
127
|
-
export type MaxValues = number | null;
|
|
128
|
-
|
|
129
|
-
export type BaseProperty={
|
|
130
|
-
id:number,
|
|
131
|
-
name:string,
|
|
132
|
-
type:PropertyType,
|
|
133
|
-
max_values:MaxValues
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
export type RelationDefinition = {
|
|
138
|
-
type:'relation';
|
|
139
|
-
relation_targets:RelationTarget[];
|
|
140
|
-
data_type?:never;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export type RelationProperty = BaseProperty & RelationDefinition;
|
|
144
|
-
|
|
145
|
-
export type DataType = 'string' |'resource' | 'number';
|
|
146
|
-
|
|
147
|
-
export type DataDefinition = {
|
|
148
|
-
type:'data';
|
|
149
|
-
data_type:DataType;
|
|
150
|
-
relation_targets?:never;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export type DataProperty = BaseProperty & DataDefinition;
|
|
154
|
-
|
|
155
|
-
export type Property = RelationProperty | DataProperty;
|
|
156
|
-
|
|
157
|
-
export type PropertyDefinition = {max_values:MaxValues} & ({type:'relation'} | DataDefinition);
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
export type ClassRow={ [key: string]: any };
|
|
161
|
-
|
|
162
|
-
export type ClassData ={
|
|
163
|
-
id:number;
|
|
164
|
-
name:string;
|
|
165
|
-
metadata:ClassMetadata;
|
|
166
|
-
items:ClassRow[];
|
|
167
|
-
properties:Property[];
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
export type ClassList =ClassData[];
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
export type JunctionSides =[RelationshipSide,RelationshipSide];
|
|
175
|
-
|
|
176
|
-
export type JunctionTable ={
|
|
177
|
-
id:number,
|
|
178
|
-
sides:JunctionSides,
|
|
179
|
-
metadata:{}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
export type JunctionList =JunctionTable[];
|
|
184
|
-
|
|
185
|
-
export type WindowType = 'home' | 'hopper' | 'workspace';
|
|
186
|
-
|
|
187
|
-
export type SQLApplicationWindow ={
|
|
188
|
-
id:number;
|
|
189
|
-
type:WindowType;
|
|
190
|
-
open:BinaryBoolean;
|
|
191
|
-
metadata:string; // JSON string
|
|
192
|
-
}
|
|
193
|
-
export type ApplicationWindow ={
|
|
194
|
-
id:number;
|
|
195
|
-
type:WindowType;
|
|
196
|
-
open:BinaryBoolean;
|
|
197
|
-
metadata:{
|
|
198
|
-
pos:[null,null] | [number,number];
|
|
199
|
-
size:[number,number];
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// maybe elaborate this in the future
|
|
204
|
-
export type ThingType = 'item' | 'class';
|
|
205
|
-
|
|
206
|
-
export type BaseWorkspaceBlock = {
|
|
207
|
-
/** this is the ID of the display element in the workspace, generated by the workspace table */
|
|
208
|
-
block_id:number;
|
|
209
|
-
|
|
210
|
-
thing_type:ThingType;
|
|
211
|
-
|
|
212
|
-
/** this is the ID of the class, item, or other “thing” represented in the data */
|
|
213
|
-
thing_id:number;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
export type SQLWorkspaceBlockRow = BaseWorkspaceBlock & {
|
|
217
|
-
metadata:string; // json string
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export type WorkspaceBlock = BaseWorkspaceBlock & {
|
|
221
|
-
metadata:{};
|
|
222
|
-
}
|
package/src/unit-tests.ts
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { JunctionSides } from "./types";
|
|
2
|
-
import { partial_relation_match } from "./utils.js";
|
|
3
|
-
|
|
4
|
-
testRelationMatching();
|
|
5
|
-
|
|
6
|
-
function testRelationMatching() {
|
|
7
|
-
const test1_old: JunctionSides = [
|
|
8
|
-
{ class_id: 1, prop_id: 100 },
|
|
9
|
-
{ class_id: 2, prop_id: 200 },
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
const test1_new: JunctionSides = [
|
|
13
|
-
{ class_id: 1, prop_id: 100 },
|
|
14
|
-
{ class_id: 2, prop_id: 300 },
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
const test2_old: JunctionSides = [
|
|
18
|
-
{ class_id: 1, prop_id: 100 },
|
|
19
|
-
{ class_id: 2, prop_id: 200 },
|
|
20
|
-
];
|
|
21
|
-
const test2_new: JunctionSides = [
|
|
22
|
-
{ class_id: 1, prop_id: 300 },
|
|
23
|
-
{ class_id: 2, prop_id: 400 },
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
// Case 3: Non-matching classes
|
|
27
|
-
const test3_old: JunctionSides = [
|
|
28
|
-
{ class_id: 1, prop_id: 100 },
|
|
29
|
-
{ class_id: 2, prop_id: 200 },
|
|
30
|
-
];
|
|
31
|
-
const test3_new: JunctionSides = [
|
|
32
|
-
{ class_id: 3, prop_id: 100 },
|
|
33
|
-
{ class_id: 4, prop_id: 200 },
|
|
34
|
-
];
|
|
35
|
-
|
|
36
|
-
const test4a_old: JunctionSides = [
|
|
37
|
-
{ class_id: 1, prop_id: 100 },
|
|
38
|
-
{ class_id: 1, prop_id: 200 },
|
|
39
|
-
];
|
|
40
|
-
const test4a_new: JunctionSides = [
|
|
41
|
-
{ class_id: 1, prop_id: 100 },
|
|
42
|
-
{ class_id: 1, prop_id: 300 },
|
|
43
|
-
];
|
|
44
|
-
|
|
45
|
-
// Case 4b: Same class on both sides with no matching properties
|
|
46
|
-
const test4b_old: JunctionSides = [
|
|
47
|
-
{ class_id: 1, prop_id: 100 },
|
|
48
|
-
{ class_id: 1, prop_id: 200 },
|
|
49
|
-
];
|
|
50
|
-
const test4b_new: JunctionSides = [
|
|
51
|
-
{ class_id: 1, prop_id: 300 },
|
|
52
|
-
{ class_id: 1, prop_id: 400 },
|
|
53
|
-
];
|
|
54
|
-
|
|
55
|
-
// Case 5: Reversed order matching
|
|
56
|
-
const test5_old: JunctionSides = [
|
|
57
|
-
{ class_id: 1, prop_id: 100 },
|
|
58
|
-
{ class_id: 2, prop_id: 200 },
|
|
59
|
-
];
|
|
60
|
-
const test5_new: JunctionSides = [
|
|
61
|
-
{ class_id: 2, prop_id: 200 },
|
|
62
|
-
{ class_id: 1, prop_id: 300 },
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
// Case 6: Undefined property IDs
|
|
66
|
-
const test6_old: JunctionSides = [
|
|
67
|
-
{ class_id: 1 },
|
|
68
|
-
{ class_id: 2, prop_id: 200 },
|
|
69
|
-
];
|
|
70
|
-
const test6_new: JunctionSides = [
|
|
71
|
-
{ class_id: 1, prop_id: 100 },
|
|
72
|
-
{ class_id: 2 },
|
|
73
|
-
];
|
|
74
|
-
|
|
75
|
-
// Case 7: Undefined property IDs on same side
|
|
76
|
-
const test7_old: JunctionSides = [
|
|
77
|
-
{ class_id: 1 },
|
|
78
|
-
{ class_id: 2, prop_id: 200 },
|
|
79
|
-
];
|
|
80
|
-
const test7_new: JunctionSides = [
|
|
81
|
-
{ class_id: 1 },
|
|
82
|
-
{ class_id: 2, prop_id: 100 },
|
|
83
|
-
];
|
|
84
|
-
|
|
85
|
-
console.log(
|
|
86
|
-
"same class, at least one prop (expect true)",
|
|
87
|
-
partial_relation_match(test1_new, test1_old)
|
|
88
|
-
);
|
|
89
|
-
console.log(
|
|
90
|
-
"same class, no props (expect false)",
|
|
91
|
-
partial_relation_match(test2_old, test2_new)
|
|
92
|
-
);
|
|
93
|
-
console.log(
|
|
94
|
-
"different classes (expect false)",
|
|
95
|
-
partial_relation_match(test3_old, test3_new)
|
|
96
|
-
);
|
|
97
|
-
console.log(
|
|
98
|
-
"only one class, matching prop (expect true)",
|
|
99
|
-
partial_relation_match(test4a_new, test4a_old)
|
|
100
|
-
);
|
|
101
|
-
console.log(
|
|
102
|
-
"only one class, no props (expect false)",
|
|
103
|
-
partial_relation_match(test4b_old, test4b_new)
|
|
104
|
-
);
|
|
105
|
-
console.log(
|
|
106
|
-
"reversed class order, prop matching (expect true)",
|
|
107
|
-
partial_relation_match(test5_new, test5_old)
|
|
108
|
-
);
|
|
109
|
-
console.log(
|
|
110
|
-
"undefined prop (expect false)",
|
|
111
|
-
partial_relation_match(test6_old, test6_new)
|
|
112
|
-
);
|
|
113
|
-
console.log(
|
|
114
|
-
"undefined prop 2 (expect false)",
|
|
115
|
-
partial_relation_match(test7_old, test7_new)
|
|
116
|
-
);
|
|
117
|
-
}
|
package/src/utils.ts
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { JunctionSides, RelationshipSide,MaxValues,RelationshipSideBase, RelationEdit, RelationEditValidSides,ClassData,JunctionList } from "./types";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export function defined<T>(v:T):v is NonNullable<T>{
|
|
5
|
-
return v!==undefined && v!==null;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// given the type above,
|
|
10
|
-
// check if two relations share class ids on both sides
|
|
11
|
-
// and share a property id on at least one side
|
|
12
|
-
// note: it’s possible for both sides of a relation to have the same class id
|
|
13
|
-
|
|
14
|
-
export function partial_relation_match(old_relation:JunctionSides,new_relation:JunctionSides):boolean{
|
|
15
|
-
|
|
16
|
-
// find class id matches in old for each side of new relation
|
|
17
|
-
let new_side_matches_in_old=[
|
|
18
|
-
[0,1].filter((i)=> old_relation[i].class_id==new_relation[0].class_id),
|
|
19
|
-
[0,1].filter((i)=> old_relation[i].class_id==new_relation[1].class_id)
|
|
20
|
-
];
|
|
21
|
-
|
|
22
|
-
// for each match in the first side of the new relation
|
|
23
|
-
for(let match_index of new_side_matches_in_old[0]){
|
|
24
|
-
|
|
25
|
-
// converts 0 to 1 and 1 to 0, to get opposite side
|
|
26
|
-
let opposite_index=Math.abs(match_index-1);
|
|
27
|
-
|
|
28
|
-
// if this check passes, the relations share class IDs on both sides
|
|
29
|
-
if(new_side_matches_in_old[1].includes(opposite_index)){
|
|
30
|
-
// class match A
|
|
31
|
-
let match_a_new=new_relation[0];
|
|
32
|
-
let match_a_old=old_relation[match_index];
|
|
33
|
-
|
|
34
|
-
// class match B
|
|
35
|
-
let match_b_new=new_relation[1];
|
|
36
|
-
let match_b_old=old_relation[opposite_index];;
|
|
37
|
-
|
|
38
|
-
// should return true if the properties match on at least one side
|
|
39
|
-
if(properties_exist_and_match(match_a_new,match_a_old) || properties_exist_and_match(match_b_new,match_b_old)){
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// if no matches found, return false found,
|
|
47
|
-
return false;
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function properties_exist_and_match(a:RelationshipSide,b:RelationshipSide){
|
|
52
|
-
return defined(a.prop_id) && defined(b.prop_id) && a.prop_id == b.prop_id;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function properties_match(a:RelationshipSide,b:RelationshipSide){
|
|
56
|
-
if(!defined(a.prop_id) && !defined(b.prop_id)) return true;
|
|
57
|
-
else return a.prop_id == b.prop_id;
|
|
58
|
-
|
|
59
|
-
// return defined(a.prop_id) && defined(b.prop_id) && a.prop_id == b.prop_id;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function side_match(x:RelationshipSide,y:RelationshipSide){
|
|
63
|
-
return x.class_id==y.class_id&&properties_match(x,y);
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
export function full_relation_match(a:JunctionSides,b:JunctionSides):boolean{
|
|
67
|
-
return (side_match(a[0],b[0])&&side_match(a[1],b[1])) ||
|
|
68
|
-
(side_match(a[0],b[1])&&side_match(a[1],b[0]));
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export function valid_sides(sides:[RelationshipSideBase,RelationshipSideBase]):sides is [RelationshipSide,RelationshipSide]{
|
|
72
|
-
return defined(sides[0].class_id) && defined(sides[1].class_id)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function two_way(sides:JunctionSides){
|
|
76
|
-
return defined(sides[0].prop_id) && defined(sides[1].prop_id);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function edit_has_valid_sides(edit:RelationEdit):edit is RelationEditValidSides{
|
|
80
|
-
switch(edit.type){
|
|
81
|
-
case 'create':
|
|
82
|
-
if(valid_sides(edit.sides)) return true;
|
|
83
|
-
break;
|
|
84
|
-
case 'transfer':
|
|
85
|
-
if(valid_sides(edit.sides)&&valid_sides(edit.new_sides)) return true;
|
|
86
|
-
break;
|
|
87
|
-
case 'delete':{
|
|
88
|
-
return true;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
export function can_have_multiple_values(max_values:MaxValues){
|
|
97
|
-
return max_values==null || max_values>1;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function junction_col_name(class_id:number,prop_id:number | undefined | null):string{
|
|
101
|
-
let prop_str=defined(prop_id)?`_prop_${prop_id}`:``
|
|
102
|
-
return `class_${class_id}${prop_str}`;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
export function readable_side(side:RelationshipSide,classlist:ClassData[]){
|
|
107
|
-
let matching_class=classlist.find(c=>c.id==side.class_id);
|
|
108
|
-
let matching_prop=side.prop_id?(matching_class?.properties?.find(p=>p.id==side.prop_id)?.name || ''):'';
|
|
109
|
-
|
|
110
|
-
matching_prop=matching_prop?`.[${matching_prop}]`:'';
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return `${matching_class?.name || ''}${matching_prop}`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function readable_sides(sides:JunctionSides,classlist:ClassData[]){
|
|
117
|
-
return `${readable_side(sides[0],classlist)} <-> ${readable_side(sides[1],classlist)}`
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
export function readable_edit(edit:RelationEditValidSides,classlist:ClassData[]){
|
|
122
|
-
if(edit.type=='delete') return `deletion of relation ${edit.id}`;
|
|
123
|
-
else if (edit.type=='transfer') return `transfer of (${readable_sides(edit.sides,classlist)}) to (${readable_sides(edit.new_sides,classlist)})`;
|
|
124
|
-
else if (edit.type=='create') return `creation of (${readable_sides(edit.sides,classlist)})`;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
export function readable_junctionlist(relationships:JunctionList,classlist:ClassData[]){
|
|
129
|
-
|
|
130
|
-
return relationships.map((r)=>{
|
|
131
|
-
return readable_sides(r.sides,classlist)
|
|
132
|
-
})
|
|
133
|
-
}
|