goby-database 2.2.27 → 2.2.29
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/index.d.ts +21 -2
- package/dist/index.js +46 -51
- package/dist/utils.d.ts +11 -1
- package/dist/utils.js +43 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -70,12 +70,31 @@ export default class Project {
|
|
|
70
70
|
delete_item_from_root(id: number): void;
|
|
71
71
|
action_set_root_item_value(id: number, value: string): void;
|
|
72
72
|
lookup_class(class_id: number): ClassData;
|
|
73
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Creates a new item and adds it to the class you indicate
|
|
75
|
+
* @param class_id - class you want to add new item to
|
|
76
|
+
* @param property_values - any properties you want to fill in as you create this item (data props only for now)
|
|
77
|
+
* @returns - id of new item
|
|
78
|
+
*/
|
|
79
|
+
action_add_row(class_id: number, property_values?: {
|
|
80
|
+
property_id: number;
|
|
81
|
+
value: any;
|
|
82
|
+
}[]): number;
|
|
74
83
|
get_next_order(table_name: string): number;
|
|
75
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Sets 1 or more data property values for a given class item.
|
|
86
|
+
* @param class_id - class of item
|
|
87
|
+
* @param item_id - id of item
|
|
88
|
+
* @param changes - array of data properties to be set
|
|
89
|
+
*/
|
|
90
|
+
action_edit_item_data(class_id: number, item_id: number, changes: {
|
|
76
91
|
property_id: number;
|
|
77
92
|
value: any;
|
|
78
93
|
}[]): void;
|
|
94
|
+
/**
|
|
95
|
+
* Adds/removes relations between items/item properties
|
|
96
|
+
* @param relations - list of pairs of items for which relations should be added or removed between specified properties
|
|
97
|
+
*/
|
|
79
98
|
action_edit_relations(relations: {
|
|
80
99
|
change: 'add' | 'remove';
|
|
81
100
|
sides: [input_1: ItemRelationSide, input_2: ItemRelationSide];
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import Database from 'better-sqlite3';
|
|
2
|
-
import { defined, partial_relation_match, full_relation_match, can_have_multiple_values, junction_col_name, side_match, two_way, edit_has_valid_sides, readable_edit } from './utils.js';
|
|
3
|
-
const text_data_types = ['string', 'resource'];
|
|
4
|
-
const integer_data_types = ['boolean'];
|
|
5
|
-
const real_data_types = ['number'];
|
|
2
|
+
import { defined, partial_relation_match, full_relation_match, can_have_multiple_values, junction_col_name, side_match, two_way, edit_has_valid_sides, readable_edit, text_data_types, integer_data_types, real_data_types, validate_data_value } from './utils.js';
|
|
6
3
|
export default class Project {
|
|
7
4
|
constructor(source) {
|
|
8
5
|
this.class_cache = [];
|
|
@@ -689,14 +686,42 @@ export default class Project {
|
|
|
689
686
|
throw new Error('Cannot find class in class list.');
|
|
690
687
|
return class_data;
|
|
691
688
|
}
|
|
692
|
-
|
|
689
|
+
/**
|
|
690
|
+
* Creates a new item and adds it to the class you indicate
|
|
691
|
+
* @param class_id - class you want to add new item to
|
|
692
|
+
* @param property_values - any properties you want to fill in as you create this item (data props only for now)
|
|
693
|
+
* @returns - id of new item
|
|
694
|
+
*/
|
|
695
|
+
action_add_row(class_id, property_values = []) {
|
|
693
696
|
const class_data = this.lookup_class(class_id);
|
|
694
697
|
let class_name = class_data.name;
|
|
695
698
|
//first add new row to root and get id
|
|
696
699
|
const root_id = this.create_item_in_root({ type: 'class_' + class_id });
|
|
700
|
+
// NOTE: I will need a second handler in the future if I want to support relation props here
|
|
701
|
+
// (probably utilizing action_edit_relations)
|
|
702
|
+
const data_property_sql = property_values.reduce((obj, current) => {
|
|
703
|
+
const corresponding_prop = class_data.properties.find((prop) => {
|
|
704
|
+
return prop.id == current.property_id;
|
|
705
|
+
});
|
|
706
|
+
if ((corresponding_prop === null || corresponding_prop === void 0 ? void 0 : corresponding_prop.type) == 'data') {
|
|
707
|
+
const validated = validate_data_value(current.value, corresponding_prop.data_type, corresponding_prop.max_values);
|
|
708
|
+
if (validated.valid) {
|
|
709
|
+
const v = text_data_types.includes(corresponding_prop.data_type) ? `'${validated.output}'` : validated.output;
|
|
710
|
+
obj.columns += `, [user_${corresponding_prop.name}]`;
|
|
711
|
+
obj.values += `, ${v}`;
|
|
712
|
+
}
|
|
713
|
+
else {
|
|
714
|
+
console.log(`Did not modify ${corresponding_prop.name} for item: ${validated.message}`);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
return obj;
|
|
718
|
+
}, {
|
|
719
|
+
columns: '',
|
|
720
|
+
values: ''
|
|
721
|
+
});
|
|
697
722
|
//get the last item in class table order and use it to get the order for the new item
|
|
698
723
|
const new_order = this.get_next_order(`[class_${class_name}]`);
|
|
699
|
-
this.db.prepare(`INSERT INTO [class_${class_name}] (system_id, system_order) VALUES (${root_id},${new_order})`).run();
|
|
724
|
+
this.db.prepare(`INSERT INTO [class_${class_name}] (system_id, system_order${data_property_sql.columns}) VALUES (${root_id},${new_order}${data_property_sql.values})`).run();
|
|
700
725
|
return root_id;
|
|
701
726
|
}
|
|
702
727
|
get_next_order(table_name) {
|
|
@@ -704,15 +729,21 @@ export default class Project {
|
|
|
704
729
|
const new_order = last_ordered_item ? last_ordered_item.system_order + 1000 : 0;
|
|
705
730
|
return new_order;
|
|
706
731
|
}
|
|
707
|
-
|
|
708
|
-
|
|
732
|
+
/**
|
|
733
|
+
* Sets 1 or more data property values for a given class item.
|
|
734
|
+
* @param class_id - class of item
|
|
735
|
+
* @param item_id - id of item
|
|
736
|
+
* @param changes - array of data properties to be set
|
|
737
|
+
*/
|
|
738
|
+
action_edit_item_data(class_id, item_id, changes) {
|
|
739
|
+
// NOTE: seems like there should be a way to pair down "value:any" in params, maybe at least make it one of a few value types
|
|
709
740
|
const class_data = this.lookup_class(class_id);
|
|
710
741
|
const sql_column_inserts = [];
|
|
711
742
|
for (let change of changes) {
|
|
712
743
|
const prop_data = class_data.properties.find((p) => p.id == change.property_id);
|
|
713
744
|
if (prop_data && prop_data.type == 'data') {
|
|
714
745
|
// const data_type=prop_data.data_type;
|
|
715
|
-
const cell_value =
|
|
746
|
+
const cell_value = validate_data_value(change.value, prop_data.data_type, prop_data.max_values);
|
|
716
747
|
if (cell_value.valid) {
|
|
717
748
|
sql_column_inserts.push({
|
|
718
749
|
column_name: `[user_${prop_data.name}]`,
|
|
@@ -731,47 +762,11 @@ export default class Project {
|
|
|
731
762
|
const set_statements = sql_column_inserts.map((p) => `${p.column_name} = ?`).join(',');
|
|
732
763
|
const insert_statement = `UPDATE [class_${class_data.name}] SET ${set_statements} WHERE system_id=${item_id}`;
|
|
733
764
|
this.db.prepare(insert_statement).run(params);
|
|
734
|
-
function validate(input, data_type, max_values) {
|
|
735
|
-
const multiple = max_values == null || max_values > 1;
|
|
736
|
-
const values = multiple ? input : [input];
|
|
737
|
-
if (!Array.isArray(values)) {
|
|
738
|
-
return { valid: false, message: 'Expecting array, got single value' };
|
|
739
|
-
}
|
|
740
|
-
const validated_values = [];
|
|
741
|
-
for (let value of values) {
|
|
742
|
-
if (real_data_types.includes(data_type) || integer_data_types.includes(data_type)) {
|
|
743
|
-
if (data_type == 'boolean') {
|
|
744
|
-
if (typeof value == 'boolean' || [0, 1].includes(value)) {
|
|
745
|
-
validated_values.push(+value);
|
|
746
|
-
}
|
|
747
|
-
else {
|
|
748
|
-
return { valid: false, message: `Expecting boolean or binary integer, got "${value}" (${typeof value})` };
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
else if (typeof value == 'number') {
|
|
752
|
-
validated_values.push(value);
|
|
753
|
-
}
|
|
754
|
-
else {
|
|
755
|
-
return { valid: false, message: `Expecting number, got "${value}" (${typeof value})` };
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
else if (text_data_types.includes(data_type)) {
|
|
759
|
-
// NOTE: could come back to validate resource as links/filepaths later, but leaving unopinionated for now
|
|
760
|
-
if (typeof value == 'string') {
|
|
761
|
-
validated_values.push(value);
|
|
762
|
-
}
|
|
763
|
-
else {
|
|
764
|
-
return { valid: false, message: `Expecting string, got "${value}" (${typeof value})` };
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
const output = multiple ? JSON.stringify(validated_values) : validated_values[0];
|
|
769
|
-
return {
|
|
770
|
-
valid: true,
|
|
771
|
-
output
|
|
772
|
-
};
|
|
773
|
-
}
|
|
774
765
|
}
|
|
766
|
+
/**
|
|
767
|
+
* Adds/removes relations between items/item properties
|
|
768
|
+
* @param relations - list of pairs of items for which relations should be added or removed between specified properties
|
|
769
|
+
*/
|
|
775
770
|
action_edit_relations(relations) {
|
|
776
771
|
// NOTE: changes to make to this in the future:
|
|
777
772
|
// - for input readability, allow class_name and prop_name as input options, assuming they’re enforced as unique, and use them to look up IDs
|
|
@@ -895,8 +890,8 @@ export default class Project {
|
|
|
895
890
|
}
|
|
896
891
|
}
|
|
897
892
|
let orderby = `ORDER BY ${class_string}.system_order`;
|
|
898
|
-
const data_prop_sql_string = data_properties.map((p) => `[user_${p.name}]`).join(',');
|
|
899
|
-
const table_selection = pagination.property_range == 'all' ? `[class_${class_name}].*` : `system_id,system_order
|
|
893
|
+
const data_prop_sql_string = data_properties.length > 0 ? ', ' + data_properties.map((p) => `[user_${p.name}]`).join(',') : '';
|
|
894
|
+
const table_selection = pagination.property_range == 'all' ? `[class_${class_name}].*` : `system_id,system_order${data_prop_sql_string}`;
|
|
900
895
|
let filter_by_items = '';
|
|
901
896
|
if (pagination.item_range && pagination.item_range !== 'all') {
|
|
902
897
|
filter_by_items = `WHERE system_id in (${pagination.item_range.join(',')})`;
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { JunctionSides, RelationshipSide, MaxValues, RelationshipSideBase, RelationEdit, RelationEditValidSides, ClassData, JunctionList } from "./types.js";
|
|
1
|
+
import { JunctionSides, RelationshipSide, MaxValues, RelationshipSideBase, RelationEdit, RelationEditValidSides, ClassData, JunctionList, DataType } from "./types.js";
|
|
2
2
|
export declare function defined<T>(v: T): v is NonNullable<T>;
|
|
3
|
+
export declare const text_data_types: string[];
|
|
4
|
+
export declare const integer_data_types: string[];
|
|
5
|
+
export declare const real_data_types: string[];
|
|
3
6
|
export declare function partial_relation_match(old_relation: JunctionSides, new_relation: JunctionSides): boolean;
|
|
4
7
|
export declare function side_match(x: RelationshipSide, y: RelationshipSide): boolean;
|
|
5
8
|
export declare function full_relation_match(a: JunctionSides, b: JunctionSides): boolean;
|
|
@@ -11,3 +14,10 @@ export declare function junction_col_name(class_id: number, prop_id: number | un
|
|
|
11
14
|
export declare function readable_side(side: RelationshipSide, classlist: ClassData[]): string;
|
|
12
15
|
export declare function readable_edit(edit: RelationEditValidSides, classlist: ClassData[]): string | undefined;
|
|
13
16
|
export declare function readable_junctionlist(relationships: JunctionList, classlist: ClassData[]): string[];
|
|
17
|
+
export declare function validate_data_value(input: any, data_type: DataType, max_values: MaxValues): {
|
|
18
|
+
valid: true;
|
|
19
|
+
output: string | number;
|
|
20
|
+
} | {
|
|
21
|
+
valid: false;
|
|
22
|
+
message: string;
|
|
23
|
+
};
|
package/dist/utils.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export function defined(v) {
|
|
2
2
|
return v !== undefined && v !== null;
|
|
3
3
|
}
|
|
4
|
+
export const text_data_types = ['string', 'resource'];
|
|
5
|
+
export const integer_data_types = ['boolean'];
|
|
6
|
+
export const real_data_types = ['number'];
|
|
4
7
|
// given the type above,
|
|
5
8
|
// check if two relations share class ids on both sides
|
|
6
9
|
// and share a property id on at least one side
|
|
@@ -103,4 +106,44 @@ export function readable_junctionlist(relationships, classlist) {
|
|
|
103
106
|
return readable_sides(r.sides, classlist);
|
|
104
107
|
});
|
|
105
108
|
}
|
|
109
|
+
export function validate_data_value(input, data_type, max_values) {
|
|
110
|
+
const multiple = max_values == null || max_values > 1;
|
|
111
|
+
const values = multiple ? input : [input];
|
|
112
|
+
if (!Array.isArray(values)) {
|
|
113
|
+
return { valid: false, message: 'Expecting array, got single value' };
|
|
114
|
+
}
|
|
115
|
+
const validated_values = [];
|
|
116
|
+
for (let value of values) {
|
|
117
|
+
if (real_data_types.includes(data_type) || integer_data_types.includes(data_type)) {
|
|
118
|
+
if (data_type == 'boolean') {
|
|
119
|
+
if (typeof value == 'boolean' || [0, 1].includes(value)) {
|
|
120
|
+
validated_values.push(+value);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
return { valid: false, message: `Expecting boolean or binary integer, got "${value}" (${typeof value})` };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else if (typeof value == 'number') {
|
|
127
|
+
validated_values.push(value);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
return { valid: false, message: `Expecting number, got "${value}" (${typeof value})` };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else if (text_data_types.includes(data_type)) {
|
|
134
|
+
// NOTE: could come back to validate resource as links/filepaths later, but leaving unopinionated for now
|
|
135
|
+
if (typeof value == 'string') {
|
|
136
|
+
validated_values.push(value);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
return { valid: false, message: `Expecting string, got "${value}" (${typeof value})` };
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const output = multiple ? JSON.stringify(validated_values) : validated_values[0];
|
|
144
|
+
return {
|
|
145
|
+
valid: true,
|
|
146
|
+
output
|
|
147
|
+
};
|
|
148
|
+
}
|
|
106
149
|
//# sourceMappingURL=utils.js.map
|