rajt 0.0.23 → 0.0.25

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.23",
4
+ "version": "0.0.25",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "exports": {
package/src/action.ts CHANGED
@@ -101,7 +101,7 @@ export default abstract class Action {
101
101
 
102
102
  async body<E>() {
103
103
  const cType = this.context.req.header('Content-Type')
104
- if (!cType) return {}
104
+ if (!cType) return {} as E
105
105
 
106
106
  if (/^application\/([a-z-\.]+\+)?json(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/.test(cType)) {
107
107
  return await this.json<E>()
@@ -114,7 +114,7 @@ export default abstract class Action {
114
114
  return await this.form() as E
115
115
  }
116
116
 
117
- return {}
117
+ return {} as E
118
118
  }
119
119
 
120
120
  get response() {
@@ -2,38 +2,43 @@ import type { SchemaStructure } from './types'
2
2
  import getLength from '../utils/lenght'
3
3
 
4
4
  export default class Compact {
5
+ static #typeRegex: RegExp
6
+ static #reverseTypeRegex: RegExp
7
+ static #reverseTypeMap: Record<string, string>
5
8
  static #typeMap: Record<string, string> = {
9
+ // Boolean
10
+ 'true': 'T',
11
+ 'false': 'F',
6
12
  // Null
7
- 'null,': 'N,',
8
- ',null': ',N',
9
- 'null]': 'N]',
10
- // True
11
- 'true,': 'T,',
12
- ',true': ',T',
13
- 'true]': 'T]',
14
- // False
15
- 'false,': 'F,',
16
- ',false': ',F',
17
- 'false]': 'F]',
13
+ 'null': 'N',
18
14
  // Array
19
- '[],': 'A,',
20
- ',[]': ',A',
21
- '[]]': 'A]',
15
+ '[]': 'A',
22
16
  // Object
23
- '{},': 'O,',
24
- ',{}': ',O',
25
- '{}]': 'O]'
17
+ '{}': 'O',
18
+ // Commons
19
+ '["0"]': 'A0',
20
+ '["1"]': 'A1',
21
+ '["true"]': 'A2',
22
+ '["false"]': 'A3',
23
+ '"true"': 'T1',
24
+ '"false"': 'T0',
25
+ }
26
+
27
+ static {
28
+ this.#reverseTypeMap = Object.fromEntries(Object.entries(this.#typeMap).map(([k, v]) => [v, k]))
29
+ this.#typeRegex = this.#mapRegex(Object.keys(this.#typeMap))
30
+ this.#reverseTypeRegex = this.#mapRegex(Object.keys(this.#reverseTypeMap))
26
31
  }
27
32
 
28
33
  static encode(obj: any, schema: SchemaStructure): string {
29
34
  const seen: any[] = []
30
- return this.replaceTypes(
31
- JSON.stringify(this.zip(obj, schema, seen)).replace(/(,|\[)"(\^\d+)"(\]|,|$)/g, '$1$2$3')
35
+ return this.#minify(
36
+ JSON.stringify(this.zip(obj, schema, seen))
37
+ .replace(/"\^(\d+)"/g, '^$1')
32
38
  .replace(/"/g, '~TDQ~')
33
39
  .replace(/'/g, '"')
34
40
  .replace(/~TDQ~/g, "'")
35
- .replace(/\\'/g, "^'"),
36
- this.#typeMap
41
+ .replace(/\\'/g, "^'")
37
42
  )
38
43
  }
39
44
 
@@ -47,16 +52,16 @@ export default class Compact {
47
52
  }
48
53
 
49
54
  static decode<T = any>(val: string, schema: SchemaStructure): T {
50
- if (!val) return val as T
55
+ if (!val || typeof val !== 'string') return val as T
51
56
 
52
- val = this.replaceTypes(val, this.reverseMap(this.#typeMap))
53
- .replace(/"/g, '~TSQ~')
54
- .replace(/'/g, '"')
55
- .replace(/~TSQ~/g, "'")
56
- .replace(/\^"/g, '\\"')
57
- .replace(/(,|\[)(\^\d+)(\]|,|$)/g, '$1"$2"$3')
58
-
59
- return this.withSchema(this.unzip(JSON.parse(val)), schema) as T
57
+ return this.withSchema(this.unzip(JSON.parse(
58
+ this.#deminify(val)
59
+ .replace(/"/g, '~TSQ~')
60
+ .replace(/'/g, '"')
61
+ .replace(/~TSQ~/g, "'")
62
+ .replace(/\^"/g, '\\"')
63
+ .replace(/(?<=[,{\[]|^)(\^\d+)(?=[,\]}[]|$)/g, '"$1"')
64
+ )), schema) as T
60
65
  }
61
66
 
62
67
  static zip(obj: any, schema: SchemaStructure, seen: any[]): any[] {
@@ -75,25 +80,30 @@ export default class Compact {
75
80
  })
76
81
  }
77
82
 
78
- static unzip(array: any[], seen: any[] = [], deep = false): any[] {
79
- return array.map(item => {
80
- const length = getLength(item)
83
+ static unzip(val: any, seen: any[] = [], deep = false): any[] {
84
+ const type = typeof val
85
+ const length = getLength(val, type)
81
86
 
82
- if ([null, true, false].includes(item) || typeof item !== 'object' && length < 2)
83
- return item
87
+ if ([null, true, false].includes(val) || type != 'object' && length < 2)
88
+ return val
84
89
 
85
- if (Array.isArray(item))
86
- return this.unzip(item, seen, true)
90
+ if (Array.isArray(val))
91
+ return val.map(item => this.unzip(item, seen, deep))
87
92
 
88
- if (typeof item === 'string' && item.startsWith('^')) {
89
- const pos = parseInt(item.slice(1), 10)
90
- const val = seen[pos]
91
- return deep || (val && !`${val}`.startsWith('^')) ? val : item
92
- }
93
+ if (type == 'object') {
94
+ for (const key in val)
95
+ val[key] = this.unzip(val[key], seen)
93
96
 
94
- seen.push(item)
95
- return item
96
- })
97
+ return val
98
+ }
99
+
100
+ if (type == 'string' && val.startsWith('^')) {
101
+ const item = seen[parseInt(val.slice(1), 10)]
102
+ return item ? item : val
103
+ }
104
+
105
+ seen.push(val)
106
+ return val
97
107
  }
98
108
 
99
109
  static withSchema(value: any[], keys: any[]): any {
@@ -108,14 +118,14 @@ export default class Compact {
108
118
  static entry(key: any, value: any): any {
109
119
  if (!key) return undefined
110
120
 
111
- if (typeof key === 'string')
121
+ if (typeof key == 'string')
112
122
  return [key, value]
113
123
 
114
124
  const mainKey = Object.keys(key)[0]
115
125
  const subKeys = key[mainKey]
116
126
 
117
127
  if (Array.isArray(value)) {
118
- if (value.length === 0)
128
+ if (value.length < 1)
119
129
  return [mainKey, []]
120
130
 
121
131
  return Array.isArray(value[0])
@@ -127,9 +137,19 @@ export default class Compact {
127
137
  }
128
138
 
129
139
  static memo(val: any, seen: any[]): any {
130
- const length = getLength(val)
131
- // TODO: may be incompatible with empty objects or arrays
132
- if (typeof val !== 'object' && length < 2) return val
140
+ if (Array.isArray(val))
141
+ return val.map(item => this.memo(item, seen))
142
+
143
+ const type = typeof val
144
+ if (type == 'object' && val != null) {
145
+ for (const key in val)
146
+ val[key] = this.memo(val[key], seen)
147
+
148
+ return val
149
+ }
150
+ const length = getLength(val, type)
151
+
152
+ if (type !== 'object' && length < 2) return val
133
153
 
134
154
  const index = seen.indexOf(val)
135
155
  if (index !== -1)
@@ -139,11 +159,16 @@ export default class Compact {
139
159
  return val
140
160
  }
141
161
 
142
- static replaceTypes(str: string, map: Record<string, string>) {
143
- return Object.entries(map).reduce((s, [from, to]) => s.replaceAll(from, to), str)
162
+ static #mapRegex(keys: string[]) {
163
+ keys = keys.sort((a, b) => b.length - a.length).map(k => k.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
164
+ return new RegExp(`(?<![^\\s,\\[\\{:])(${keys.join('|')})(?![^\\s,\\]\\}:])`, 'g')
165
+ }
166
+
167
+ static #minify(val: string): string {
168
+ return val.replace(this.#typeRegex, match => this.#typeMap[match])
144
169
  }
145
170
 
146
- static reverseMap(map: Record<string, string>): Record<string, string> {
147
- return Object.fromEntries(Object.entries(map).map(([k, v]) => [v, k]))
171
+ static #deminify(val: string): string {
172
+ return val.replace(this.#reverseTypeRegex, match => this.#reverseTypeMap[match])
148
173
  }
149
174
  }
@@ -105,7 +105,7 @@ export default class AbstractModel<T extends object> {
105
105
  keys = this.#getItemKey(item, key)
106
106
  this.#validateKeys(keys)
107
107
  // @ts-ignore
108
- item = { ...keys, V: Compact.encode(this.getItemWithoutKeys(item), this.meta.fields) }
108
+ item = { ...keys, V: Compact.encode(this.#getItemWithoutKeys(item), this.#meta.fields) }
109
109
  } else {
110
110
  this.#validateKeys(item)
111
111
  }
@@ -120,7 +120,7 @@ export default class AbstractModel<T extends object> {
120
120
  keys = this.#getItemKey(attrs, key)
121
121
  this.#validateKeys(keys)
122
122
  // @ts-ignore
123
- attrs = { V: Compact.encode(this.getItemWithoutKeys(attrs), this.meta.fields) }
123
+ attrs = { V: Compact.encode(this.#getItemWithoutKeys(attrs), this.#meta.fields) }
124
124
  } else {
125
125
  this.#validateKeys(attrs)
126
126
  }
@@ -226,7 +226,7 @@ export default class AbstractModel<T extends object> {
226
226
  if (this.#meta.keys?.SK) {
227
227
  if (key.length > 1)
228
228
  // @ts-ignore
229
- keys[this.meta.keys.SK] = key[1]
229
+ keys[this.#meta.keys.SK] = key[1]
230
230
  else if (this.#meta.defaultSK)
231
231
  keys[this.#meta.keys.SK] = this.#meta.defaultSK
232
232
  }
@@ -284,7 +284,7 @@ export default class AbstractModel<T extends object> {
284
284
  if (!keys) keys = this.#getItemKey(item)
285
285
 
286
286
  // @ts-ignore
287
- return model.withKey(keys[this.meta.keys.PK], keys[this.meta.keys.SK] || undefined)
287
+ return model.withKey(keys[this.#meta.keys.PK], keys[this.#meta.keys.SK] || undefined)
288
288
  }
289
289
 
290
290
  return new this.#cls(item)
@@ -1,5 +1,5 @@
1
- export default function getLength(item: any): number {
2
- const type = typeof item
1
+ export default function getLength(item: any, type?: string): number {
2
+ if (!type) type = typeof item
3
3
 
4
4
  switch (type) {
5
5
  case 'string':