@nxtedition/lib 19.4.11 → 19.5.1

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/lib",
3
- "version": "19.4.11",
3
+ "version": "19.5.1",
4
4
  "license": "MIT",
5
5
  "author": "Robert Nagy <robert.nagy@boffins.se>",
6
6
  "type": "module",
package/sequence.js CHANGED
@@ -55,7 +55,7 @@ export class Sequence {
55
55
  }
56
56
 
57
57
  if (identity != null) {
58
- if (typeof identity === 'string') {
58
+ if (typeof identity === 'number') {
59
59
  assert(identity === this.identity)
60
60
  } else if (Array.isArray(identity)) {
61
61
  for (let n = 0; n < identity.length; n++) {
@@ -12,6 +12,8 @@ import _ from 'lodash'
12
12
  import moment from 'moment-timezone'
13
13
  import Timecode from 'smpte-timecode'
14
14
 
15
+ const SEP = String.fromCharCode(30) // ASCII 1E
16
+
15
17
  const kSuspend = Symbol('kSuspend')
16
18
  const kEmpty = Symbol('kEmpty')
17
19
  const maxInt = 2147483647
@@ -52,6 +54,7 @@ class FetchEntry {
52
54
  dispatcher: fetchClient,
53
55
  })
54
56
  .then(async (res) => {
57
+ // TODO (fix): Check cache-control and invalidate entry...
55
58
  const body = await res.text()
56
59
  if (this.refresh) {
57
60
  // TODO (fix): max size...
@@ -82,12 +85,33 @@ class FetchEntry {
82
85
  }
83
86
 
84
87
  class RecordEntry {
85
- constructor(key, refresh, ds) {
88
+ constructor(key, refresh, { name, path, ds, state }) {
89
+ if (state == null) {
90
+ state =
91
+ name.startsWith('{') || name.includes('?')
92
+ ? ds.record.STATE.PROVIDER
93
+ : ds.record.STATE.SERVER
94
+ } else if (typeof state === 'string') {
95
+ state = ds.record.STATE[state.toUpperCase()] ?? ds.record.STATE.SERVER
96
+ }
97
+
86
98
  this.key = key
87
99
  this.counter = -1
88
100
 
89
- this.refresh = refresh
90
- this.record = ds.record.getRecord(key)
101
+ this.record = ds.record.getRecord(name)
102
+
103
+ this.data = this.record.get(path)
104
+ this.ready = this.record.state >= state
105
+ this.refresh = () => {
106
+ const data = this.record.get(path)
107
+ const ready = this.record.state >= state
108
+
109
+ if (data !== this.data || ready !== this.ready) {
110
+ this.data = data
111
+ this.ready = ready
112
+ refresh()
113
+ }
114
+ }
91
115
 
92
116
  if (this.record.subscribe) {
93
117
  this.record.subscribe(this.refresh)
@@ -106,6 +130,8 @@ class RecordEntry {
106
130
 
107
131
  this.record = null
108
132
  this.refresh = null
133
+ this.data = null
134
+ this.ready = false
109
135
  }
110
136
  }
111
137
 
@@ -203,8 +229,6 @@ function proxify(value, expression, handler, suspend = true) {
203
229
  }
204
230
  }
205
231
 
206
- const MAP_POOL = []
207
-
208
232
  function makeWrapper(expression) {
209
233
  const handler = {
210
234
  get: (target, prop) => proxify(target[prop], expression, handler),
@@ -222,7 +246,7 @@ export default function ({ ds, proxify, compiler }) {
222
246
 
223
247
  // TODO (perf): This could be faster by using an array + indices.
224
248
  // A bit similar to how react-hooks works.
225
- this._entries = null
249
+ this._entries = new Map()
226
250
  this._refreshing = false
227
251
  this._counter = 0
228
252
  this._value = kEmpty
@@ -276,8 +300,19 @@ export default function ({ ds, proxify, compiler }) {
276
300
  return this._getPromise(promise, suspend)
277
301
  }
278
302
 
279
- ds(id, state, suspend) {
280
- return this._getRecord(id, state, suspend)
303
+ /** @deprecated */
304
+ ds(name, state, suspend) {
305
+ return !name || typeof name !== 'string'
306
+ ? ds.record.JSON.EMPTY_OBJ
307
+ : this._getRecord(name, null, state, suspend)
308
+ }
309
+
310
+ get(name, path, state, suspend) {
311
+ return !name || typeof name !== 'string'
312
+ ? path
313
+ ? undefined
314
+ : ds.record.JSON.EMPTY_OBJ
315
+ : this._getRecord(name, path, state, suspend)
281
316
  }
282
317
 
283
318
  timer(dueTime, dueValue = dueTime, suspend) {
@@ -292,10 +327,19 @@ export default function ({ ds, proxify, compiler }) {
292
327
  return objectHash(value)
293
328
  }
294
329
 
295
- _ds(key, postfix, state, suspend) {
296
- return !key || typeof key !== 'string'
297
- ? null
298
- : this._getRecord(postfix ? key + postfix : key, state, suspend)
330
+ /** @deprecated */
331
+ _ds(name, postfix, state, suspend) {
332
+ return !name || typeof name !== 'string'
333
+ ? ds.record.JSON.EMPTY_OBJ
334
+ : this._getRecord(postfix ? name + postfix : name, null, state, suspend)
335
+ }
336
+
337
+ _get(name, postfix, path, state, suspend) {
338
+ return !name || typeof name !== 'string'
339
+ ? path
340
+ ? undefined
341
+ : ds.record.JSON.EMPTY_OBJ
342
+ : this._getRecord(postfix ? name + postfix : name, path, state, suspend)
299
343
  }
300
344
 
301
345
  _asset(id, type, state, suspend) {
@@ -312,18 +356,10 @@ export default function ({ ds, proxify, compiler }) {
312
356
  this._destroyed = true
313
357
  this._subscription?.unsubscribe()
314
358
 
315
- if (this._entries) {
316
- for (const entry of this._entries.values()) {
317
- entry.dispose()
318
- }
319
- this._entries.clear()
320
-
321
- if (MAP_POOL.length < 1024) {
322
- MAP_POOL.push(this._entries)
323
- }
324
-
325
- this._entries = null
359
+ for (const entry of this._entries.values()) {
360
+ entry.dispose()
326
361
  }
362
+ this._entries.clear()
327
363
  }
328
364
 
329
365
  _refreshImpl() {
@@ -380,15 +416,10 @@ export default function ({ ds, proxify, compiler }) {
380
416
  this._suspended = false
381
417
  this._disposing = true
382
418
 
383
- if (this._entries) {
384
- for (const entry of this._entries.values()) {
385
- if (entry.counter !== this._counter) {
386
- entry.dispose()
387
- this._entries.delete(entry.key)
388
- }
389
- }
390
- if (this._entries.size === 0) {
391
- this._entries = null
419
+ for (const entry of this._entries.values()) {
420
+ if (entry.counter !== this._counter) {
421
+ entry.dispose()
422
+ this._entries.delete(entry.key)
392
423
  }
393
424
  }
394
425
 
@@ -411,7 +442,6 @@ export default function ({ ds, proxify, compiler }) {
411
442
  }
412
443
 
413
444
  _getEntry(key, Entry, opaque) {
414
- this._entries ??= MAP_POOL.pop() ?? new Map()
415
445
  let entry = this._entries.get(key)
416
446
  if (!entry) {
417
447
  entry = new Entry(key, this._refresh, opaque)
@@ -519,35 +549,32 @@ export default function ({ ds, proxify, compiler }) {
519
549
  return dueValue
520
550
  }
521
551
 
522
- _getRecord(key, state, suspend) {
523
- if (!key || typeof key !== 'string') {
524
- throw new Error(`invalid argument: key (${key})`)
552
+ _getRecord(name, path, state, suspend) {
553
+ if (name != null && typeof name !== 'string') {
554
+ throw new Error(`invalid argument: key (${name})`)
525
555
  }
526
556
 
527
- if (state == null) {
528
- state =
529
- key.startsWith('{') || key.includes('?')
530
- ? ds.record.STATE.PROVIDER
531
- : ds.record.STATE.SERVER
532
- } else if (typeof state === 'string') {
533
- state = ds.record.STATE[state.toUpperCase()]
534
- if (state == null) {
535
- throw new Error(`invalid argument: state (${state})`)
536
- }
557
+ if (path != null && typeof path !== 'string') {
558
+ throw new Error(`invalid argument: path (${path})`)
559
+ }
560
+
561
+ if (state != null && typeof state !== 'string' && typeof state !== 'number') {
562
+ throw new Error(`invalid argument: state (${state})`)
537
563
  }
538
564
 
539
- const entry = this._getEntry(key, RecordEntry, ds)
565
+ const key = '' + (name ?? '') + SEP + (path ?? '') + SEP + (state ?? '')
566
+ const entry = this._getEntry(key, RecordEntry, { ds, name, path, state })
540
567
 
541
- if (entry.record.state < state) {
568
+ if (!entry.ready) {
542
569
  this._suspended = true
543
570
  if (suspend ?? this._errored) {
544
571
  throw kSuspend
545
572
  } else {
546
- return entry.record.data
573
+ return entry.data
547
574
  }
548
575
  }
549
576
 
550
- return entry.record.data
577
+ return entry.data
551
578
  }
552
579
 
553
580
  _getHasRawAssetType(id, type, state, suspend) {
@@ -559,8 +586,13 @@ export default function ({ ds, proxify, compiler }) {
559
586
  throw new Error(`invalid argument: type (${type})`)
560
587
  }
561
588
 
562
- const data = this._getRecord(id + ':asset.rawTypes?', state ?? ds.record.PROVIDER, suspend)
563
- return data && Array.isArray(data.value) && data.value.includes(type) ? id : null
589
+ const rawTypes = this._getRecord(
590
+ id + ':asset.rawTypes?',
591
+ 'value',
592
+ state ?? ds.record.PROVIDER,
593
+ suspend,
594
+ )
595
+ return Array.isArray(rawTypes) && rawTypes.includes(type) ? id : null
564
596
  }
565
597
  }
566
598
 
@@ -571,10 +603,11 @@ export default function ({ ds, proxify, compiler }) {
571
603
  "use strict";
572
604
  {
573
605
  const _ = pipe;
574
- _.asset = (type, state, throws) => (id) => nxt._asset(id, type, state, throws);
575
- _.ds = (postfix, state, throws) => (id) => nxt._ds(id, postfix, state, throws);
606
+ _.asset = (type, state, suspend) => (name) => nxt._asset(name, type, state, suspend);
607
+ _.ds = (postfix, state, suspend) => (name) => nxt._ds(name, postfix, state, suspend);
608
+ _.get = (postfix, path, state, suspend) => (name) => nxt._get(name, postfix, path, state, suspend);
576
609
  _.timer = (dueTime) => (dueValue) => nxt.timer(dueTime, dueValue);
577
- _.fetch = (options, throws) => (resource) => nxt.fetch(resource, options, throws);
610
+ _.fetch = (options, suspend) => (resource) => nxt.fetch(resource, options, suspend);
578
611
  ${expression}
579
612
  }
580
613
  `)