@cuboapp/api-backend 3.0.15 → 4.0.0

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.
Files changed (56) hide show
  1. package/dist/constants/index.d.ts +35 -0
  2. package/dist/constants/index.d.ts.map +1 -0
  3. package/dist/core/index.d.ts +77 -0
  4. package/dist/core/index.d.ts.map +1 -0
  5. package/dist/crdt/index.d.ts +45 -0
  6. package/dist/crdt/index.d.ts.map +1 -0
  7. package/dist/dialects/index.d.ts +21 -0
  8. package/dist/dialects/index.d.ts.map +1 -0
  9. package/dist/helpers/convert.d.ts +11 -0
  10. package/dist/helpers/convert.d.ts.map +1 -0
  11. package/dist/helpers/data.d.ts +5 -0
  12. package/dist/helpers/data.d.ts.map +1 -0
  13. package/dist/helpers/index.d.ts +42 -0
  14. package/dist/helpers/index.d.ts.map +1 -0
  15. package/dist/helpers/withes.d.ts +10 -0
  16. package/dist/helpers/withes.d.ts.map +1 -0
  17. package/dist/hooks/constants.d.ts +7 -0
  18. package/dist/hooks/constants.d.ts.map +1 -0
  19. package/dist/hooks/define.d.ts +63 -0
  20. package/dist/hooks/define.d.ts.map +1 -0
  21. package/dist/hooks/index.d.ts +5 -0
  22. package/dist/hooks/index.d.ts.map +1 -0
  23. package/dist/hooks/subscribe.d.ts +83 -0
  24. package/dist/hooks/subscribe.d.ts.map +1 -0
  25. package/dist/hooks/types.d.ts +60 -0
  26. package/dist/hooks/types.d.ts.map +1 -0
  27. package/dist/index.d.ts +8 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/query/compile.d.ts +14 -0
  30. package/dist/query/compile.d.ts.map +1 -0
  31. package/dist/query/index.d.ts +3 -0
  32. package/dist/query/index.d.ts.map +1 -0
  33. package/dist/query/types.d.ts +78 -0
  34. package/dist/query/types.d.ts.map +1 -0
  35. package/dist/types/basic.d.ts +60 -0
  36. package/dist/types/basic.d.ts.map +1 -0
  37. package/dist/types/db.d.ts +58 -0
  38. package/dist/types/db.d.ts.map +1 -0
  39. package/dist/types/index.d.ts +37 -0
  40. package/dist/types/index.d.ts.map +1 -0
  41. package/package.json +31 -21
  42. package/src/constants/index.ts +30 -20
  43. package/src/core/index.ts +6 -5
  44. package/src/crdt/index.ts +67 -13
  45. package/src/helpers/data.ts +14 -2
  46. package/src/helpers/index.ts +101 -46
  47. package/src/helpers/withes.ts +1 -1
  48. package/src/hooks/index.ts +1 -0
  49. package/src/hooks/subscribe.ts +160 -0
  50. package/src/hooks/types.ts +6 -3
  51. package/src/types/basic.ts +2 -2
  52. package/src/types/db.ts +1 -1
  53. package/.prettierrc +0 -8
  54. package/tsconfig.build.json +0 -4
  55. package/tsconfig.json +0 -22
  56. package/tsconfig.tsbuildinfo +0 -1
@@ -9,7 +9,8 @@ import {
9
9
  CUBO_CRUD_MAX_PAGE_LIMIT,
10
10
  CUBO_CRUD_QUERY_CONDITION,
11
11
  CUBO_CRUD_QUERY_KEY_REGEX,
12
- CUBO_CRUD_QUERY_SYMBOL_NOT
12
+ CUBO_CRUD_QUERY_SYMBOL_NOT,
13
+ CUBO_CRUD_QUERY_SYMBOL_OR
13
14
  } from '../constants'
14
15
  import type { CuboBackendApi } from '../core'
15
16
  import { CuboDialect, getDialect } from '../dialects'
