@live-change/framework 0.9.105 → 0.9.107

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/lib/App.js CHANGED
@@ -632,20 +632,28 @@ class App {
632
632
  }
633
633
 
634
634
  async cachedTask(taskDescription, expireAfter, task) {
635
- const taskDescriptionHash = crypto.createHash('sha256').update(taskDescription).digest('hex')
635
+ /// Parse expireAfter in format "10s", "1m", "1h", "1d"
636
+ const expireAfterMs = utils.parseDuration(expireAfter)
637
+ const utf8 = new TextEncoder().encode(JSON.stringify(taskDescription))
638
+ const taskDescriptionHashBinary = await crypto.subtle.digest('SHA-256', utf8)
639
+ const taskDescriptionHash = Array.from(new Uint8Array(taskDescriptionHashBinary))
640
+ .map(b => b.toString(16).padStart(2, '0')).join('')
641
+ //console.log("taskDescriptionHash", taskDescriptionHash)
636
642
  let cacheEntry = await this.dao.get(['database', 'tableObject', this.databaseName, 'cache', taskDescriptionHash])
637
- if(!cacheEntry || cacheEntry.createdAt < new Date(Date.now() - expireAfter).toISOString()) {
643
+ if(!cacheEntry || cacheEntry.createdAt < new Date(Date.now() - expireAfterMs).toISOString()) {
644
+ //console.log("cache miss", taskDescription)
638
645
  const result = await task()
639
- const expiresAt = new Date(Date.now() + expireAfter).toISOString()
646
+ const expiresAt = new Date(Date.now() + expireAfterMs).toISOString()
640
647
  cacheEntry = {
641
648
  id: taskDescriptionHash,
642
649
  createdAt: new Date().toISOString(),
643
- expiresAt: expiresAt > cacheEntry.expiresAt ? expiresAt : cacheEntry.expiresAt,
650
+ expiresAt,
644
651
  result
645
652
  }
646
653
  await this.dao.request(['database', 'put'], this.databaseName, 'cache', cacheEntry)
647
654
  } else { // extend cache entry expiration
648
- const newExpiresAt = new Date(new Date(cacheEntry.createdAt).getTime() + expireAfter).toISOString()
655
+ //console.log("cache hit", taskDescription)
656
+ const newExpiresAt = new Date(new Date(cacheEntry.createdAt).getTime() + expireAfterMs).toISOString()
649
657
  if(cacheEntry.expiresAt < newExpiresAt) {
650
658
  cacheEntry.expiresAt = newExpiresAt
651
659
  await this.dao.request(['database', 'put'], this.databaseName, 'cache', cacheEntry)
@@ -654,6 +662,32 @@ class App {
654
662
  return cacheEntry.result
655
663
  }
656
664
 
665
+ async cacheGet(taskDescription, expireAfter) {
666
+ const expireAfterMs = utils.parseDuration(expireAfter)
667
+ const utf8 = new TextEncoder().encode(JSON.stringify(taskDescription))
668
+ const taskDescriptionHashBinary = await crypto.subtle.digest('SHA-256', utf8)
669
+ const taskDescriptionHash = Array.from(new Uint8Array(taskDescriptionHashBinary))
670
+ .map(b => b.toString(16).padStart(2, '0')).join('')
671
+ const cacheEntry = await this.dao.get(['database', 'tableObject', this.databaseName, 'cache', taskDescriptionHash])
672
+ if(!cacheEntry || cacheEntry.createdAt < new Date(Date.now() - expireAfterMs).toISOString()) {
673
+ return null
674
+ }
675
+ return cacheEntry.result
676
+ }
677
+
678
+ async cachePut(taskDescription, result) {
679
+ const utf8 = new TextEncoder().encode(JSON.stringify(taskDescription))
680
+ const taskDescriptionHashBinary = await crypto.subtle.digest('SHA-256', utf8)
681
+ const taskDescriptionHash = Array.from(new Uint8Array(taskDescriptionHashBinary))
682
+ .map(b => b.toString(16).padStart(2, '0')).join('')
683
+ const cacheEntry = {
684
+ id: taskDescriptionHash,
685
+ createdAt: new Date().toISOString(),
686
+ result
687
+ }
688
+ await this.dao.request(['database', 'put'], this.databaseName, 'cache', cacheEntry)
689
+ }
690
+
657
691
  }
658
692
 
659
693
  export default App
@@ -10,8 +10,16 @@ export interface ModelIndexDefinitionSpecification {
10
10
  multi?: boolean,
11
11
  }
12
12
 
13
+ export type ValidationConfig = string | {
14
+ name: string,
15
+ [key: string]: any
16
+ }
17
+
13
18
  export interface ModelPropertyDefinitionSpecification {
14
19
  type?: any,
20
+ default?: ((...args: any[]) => any) | any,
21
+ updated?: (...args: any[]) => any,
22
+ validation?: ValidationConfig[],
15
23
  index?: ModelIndexDefinitionSpecification
16
24
  }
17
25
 
@@ -31,12 +31,16 @@ class LiveDao extends LcDao.DaoProxy {
31
31
 
32
32
  computeCredentials() {
33
33
  let credentials = JSON.parse(JSON.stringify(this.initialCredentials))
34
+ const keys = Object.keys(credentials).filter(key => key.endsWith("Key"))
34
35
  for(const credentialsObserver of this.credentialsObservations) {
35
36
  credentials = {
36
37
  ...credentials,
37
38
  ...credentialsObserver.credentials,
38
39
  roles: [...credentials.roles, ...(credentialsObserver.credentials.roles || [])]
39
40
  }
41
+ }
42
+ for(const key of keys) {
43
+ delete credentials[key]
40
44
  }
41
45
  return credentials
42
46
  }
package/lib/utils.js CHANGED
@@ -229,7 +229,6 @@ function prefixRange({ gt, lt, gte, lte, limit, reverse }, prefix, from = "") {
229
229
  if(id.length > from.length) {
230
230
  if(id.slice(0, from.length) !== from) {
231
231
  console.error("ID:", id, "does not start with", from)
232
- console.trace('id does not match prefix')
233
232
  throw new Error("id does not match prefix")
234
233
  }
235
234
  id = id.slice(from.length)
@@ -354,3 +353,16 @@ export {
354
353
  prefixRange, rangeProperties, fieldListToFieldsObject,
355
354
  encodeIdentifier, extractRange, isomorphic, computeDefaults, computeUpdates
356
355
  }
356
+
357
+ export function parseDuration(duration) {
358
+ if(typeof duration === 'number') return duration
359
+ const match = duration.match(/(\d+)([smhd])/g)
360
+ if(!match || match.length === 0) throw new Error(`Invalid duration: ${duration}`)
361
+ let result = 0
362
+ for(const m of match) {
363
+ const value = parseInt(m.slice(0, -1))
364
+ const unit = m.slice(-1)
365
+ result += value * { s: 1000, m: 60000, h: 3600000, d: 86400000 }[unit]
366
+ }
367
+ return result
368
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@live-change/framework",
3
- "version": "0.9.105",
3
+ "version": "0.9.107",
4
4
  "description": "Live Change Framework - ultimate solution for real time mobile/web apps",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -22,11 +22,11 @@
22
22
  },
23
23
  "homepage": "https://github.com/live-change/live-change-stack",
24
24
  "devDependencies": {
25
- "@live-change/dao": "^0.9.105",
26
- "@live-change/uid": "^0.9.105",
25
+ "@live-change/dao": "^0.9.107",
26
+ "@live-change/uid": "^0.9.107",
27
27
  "typedoc": "0.28.3",
28
28
  "typedoc-plugin-markdown": "^4.6.3",
29
29
  "typedoc-plugin-rename-defaults": "^0.7.3"
30
30
  },
31
- "gitHead": "e96d52126ea0b5af39ecf6d4ea5120c0ec58346d"
31
+ "gitHead": "c546be0c12841aa8eca060d4c53d6d89bac2d088"
32
32
  }