@quatrain/core 1.1.24 → 1.1.28
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/README.md +56 -8
- package/{lib → dist}/Core.d.ts +3 -17
- package/dist/Core.d.ts.map +1 -0
- package/dist/Core.js +105 -0
- package/dist/Core.js.map +1 -0
- package/dist/common/DataGenerator.d.ts +3 -0
- package/dist/common/DataGenerator.d.ts.map +1 -0
- package/dist/common/DataGenerator.js +86 -0
- package/dist/common/DataGenerator.js.map +1 -0
- package/{lib → dist}/common/ResourcesErrors.d.ts +1 -0
- package/dist/common/ResourcesErrors.d.ts.map +1 -0
- package/{lib → dist}/common/ResourcesErrors.js +1 -0
- package/dist/common/ResourcesErrors.js.map +1 -0
- package/{lib → dist}/common/statuses.d.ts +1 -0
- package/dist/common/statuses.d.ts.map +1 -0
- package/{lib → dist}/common/statuses.js +1 -0
- package/dist/common/statuses.js.map +1 -0
- package/{lib → dist}/components/AbstractObject.d.ts +1 -5
- package/dist/components/AbstractObject.d.ts.map +1 -0
- package/{lib → dist}/components/AbstractObject.js +7 -10
- package/dist/components/AbstractObject.js.map +1 -0
- package/{lib → dist}/components/BaseObject.d.ts +4 -17
- package/dist/components/BaseObject.d.ts.map +1 -0
- package/dist/components/BaseObject.js +71 -0
- package/dist/components/BaseObject.js.map +1 -0
- package/dist/components/BaseObjectProperties.d.ts +2 -0
- package/dist/components/BaseObjectProperties.d.ts.map +1 -0
- package/{lib → dist}/components/BaseObjectProperties.js +1 -2
- package/dist/components/BaseObjectProperties.js.map +1 -0
- package/{lib → dist}/components/DataObject.d.ts +2 -51
- package/dist/components/DataObject.d.ts.map +1 -0
- package/{lib → dist}/components/DataObject.js +38 -111
- package/dist/components/DataObject.js.map +1 -0
- package/{lib → dist}/components/Entity.d.ts +1 -0
- package/dist/components/Entity.d.ts.map +1 -0
- package/dist/components/Entity.js +48 -0
- package/dist/components/Entity.js.map +1 -0
- package/{lib → dist}/components/ObjectUri.d.ts +1 -26
- package/dist/components/ObjectUri.d.ts.map +1 -0
- package/{lib → dist}/components/ObjectUri.js +13 -41
- package/dist/components/ObjectUri.js.map +1 -0
- package/{lib → dist}/components/User.d.ts +1 -0
- package/dist/components/User.d.ts.map +1 -0
- package/{lib → dist}/components/User.js +7 -26
- package/dist/components/User.js.map +1 -0
- package/dist/components/__test__/fixtures/dao.d.ts +37 -0
- package/dist/components/__test__/fixtures/dao.d.ts.map +1 -0
- package/dist/components/__test__/fixtures/dao.js +100 -0
- package/dist/components/__test__/fixtures/dao.js.map +1 -0
- package/{lib → dist}/components/index.d.ts +5 -2
- package/dist/components/index.d.ts.map +1 -0
- package/{lib → dist}/components/index.js +1 -0
- package/dist/components/index.js.map +1 -0
- package/{lib → dist}/components/types/AbstractObjectClass.d.ts +1 -0
- package/dist/components/types/AbstractObjectClass.d.ts.map +1 -0
- package/dist/components/types/AbstractObjectClass.js +3 -0
- package/dist/components/types/AbstractObjectClass.js.map +1 -0
- package/{lib → dist}/components/types/BaseObjectClass.d.ts +1 -0
- package/dist/components/types/BaseObjectClass.d.ts.map +1 -0
- package/{lib → dist}/components/types/BaseObjectClass.js +1 -0
- package/dist/components/types/BaseObjectClass.js.map +1 -0
- package/{lib → dist}/components/types/BaseObjectType.d.ts +2 -1
- package/dist/components/types/BaseObjectType.d.ts.map +1 -0
- package/{lib → dist}/components/types/BaseObjectType.js +1 -0
- package/dist/components/types/BaseObjectType.js.map +1 -0
- package/{lib → dist}/components/types/DataObjectClass.d.ts +1 -0
- package/dist/components/types/DataObjectClass.d.ts.map +1 -0
- package/{lib → dist}/components/types/DataObjectClass.js +1 -0
- package/dist/components/types/DataObjectClass.js.map +1 -0
- package/dist/components/types/DataObjectParams.d.ts +8 -0
- package/dist/components/types/DataObjectParams.d.ts.map +1 -0
- package/dist/components/types/DataObjectParams.js +3 -0
- package/dist/components/types/DataObjectParams.js.map +1 -0
- package/{lib → dist}/components/types/DataObjectType.d.ts +1 -0
- package/dist/components/types/DataObjectType.d.ts.map +1 -0
- package/{lib → dist}/components/types/DataObjectType.js +1 -0
- package/dist/components/types/DataObjectType.js.map +1 -0
- package/{lib → dist}/components/types/EntityClass.d.ts +1 -0
- package/dist/components/types/EntityClass.d.ts.map +1 -0
- package/{lib → dist}/components/types/EntityClass.js +1 -0
- package/dist/components/types/EntityClass.js.map +1 -0
- package/{lib → dist}/components/types/Payload.d.ts +1 -0
- package/dist/components/types/Payload.d.ts.map +1 -0
- package/{lib → dist}/components/types/Payload.js +1 -0
- package/dist/components/types/Payload.js.map +1 -0
- package/{lib → dist}/components/types/Persisted.d.ts +1 -0
- package/dist/components/types/Persisted.d.ts.map +1 -0
- package/{lib → dist}/components/types/Persisted.js +1 -0
- package/dist/components/types/Persisted.js.map +1 -0
- package/dist/components/types/Properties.d.ts +2 -0
- package/dist/components/types/Properties.d.ts.map +1 -0
- package/{lib/components/types/AbstractObjectClass.js → dist/components/types/Properties.js} +1 -0
- package/dist/components/types/Properties.js.map +1 -0
- package/{lib → dist}/components/types/ProxyConstructor.d.ts +1 -0
- package/dist/components/types/ProxyConstructor.d.ts.map +1 -0
- package/{lib → dist}/components/types/ProxyConstructor.js +1 -0
- package/dist/components/types/ProxyConstructor.js.map +1 -0
- package/{lib → dist}/components/types/toJSONParams.d.ts +1 -0
- package/dist/components/types/toJSONParams.d.ts.map +1 -0
- package/{lib → dist}/components/types/toJSONParams.js +1 -0
- package/dist/components/types/toJSONParams.js.map +1 -0
- package/{lib → dist}/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -0
- package/{lib → dist}/index.js +4 -1
- package/dist/index.js.map +1 -0
- package/{lib → dist}/properties/ArrayProperty.d.ts +1 -0
- package/dist/properties/ArrayProperty.d.ts.map +1 -0
- package/{lib → dist}/properties/ArrayProperty.js +5 -4
- package/dist/properties/ArrayProperty.js.map +1 -0
- package/{lib → dist}/properties/BaseProperty.d.ts +3 -2
- package/dist/properties/BaseProperty.d.ts.map +1 -0
- package/{lib → dist}/properties/BaseProperty.js +18 -11
- package/dist/properties/BaseProperty.js.map +1 -0
- package/{lib → dist}/properties/BooleanProperty.d.ts +1 -0
- package/dist/properties/BooleanProperty.d.ts.map +1 -0
- package/{lib → dist}/properties/BooleanProperty.js +2 -1
- package/dist/properties/BooleanProperty.js.map +1 -0
- package/{lib → dist}/properties/CollectionProperty.d.ts +1 -0
- package/dist/properties/CollectionProperty.d.ts.map +1 -0
- package/{lib → dist}/properties/CollectionProperty.js +6 -4
- package/dist/properties/CollectionProperty.js.map +1 -0
- package/{lib → dist}/properties/DateTimeProperty.d.ts +1 -0
- package/dist/properties/DateTimeProperty.d.ts.map +1 -0
- package/{lib → dist}/properties/DateTimeProperty.js +12 -5
- package/dist/properties/DateTimeProperty.js.map +1 -0
- package/{lib → dist}/properties/EnumProperty.d.ts +1 -0
- package/dist/properties/EnumProperty.d.ts.map +1 -0
- package/{lib → dist}/properties/EnumProperty.js +4 -3
- package/dist/properties/EnumProperty.js.map +1 -0
- package/{lib → dist}/properties/FileProperty.d.ts +1 -0
- package/dist/properties/FileProperty.d.ts.map +1 -0
- package/{lib → dist}/properties/FileProperty.js +3 -2
- package/dist/properties/FileProperty.js.map +1 -0
- package/{lib → dist}/properties/HashProperty.d.ts +2 -7
- package/dist/properties/HashProperty.d.ts.map +1 -0
- package/{lib → dist}/properties/HashProperty.js +15 -23
- package/dist/properties/HashProperty.js.map +1 -0
- package/{lib → dist}/properties/MapProperty.d.ts +1 -0
- package/dist/properties/MapProperty.d.ts.map +1 -0
- package/{lib → dist}/properties/MapProperty.js +2 -1
- package/dist/properties/MapProperty.js.map +1 -0
- package/{lib → dist}/properties/NumberProperty.d.ts +1 -0
- package/dist/properties/NumberProperty.d.ts.map +1 -0
- package/{lib → dist}/properties/NumberProperty.js +15 -14
- package/dist/properties/NumberProperty.js.map +1 -0
- package/{lib → dist}/properties/ObjectProperty.d.ts +1 -0
- package/dist/properties/ObjectProperty.d.ts.map +1 -0
- package/{lib → dist}/properties/ObjectProperty.js +4 -3
- package/dist/properties/ObjectProperty.js.map +1 -0
- package/{lib → dist}/properties/Property.d.ts +1 -0
- package/dist/properties/Property.d.ts.map +1 -0
- package/{lib → dist}/properties/Property.js +12 -11
- package/dist/properties/Property.js.map +1 -0
- package/{lib → dist}/properties/StringProperty.d.ts +3 -5
- package/dist/properties/StringProperty.d.ts.map +1 -0
- package/{lib → dist}/properties/StringProperty.js +20 -28
- package/dist/properties/StringProperty.js.map +1 -0
- package/{lib → dist}/properties/index.d.ts +4 -2
- package/dist/properties/index.d.ts.map +1 -0
- package/{lib → dist}/properties/index.js +1 -0
- package/dist/properties/index.js.map +1 -0
- package/{lib → dist}/properties/types/AbstractPropertyType.d.ts +1 -0
- package/dist/properties/types/AbstractPropertyType.d.ts.map +1 -0
- package/{lib → dist}/properties/types/AbstractPropertyType.js +1 -0
- package/dist/properties/types/AbstractPropertyType.js.map +1 -0
- package/{lib → dist}/properties/types/PropertyClassType.d.ts +1 -0
- package/dist/properties/types/PropertyClassType.d.ts.map +1 -0
- package/{lib → dist}/properties/types/PropertyClassType.js +1 -0
- package/dist/properties/types/PropertyClassType.js.map +1 -0
- package/{lib → dist}/properties/types/PropertyHTMLType.d.ts +1 -0
- package/dist/properties/types/PropertyHTMLType.d.ts.map +1 -0
- package/{lib → dist}/properties/types/PropertyHTMLType.js +1 -2
- package/dist/properties/types/PropertyHTMLType.js.map +1 -0
- package/{lib → dist}/properties/types/PropertyTypes.d.ts +1 -0
- package/dist/properties/types/PropertyTypes.d.ts.map +1 -0
- package/{lib → dist}/properties/types/PropertyTypes.js +1 -0
- package/dist/properties/types/PropertyTypes.js.map +1 -0
- package/package.json +47 -46
- package/src/Core.ts +145 -0
- package/src/common/DataGenerator.ts +81 -0
- package/src/common/ResourcesErrors.ts +17 -0
- package/src/common/statuses.ts +20 -0
- package/src/components/AbstractObject.ts +71 -0
- package/src/components/BaseObject.ts +123 -0
- package/src/components/BaseObjectProperties.ts +65 -0
- package/src/components/DataObject.ts +418 -0
- package/src/components/Entity.ts +38 -0
- package/src/components/ObjectUri.test.ts +74 -0
- package/src/components/ObjectUri.ts +174 -0
- package/src/components/User.ts +111 -0
- package/src/components/index.ts +19 -0
- package/src/components/types/AbstractObjectClass.ts +7 -0
- package/src/components/types/BaseObjectClass.ts +8 -0
- package/src/components/types/BaseObjectType.ts +10 -0
- package/src/components/types/DataObjectClass.ts +27 -0
- package/src/components/types/DataObjectParams.ts +8 -0
- package/src/components/types/DataObjectType.ts +27 -0
- package/src/components/types/EntityClass.ts +3 -0
- package/src/components/types/Payload.ts +11 -0
- package/src/components/types/Persisted.ts +7 -0
- package/src/components/types/Properties.ts +1 -0
- package/src/components/types/ProxyConstructor.ts +13 -0
- package/src/components/types/toJSONParams.ts +12 -0
- package/src/index.ts +97 -0
- package/src/properties/ArrayProperty.test.ts +46 -0
- package/src/properties/ArrayProperty.ts +87 -0
- package/src/properties/BaseProperty.test.ts +79 -0
- package/src/properties/BaseProperty.ts +140 -0
- package/src/properties/BooleanProperty.ts +11 -0
- package/src/properties/CollectionProperty.test.ts +22 -0
- package/src/properties/CollectionProperty.ts +43 -0
- package/src/properties/DateTimeProperty.ts +47 -0
- package/src/properties/EnumProperty.ts +36 -0
- package/src/properties/FileProperty.ts +14 -0
- package/src/properties/HashProperty.test.ts +108 -0
- package/src/properties/HashProperty.ts +70 -0
- package/src/properties/MapProperty.ts +19 -0
- package/src/properties/NumberProperty.test.ts +38 -0
- package/src/properties/NumberProperty.ts +110 -0
- package/src/properties/ObjectProperty.ts +118 -0
- package/src/properties/Property.ts +85 -0
- package/src/properties/StringProperty.test.ts +46 -0
- package/src/properties/StringProperty.ts +121 -0
- package/src/properties/index.ts +62 -0
- package/src/properties/types/AbstractPropertyType.ts +8 -0
- package/src/properties/types/PropertyClassType.ts +11 -0
- package/src/properties/types/PropertyHTMLType.ts +23 -0
- package/src/properties/types/PropertyTypes.ts +13 -0
- package/lib/Core.js +0 -133
- package/lib/components/BaseObject.js +0 -103
- package/lib/components/BaseObjectProperties.d.ts +0 -1
- package/lib/components/Entity.js +0 -71
- package/lib/components/types/Properties.d.ts +0 -3
- package/lib/components/types/Properties.js +0 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { ObjectUri } from './ObjectUri'
|
|
2
|
+
import { DataObjectClass } from './types/DataObjectClass'
|
|
3
|
+
import { DataObject } from './DataObject'
|
|
4
|
+
import { BaseObjectType } from './types/BaseObjectType'
|
|
5
|
+
import { BaseObjectProperties } from './BaseObjectProperties'
|
|
6
|
+
import { AbstractObject } from './AbstractObject'
|
|
7
|
+
import { DataObjectType } from './types/DataObjectType'
|
|
8
|
+
|
|
9
|
+
export class BaseObject extends AbstractObject {
|
|
10
|
+
// implements BaseObjectClass {
|
|
11
|
+
static PROPS_DEFINITION: any /*DataObjectProperties*/ = BaseObjectProperties
|
|
12
|
+
|
|
13
|
+
static getProperty(key: string) {
|
|
14
|
+
return BaseObject.PROPS_DEFINITION.find((prop: any) => prop.name === key)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static fillProperties(child: any = this) {
|
|
18
|
+
// merge base properties with additional or redefined ones
|
|
19
|
+
const base = [...BaseObject.PROPS_DEFINITION]
|
|
20
|
+
|
|
21
|
+
child.PROPS_DEFINITION.forEach((property: any) => {
|
|
22
|
+
// manage parent properties potential redeclaration
|
|
23
|
+
const found = base.findIndex((el: any) => el.name === property.name)
|
|
24
|
+
if (found !== -1) {
|
|
25
|
+
base[found] = property
|
|
26
|
+
} else {
|
|
27
|
+
base.push(property)
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const dao = DataObject.factory({
|
|
32
|
+
properties: base,
|
|
33
|
+
parentProp: this.PARENT_PROP,
|
|
34
|
+
})
|
|
35
|
+
dao.uri.class = child
|
|
36
|
+
|
|
37
|
+
return dao
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static async daoFactory(
|
|
41
|
+
src: string | ObjectUri | DataObjectType | undefined = undefined,
|
|
42
|
+
child: any = this
|
|
43
|
+
): Promise<DataObjectType> {
|
|
44
|
+
const dao = this.fillProperties(child)
|
|
45
|
+
|
|
46
|
+
return dao
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Instantiates from an object
|
|
51
|
+
* @param src
|
|
52
|
+
* @param child
|
|
53
|
+
* @returns
|
|
54
|
+
*/
|
|
55
|
+
static fromObject<T extends BaseObjectType>(src: T, child: any = this): any {
|
|
56
|
+
const dao = this.fillProperties(child)
|
|
57
|
+
|
|
58
|
+
dao.uri = new ObjectUri(
|
|
59
|
+
`${this.COLLECTION}${ObjectUri.DEFAULT}`,
|
|
60
|
+
Reflect.get(src, 'name')
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
dao.uri.class = child
|
|
64
|
+
|
|
65
|
+
dao.populateFromData(src as any)
|
|
66
|
+
|
|
67
|
+
const obj = new this(dao)
|
|
68
|
+
|
|
69
|
+
return obj
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
static async factory(
|
|
73
|
+
src: string | ObjectUri | BaseObjectType | undefined = undefined,
|
|
74
|
+
child: any = this
|
|
75
|
+
): Promise<any> {
|
|
76
|
+
try {
|
|
77
|
+
if (typeof src == 'object' && !(src instanceof ObjectUri)) {
|
|
78
|
+
return this.fromObject(src)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const dao = await this.daoFactory(src, child)
|
|
82
|
+
|
|
83
|
+
const constructedObject = Reflect.construct(this, [dao])
|
|
84
|
+
|
|
85
|
+
return constructedObject
|
|
86
|
+
} catch (err) {
|
|
87
|
+
throw new Error(
|
|
88
|
+
`Unable to build instance for '${this.name}': ${
|
|
89
|
+
(err as Error).message
|
|
90
|
+
}`
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Fetches an object from its backend path
|
|
97
|
+
* @param path
|
|
98
|
+
* @returns
|
|
99
|
+
*/
|
|
100
|
+
static async fromBackend<T>(path: string): Promise<T> {
|
|
101
|
+
if (!path.includes('/')) {
|
|
102
|
+
return this.factory(`${this.COLLECTION}/${path}`)
|
|
103
|
+
}
|
|
104
|
+
return this.factory(path)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Instantiates from a DataObject
|
|
109
|
+
* @param dao
|
|
110
|
+
* @returns
|
|
111
|
+
*/
|
|
112
|
+
static fromDataObject<T extends BaseObjectType>(
|
|
113
|
+
dao: DataObjectClass<any>
|
|
114
|
+
): any {
|
|
115
|
+
const obj = new this(dao)
|
|
116
|
+
|
|
117
|
+
return obj //.toProxy()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
asReference() {
|
|
121
|
+
return this._dataObject.toReference()
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as statuses from '../common/statuses'
|
|
2
|
+
import { StringProperty } from '../properties/StringProperty'
|
|
3
|
+
import { ObjectProperty } from '../properties/ObjectProperty'
|
|
4
|
+
import { EnumProperty } from '../properties/EnumProperty'
|
|
5
|
+
import { DateTimeProperty } from '../properties/DateTimeProperty'
|
|
6
|
+
import * as htmlType from '../properties/types/PropertyHTMLType'
|
|
7
|
+
|
|
8
|
+
export const BaseObjectProperties: any = [
|
|
9
|
+
{
|
|
10
|
+
name: 'name',
|
|
11
|
+
mandatory: true,
|
|
12
|
+
type: StringProperty.TYPE,
|
|
13
|
+
minLength: 1,
|
|
14
|
+
maxLength: 100,
|
|
15
|
+
fullSearch: true,
|
|
16
|
+
htmlType: htmlType.NAME,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'status',
|
|
20
|
+
mandatory: true,
|
|
21
|
+
type: EnumProperty.TYPE,
|
|
22
|
+
values: [
|
|
23
|
+
statuses.CREATED,
|
|
24
|
+
statuses.PENDING,
|
|
25
|
+
statuses.ACTIVE,
|
|
26
|
+
statuses.DELETED,
|
|
27
|
+
],
|
|
28
|
+
defaultValue: statuses.CREATED,
|
|
29
|
+
},
|
|
30
|
+
// the following properties may be optionally
|
|
31
|
+
// populated with a backend middleware
|
|
32
|
+
{
|
|
33
|
+
name: 'createdBy',
|
|
34
|
+
type: ObjectProperty.TYPE,
|
|
35
|
+
instanceOf: 'User',
|
|
36
|
+
mandatory: true,
|
|
37
|
+
protected: true,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'createdAt',
|
|
41
|
+
type: DateTimeProperty.TYPE,
|
|
42
|
+
mandatory: true,
|
|
43
|
+
protected: true,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'updatedBy',
|
|
47
|
+
type: ObjectProperty.TYPE,
|
|
48
|
+
instanceOf: 'User',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'updatedAt',
|
|
52
|
+
type: DateTimeProperty.TYPE,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'deletedBy',
|
|
56
|
+
type: ObjectProperty.TYPE,
|
|
57
|
+
instanceOf: 'User',
|
|
58
|
+
protected: true,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'deletedAt',
|
|
62
|
+
type: DateTimeProperty.TYPE,
|
|
63
|
+
protected: true,
|
|
64
|
+
},
|
|
65
|
+
]
|
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
import { Property } from '../properties/Property'
|
|
2
|
+
import { PropertyClassType } from '../properties/types/PropertyClassType'
|
|
3
|
+
import { AbstractObject } from './AbstractObject'
|
|
4
|
+
import { ObjectUri } from './ObjectUri'
|
|
5
|
+
import { NotFoundError } from '../common/ResourcesErrors'
|
|
6
|
+
import { toJSONParams } from './types/toJSONParams'
|
|
7
|
+
import { BaseObject } from './BaseObject'
|
|
8
|
+
import { DataObjectType } from './types/DataObjectType'
|
|
9
|
+
import { DataObjectParams } from './types/DataObjectParams'
|
|
10
|
+
|
|
11
|
+
export type CoreObject<T extends AbstractObject> = T
|
|
12
|
+
|
|
13
|
+
export type Properties = { [x: string]: PropertyClassType }
|
|
14
|
+
|
|
15
|
+
export interface DataObjectFactoryType {
|
|
16
|
+
path: string
|
|
17
|
+
[x: string]: any
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Data objects constitute the agnostic glue between objects and backends.
|
|
22
|
+
* They handle data and identifiers in a protected registry
|
|
23
|
+
* This is what backends and objects manipulate, oblivious of the other.
|
|
24
|
+
*/
|
|
25
|
+
export class DataObject implements DataObjectType {
|
|
26
|
+
protected _objectUri: ObjectUri
|
|
27
|
+
protected _uid: string | undefined = undefined
|
|
28
|
+
protected _properties: Properties = {}
|
|
29
|
+
protected _populated: boolean = false
|
|
30
|
+
protected _parentProp: string | undefined
|
|
31
|
+
|
|
32
|
+
protected _proxied: any
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Has data been modified since last backend operation?
|
|
36
|
+
*/
|
|
37
|
+
protected _modified: boolean = false
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Constructor is protected, use factory() instead
|
|
41
|
+
* @param params object of parameters
|
|
42
|
+
*/
|
|
43
|
+
protected constructor(params: DataObjectParams | undefined) {
|
|
44
|
+
if (params) {
|
|
45
|
+
if (typeof params.uri !== 'object') {
|
|
46
|
+
this._objectUri = new ObjectUri(params.uri)
|
|
47
|
+
} else {
|
|
48
|
+
this._objectUri = params.uri
|
|
49
|
+
}
|
|
50
|
+
this._parentProp = params.parentProp
|
|
51
|
+
} else {
|
|
52
|
+
this._objectUri = new ObjectUri()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (params && Array.isArray(params.properties)) {
|
|
56
|
+
this._init(params.properties)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
protected _init(properties: any[]) {
|
|
61
|
+
properties.forEach((prop) => {
|
|
62
|
+
this._properties[prop.name] = Property.factory(prop, this)
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Wrap instance into proxy to get access to properties
|
|
68
|
+
* @returns Proxy
|
|
69
|
+
*/
|
|
70
|
+
public asProxy() {
|
|
71
|
+
return new Proxy(this, {
|
|
72
|
+
get: (target, prop) => {
|
|
73
|
+
return target.val(prop as string)
|
|
74
|
+
},
|
|
75
|
+
set(target, prop, newValue) {
|
|
76
|
+
if (prop === 'uid' || prop === 'core') {
|
|
77
|
+
throw new Error(`Property '${prop}' is readonly`)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
target.set(prop as string, newValue)
|
|
81
|
+
return true
|
|
82
|
+
},
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public setProperties(properties: Properties) {
|
|
87
|
+
// TODO check if doable
|
|
88
|
+
this._properties = properties
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Return a map of all propoerties or only those matching the provided type
|
|
93
|
+
* @param type
|
|
94
|
+
* @returns
|
|
95
|
+
*/
|
|
96
|
+
public getProperties(type?: string) {
|
|
97
|
+
if (type) {
|
|
98
|
+
const matches = {}
|
|
99
|
+
for (let k of Object.keys(this._properties)) {
|
|
100
|
+
if (this._properties[k].constructor.name === type) {
|
|
101
|
+
Reflect.set(matches, k, this._properties[k])
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return matches
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return this._properties
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public addProperty(property: PropertyClassType) {
|
|
112
|
+
if (Object.keys(this._properties).includes(property.name)) {
|
|
113
|
+
throw new Error(`Property ${property.name} already exists`)
|
|
114
|
+
}
|
|
115
|
+
this._properties[property.name] = property
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Populate data object from instant data or backend query
|
|
120
|
+
* @param data
|
|
121
|
+
*/
|
|
122
|
+
async populate(
|
|
123
|
+
data: { name: string; [x: string]: unknown } | undefined = undefined
|
|
124
|
+
): Promise<DataObject> {
|
|
125
|
+
if (this._populated === false) {
|
|
126
|
+
if (data) {
|
|
127
|
+
this.populateFromData(data)
|
|
128
|
+
// } else if (this.path !== '/' && this.path !== '') {
|
|
129
|
+
// await this.populateFromBackend()
|
|
130
|
+
}
|
|
131
|
+
this._populated = true
|
|
132
|
+
|
|
133
|
+
if (Reflect.get(this._properties, 'name')) {
|
|
134
|
+
this.uri.label = this.val('name')
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return this
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Populate data object from instant data or backend query
|
|
143
|
+
* @param data
|
|
144
|
+
*/
|
|
145
|
+
populateFromData(data: { [x: string]: unknown }): this {
|
|
146
|
+
if (this._populated === false) {
|
|
147
|
+
for (const key in data) {
|
|
148
|
+
if (Reflect.get(this._properties, key)) {
|
|
149
|
+
const val = data[key]
|
|
150
|
+
if (
|
|
151
|
+
val &&
|
|
152
|
+
typeof val === 'object' &&
|
|
153
|
+
!val.hasOwnProperty('bucket') &&
|
|
154
|
+
'ref' in val &&
|
|
155
|
+
typeof val.ref == 'string' &&
|
|
156
|
+
'label' in val &&
|
|
157
|
+
typeof val.label == 'string'
|
|
158
|
+
) {
|
|
159
|
+
const { ref, label } = val
|
|
160
|
+
|
|
161
|
+
Reflect.get(this._properties, key).set(
|
|
162
|
+
new ObjectUri(ref, label),
|
|
163
|
+
false
|
|
164
|
+
)
|
|
165
|
+
} else {
|
|
166
|
+
Reflect.get(this._properties, key).set(data[key], false)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
this._populated = true
|
|
172
|
+
|
|
173
|
+
if (Reflect.get(this._properties, 'name')) {
|
|
174
|
+
this.uri.label = this.val('name')
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return this
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
isPopulated() {
|
|
182
|
+
return this._populated
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
get properties(): Properties {
|
|
186
|
+
return this._properties
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// get backend() {
|
|
190
|
+
// return this._objectUri ? this._objectUri.backend : undefined
|
|
191
|
+
// }
|
|
192
|
+
|
|
193
|
+
get path() {
|
|
194
|
+
return this._objectUri ? this._objectUri.path : ''
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
set uid(uid: string | undefined) {
|
|
198
|
+
if (this._uid !== undefined) {
|
|
199
|
+
throw new Error(`DataObject already has an uid`)
|
|
200
|
+
}
|
|
201
|
+
this._uid = uid
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
get uid(): string | undefined {
|
|
205
|
+
return this._objectUri ? this._objectUri.uid : undefined
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
get data(): any {
|
|
209
|
+
return this._properties
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
set uri(uri: ObjectUri) {
|
|
213
|
+
this._objectUri = uri
|
|
214
|
+
if (this._objectUri.collection !== ObjectUri.MISSING_COLLECTION) {
|
|
215
|
+
// this._persisted = true
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
get uri(): ObjectUri {
|
|
220
|
+
return this._objectUri
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
get class(): any {
|
|
224
|
+
// TODO get class type
|
|
225
|
+
return this.uri.class
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
get parentProp() {
|
|
229
|
+
return this._parentProp
|
|
230
|
+
}
|
|
231
|
+
set parentProp(str) {
|
|
232
|
+
this._parentProp = str
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
has(key: string) {
|
|
236
|
+
return Reflect.has(this._properties, key)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Returns property matching key or throw
|
|
241
|
+
* @param key string
|
|
242
|
+
* @returns BaseProperty
|
|
243
|
+
*/
|
|
244
|
+
get(key: string) {
|
|
245
|
+
if (!Reflect.has(this._properties, key)) {
|
|
246
|
+
throw new NotFoundError(`No property matching key '${key}'`)
|
|
247
|
+
}
|
|
248
|
+
return Reflect.get(this._properties, key)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
set(key: string, val: any) {
|
|
252
|
+
if (!this.has(key)) {
|
|
253
|
+
throw new Error(`Unknown property in data object: ${key}`)
|
|
254
|
+
}
|
|
255
|
+
this._properties[key].set(val)
|
|
256
|
+
this._populated = true
|
|
257
|
+
this._modified = true
|
|
258
|
+
|
|
259
|
+
return this
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Get value of given property
|
|
264
|
+
* @param key string
|
|
265
|
+
* @returns any
|
|
266
|
+
*/
|
|
267
|
+
val(key: string, transform: string | undefined = undefined) {
|
|
268
|
+
if (this.has(key)) {
|
|
269
|
+
return Reflect.get(this._properties, key).val(transform)
|
|
270
|
+
} else {
|
|
271
|
+
return undefined
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
toJSON(params: boolean | toJSONParams = false): { [x: string]: any } {
|
|
276
|
+
let objectsAsReferences: boolean = false,
|
|
277
|
+
withoutURIData: boolean = false,
|
|
278
|
+
ignoreUnchanged: boolean = false,
|
|
279
|
+
ignoreNulls: boolean = false,
|
|
280
|
+
converters: any = {}
|
|
281
|
+
|
|
282
|
+
if (typeof params === 'object') {
|
|
283
|
+
// Any missing parameter should resolve to false
|
|
284
|
+
objectsAsReferences = Boolean(params.objectsAsReferences)
|
|
285
|
+
withoutURIData = Boolean(params.withoutURIData)
|
|
286
|
+
ignoreUnchanged = Boolean(params.ignoreUnchanged)
|
|
287
|
+
ignoreNulls = Boolean(params.ignoreNulls)
|
|
288
|
+
converters = params.converters
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return {
|
|
292
|
+
...(!withoutURIData &&
|
|
293
|
+
this.uri && { uid: this.uri.uid, path: this.uri.path }),
|
|
294
|
+
...this._dataToJSON(
|
|
295
|
+
objectsAsReferences,
|
|
296
|
+
ignoreUnchanged,
|
|
297
|
+
ignoreNulls,
|
|
298
|
+
converters
|
|
299
|
+
),
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
toReference() {
|
|
304
|
+
return {
|
|
305
|
+
...this._objectUri.toReference(),
|
|
306
|
+
label: this.val('name') || '',
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
protected _dataToJSON(
|
|
311
|
+
objectsAsReferences = false,
|
|
312
|
+
ignoreUnchanged = false,
|
|
313
|
+
ignoreNulls = false,
|
|
314
|
+
converters = {}
|
|
315
|
+
) {
|
|
316
|
+
const data = {}
|
|
317
|
+
Object.keys(this._properties).forEach((key: string) => {
|
|
318
|
+
const prop = Reflect.get(this._properties, key)
|
|
319
|
+
if (ignoreNulls && (prop.val() === null || prop.val() === undefined))
|
|
320
|
+
return
|
|
321
|
+
if (ignoreUnchanged && prop.hasChanged === false) return
|
|
322
|
+
|
|
323
|
+
switch (prop.constructor.name) {
|
|
324
|
+
case 'CollectionProperty':
|
|
325
|
+
// ignore
|
|
326
|
+
break
|
|
327
|
+
case 'ObjectProperty':
|
|
328
|
+
const value: BaseObject | ObjectUri | undefined = prop.val()
|
|
329
|
+
Reflect.set(
|
|
330
|
+
data,
|
|
331
|
+
key,
|
|
332
|
+
value
|
|
333
|
+
? objectsAsReferences && !(value instanceof ObjectUri)
|
|
334
|
+
? value.asReference()
|
|
335
|
+
: value.toJSON
|
|
336
|
+
? value.toJSON()
|
|
337
|
+
: value
|
|
338
|
+
: null
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
break
|
|
342
|
+
|
|
343
|
+
case 'BooleanProperty':
|
|
344
|
+
Reflect.set(data, key, Boolean(prop.val()))
|
|
345
|
+
break
|
|
346
|
+
|
|
347
|
+
case 'ArrayProperty':
|
|
348
|
+
Reflect.set(data, key, prop.val() || [])
|
|
349
|
+
break
|
|
350
|
+
|
|
351
|
+
case 'DateTimeProperty':
|
|
352
|
+
Reflect.set(
|
|
353
|
+
data,
|
|
354
|
+
key,
|
|
355
|
+
prop.val(Reflect.get(converters, 'datetime')) || null
|
|
356
|
+
)
|
|
357
|
+
break
|
|
358
|
+
|
|
359
|
+
default:
|
|
360
|
+
Reflect.set(data, key, prop.val() || null)
|
|
361
|
+
break
|
|
362
|
+
}
|
|
363
|
+
})
|
|
364
|
+
|
|
365
|
+
return data
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// async read(): Promise<DataObjectClass<any>> {
|
|
369
|
+
// throw new Error(
|
|
370
|
+
// `This is just a stub, please use DataObject from @quatrain/backend to persist`
|
|
371
|
+
// )
|
|
372
|
+
// }
|
|
373
|
+
|
|
374
|
+
// save(): Promise<DataObjectClass<any>> {
|
|
375
|
+
// throw new Error(
|
|
376
|
+
// `This is just a stub, please use DataObject from @quatrain/backend to persist`
|
|
377
|
+
// )
|
|
378
|
+
// }
|
|
379
|
+
|
|
380
|
+
// async delete(): Promise<DataObjectClass<any>> {
|
|
381
|
+
// throw new Error(
|
|
382
|
+
// `This is just a stub, please use DataObject from @quatrain/backend to persist`
|
|
383
|
+
// )
|
|
384
|
+
// }
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Data object must be created from factory in order for async-loaded data to be available
|
|
388
|
+
* @param className
|
|
389
|
+
* @param param
|
|
390
|
+
* @returns DataObject
|
|
391
|
+
*/
|
|
392
|
+
static factory(param: DataObjectParams | undefined = undefined): DataObject {
|
|
393
|
+
try {
|
|
394
|
+
return new this(param)
|
|
395
|
+
} catch (err) {
|
|
396
|
+
console.log(err)
|
|
397
|
+
throw new Error(
|
|
398
|
+
`Unable to build data object: ${(err as Error).message}`
|
|
399
|
+
)
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
async clone(data: any = {}): Promise<DataObject> {
|
|
404
|
+
const cloned = await DataObject.factory()
|
|
405
|
+
cloned.uri.class = this.uri.class
|
|
406
|
+
cloned._populated = false
|
|
407
|
+
|
|
408
|
+
for (let property of Object.keys(this._properties)) {
|
|
409
|
+
cloned._properties[property] = this._properties[property].clone()
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (data) {
|
|
413
|
+
await cloned.populate(data)
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return cloned
|
|
417
|
+
}
|
|
418
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { BaseObject } from './BaseObject'
|
|
2
|
+
import { BaseObjectProperties } from './BaseObjectProperties'
|
|
3
|
+
//import { User } from './User'
|
|
4
|
+
//import { CollectionProperty } from '../properties/CollectionProperty'
|
|
5
|
+
import { StringProperty } from '../properties/StringProperty'
|
|
6
|
+
import * as htmlType from '../properties/types/PropertyHTMLType'
|
|
7
|
+
import { BaseObjectType } from './types/BaseObjectType'
|
|
8
|
+
|
|
9
|
+
export interface EntityType extends BaseObjectType {
|
|
10
|
+
// users?: User[]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class Entity extends BaseObject {
|
|
14
|
+
static COLLECTION = 'entities'
|
|
15
|
+
|
|
16
|
+
static PROPS_DEFINITION = [
|
|
17
|
+
...BaseObjectProperties,
|
|
18
|
+
{
|
|
19
|
+
// surcharge property minLength and htmlType
|
|
20
|
+
name: 'name',
|
|
21
|
+
type: StringProperty.TYPE,
|
|
22
|
+
mandatory: true,
|
|
23
|
+
minLength: 1,
|
|
24
|
+
htmlType: htmlType.ORG,
|
|
25
|
+
},
|
|
26
|
+
// {
|
|
27
|
+
// name: 'users',
|
|
28
|
+
// mandatory: true,
|
|
29
|
+
// type: CollectionProperty.TYPE,
|
|
30
|
+
// instanceOf: User,
|
|
31
|
+
// parentKey: 'entity',
|
|
32
|
+
// },
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
static async factory(src: any = undefined): Promise<Entity> {
|
|
36
|
+
return super.factory(src, Entity)
|
|
37
|
+
}
|
|
38
|
+
}
|