rajt 0.0.22 → 0.0.24

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.22",
4
+ "version": "0.0.24",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "exports": {
@@ -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
  }
@@ -34,7 +34,7 @@ function _key(target: Function | any, pk: string, sk?: string) {
34
34
  target.m[1] = pk && sk ? [pk, sk] : [pk]
35
35
  }
36
36
 
37
- function _model(target: any, opt?: ModelOpts) {
37
+ export function _model(target: any, opt?: ModelOpts) {
38
38
  _table(target, opt)
39
39
  const notStr = typeof opt !== 'string'
40
40
 
@@ -1,3 +1,4 @@
1
1
  export { Dynamodb } from './client'
2
2
  export { Model, Entity, Zip, PartitionKey, SortKey, Key, Keys } from './decorators'
3
- export { default as Schema } from './schema'
3
+ export { Schema } from './schema'
4
+ export { Repository } from './repository'
@@ -0,0 +1,21 @@
1
+ import { ZodTypeAny } from 'zod'
2
+ import { Dynamodb } from './client'
3
+ import { Schema } from './schema'
4
+ import { _model } from './decorators'
5
+ import type { ModelOpts } from './types'
6
+
7
+ export function Repository<M extends object, S extends ZodTypeAny>(
8
+ schema: S,
9
+ model: new (...args: any[]) => M,
10
+ opts?: ModelOpts
11
+ ) {
12
+ const BaseSchemaClass = Schema(schema, model)
13
+ _model(BaseSchemaClass, opts)
14
+
15
+ return class extends BaseSchemaClass {
16
+ static model = Dynamodb.model<M>(BaseSchemaClass as unknown as new (...args: any[]) => M)
17
+ } as unknown as (typeof BaseSchemaClass) & {
18
+ model: ReturnType<typeof Dynamodb.model<M>>
19
+ new (...args: any[]): InstanceType<typeof BaseSchemaClass>
20
+ }
21
+ }
@@ -3,9 +3,7 @@ import type { SchemaStructure } from './types'
3
3
 
4
4
  function extractZodKeys(schema: ZodTypeAny): SchemaStructure {
5
5
  if (schema instanceof z.ZodObject) {
6
- const shape = schema.shape
7
-
8
- return Object.entries(shape).map(([key, value]) => {
6
+ return Object.entries(schema.shape).map(([key, value]) => {
9
7
  const inner = unwrap(value as ZodTypeAny)
10
8
 
11
9
  if (inner instanceof z.ZodObject)
@@ -33,14 +31,24 @@ function unwrap(schema: ZodTypeAny): ZodTypeAny {
33
31
  return schema
34
32
  }
35
33
 
36
- export default function Schema<T extends ZodTypeAny>(schema: T) {
37
- return class {
34
+ export function Schema<
35
+ T extends ZodTypeAny,
36
+ B extends object
37
+ >(
38
+ schema: T,
39
+ BaseClass?: new (...args: any[]) => B
40
+ ) {
41
+ const Base = (BaseClass || class {})
42
+
43
+ return class extends Base {
38
44
  static _schema = schema
39
- static defaultSortKey?: string = undefined
40
- #PK?: string = undefined
41
- #SK?: string = undefined
45
+ static defaultSortKey?: string
46
+
47
+ #PK?: string
48
+ #SK?: string
42
49
 
43
50
  constructor(data: z.infer<T>) {
51
+ super()
44
52
  Object.assign(this, data)
45
53
  }
46
54
 
@@ -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':