Skip to content

Commit f781397

Browse files
committed
real db test file organisation
1 parent 81c3990 commit f781397

File tree

3 files changed

+174
-158
lines changed

3 files changed

+174
-158
lines changed

src/examples/realDbTest/data.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import {
2+
Stores,
3+
CreateUserRecordOptions,
4+
CreateImageRecordOptions,
5+
CreateArticleRecordOptions,
6+
CreateUserAddressRecordOptions,
7+
CreateUserGroupRecordOptions,
8+
CreateUserToUserGroupLinkOptions,
9+
} from './orm'
10+
11+
export const addData = async (stores: Stores) => {
12+
// Add users
13+
const createUserRecordsOptions: CreateUserRecordOptions[] = [
14+
{ name: 'user 1', email: 'user1@email.com', passwordHash: '123' },
15+
{ name: 'user 2', email: 'user2@email.com', passwordHash: '456' },
16+
{ name: 'user 3', email: 'user3@email.com', passwordHash: '789' },
17+
]
18+
await Promise.all(createUserRecordsOptions.map(stores.user.create))
19+
20+
// Add images
21+
const createImageRecordsOptions: CreateImageRecordOptions[] = [
22+
{ fileName: 'funnydog.png', creatorUserId: 1 },
23+
{ fileName: 'funnycat.png', creatorUserId: 2 },
24+
{ fileName: 'user3avatar.png', creatorUserId: 3 },
25+
]
26+
await Promise.all(createImageRecordsOptions.map(stores.image.create))
27+
28+
// Add articles
29+
const createArticleRecordsOptions: CreateArticleRecordOptions[] = [
30+
{ title: 'Here is a funny dog!', creatorUserId: 3, thumbnailImageId: 1 },
31+
{ title: 'Here is a funny cat!', creatorUserId: 3, thumbnailImageId: 2 },
32+
{ title: 'I am User 3', creatorUserId: 3, thumbnailImageId: 3 },
33+
]
34+
await Promise.all(createArticleRecordsOptions.map(stores.article.create))
35+
36+
// Add user addresses
37+
const createUserAddressRecordsOptions: CreateUserAddressRecordOptions[] = [
38+
{ userId: 1, city: 'London', country: 'UK', postCode: 'SE11 119', streetAddress: '1 FooStreet Lane' },
39+
{ userId: 2, city: 'Madrid', country: 'Spain', postCode: 'BON BON', streetAddress: '2 FooStreet Lane' },
40+
{ userId: 3, city: 'Paris', country: 'France', postCode: 'SUI SUI', streetAddress: '3 FooStreet Lane' },
41+
]
42+
await Promise.all(createUserAddressRecordsOptions.map(stores.userAddress.create))
43+
44+
// Add user groups
45+
const createUserGroupRecordsOptions: CreateUserGroupRecordOptions[] = [
46+
{ name: 'User group 1' },
47+
{ name: 'User group 2' },
48+
{ name: 'User group 3' },
49+
]
50+
await Promise.all(createUserGroupRecordsOptions.map(stores.userGroup.create))
51+
52+
const createUserToUserGroupLinkOptions: CreateUserToUserGroupLinkOptions[] = [
53+
{ userId: 1, userGroupId: 1 },
54+
{ userId: 2, userGroupId: 2 },
55+
{ userId: 3, userGroupId: 3 },
56+
]
57+
await Promise.all(createUserToUserGroupLinkOptions.map(stores['user.id <<-->> userGroup.id'].create))
58+
}

src/examples/realDbTest/index.ts

