rajt 0.0.31 → 0.0.33

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rajt",
3
3
  "description": "A serverless bundler layer, fully typed for AWS Lambda (Node.js and LLRT) and Cloudflare Workers.",
4
- "version": "0.0.31",
4
+ "version": "0.0.33",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "exports": {
@@ -13,7 +13,7 @@ export class Ability {
13
13
  static fromRoutes(actions: Routes) {
14
14
  if (!actions?.length) return
15
15
 
16
- const paths = actions?.map(a => Array.isArray(a) ? a[1] : a.path) ?? []
16
+ const paths = actions?.map(a => Array.isArray(a) ? a[0]+a[1] : a.method+a.path) || []
17
17
  const items = new Set(paths)
18
18
 
19
19
  if (items.size !== actions.length)
package/src/auth/token.ts CHANGED
@@ -40,7 +40,7 @@ export class Token {
40
40
  }
41
41
 
42
42
  static parse(token: string) {
43
- const host = this.host(Envir.get('FLOW_SERVER') || c.cx.req.header('host') || '')
43
+ const host = this.host(Envir.get('FLOW_SERVER'))
44
44
 
45
45
  return Factory.parse(token)
46
46
  .issuedBy(host)
@@ -67,8 +67,8 @@ export class Token {
67
67
  this.#name = name
68
68
  }
69
69
 
70
- static host(url: string | null | undefined): string {
71
- if (!url) return ''
70
+ static host(url?: string | null | undefined): string {
71
+ if (!url) url = c.cx.req.url || c.cx.req.header('host') || ''
72
72
 
73
73
  let formattedUrl = String(url)
74
74
  if (!formattedUrl.startsWith('http'))
@@ -147,9 +147,10 @@ export default class Compact {
147
147
 
148
148
  return val
149
149
  }
150
- const length = getLength(val, type)
151
150
 
152
- if (type !== 'object' && length < 2) return val
151
+ const length = getLength(val, type)
152
+ if ([null, true, false].includes(val) || type != 'object' && length < 2)
153
+ return val
153
154
 
154
155
  const index = seen.indexOf(val)
155
156
  if (index !== -1)
@@ -17,7 +17,7 @@ import getLength from '../utils/lenght'
17
17
 
18
18
  export default class AbstractModel<T extends object> {
19
19
  #meta: ModelMetadata
20
- #cls!: Model<T>
20
+ cls?: Model<T>
21
21
  lastKey?: Record<string, any>
22
22
  #db: DynamoDBDocumentClient
23
23
  #queryBuilder?: QueryBuilder
@@ -35,6 +35,7 @@ export default class AbstractModel<T extends object> {
35
35
 
36
36
  if (typeof (cls as ModelMetadata).table === 'string') {
37
37
  this.#meta = cls as ModelMetadata
38
+ this.cls = model?.cls
38
39
  return
39
40
  }
40
41
 
@@ -43,7 +44,7 @@ export default class AbstractModel<T extends object> {
43
44
  throw new Error('Missing model metadata')
44
45
 
45
46
  this.#meta = meta
46
- this.#cls = cls as Model<T>
47
+ this.cls = cls as Model<T>
47
48
  }
48
49
 
49
50
  get table(): string {
@@ -272,21 +273,20 @@ export default class AbstractModel<T extends object> {
272
273
  }
273
274
 
274
275
  #processItems(items: any[] | undefined, filterFn?: Filter<T>): T[] {
275
- if (!items) return []
276
-
277
- items = this.#meta.zip ? Compact.smartDecode<T[]>(items, this.#meta.fields) : items as T[]
276
+ if (!items || !items.length) return []
277
+ items = items.map(item => this.#processItem(item))
278
278
  return filterFn ? items.filter(filterFn) : items
279
279
  }
280
280
 
281
281
  #processItem(item: any, keys?: Record<string, string>): T {
282
282
  if (this.#meta.zip && item?.V) {
283
- const model = new this.#cls(Compact.decode(item.V, this.#meta.fields))
283
+ const model = new this.cls!(Compact.decode<T>(item.V, this.#meta.fields))
284
284
  if (!keys) keys = this.#getItemKey(item)
285
285
 
286
286
  // @ts-ignore
287
287
  return model.withKey(keys[this.#meta.keys.PK], keys[this.#meta.keys.SK] || undefined)
288
288
  }
289
289
 
290
- return new this.#cls(item)
290
+ return new this.cls!(item)
291
291
  }
292
292
  }
@@ -1,19 +1,24 @@
1
1
  import type { Condition, Operator } from './types'
2
2
 
3
3
  export default class QueryBuilder {
4
- #conditions: Condition[] = []
4
+ #filters: Condition[] = []
5
+ #keyConditions: Condition[] = []
5
6
  #limit?: number
6
7
  #startKey?: Record<string, any>
7
8
  #index?: string
9
+ #attrCounter = 1
10
+ #valCounter = 1
11
+ #fieldAttrMap: Record<string, string> = {}
12
+ #fieldValMap: Record<string, string> = {}
8
13
 
9
14
  filter(field: string, operator: Operator, value: any = null) {
10
- this.#conditions.push({ type: 'filter', field, operator, value })
15
+ this.#filters.push({ type: 'filter', field, operator, value })
11
16
  return this
12
17
  }
13
18
 
14
19
  keyCondition(field: string, operator: Operator | any, value?: any) {
15
20
  const noVal = value === undefined
16
- this.#conditions.push({ type: 'keyCondition', field, operator: noVal ? '=' : operator, value: noVal ? operator : value })
21
+ this.#keyConditions.push({ type: 'keyCondition', field, operator: noVal ? '=' : operator, value: noVal ? operator : value })
17
22
  return this
18
23
  }
19
24
 
@@ -32,22 +37,45 @@ export default class QueryBuilder {
32
37
  return this
33
38
  }
34
39
 
35
- buildExpression(type: 'filter' | 'keyCondition') {
40
+ private attrName(field: string) {
41
+ if (!this.#fieldAttrMap[field])
42
+ this.#fieldAttrMap[field] = '#a'+ this.#attrCounter++
43
+
44
+ return this.#fieldAttrMap[field]
45
+ }
46
+
47
+ private valName(val: any) {
48
+ val = String(val)
49
+ if (!this.#fieldValMap[val])
50
+ this.#fieldValMap[val] = ':v'+ this.#valCounter++
51
+
52
+ return this.#fieldValMap[val]
53
+ }
54
+
55
+ #resetCounters() {
56
+ this.#attrCounter = 0
57
+ this.#valCounter = 0
58
+ this.#fieldAttrMap = {}
59
+ this.#fieldValMap = {}
60
+ }
61
+
62
+ buildExpression(conditions: Condition[]) {
36
63
  const exprParts: string[] = []
37
64
  const values: Record<string, any> = {}
38
65
  const names: Record<string, string> = {}
39
66
 
40
- let i = 0
41
- for (const cond of this.#conditions.filter(c => c.type === type)) {
42
- const attr = `#attr${i}`
43
- const val = `:val${i}`
67
+ for (const cond of conditions) {
68
+ const attr = this.attrName(cond.field)
69
+ const val = Array.isArray(cond.value) ? '' : this.valName(cond.value)
44
70
  names[attr] = cond.field
45
71
 
46
72
  switch (cond.operator) {
47
73
  case 'between': {
48
- exprParts.push(`${attr} BETWEEN ${val}a AND ${val}b`)
49
- values[`${val}a`] = cond.value[0]
50
- values[`${val}b`] = cond.value[1]
74
+ const val0 = this.valName(cond.value[0])
75
+ const val1 = this.valName(cond.value[1])
76
+ exprParts.push(`${attr} BETWEEN ${val0} AND ${val1}`)
77
+ values[val0] = cond.value[0]
78
+ values[val1] = cond.value[1]
51
79
  break
52
80
  }
53
81
  case 'begins_with': {
@@ -56,10 +84,10 @@ export default class QueryBuilder {
56
84
  break
57
85
  }
58
86
  case 'in': {
59
- const inVals = cond.value.map((v: any, j: number) => {
60
- const vKey = `${val}_${j}`
61
- values[vKey] = v
62
- return vKey
87
+ const inVals = cond.value.map((v: any) => {
88
+ const key = this.valName(v)
89
+ values[key] = v
90
+ return key
63
91
  })
64
92
  exprParts.push(`${attr} IN (${inVals.join(', ')})`)
65
93
  break
@@ -92,8 +120,6 @@ export default class QueryBuilder {
92
120
  values[val] = cond.value
93
121
  }
94
122
  }
95
-
96
- i++
97
123
  }
98
124
 
99
125
  return {
@@ -104,7 +130,7 @@ export default class QueryBuilder {
104
130
  }
105
131
 
106
132
  get filters() {
107
- const filter = this.buildExpression('filter')
133
+ const filter = this.buildExpression(this.#filters)
108
134
  const params: any = {}
109
135
 
110
136
  if (this.#limit)
@@ -126,7 +152,7 @@ export default class QueryBuilder {
126
152
  }
127
153
 
128
154
  get conditions() {
129
- const keys = this.buildExpression('keyCondition')
155
+ const keys = this.buildExpression(this.#keyConditions)
130
156
  const filters = this.filters
131
157
 
132
158
  const params: any = { ...filters }