@cuboapp/api-backend 1.0.0 → 1.0.2

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.
@@ -0,0 +1,18 @@
1
+ {
2
+ "editor.minimap.enabled": false,
3
+ "editor.formatOnSave": true,
4
+ "editor.codeActionsOnSave": {
5
+ "source.fixAll.eslint": "explicit",
6
+ "source.fixAll.stylelint": "explicit",
7
+ "source.organizeImports": "explicit",
8
+ "source.organizeExports": "explicit"
9
+ },
10
+ "emmet.includeLanguages": {
11
+ "javascriptreact": "html",
12
+ "typescriptreact": "html"
13
+ },
14
+ "files.exclude": {
15
+ "node_modules/": true
16
+ },
17
+ "typescript.tsdk": "node_modules/typescript/lib"
18
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cuboapp/api-backend",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Backend Api for CuboApp",
5
5
  "main": "src/index.ts",
6
6
  "repository": "git@github.com:cuboapp/api-backend.git",
@@ -12,7 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@cuboapp/config": "^0.0.6",
15
- "@cuboapp/types": "^1.0.19",
15
+ "@cuboapp/types": "^1.0.20",
16
16
  "lodash-es": "^4.17.21",
17
17
  "pg": "^8.13.3",
18
18
  "sequelize": "^6.37.6"
package/pnpm-lock.yaml CHANGED
@@ -12,8 +12,8 @@ importers:
12
12
  specifier: ^0.0.6
13
13
  version: 0.0.6
14
14
  '@cuboapp/types':
15
- specifier: ^1.0.19
16
- version: 1.0.19
15
+ specifier: ^1.0.20
16
+ version: 1.0.20
17
17
  lodash-es:
18
18
  specifier: ^4.17.21
19
19
  version: 4.17.21
@@ -42,6 +42,9 @@ packages:
42
42
  '@cuboapp/types@1.0.19':
43
43
  resolution: {integrity: sha512-CZyut9MmCT+5bBBbZF3ETiJnRbgnExvx/+zT/UKj4NxZKlqQAnzX8hWIFMBbed3YoSkbS+cdZcJE26k5mLNPjw==}
44
44
 
45
+ '@cuboapp/types@1.0.20':
46
+ resolution: {integrity: sha512-PDeJ4GOsVA6OhC1ryd8XwBrnZ7k6mB48GEnMLDdgw3ACRxV2KaWc/5bDrZUdfRjggOAXmwEhX+8rvqfNvp93hg==}
47
+
45
48
  '@types/debug@4.1.12':
46
49
  resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
47
50
 
@@ -239,6 +242,10 @@ snapshots:
239
242
  dependencies:
240
243
  '@types/events': 3.0.3
241
244
 
245
+ '@cuboapp/types@1.0.20':
246
+ dependencies:
247
+ '@types/events': 3.0.3
248
+
242
249
  '@types/debug@4.1.12':
243
250
  dependencies:
244
251
  '@types/ms': 2.1.0
@@ -1,16 +1,17 @@
1
+ import { CuboApiEntitiesMap, CuboEntity, CuboEntityField } from '@cuboapp/types'
1
2
  import get from 'lodash-es/get'
2
3
  import set from 'lodash-es/set'
3
4
  import unset from 'lodash-es/unset'
4
5
 
5
- import { CUBO_CRUD_DEFAULT_FIELDS, CUBO_ENTITY_FIELD_TYPE } from '../../constants'
6
- import { CuboCrudFindQuery, CuboCrudRequest, CuboEntitiesMap, CuboEntityFieldModel, CuboEntityModel } from '../../types'
6
+ import { CUBO_CRUD_DEFAULT_FIELDS, CUBO_ENTITY_FIELD_TYPE } from '../constants'
7
+ import { CuboCrudFindQuery, CuboCrudRequest } from '../types'
7
8
 
8
9
  import { ApiHelpers } from '.'
9
10
 
10
- export class ApiHelpersConvert<T extends CuboEntitiesMap<T>> {
11
+ export class ApiHelpersConvert<T extends CuboApiEntitiesMap<T>> {
11
12
  constructor(public helpers: ApiHelpers<T>) {}
12
13
 
13
- public async prepareAll(req: CuboCrudRequest, entity: CuboEntityModel, rows: any[], query?: Partial<CuboCrudFindQuery>): Promise<any[]> {
14
+ public async prepareAll(req: CuboCrudRequest, entity: CuboEntity, rows: any[], query?: Partial<CuboCrudFindQuery>): Promise<any[]> {
14
15
  for (const rowKey in rows) {
15
16
  rows[rowKey] = await this.prepareOne(req, entity, rows[rowKey], query)
16
17
  }
@@ -18,7 +19,7 @@ export class ApiHelpersConvert<T extends CuboEntitiesMap<T>> {
18
19
  return rows
19
20
  }
20
21
 
21
- public async prepareOne(req: CuboCrudRequest, entity: CuboEntityModel, row: any, query?: Partial<CuboCrudFindQuery>) {
22
+ public async prepareOne(req: CuboCrudRequest, entity: CuboEntity, row: any, query?: Partial<CuboCrudFindQuery>) {
22
23
  const usersDefaultFields = ['created_by', 'modified_by', 'deleted_by']
23
24
 
24
25
  const toPrepare: Record<string, any> = {}
@@ -111,7 +112,7 @@ export class ApiHelpersConvert<T extends CuboEntitiesMap<T>> {
111
112
  return row
112
113
  }
113
114
 
114
- private prepareFieldValue(field: Pick<CuboEntityFieldModel, 'type_id' | 'alias' | 'extra'>, value: any) {
115
+ private prepareFieldValue(field: Pick<CuboEntityField, 'type_id' | 'alias' | 'extra'>, value: any) {
115
116
  switch (field.type_id) {
116
117
  case CUBO_ENTITY_FIELD_TYPE.BOOLEAN:
117
118
  return value !== undefined ? (['true', true].includes(value) ? true : false) : null
@@ -1,15 +1,14 @@
1
+ import { CuboApiEntitiesMap, CuboEntityField } from '@cuboapp/types'
1
2
  import keyBy from 'lodash-es/keyBy'
2
3
 
3
- import { CUBO_ENTITY_FIELD_TYPE } from '../../constants'
4
- import { CuboEntitiesMap, CuboEntityFieldModel } from '../../types'
5
- import { isDateValid } from '../../utils'
4
+ import { CUBO_ENTITY_FIELD_TYPE } from '../constants'
6
5
 
7
6
  import { ApiHelpers } from '.'
8
7
 
9
- export class ApiHelpersData<T extends CuboEntitiesMap<T>> {
8
+ export class ApiHelpersData<T extends CuboApiEntitiesMap<T>> {
10
9
  constructor(private helpers: ApiHelpers<T>) {}
11
10
 
12
- public prepare(type: 'create' | 'update' | 'delete', fields: CuboEntityFieldModel[], dto?: any, performer_id?: number) {
11
+ public prepare(type: 'create' | 'update' | 'delete', fields: CuboEntityField[], dto?: any, performer_id?: number) {
13
12
  const fieldsByAlias = keyBy(fields, (i) => i.alias)
14
13
 
15
14
  const errors: string[] = []
@@ -109,7 +108,7 @@ export class ApiHelpersData<T extends CuboEntitiesMap<T>> {
109
108
  {
110
109
  if (value === null) {
111
110
  prepared[key] = value
112
- } else if (tval !== 'string' || !isDateValid(value)) {
111
+ } else if (tval !== 'string') {
113
112
  errors.push(`"${key}": value must be a valid date string in format YYYY-MM-DD`)
114
113
  } else {
115
114
  prepared[key] = value
@@ -1,28 +1,28 @@
1
- import { CuboEntitiesMap, CuboEntityModel } from '../../types'
1
+ import { CuboApiEntitiesMap, CuboEntity } from '@cuboapp/types'
2
2
 
3
3
  import { ApiHelpers } from '.'
4
4
 
5
- export class ApiHelpersEntities<T extends CuboEntitiesMap<T>> {
5
+ export class ApiHelpersEntities<T extends CuboApiEntitiesMap<T>> {
6
6
  constructor(private helpers: ApiHelpers<T>) {}
7
7
 
8
- public async getMany(force = false): Promise<CuboEntityModel[]> {
8
+ public async getMany(force = false): Promise<CuboEntity[]> {
9
9
  return (
10
10
  this.helpers?.api?.options?.entities ??
11
11
  this.helpers.getCached(
12
12
  `get_entities`,
13
- () => this.helpers.api.apiRequest<{ items: CuboEntityModel[] }>(`/api/v1/entities?with=fields`).then((res) => res.items),
13
+ () => this.helpers.api.apiRequest<{ items: CuboEntity[] }>(`/api/v1/entities?with=fields`).then((res) => res.items),
14
14
  force
15
15
  )
16
16
  )
17
17
  }
18
18
 
19
- public async getByAlias(alias: keyof T): Promise<CuboEntityModel | undefined> {
19
+ public async getByAlias(alias: keyof T): Promise<CuboEntity | undefined> {
20
20
  const entities = await this.getMany()
21
21
 
22
22
  return entities.find((e) => e.alias === alias)
23
23
  }
24
24
 
25
- public async getById(id: number): Promise<CuboEntityModel | undefined> {
25
+ public async getById(id: number): Promise<CuboEntity | undefined> {
26
26
  const entities = await this.getMany()
27
27
 
28
28
  return entities.find((e) => e.id === id)
@@ -1,9 +1,9 @@
1
1
  import { CuboConfigDatabase } from '@cuboapp/config'
2
+ import { CuboApiEntitiesMap, CuboEntityField, CuboEntityFieldExtra } from '@cuboapp/types'
2
3
  import { Sequelize, type Options } from 'sequelize'
3
4
 
4
5
  import { CuboBackendApi } from '../..'
5
- import { CUBO_CRUD_QUERY_CONDITION, CUBO_CRUD_QUERY_SYMBOL_NOT, CUBO_ENTITY_FIELD_TYPE } from '../../constants'
6
- import { CuboEntitiesMap, CuboEntityFieldModel, CuboEntityFieldModelExtra } from '../../types'
6
+ import { CUBO_CRUD_QUERY_CONDITION, CUBO_CRUD_QUERY_SYMBOL_NOT, CUBO_ENTITY_FIELD_TYPE } from '../constants'
7
7
 
8
8
  import { ApiHelpersConvert } from './convert'
9
9
  import { ApiHelpersData } from './data'
@@ -12,7 +12,7 @@ import { ApiHelpersQuery } from './query'
12
12
  import { ApiHelpersUsers } from './users'
13
13
  import { ApiHelpersWithes } from './withes'
14
14
 
15
- export class ApiHelpers<T extends CuboEntitiesMap<T>> {
15
+ export class ApiHelpers<T extends CuboApiEntitiesMap<T>> {
16
16
  constructor(public api: CuboBackendApi<T>) {}
17
17
 
18
18
  public withes = new ApiHelpersWithes<T>(this)
@@ -49,10 +49,7 @@ export class ApiHelpers<T extends CuboEntitiesMap<T>> {
49
49
  return this.fetching[alias]
50
50
  }
51
51
 
52
- public clearFieldConditionValue(
53
- field: CuboEntityFieldModel | { type_id: number; alias: string; extra: CuboEntityFieldModelExtra },
54
- value: any
55
- ) {
52
+ public clearFieldConditionValue(field: CuboEntityField | { type_id: number; alias: string; extra?: CuboEntityFieldExtra }, value: any) {
56
53
  const type = typeof value
57
54
 
58
55
  const parts = `${value}`.split(':')
@@ -121,7 +118,8 @@ export class ApiHelpers<T extends CuboEntitiesMap<T>> {
121
118
  }
122
119
  break
123
120
  case CUBO_ENTITY_FIELD_TYPE.NUMBER:
124
- const precision = field.extra?.number_precision || 0
121
+ // const precision = field.extra?.number_precision || 0
122
+ const precision = 0
125
123
 
126
124
  switch (type) {
127
125
  case 'object':
@@ -284,8 +282,6 @@ export class ApiHelpers<T extends CuboEntitiesMap<T>> {
284
282
  }
285
283
 
286
284
  this.connecting[cacheKey] = new Promise(async (success) => {
287
- const { storage } = this.api.account
288
-
289
285
  let database: string = ''
290
286
  let host: string = ''
291
287
  let port: number = 0
@@ -294,37 +290,28 @@ export class ApiHelpers<T extends CuboEntitiesMap<T>> {
294
290
  let schema: string = ''
295
291
  let dialect: string = ''
296
292
 
297
- if (storage?.database) {
298
- database = storage?.database
299
- host = storage?.[type]?.host
300
- port = storage?.[type]?.port
301
- username = storage?.[type]?.username
302
- password = storage?.[type]?.password
303
- schema = storage?.[type]?.schema
304
- } else {
305
- if (!this.api.config.db) {
306
- throw 'DB connection is not configured'
307
- }
293
+ if (!this.api.config.db) {
294
+ throw 'DB connection is not configured'
295
+ }
308
296
 
309
- const dbConfig = this.api.config.db as any
310
- let cfg: CuboConfigDatabase = {} as any
311
- if (dbConfig) {
312
- if (dbConfig[type]) {
313
- cfg = dbConfig[type]
314
- } else {
315
- cfg = dbConfig as CuboConfigDatabase
316
- }
297
+ const dbConfig = this.api.config.db as any
298
+ let cfg: CuboConfigDatabase = {} as any
299
+ if (dbConfig) {
300
+ if (dbConfig[type]) {
301
+ cfg = dbConfig[type]
302
+ } else {
303
+ cfg = dbConfig as CuboConfigDatabase
317
304
  }
318
-
319
- database = cfg.database as string
320
- host = cfg.host as string
321
- port = cfg.port as number
322
- username = cfg.username as string
323
- password = cfg.password as string
324
- schema = cfg.schema as string
325
- dialect = cfg.dialect as string
326
305
  }
327
306
 
307
+ database = cfg.database as string
308
+ host = cfg.host as string
309
+ port = cfg.port as number
310
+ username = cfg.username as string
311
+ password = cfg.password as string
312
+ schema = cfg.schema as string
313
+ dialect = cfg.dialect as string
314
+
328
315
  if (!schema) {
329
316
  schema = `account_${this.api.account.id}`
330
317
  }
@@ -1,15 +1,17 @@
1
- import { CUBO_CRUD_DEFAULT_FIELDS, CUBO_CRUD_DEFAULT_PAGE_LIMIT, CUBO_CRUD_MAX_PAGE_LIMIT, CUBO_CRUD_QUERY_KEY_REGEX } from '../../constants'
2
- import { CuboCrudFindQuery, CuboCrudRequest, CuboEntitiesMap, CuboEntityModel } from '../../types'
3
- import { dbPrepareUpdateQueryString } from '../../utils'
1
+ import { CuboApiEntitiesMap, CuboEntity } from '@cuboapp/types'
2
+
3
+ import { CUBO_CRUD_DEFAULT_FIELDS, CUBO_CRUD_DEFAULT_PAGE_LIMIT, CUBO_CRUD_MAX_PAGE_LIMIT, CUBO_CRUD_QUERY_KEY_REGEX } from '../constants'
4
+ import { CuboCrudFindQuery, CuboCrudRequest } from '../types'
5
+ import { dbPrepareUpdateQueryString } from '../utils'
4
6
 
5
7
  import { ApiHelpers } from '.'
6
8
 
7
- export class ApiHelpersQuery<T extends CuboEntitiesMap<T>> {
9
+ export class ApiHelpersQuery<T extends CuboApiEntitiesMap<T>> {
8
10
  constructor(private helpers: ApiHelpers<T>) {}
9
11
 
10
12
  public async createFindQuery(
11
13
  req: CuboCrudRequest,
12
- entity: CuboEntityModel,
14
+ entity: CuboEntity,
13
15
  queryDto?: Partial<CuboCrudFindQuery>,
14
16
  isCount?: boolean
15
17
  ): Promise<Partial<CuboCrudFindQuery>> {
@@ -133,7 +135,7 @@ export class ApiHelpersQuery<T extends CuboEntitiesMap<T>> {
133
135
  }
134
136
  }
135
137
 
136
- public async createUpdateQuery(req: CuboCrudRequest, entity: CuboEntityModel, queryDto?: Partial<CuboCrudFindQuery>) {
138
+ public async createUpdateQuery(req: CuboCrudRequest, entity: CuboEntity, queryDto?: Partial<CuboCrudFindQuery>) {
137
139
  const dto = await this.helpers.data.prepare('update', entity.fields, req.body)
138
140
 
139
141
  if (!Object.keys(dto)) {
@@ -1,18 +1,17 @@
1
+ import { CuboApiEntitiesMap, CuboUser } from '@cuboapp/types'
1
2
  import keyBy from 'lodash-es/keyBy'
2
3
 
3
- import { CuboEntitiesMap, CuboUserModel } from '../../types'
4
-
5
4
  import { ApiHelpers } from '.'
6
5
 
7
- export class ApiHelpersUsers<T extends CuboEntitiesMap<T>> {
6
+ export class ApiHelpersUsers<T extends CuboApiEntitiesMap<T>> {
8
7
  constructor(private helpers: ApiHelpers<T>) {}
9
8
 
10
- public async getMany(force = false): Promise<CuboUserModel[]> {
9
+ public async getMany(force = false): Promise<CuboUser[]> {
11
10
  const users = await this.helpers.getCached(
12
11
  `users`,
13
12
  async () => {
14
13
  return this.helpers.api
15
- .apiRequest<{ items: CuboUserModel[] }>(`/api/v1/users?account_id=${this.helpers.api.account.id}`)
14
+ .apiRequest<{ items: CuboUser[] }>(`/api/v1/users?account_id=${this.helpers.api.account.id}`)
16
15
  .then((res) => res.items)
17
16
  },
18
17
  force
@@ -26,12 +25,12 @@ export class ApiHelpersUsers<T extends CuboEntitiesMap<T>> {
26
25
  return this.helpers.getCached(`users_by_id`, async () => keyBy(users, (i) => +i.id), force)
27
26
  }
28
27
 
29
- public async getByEmail(email: string): Promise<CuboUserModel | undefined> {
28
+ public async getByEmail(email: string): Promise<CuboUser | undefined> {
30
29
  const entities = await this.getMany()
31
30
  return entities.find((e) => e.email === email)
32
31
  }
33
32
 
34
- public async getById(id: number): Promise<CuboUserModel | undefined> {
33
+ public async getById(id: number): Promise<CuboUser | undefined> {
35
34
  const entities = await this.getManyById()
36
35
  return entities[id]
37
36
  }
@@ -1,25 +1,17 @@
1
+ import { CuboApiEntitiesMap, CuboApiEntityDefaultUsersKeys, CuboEntity, CuboEntityField } from '@cuboapp/types'
1
2
  import cloneDeep from 'lodash-es/cloneDeep'
2
3
 
3
- import { CUBO_CRUD_DEFAULT_FIELDS, CUBO_CRUD_QUERY_KEY_REGEX } from '../../constants'
4
- import {
5
- CuboCrudFindQuery,
6
- CuboCrudMethodOptions,
7
- CuboCrudRequest,
8
- CuboCrudWith,
9
- CuboEntitiesMap,
10
- CuboEntityDefaultUsersKeys,
11
- CuboEntityFieldModel,
12
- CuboEntityModel
13
- } from '../../types'
4
+ import { CUBO_CRUD_DEFAULT_FIELDS, CUBO_CRUD_QUERY_KEY_REGEX } from '../constants'
5
+ import { CuboCrudFindQuery, CuboCrudMethodOptions, CuboCrudRequest, CuboCrudWith } from '../types'
14
6
 
15
7
  import { ApiHelpers } from '.'
16
8
 
17
- export class ApiHelpersWithes<T extends CuboEntitiesMap<T>> {
9
+ export class ApiHelpersWithes<T extends CuboApiEntitiesMap<T>> {
18
10
  constructor(private helpers: ApiHelpers<T>) {}
19
11
 
20
12
  private async getKeyWithes(
21
13
  key: string,
22
- entity: CuboEntityModel,
14
+ entity: CuboEntity,
23
15
  withes: CuboCrudWith[],
24
16
  opts: {
25
17
  replacements?: Record<string, any>
@@ -52,10 +44,10 @@ export class ApiHelpersWithes<T extends CuboEntitiesMap<T>> {
52
44
 
53
45
  const needSorts = opts.sorts !== undefined && Array.isArray(opts.sorts)
54
46
 
55
- const parts = normalKey.split('.') as (keyof T | CuboEntityDefaultUsersKeys)[]
47
+ const parts = normalKey.split('.') as (keyof T | CuboApiEntityDefaultUsersKeys)[]
56
48
 
57
49
  const currentKey: string[] = []
58
- let lastEntity: CuboEntityModel | undefined = entity
50
+ let lastEntity: CuboEntity | undefined = entity
59
51
  let joinIndex = (opts.joins.length || 0) + 1
60
52
  let joinAlias = 0
61
53
 
@@ -68,7 +60,7 @@ export class ApiHelpersWithes<T extends CuboEntitiesMap<T>> {
68
60
  const partKey = currentKey.join('.')
69
61
  const tableName = currentKey.join('_')
70
62
 
71
- const joinCustomField: CuboEntityFieldModel | undefined = lastEntity?.fields?.find((f) => f.extra?.select_entity_key === part)
63
+ const joinCustomField: CuboEntityField | undefined = lastEntity?.fields?.find((f) => f.extra?.select_entity_key === part)
72
64
  const joinDefaultField = CUBO_CRUD_DEFAULT_FIELDS.find((f) => f.extra?.select_entity_key === part)
73
65
 
74
66
  const ex = withes.find((i) => i.key === partKey)
@@ -221,7 +213,7 @@ export class ApiHelpersWithes<T extends CuboEntitiesMap<T>> {
221
213
  return ret
222
214
  }
223
215
 
224
- public async prepare(req: CuboCrudRequest, entity: CuboEntityModel, opts?: CuboCrudMethodOptions): Promise<Partial<CuboCrudFindQuery>> {
216
+ public async prepare(req: CuboCrudRequest, entity: CuboEntity, opts?: CuboCrudMethodOptions): Promise<Partial<CuboCrudFindQuery>> {
225
217
  const { with: __withes, sort: _sort, limit: _limit, ...other } = req.query || {}
226
218
 
227
219
  const _withes = (__withes || '').split(',').filter((i: string) => i !== '')