Lines changed: 10 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,11 @@
1-
/* eslint-disable @typescript-eslint/no-unused-vars */
21
/* eslint-disable no-console */
32
import { Operator } from '@samhuk/data-filter/dist/types'
43
import { SortingDirection } from '@samhuk/data-query/dist/sorting/types'
54
import * as fs from 'fs'
65
import path from 'path'
76
import { createConsoleLogEventHandlers } from 'simple-pg-client'
8-
import { createTsPgOrm } from '../..'
9-
import { createDataFormatDeclaration } from '../../dataFormat'
10-
import { BASE_ENTITY_FIELDS, COMMON_FIELDS } from '../../dataFormat/common'
11-
import { StringDataSubType, NumberDataSubType, DataType, CreateRecordOptions } from '../../dataFormat/types'
12-
import { RelationType } from '../../relations/types'
13-
import { _CreateJoinTableRecordOptions } from '../../store/joinTable/types'
14-
import { StoresAndJoinTableStoresDict } from '../../types'
15-
16-
const USER_DFD = createDataFormatDeclaration({
17-
name: 'user',
18-
fields: [
19-
...BASE_ENTITY_FIELDS,
20-
COMMON_FIELDS.name50,
21-
{ name: 'email', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 100 },
22-
{ name: 'passwordHash', dataType: DataType.STRING, dataSubType: StringDataSubType.FIXED_LENGTH, length: 64 },
23-
],
24-
} as const)
25-
26-
const ARTICLE_DFD = createDataFormatDeclaration({
27-
name: 'article',
28-
fields: [
29-
...BASE_ENTITY_FIELDS,
30-
{ name: 'title', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 100 },
31-
{ name: 'creatorUserId', dataType: DataType.NUMBER, dataSubType: NumberDataSubType.INTEGER },
32-
{ name: 'thumbnailImageId', dataType: DataType.NUMBER, dataSubType: NumberDataSubType.INTEGER },
33-
],
34-
} as const)
35-
36-
const IMAGE_DFD = createDataFormatDeclaration({
37-
name: 'image',
38-
fields: [
39-
...BASE_ENTITY_FIELDS,
40-
{ name: 'fileName', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 200 },
41-
{ name: 'creatorUserId', dataType: DataType.NUMBER, dataSubType: NumberDataSubType.INTEGER },
42-
],
43-
} as const)
44-
45-
const USER_ADDRESS_DFD = createDataFormatDeclaration({
46-
name: 'userAddress',
47-
fields: [
48-
...BASE_ENTITY_FIELDS,
49-
{ name: 'userId', dataType: DataType.NUMBER, dataSubType: NumberDataSubType.INTEGER },
50-
{ name: 'postCode', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 10 },
51-
{ name: 'streetAddress', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 200 },
52-
{ name: 'city', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 100 },
53-
{ name: 'country', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 100 },
54-
],
55-
} as const)
56-
57-
const USER_GROUP_DFD = createDataFormatDeclaration({
58-
name: 'userGroup',
59-
fields: [
60-
...BASE_ENTITY_FIELDS,
61-
{ name: 'name', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 100 },
62-
{ name: 'description', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 300, allowNull: true },
63-
{ name: 'imageId', dataType: DataType.NUMBER, dataSubType: NumberDataSubType.INTEGER, allowNull: true },
64-
],
65-
} as const)
66-
67-
const ORM = createTsPgOrm()
68-
.loadDataFormats([USER_DFD, IMAGE_DFD, ARTICLE_DFD, USER_ADDRESS_DFD, USER_GROUP_DFD] as const)
69-
.loadRelations(dfs => [
70-
{
71-
type: RelationType.ONE_TO_MANY,
72-
fromOneField: dfs.user.fieldRefs.id,
73-
toManyField: dfs.article.fieldRefs.creatorUserId,
74-
},
75-
{
76-
type: RelationType.ONE_TO_MANY,
77-
fromOneField: dfs.image.fieldRefs.id,
78-
toManyField: dfs.article.fieldRefs.thumbnailImageId,
79-
},
80-
{
81-
type: RelationType.ONE_TO_MANY,
82-
fromOneField: dfs.user.fieldRefs.id,
83-
toManyField: dfs.image.fieldRefs.creatorUserId,
84-
},
85-
{
86-
type: RelationType.ONE_TO_ONE,
87-
fromOneField: dfs.user.fieldRefs.id,
88-
toOneField: dfs.userAddress.fieldRefs.userId,
89-
},
90-
{
91-
type: RelationType.MANY_TO_MANY,
92-
fieldRef1: dfs.user.fieldRefs.id,
93-
fieldRef2: dfs.userGroup.fieldRefs.id,
94-
includeDateCreated: true,
95-
},
96-
] as const)
97-
98-
type Stores = StoresAndJoinTableStoresDict<typeof ORM['dataFormatDeclarations'], typeof ORM['relationDeclarations']>
99-
100-
type CreateUserRecordOptions = CreateRecordOptions<typeof USER_DFD>
101-
102-
type CreateImageRecordOptions = CreateRecordOptions<typeof IMAGE_DFD>
103-
104-
type CreateArticleRecordOptions = CreateRecordOptions<typeof ARTICLE_DFD>
105-
106-
type CreateUserAddressRecordOptions = CreateRecordOptions<typeof USER_ADDRESS_DFD>
107-
108-
type CreateUserGroupRecordOptions = CreateRecordOptions<typeof USER_GROUP_DFD>
109-
110-
type CreateUserToUserGroupLinkOptions = _CreateJoinTableRecordOptions<
111-
typeof ORM['dataFormatDeclarations'],
112-
typeof ORM['relations']['user.id <<-->> userGroup.id']
113-
>
7+
import { addData } from './data'
8+
import { ORM, Stores } from './orm'
1149