@@ -69,37 +70,61 @@ export class ApiHelpers<T extends CuboApiEntitiesMap<T>, A = unknown> {
69
70
  let is_not = false
70
71
  let condition = 'eq'
71
72
 
73
+ // Read the condition off the PREFIX when the value carries one, and leave the rest verbatim.
74
+ //
75
+ // The parse below derives the condition by counting `value.split(':')`, which means a value
76
+ // containing a colon of its own has no way through it: `gte:2026-08-01 00:00:00` is four parts
77
+ // and gets rejected, as does a `btw` whose bounds are timestamps. Timestamps are the obvious
78
+ // case, but any text with a colon in it has the same problem.
79
+ //
80
+ // Only a RECOGNISED `[not:]<condition>:` prefix takes this path, so nothing that works today
81
+ // changes and nothing that is rejected today is quietly accepted: `typo:5` still has no known
82
+ // condition, still falls through, and still fails loudly. A `btw` range whose bounds are
83
+ // themselves colon-bearing separates them with `..` rather than `:`.
84
+ // Longest first, so `gte` is not shadowed by `gt` and `ilike` not by `in`.
85
+ const known = Object.values(CUBO_CRUD_QUERY_CONDITION)
86
+ .slice()
87
+ .sort((a, b) => b.length - a.length)
88
+ .join('|')
89
+ const prefixed = typeof value === 'string' ? new RegExp(`^(${CUBO_CRUD_QUERY_SYMBOL_NOT}:)?(${known}):`).exec(value) : null
90
+
72
91
  // condition parts
73
- switch (parts.length) {
74
- case 3:
75
- if (parts[0] === 'btw') {
76
- condition = parts[0]
77
- value = `${parts[1]}:${parts[2]}`
78
- } else if (parts[0] !== CUBO_CRUD_QUERY_SYMBOL_NOT) {
79
- throw new Error(`"${field.alias}": three-level value allow only "not" condition at first level (${value})`)
80
- } else if (!Object.values(CUBO_CRUD_QUERY_CONDITION).includes(parts[1])) {
81
- throw new Error(`"${field.alias}": incorrect condition "${parts[1]}" in second level (${value})`)
82
- } else {
83
- is_not = true
84
- condition = parts[1]
85
- value = parts[2]
86
- }
87
- break
88
- case 2:
89
- if (parts[0] === CUBO_CRUD_QUERY_SYMBOL_NOT) {
90
- is_not = true
91
- value = parts[1]
92
- } else if (Object.values(CUBO_CRUD_QUERY_CONDITION).includes(parts[0])) {
93
- condition = parts[0]
94
- value = parts[1]
95
- } else {
96
- throw new Error(`"${field.alias}": incorrect condition "${parts[0]}" in second level (${value})`)
97
- }
98
- break
99
- case 1:
100
- break
101
- default:
102
- throw new Error(`"${field.alias}": incorrect condition value "${value}"`)
92
+ if (prefixed) {
93
+ is_not = Boolean(prefixed[1])
94
+ condition = prefixed[2]
95
+ value = (value as string).slice(prefixed[0].length)
96
+ } else {
97
+ switch (parts.length) {
98
+ case 3:
99
+ if (parts[0] === 'btw') {
100
+ condition = parts[0]
101
+ value = `${parts[1]}:${parts[2]}`
102
+ } else if (parts[0] !== CUBO_CRUD_QUERY_SYMBOL_NOT) {
103
+ throw new Error(`"${field.alias}": three-level value allow only "not" condition at first level (${value})`)
104
+ } else if (!Object.values(CUBO_CRUD_QUERY_CONDITION).includes(parts[1])) {
105
+ throw new Error(`"${field.alias}": incorrect condition "${parts[1]}" in second level (${value})`)
106
+ } else {
107
+ is_not = true
108
+ condition = parts[1]
109
+ value = parts[2]
110
+ }
111
+ break
112
+ case 2:
113
+ if (parts[0] === CUBO_CRUD_QUERY_SYMBOL_NOT) {
114
+ is_not = true
115
+ value = parts[1]
116
+ } else if (Object.values(CUBO_CRUD_QUERY_CONDITION).includes(parts[0])) {
117
+ condition = parts[0]
118
+ value = parts[1]
119
+ } else {
120
+ throw new Error(`"${field.alias}": incorrect condition "${parts[0]}" in second level (${value})`)
121
+ }
122
+ break
123
+ case 1:
124
+ break
125
+ default:
126
+ throw new Error(`"${field.alias}": incorrect condition value "${value}"`)
127
+ }
103
128
  }
104
129
 
105
130
  switch (field.type) {
@@ -158,7 +183,7 @@ export class ApiHelpers<T extends CuboApiEntitiesMap<T>, A = unknown> {
158
183
  if ([CUBO_CRUD_QUERY_CONDITION.IN, CUBO_CRUD_QUERY_CONDITION.NIN].includes(condition)) {
159
184
  value = value.split(',').map(Number)
160
185
  } else if (condition === CUBO_CRUD_QUERY_CONDITION.BTW) {
161
- const [fromStr, toStr] = value.split(':')
186
+ const [fromStr, toStr] = value.includes('..') ? value.split('..') : value.split(':')
162
187
  const from = precision === 0 ? parseInt(fromStr) : parseFloat(fromStr)
163
188
  const to = precision === 0 ? parseInt(toStr) : parseFloat(toStr)
164
189
 
@@ -284,7 +309,10 @@ export class ApiHelpers<T extends CuboApiEntitiesMap<T>, A = unknown> {
284
309
  replacements[replacement] = value
285
310
  break
286
311
  case CUBO_CRUD_QUERY_CONDITION.BTW: {
287
- const [from, to] = String(value).split(':')
312
+ // `..` when the bounds carry their own colons (timestamps), `:` otherwise. Splitting on `:`
313
+ // unconditionally would take `00` as the whole upper bound of a `10:00:00` range.
314
+ const raw = String(value)
315
+ const [from, to] = raw.includes('..') ? raw.split('..') : raw.split(':')
288
316
  const fromKey = `${replacement}_from`
289
317
  const toKey = `${replacement}_to`
290
318
 
@@ -464,7 +492,7 @@ export class ApiHelpers<T extends CuboApiEntitiesMap<T>, A = unknown> {
464
492
  return this.api.options.entities.find((e) => e.alias === alias)
465
493
  }
466
494
 
467
- public async getEntityById(id: number): Promise<CuboEntity | undefined> {
495
+ public async getEntityById(id: string): Promise<CuboEntity | undefined> {
468
496
  return this.api.options.entities.find((e) => e.id === id)
469
497
  }
470
498
 
@@ -488,31 +516,58 @@ export class ApiHelpers<T extends CuboApiEntitiesMap<T>, A = unknown> {
488
516
  const { sort, limit: _limit, page, with: _withes, ...query } = cloneDeep(req.query || {})
489
517
 
490
518
  // plain conditions (nested are in withes.ts)
519
+ //
520
+ // Counted, because a field can now legitimately be named by two different keys — `?a=1&a|b=2` —
521
+ // and a replacement name derived from the field alone would have the second silently overwrite
522
+ // the first, changing what the first condition filters on rather than failing.
523
+ let conditionIndex = 0
491
524
  for (const key in query || {}) {
492
525
  const parts = key.replace(CUBO_CRUD_QUERY_KEY_REGEX, '')?.split('.')
493
526
 
494
527
  if (parts.length === 1) {
495
- const conditionField = entity.fields?.find((f) => f.alias === parts[0])
496
- const defaultField = CUBO_CRUD_DEFAULT_FIELDS.find((f) => f.alias === parts[0])
497
-
498
- // if (!conditionField && !defaultField) {
499
- // throw new Error('condition field "' + parts[0] + '" not found in entity "' + entity.alias + '"')
500
- // }
528
+ // A key may name several fields to be OR-ed: `?a|b=<value>` asks the same condition of each
529
+ // and matches a row where ANY of them holds. One field is just the one-element case, so
530
+ // there is a single path through here rather than two that can drift apart.
531
+ const aliases = parts[0].split(CUBO_CRUD_QUERY_SYMBOL_OR).filter((a) => a.length > 0)
532
+ if (!aliases.length) continue
533
+ conditionIndex += 1
534
+
535
+ const anyOf: string[] = []
536
+ for (const alias of aliases) {
537
+ const conditionField = entity.fields?.find((f) => f.alias === alias)
538
+ const defaultField = CUBO_CRUD_DEFAULT_FIELDS.find((f) => f.alias === alias)
539
+
540
+ if (!conditionField && !defaultField) {
541
+ throw new Error('condition field "' + alias + '" not found in entity "' + entity.alias + '"')
542
+ }
501
543
 
502
- if (conditionField || defaultField) {
503
- const fieldAlias = conditionField ? conditionField.alias : defaultField!.alias
504
- const preparedCondition = this.clearFieldConditionValue(conditionField ? conditionField : defaultField!, query[key])
544
+ // Upstream replaced the throw above with `if (conditionField || defaultField)`, skipping an
545
+ // unknown field silently. Not adopted: a filter naming a field that does not exist is a
546
+ // caller mistake, and answering it with an unfiltered list is the wrong answer delivered
547
+ // confidently. The throw is also what our OR-alias loop needs — a skipped alias would make
548
+ // `a|b` quietly mean `b`.
549
+ const field = conditionField ?? defaultField!
550
+ const preparedCondition = this.clearFieldConditionValue(field, query[key])
505
551
  const prepared = this.prepareConditionSql(
506
- `t1.${fieldAlias}`,
507
- `c_1_${fieldAlias}_value`,
552
+ `t1.${field.alias}`,
553
+ // `conditionIndex` is OURS and upstream still names the parameter after the field alone.
554
+ // Two conditions on one field then bind the same name and the second silently overwrites
555
+ // the first — which is how the documents list lost its filters (f5eb8de).
556
+ `c_1_${conditionIndex}_${field.alias}_value`,
508
557
  preparedCondition.value,
509
558
  preparedCondition.condition,
510
559
  preparedCondition.is_not
511
560
  )
512
561
 
513
- conditions.push(...(prepared.conditions || []))
562
+ anyOf.push(...(prepared.conditions || []))
514
563
  Object.assign(replacements, prepared.replacements || {})
515
564
  }
565
+
566
+ // Parenthesised as one condition. The caller AND-s the list, so an unwrapped `a or b` would
567
+ // bind looser than the surrounding ANDs and quietly widen every other filter on the query.
568
+ // Upstream pushes the parts straight into `conditions`, which has that effect.
569
+ if (anyOf.length === 1) conditions.push(anyOf[0])
570
+ else if (anyOf.length > 1) conditions.push(`(${anyOf.join(' or ')})`)
516
571
  }
517
572
  }
518
573
 
@@ -69,7 +69,7 @@ export class ApiHelpersWithes<T extends CuboApiEntitiesMap<T>> {
69
69
 
70
70
  // если нашли кастомное поле
71
71
  if (joinCustomField) {
72
- const relation_entity_id: number | undefined = joinCustomField?.extra?.select_entity_id
72
+ const relation_entity_id: string | undefined = joinCustomField?.extra?.select_entity_id
73
73
  const relation_entity_alias: keyof T | undefined = joinCustomField?.extra?.select_entity_alias as keyof T
74
74
 
75
75
  if (!relation_entity_id && !relation_entity_alias) {
@@ -1,3 +1,4 @@
1
1
  export * from './constants'
2
2
  export * from './types'
3
3
  export * from './define'
4
+ export * from './subscribe'
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Subscribing a module backend to its declared hooks (hooks.md §5).
3
+ *
4
+ * A module's hooks are declared on its version, next to the entities they belong to. This is the
5
+ * other half: the running build telling the core "I am alive, I am this version, and these are the
6
+ * tuples I actually implement". The core binds the declarations to this process, works out which
7
+ * accounts that touches — a module backend serves every account it is installed in and deliberately
8
+ * cannot enumerate them — and compiles the chain.
9
+ *
10
+ * What a module backend has to write is one call:
11
+ *
12
+ * const stop = subscribeHooks({
13
+ * apiUrl: process.env.CUBO_API_URL!,
14
+ * token: process.env.CUBO_TOKEN!,
15
+ * version: process.env.CUBO_MODULE_VERSION!,
16
+ * baseUrl: 'http://flowers-be:9100',
17
+ * implemented: tuplesFrom(READS, ENRICH, AFTER, VIRTUAL_FIELDS)
18
+ * })
19
+ *
20
+ * and call `stop()` on shutdown. Everything else — the renewal interval, the TTL contract, the boot
21
+ * diff, the graceful unsubscribe — lives here so no module has to reimplement a protocol.
22
+ */
23
+
24
+ /** How often to renew. The core treats a subscription older than 30s as dead, so this has slack. */
25
+ export const SUBSCRIBE_INTERVAL_MS = 10_000
26
+
27
+ export interface SubscribeOptions {
28
+ /** The core API base url, e.g. `http://cubo-api:4000`. */
29
+ apiUrl: string
30
+ /** This service's `cubo-module-service` token — the same one `/auth/me` accepts. */
31
+ token: string
32
+ /** The module VERSION id this build implements. Hooks are a contract with one specific build. */
33
+ version: string
34
+ /**
35
+ * Where this service can be reached, e.g. `http://flowers-be:9100`.
36
+ *
37
+ * Honoured only for the module owner's own account. Everywhere else the core resolves the endpoint
38
+ * from the deployment record instead — the hook url is where the instance sends a live,
39
+ * identity-scoped credential, so it must not be settable by whoever holds this token.
40
+ */
41
+ baseUrl?: string
42
+ /** The tuples this build implements: `entity:method:phase`. See `hookTuples`. */
43
+ implemented: string[]
44
+ /** Called with the core's boot diff on every successful subscribe. */
45
+ onDiff?: (diff: SubscribeDiff) => void
46
+ /** Called when a renewal fails. Default logs; the loop keeps trying. */
47
+ onError?: (error: unknown) => void
48
+ fetchImpl?: typeof fetch
49
+ }
50
+
51
+ export interface SubscribeDiff {
52
+ declared: string[]
53
+ /** Declared but not implemented by this build. */
54
+ missing: string[]
55
+ /** The subset of `missing` the module marked required — every write on those will fail closed. */
56
+ missing_required: string[]
57
+ /** Implemented but never declared. Harmless (the core will not call them) but usually an oversight. */
58
+ undeclared: string[]
59
+ }
60
+
61
+ /**
62
+ * Turn a module's dispatch maps into the tuple list the core diffs against.
63
+ *
64
+ * Module backends key their handlers by `entity:method` and split before/after by route, which is the
65
+ * convention the declaration format was lifted FROM — so the tuples can be derived from the code
66
+ * rather than maintained beside it. Anything derived cannot drift.
67
+ */
68
+ export function hookTuples(maps: {
69
+ /** Read rewrites — before-phase on the methods each key names. */
70
+ before?: Record<string, unknown>
71
+ /** Response shaping / write effects — after-phase. */
72
+ after?: Record<string, unknown>
73
+ /** Entities whose write bodies are stripped before the engine sees them: create + update, before. */
74
+ virtualFields?: string[] | Record<string, unknown>
75
+ }): string[] {
76
+ const out = new Set<string>()
77
+ for (const key of Object.keys(maps.before ?? {})) out.add(`${key}:before`)
78
+ for (const key of Object.keys(maps.after ?? {})) out.add(`${key}:after`)
79
+ const virtual = Array.isArray(maps.virtualFields) ? maps.virtualFields : Object.keys(maps.virtualFields ?? {})
80
+ for (const entity of virtual) {
81
+ out.add(`${entity}:create:before`)
82
+ out.add(`${entity}:update:before`)
83
+ }
84
+ return [...out].sort()
85
+ }
86
+
87
+ export interface Subscription {
88
+ /** Unsubscribe and stop renewing. Safe to call more than once. */
89
+ stop: () => Promise<void>
90
+ /** Force a renewal now — useful in tests, and after a deploy changes what is implemented. */
91
+ renew: () => Promise<SubscribeDiff | null>
92
+ }
93
+
94
+ /**
95
+ * Start the subscribe loop. Returns immediately; the first renewal runs in the background so a slow
96
+ * or unreachable core cannot hold up the service's own boot.
97
+ */
98
+ export function subscribeHooks(options: SubscribeOptions): Subscription {
99
+ const fetchImpl = options.fetchImpl ?? fetch
100
+ const url = `${options.apiUrl.replace(/\/+$/, '')}/modules-api/subscription`
101
+ const headers = { 'content-type': 'application/json', 'cubo-module-service': options.token }
102
+ const onError =
103
+ options.onError ??
104
+ ((error: unknown) => {
105
+ // eslint-disable-next-line no-console
106
+ console.error('[hooks] subscribe failed:', error instanceof Error ? error.message : String(error))
107
+ })
108
+
109
+ let timer: ReturnType<typeof setInterval> | null = null
110
+ let stopped = false
111
+
112
+ async function renew(): Promise<SubscribeDiff | null> {
113
+ if (stopped) return null
114
+ try {
115
+ const res = await fetchImpl(url, {
116
+ method: 'PUT',
117
+ headers,
118
+ body: JSON.stringify({
119
+ version: options.version,
120
+ base_url: options.baseUrl ?? '',
121
+ implemented: options.implemented
122
+ })
123
+ })
124
+ if (!res.ok) throw new Error(`core replied ${res.status}`)
125
+ const diff = (await res.json()) as SubscribeDiff
126
+ // A required tuple this build does not implement is fatal for those writes — say so loudly at
127
+ // boot rather than letting it surface as an empty `{}` reply at the first save.
128
+ if (diff.missing_required?.length) {
129
+ // eslint-disable-next-line no-console
130
+ console.error(`[hooks] REQUIRED hooks declared but not implemented: ${diff.missing_required.join(', ')}`)
131
+ }
132
+ options.onDiff?.(diff)
133
+ return diff
134
+ } catch (error) {
135
+ onError(error)
136
+ return null
137
+ }
138
+ }
139
+
140
+ void renew()
141
+ timer = setInterval(() => void renew(), SUBSCRIBE_INTERVAL_MS)
142
+ // Never hold the process open on our account: a renewal loop is not a reason not to exit.
143
+ timer.unref?.()
144
+
145
+ return {
146
+ renew,
147
+ stop: async () => {
148
+ if (stopped) return
149
+ stopped = true
150
+ if (timer) clearInterval(timer)
151
+ timer = null
152
+ try {
153
+ await fetchImpl(url, { method: 'DELETE', headers })
154
+ } catch (error) {
155
+ // A crash-stop is covered by the TTL anyway; failing to say goodbye is not worth an error.
156
+ onError(error)
157
+ }
158
+ }
159
+ }
160
+ }
@@ -17,7 +17,7 @@ export type CuboHookCtx<R, A = unknown> = {
17
17
  entity: CuboEntity
18
18
  req: CuboCrudRequest
19
19
  auth?: A
20
- performer_id?: number
20
+ performer_id?: string
21
21
  queryOptions: CuboCrudQueryOptions
22
22
  }
23
23
 
@@ -43,8 +43,11 @@ export interface CuboAugmentation<R, A = unknown> {
43
43
  // авторизация конкретного действия над строкой
44
44
  can?(action: CuboCrudAction, ctx: CuboHookCtx<R, A> & { row?: R }): MaybePromise<boolean>
45
45
 
46
- // фильтр строки под CRDT-подписку
47
- filterRowForCrdtEvent?(row: R, filters: Record<string, any>): boolean
46
+ // фильтр строки под CRDT-подписку.
47
+ // `auth` — авторизация КЛИЕНТА, владеющего подпиской (адаптер резолвит её по subscribe.client_id).
48
+ // Без неё пуш нельзя ограничить по правам: первичная гидрация подписки идёт через getMany с auth
49
+ // и уважает beforeGetMany, а живые пуши — нет, и строка, скрытая при гидрации, всё равно долетела бы.
50
+ filterRowForCrdtEvent?(row: R, filters: Record<string, any>, auth?: A): boolean
48
51
  }
49
52
 
50
53
  export type CuboAugmentationsStore<T extends CuboApiEntitiesMap<T>, A = unknown> = {
@@ -1,7 +1,7 @@
1
1
  import { type Transaction } from '@cuboapp/database'
2
2
  import { CuboEntity, CuboEntityField } from '@cuboapp/types'
3
3
 
4
- import { CUBO_CRUD_ACTION } from '@/constants'
4
+ import { CUBO_CRUD_ACTION } from '../constants'
5
5
 
6
6
  export type CuboCrudAction = (typeof CUBO_CRUD_ACTION)[number]
7
7
 
@@ -27,7 +27,7 @@ export type CuboCrudRequest = {
27
27
  }
28
28
 
29
29
  export type CuboCrudOptions = {
30
- performer_id?: number
30
+ performer_id?: string
31
31
  transaction?: Transaction
32
32
  }
33
33
 
package/src/types/db.ts CHANGED
@@ -78,7 +78,7 @@ export const normalizeCuboCrudQueryOptions = (input?: CuboCrudQueryOptionsInput
78
78
 
79
79
  export type CuboCrudMethodOptions<E extends object = {}> = {
80
80
  transaction?: Transaction
81
- performer_id?: number
81
+ performer_id?: string
82
82
  auth?: any
83
83
  extra?: any
84
84
  debounce?: number
package/.prettierrc DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "trailingComma": "none",
3
- "tabWidth": 2,
4
- "semi": false,
5
- "singleQuote": true,
6
- "eslintIntegration": true,
7
- "printWidth": 140
8
- }
@@ -1,4 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4
- }
package/tsconfig.json DELETED
@@ -1,22 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "module": "commonjs",
4
- "declaration": true,
5
- "removeComments": true,
6
- "emitDecoratorMetadata": true,
7
- "experimentalDecorators": true,
8
- "allowSyntheticDefaultImports": true,
9
- "target": "ES2021",
10
- "sourceMap": true,
11
- "rootDir": ".",
12
- "incremental": true,
13
- "skipLibCheck": true,
14
- "strict": false,
15
- "paths": {
16
- "@/*": ["./src/*"]
17
- },
18
- "types": ["node"]
19
- },
20
- "include": ["src/**/*"],
21
- "exclude": ["node_modules", "dist"]
22
- }