11510
const provision = async (): Promise<Stores> => {
11611
await ORM.initDbClient({
@@ -134,56 +29,12 @@ const provision = async (): Promise<Stores> => {
13429
return stores
13530
}
13631

137-
const addData = async (stores: Stores) => {
138-
// Add users
139-
const createUserRecordsOptions: CreateUserRecordOptions[] = [
140-
{ name: 'user 1', email: 'user1@email.com', passwordHash: '123' },
141-
{ name: 'user 2', email: 'user2@email.com', passwordHash: '456' },
142-
{ name: 'user 3', email: 'user3@email.com', passwordHash: '789' },
143-
]
144-
await Promise.all(createUserRecordsOptions.map(stores.user.create))
145-
146-
// Add images
147-
const createImageRecordsOptions: CreateImageRecordOptions[] = [
148-
{ fileName: 'funnydog.png', creatorUserId: 1 },
149-
{ fileName: 'funnycat.png', creatorUserId: 2 },
150-
{ fileName: 'user3avatar.png', creatorUserId: 3 },
151-
]
152-
await Promise.all(createImageRecordsOptions.map(stores.image.create))
153-
154-
// Add articles
155-
const createArticleRecordsOptions: CreateArticleRecordOptions[] = [
156-
{ title: 'Here is a funny dog!', creatorUserId: 3, thumbnailImageId: 1 },
157-
{ title: 'Here is a funny cat!', creatorUserId: 3, thumbnailImageId: 2 },
158-
{ title: 'I am User 3', creatorUserId: 3, thumbnailImageId: 3 },
159-
]
160-
await Promise.all(createArticleRecordsOptions.map(stores.article.create))
161-
162-
// Add user addresses
163-
const createUserAddressRecordsOptions: CreateUserAddressRecordOptions[] = [
164-
{ userId: 1, city: 'London', country: 'UK', postCode: 'SE11 119', streetAddress: '1 FooStreet Lane' },
165-
{ userId: 2, city: 'Madrid', country: 'Spain', postCode: 'BON BON', streetAddress: '2 FooStreet Lane' },
166-
{ userId: 3, city: 'Paris', country: 'France', postCode: 'SUI SUI', streetAddress: '3 FooStreet Lane' },
167-
]
168-
await Promise.all(createUserAddressRecordsOptions.map(stores.userAddress.create))
169-
170-
// Add user groups
171-
const createUserGroupRecordsOptions: CreateUserGroupRecordOptions[] = [
172-
{ name: 'User group 1' },
173-
{ name: 'User group 2' },
174-
{ name: 'User group 3' },
175-
]
176-
await Promise.all(createUserGroupRecordsOptions.map(stores.userGroup.create))
177-
178-
const createUserToUserGroupLinkOptions: CreateUserToUserGroupLinkOptions[] = [
179-
{ userId: 1, userGroupId: 1 },
180-
{ userId: 2, userGroupId: 2 },
181-
{ userId: 3, userGroupId: 3 },
182-
]
183-
await Promise.all(createUserToUserGroupLinkOptions.map(stores['user.id <<-->> userGroup.id'].create))
184-
}
185-
18632
const getResult = (stores: Stores) => (
33+
/* E.g.:
34+
* Get all undeleted users sorted by newest to oldest, and each
35+
* with all of their uploaded articles and images, and each of those
36+
* articles with it's image.
37+
*/
18738
stores.user.getMultiple({
18839
fields: ['uuid', 'name', 'email', 'dateCreated'],
18940
query: {
@@ -241,14 +92,15 @@ const init = async () => {
24192
const result1 = await timedFn(() => getResult(stores), 'query')
24293
fs.writeFileSync(path.resolve(outputDir, 'articles-query.json'), JSON.stringify(result1.result, null, 2))
24394

95+
// many-to-many
24496
const result2 = await timedFn(() => stores.user.getMultiple({
245-
fields: [],
97+
fields: ['name'],
24698
relations: { userGroups: {} },
24799
}), 'query')
248100
fs.writeFileSync(path.resolve(outputDir, 'user-user-groups-query.json'), JSON.stringify(result2.result, null, 2))
249101

250102
const result3 = await timedFn(() => stores.user.getMultiple({
251-
fields: [],
103+
fields: ['name'],
252104
relations: {
253105
userGroups: {
254106
query: {

src/examples/realDbTest/orm.ts

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import { createTsPgOrm } from '../..'
2+
import { createDataFormatDeclaration } from '../../dataFormat'
3+
import { BASE_ENTITY_FIELDS, COMMON_FIELDS } from '../../dataFormat/common'
4+
import { StringDataSubType, NumberDataSubType, CreateRecordOptions, DataType } from '../../dataFormat/types'
5+
import { RelationType } from '../../relations/types'
6+
import { _CreateJoinTableRecordOptions } from '../../store/joinTable/types'
7+
import { StoresAndJoinTableStoresDict } from '../../types'
8+
9+
const USER_DFD = createDataFormatDeclaration({
10+
name: 'user',
11+
fields: [
12+
...BASE_ENTITY_FIELDS,
13+
COMMON_FIELDS.name50,
14+
{ name: 'email', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 100 },
15+
{ name: 'passwordHash', dataType: DataType.STRING, dataSubType: StringDataSubType.FIXED_LENGTH, length: 64 },
16+
],
17+
} as const)
18+
19+
const ARTICLE_DFD = createDataFormatDeclaration({
20+
name: 'article',
21+
fields: [
22+
...BASE_ENTITY_FIELDS,
23+
{ name: 'title', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 100 },
24+
{ name: 'creatorUserId', dataType: DataType.NUMBER, dataSubType: NumberDataSubType.INTEGER },
25+
{ name: 'thumbnailImageId', dataType: DataType.NUMBER, dataSubType: NumberDataSubType.INTEGER },
26+
],
27+
} as const)
28+
29+
const IMAGE_DFD = createDataFormatDeclaration({
30+
name: 'image',
31+
fields: [
32+
...BASE_ENTITY_FIELDS,
33+
{ name: 'fileName', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 200 },
34+
{ name: 'creatorUserId', dataType: DataType.NUMBER, dataSubType: NumberDataSubType.INTEGER },
35+
],
36+
} as const)
37+
38+
const USER_ADDRESS_DFD = createDataFormatDeclaration({
39+
name: 'userAddress',
40+
fields: [
41+
...BASE_ENTITY_FIELDS,
42+
{ name: 'userId', dataType: DataType.NUMBER, dataSubType: NumberDataSubType.INTEGER },
43+
{ name: 'postCode', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 10 },
44+
{ name: 'streetAddress', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 200 },
45+
{ name: 'city', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 100 },
46+
{ name: 'country', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 100 },
47+
],
48+
} as const)
49+
50+
const USER_GROUP_DFD = createDataFormatDeclaration({
51+
name: 'userGroup',
52+
fields: [
53+
...BASE_ENTITY_FIELDS,
54+
{ name: 'name', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 100 },
55+
{ name: 'description', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 300, allowNull: true },
56+
{ name: 'imageId', dataType: DataType.NUMBER, dataSubType: NumberDataSubType.INTEGER, allowNull: true },
57+
],
58+
} as const)
59+
60+
export const ORM = createTsPgOrm()
61+
.loadDataFormats([USER_DFD, IMAGE_DFD, ARTICLE_DFD, USER_ADDRESS_DFD, USER_GROUP_DFD] as const)
62+
.loadRelations(dfs => [
63+
{
64+
type: RelationType.ONE_TO_MANY,
65+
fromOneField: dfs.user.fieldRefs.id,
66+
toManyField: dfs.article.fieldRefs.creatorUserId,
67+
},
68+
{
69+
type: RelationType.ONE_TO_MANY,
70+
fromOneField: dfs.image.fieldRefs.id,
71+
toManyField: dfs.article.fieldRefs.thumbnailImageId,
72+
},
73+
{
74+
type: RelationType.ONE_TO_MANY,
75+
fromOneField: dfs.user.fieldRefs.id,
76+
toManyField: dfs.image.fieldRefs.creatorUserId,
77+
},
78+
{
79+
type: RelationType.ONE_TO_ONE,
80+
fromOneField: dfs.user.fieldRefs.id,
81+
toOneField: dfs.userAddress.fieldRefs.userId,
82+
},
83+
{
84+
type: RelationType.MANY_TO_MANY,
85+
fieldRef1: dfs.user.fieldRefs.id,
86+
fieldRef2: dfs.userGroup.fieldRefs.id,
87+
includeDateCreated: true,
88+
},
89+
] as const)
90+
91+
export type Stores = StoresAndJoinTableStoresDict<typeof ORM['dataFormatDeclarations'], typeof ORM['relationDeclarations']>
92+
93+
export type CreateUserRecordOptions = CreateRecordOptions<typeof USER_DFD>
94+
95+
export type CreateImageRecordOptions = CreateRecordOptions<typeof IMAGE_DFD>
96+
97+
export type CreateArticleRecordOptions = CreateRecordOptions<typeof ARTICLE_DFD>
98+
99+
export type CreateUserAddressRecordOptions = CreateRecordOptions<typeof USER_ADDRESS_DFD>
100+
101+
export type CreateUserGroupRecordOptions = CreateRecordOptions<typeof USER_GROUP_DFD>
102+
103+
export type CreateUserToUserGroupLinkOptions = _CreateJoinTableRecordOptions<
104+
typeof ORM['dataFormatDeclarations'],
105+
typeof ORM['relations']['user.id <<-->> userGroup.id']
106+
>

0 commit comments

Comments
 (0)