reactronic 0.22.510 → 0.23.100

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.
@@ -1,7 +1,7 @@
1
- export declare type BoolOnly<T> = Pick<T, {
1
+ export type BoolOnly<T> = Pick<T, {
2
2
  [P in keyof T]: T[P] extends boolean ? P : never;
3
3
  }[keyof T]>;
4
- export declare type GivenTypeOnly<T, V> = Pick<T, {
4
+ export type GivenTypeOnly<T, V> = Pick<T, {
5
5
  [P in keyof T]: T[P] extends V ? P : never;
6
6
  }[keyof T]>;
7
7
  declare global {
@@ -49,7 +49,7 @@ export declare class Changeset implements AbstractChangeset {
49
49
  static _init(): void;
50
50
  }
51
51
  export declare class Dump {
52
- static valueHint: (value: any, m?: MemberName) => string;
52
+ static valueHint: (value: any) => string;
53
53
  static obj(h: ObjectHandle | undefined, m?: MemberName | undefined, stamp?: number, snapshotId?: number, originSnapshotId?: number, value?: any): string;
54
54
  static snapshot2(h: ObjectHandle, s: AbstractChangeset, m?: MemberName, o?: Observable): string;
55
55
  static snapshot(os: ObjectSnapshot, m?: MemberName): string;
@@ -27,6 +27,8 @@ Object.defineProperty(ObjectHandle.prototype, '#this#', {
27
27
  const EMPTY_ARRAY = Object.freeze([]);
28
28
  const EMPTY_MAP = Utils.freezeMap(new Map());
29
29
  export class Changeset {
30
+ get hint() { var _a; return (_a = this.options.hint) !== null && _a !== void 0 ? _a : 'noname'; }
31
+ get timestamp() { return this.revision; }
30
32
  constructor(options) {
31
33
  this.id = ++Changeset.idGen;
32
34
  this.options = options !== null && options !== void 0 ? options : DefaultSnapshotOptions;
@@ -36,8 +38,6 @@ export class Changeset {
36
38
  this.reactive = [];
37
39
  this.sealed = false;
38
40
  }
39
- get hint() { var _a; return (_a = this.options.hint) !== null && _a !== void 0 ? _a : 'noname'; }
40
- get timestamp() { return this.revision; }
41
41
  lookupObjectSnapshot(h, m) {
42
42
  let os = h.editing;
43
43
  if (os && os.changeset !== this) {
@@ -55,7 +55,7 @@ export class Changeset {
55
55
  getObjectSnapshot(h, m) {
56
56
  const r = this.lookupObjectSnapshot(h, m);
57
57
  if (r === EMPTY_SNAPSHOT)
58
- throw misuse(`cannot use data from a transaction started after the current one T${this.id}[${this.hint}]: ${Dump.obj(h, m)} (head is T${h.head.changeset.id}[${h.head.changeset.hint}]${h.editing ? `, uncommitted T${h.editing.changeset.id}[${h.editing.changeset.hint}]` : ''})`);
58
+ throw misuse(`${Dump.obj(h, m)} is not yet available for T${this.id}[${this.hint}] because of uncommitted ${h.editing ? `T${h.editing.changeset.id}[${h.editing.changeset.hint}]` : ''} (last committed T${h.head.changeset.id}[${h.head.changeset.hint}])`);
59
59
  return r;
60
60
  }
61
61
  getEditableObjectSnapshot(h, m, value, token) {
@@ -73,7 +73,7 @@ export class Changeset {
73
73
  h.editing = os;
74
74
  h.editors++;
75
75
  if (Log.isOn && Log.opt.write)
76
- Log.write('║', ' ⎘⎘', `${Dump.obj(h)} - new snapshot is created (revision ${revision})`);
76
+ Log.write('║', ' ++', `${Dump.obj(h)} - new snapshot is created (revision ${revision})`);
77
77
  }
78
78
  }
79
79
  else
@@ -106,7 +106,7 @@ export class Changeset {
106
106
  }
107
107
  }
108
108
  if (os === EMPTY_SNAPSHOT)
109
- throw misuse(`cannot use data from a transaction started after the current one T${this.id}[${this.hint}]: ${Dump.snapshot(os, m)} (head is T${h.head.changeset.id}[${h.head.changeset.hint}]${h.editing ? `, uncommitted T${h.editing.changeset.id}[${h.editing.changeset.hint}]` : ''})`);
109
+ throw misuse(`${Dump.snapshot(os, m)} is not yet available for T${this.id}[${this.hint}] because of uncommitted ${h.editing ? `T${h.editing.changeset.id}[${h.editing.changeset.hint}]` : ''} (last committed T${h.head.changeset.id}[${h.head.changeset.hint}])`);
110
110
  }
111
111
  return os.changeset !== this && !this.sealed;
112
112
  }
@@ -118,7 +118,7 @@ export class Changeset {
118
118
  if (Changeset.oldest === undefined)
119
119
  Changeset.oldest = this;
120
120
  if (Log.isOn && Log.opt.transaction)
121
- Log.write('╔══', `v${this.revision}`, `${this.hint}`);
121
+ Log.write('╔══', `s${this.revision}`, `${this.hint}`);
122
122
  }
123
123
  }
124
124
  bumpBy(timestamp) {
@@ -206,11 +206,11 @@ export class Changeset {
206
206
  const members = [];
207
207
  os.changes.forEach((o, m) => members.push(m.toString()));
208
208
  const s = members.join(', ');
209
- Log.write('║', '√', `${Dump.snapshot2(h, os.changeset)} (${s}) is ${os.former.snapshot === EMPTY_SNAPSHOT ? 'constructed' : `applied on top of ${Dump.snapshot2(h, os.former.snapshot.changeset)}`}`);
209
+ Log.write('║', '√', `${Dump.snapshot2(h, os.changeset)} (${s}) is ${os.former.snapshot === EMPTY_SNAPSHOT ? 'constructed' : `applied over #${h.id}t${os.former.snapshot.changeset.id}s${os.former.snapshot.changeset.timestamp}`}`);
210
210
  });
211
211
  }
212
212
  if (Log.opt.transaction)
213
- Log.write(this.revision < UNDEFINED_REVISION ? '╚══' : '═══', `v${this.revision}`, `${this.hint} - ${error ? 'CANCEL' : 'APPLY'}(${this.items.size})${error ? ` - ${error}` : ''}`);
213
+ Log.write(this.revision < UNDEFINED_REVISION ? '╚══' : '═══', `s${this.revision}`, `${this.hint} - ${error ? 'CANCEL' : 'APPLY'}(${this.items.size})${error ? ` - ${error}` : ''}`);
214
214
  }
215
215
  if (!error)
216
216
  Changeset.propagateAllChangesThroughSubscriptions(this);
@@ -263,7 +263,7 @@ export class Changeset {
263
263
  }
264
264
  unlinkHistory() {
265
265
  if (Log.isOn && Log.opt.gc)
266
- Log.write('', '[G]', `Dismiss history below v${this.revision}t${this.id} (${this.hint})`);
266
+ Log.write('', '[G]', `Dismiss history below t${this.id}s${this.revision} (${this.hint})`);
267
267
  this.items.forEach((os, h) => {
268
268
  if (Log.isOn && Log.opt.gc && os.former.snapshot !== EMPTY_SNAPSHOT)
269
269
  Log.write(' ', ' ', `${Dump.snapshot2(h, os.former.snapshot.changeset)} is ready for GC because overwritten by ${Dump.snapshot2(h, os.changeset)}`);
@@ -319,7 +319,7 @@ export class Dump {
319
319
  if (stamp === undefined)
320
320
  result = `${h.hint}${member}${v} #${h.id}`;
321
321
  else
322
- result = `${h.hint}${member}${v} #${h.id}t${snapshotId}v${stamp}${originSnapshotId !== undefined && originSnapshotId !== 0 ? `t${originSnapshotId}` : ''}`;
322
+ result = `${h.hint}${member}${v} #${h.id}t${snapshotId}s${stamp}${originSnapshotId !== undefined && originSnapshotId !== 0 ? `t${originSnapshotId}` : ''}`;
323
323
  }
324
324
  else
325
325
  result = `boot${member}`;
@@ -347,8 +347,8 @@ export class Dump {
347
347
  return `${theirs.changeset.hint} (${Dump.snapshot(theirs, m)})`;
348
348
  }
349
349
  }
350
- Dump.valueHint = (value, m) => '???';
351
- export const EMPTY_SNAPSHOT = new ObjectSnapshot(new Changeset({ hint: '<empty>' }), undefined, {});
350
+ Dump.valueHint = (value) => '???';
351
+ export const EMPTY_SNAPSHOT = new ObjectSnapshot(new Changeset({ hint: '<boot>' }), undefined, {});
352
352
  export const DefaultSnapshotOptions = Object.freeze({
353
353
  hint: 'noname',
354
354
  separation: false,
@@ -12,7 +12,7 @@ export declare class Observable {
12
12
  get originSnapshotId(): number | undefined;
13
13
  constructor(content: any);
14
14
  }
15
- export declare type SeparationMode = boolean | 'isolated' | 'disposal';
15
+ export type SeparationMode = boolean | 'isolated' | 'disposal';
16
16
  export interface Observer {
17
17
  readonly order: number;
18
18
  readonly observables: Map<Observable, Subscription> | undefined;
@@ -21,7 +21,7 @@ export interface Observer {
21
21
  markObsoleteDueTo(observable: Observable, m: MemberName, changeset: AbstractChangeset, h: ObjectHandle, outer: string, since: number, reactive: Array<Observer>): void;
22
22
  runIfNotUpToDate(now: boolean, nothrow: boolean): void;
23
23
  }
24
- export declare type MemberName = PropertyKey;
24
+ export type MemberName = PropertyKey;
25
25
  export interface Subscription {
26
26
  readonly memberHint: string;
27
27
  readonly usageCount: number;
@@ -51,7 +51,7 @@ export declare class ObjectHandle {
51
51
  constructor(data: any, proxy: any, handler: ProxyHandler<ObjectHandle>, head: ObjectSnapshot, hint: string);
52
52
  static getHint(obj: object, full: boolean): string | undefined;
53
53
  }
54
- export declare type PatchSet = Map<object, Map<MemberName, ValuePatch>>;
54
+ export type PatchSet = Map<object, Map<MemberName, ValuePatch>>;
55
55
  export interface ValuePatch {
56
56
  memberName: MemberName;
57
57
  patchKind: 'update' | 'add' | 'remove';
@@ -2,9 +2,9 @@ import { Log } from '../util/Dbg';
2
2
  import { Meta } from './Meta';
3
3
  export { Meta } from './Meta';
4
4
  export class Observable {
5
- constructor(content) { this.content = content; }
6
5
  get isOperation() { return false; }
7
6
  get originSnapshotId() { return 0; }
7
+ constructor(content) { this.content = content; }
8
8
  }
9
9
  export class ObjectSnapshot {
10
10
  constructor(changeset, former, data) {
@@ -1,6 +1,6 @@
1
1
  import { ObservableObject } from './Mvcc';
2
2
  import { ObjectHandle, ObjectSnapshot, PatchSet } from './Data';
3
- export declare type Saver = (patch: PatchSet) => Promise<void>;
3
+ export type Saver = (patch: PatchSet) => Promise<void>;
4
4
  export declare abstract class Journal extends ObservableObject {
5
5
  abstract capacity: number;
6
6
  abstract readonly edits: ReadonlyArray<PatchSet>;
@@ -9,13 +9,8 @@ import { Mvcc, OptionsImpl } from './Mvcc';
9
9
  import { JournalImpl } from './Journal';
10
10
  const BOOT_ARGS = [];
11
11
  const BOOT_CAUSE = '<boot>';
12
- const EMPTY_HANDLE = new ObjectHandle(undefined, undefined, Mvcc.observable, EMPTY_SNAPSHOT, '<empty>');
12
+ const EMPTY_HANDLE = new ObjectHandle(undefined, undefined, Mvcc.observable, EMPTY_SNAPSHOT, '<boot>');
13
13
  export class OperationController extends Controller {
14
- constructor(h, m) {
15
- super();
16
- this.objectHandle = h;
17
- this.memberName = m;
18
- }
19
14
  configure(options) { return OperationController.configureImpl(this, options); }
20
15
  get options() { return this.peek(undefined).operation.options; }
21
16
  get unobservable() { return this.peek(undefined).operation.content; }
@@ -26,6 +21,11 @@ export class OperationController extends Controller {
26
21
  get isUpToDate() { return this.use().isUpToDate; }
27
22
  markObsolete() { Transaction.run({ hint: Log.isOn ? `markObsolete(${Dump.obj(this.objectHandle, this.memberName)})` : 'markObsolete()' }, OperationController.markObsolete, this); }
28
23
  pullLastResult(args) { return this.useOrRun(true, args).content; }
24
+ constructor(h, m) {
25
+ super();
26
+ this.objectHandle = h;
27
+ this.memberName = m;
28
+ }
29
29
  useOrRun(weak, args) {
30
30
  var _a;
31
31
  let oc = this.peek(args);
@@ -69,7 +69,7 @@ export class OperationController extends Controller {
69
69
  throw misuse('reactronic decorator is only applicable to methods');
70
70
  op.options = new OptionsImpl(op.options.getter, op.options.setter, op.options, options, false);
71
71
  if (Log.isOn && Log.opt.write)
72
- Log.write('║', ' ', `${op.hint()}.options are changed`);
72
+ Log.write('║', ' =', `${op.hint()}.options are changed`);
73
73
  return op.options;
74
74
  }
75
75
  static runWithin(op, func, ...args) {
@@ -136,7 +136,7 @@ export class OperationController extends Controller {
136
136
  let op = os.data[m];
137
137
  if (op.controller !== this) {
138
138
  if (os.changeset !== EMPTY_SNAPSHOT.changeset) {
139
- const hint = Log.isOn ? `${Dump.obj(this.objectHandle, m)}/boot` : 'MethodController/init';
139
+ const hint = Log.isOn ? `${Dump.obj(this.objectHandle, m)}/init` : 'MethodController/init';
140
140
  const separation = os.changeset.sealed || os.former.snapshot !== EMPTY_SNAPSHOT;
141
141
  op = Transaction.run({ hint, separation, token: this }, () => {
142
142
  const h = this.objectHandle;
@@ -163,7 +163,7 @@ export class OperationController extends Controller {
163
163
  os.data[m] = t;
164
164
  op = t;
165
165
  if (Log.isOn && Log.opt.write)
166
- Log.write('║', ' ⎘⎘', `${Dump.obj(this.objectHandle, m)} - new snapshot is created outside of transaction (revision ${os.revision})`);
166
+ Log.write('║', ' ++', `${Dump.obj(this.objectHandle, m)} is initialized (revision ${os.revision})`);
167
167
  }
168
168
  }
169
169
  return op;
@@ -176,7 +176,7 @@ export class OperationController extends Controller {
176
176
  if (!oc.operation.transaction.isCanceled) {
177
177
  oc = this.edit();
178
178
  if (Log.isOn && Log.opt.operation)
179
- Log.write('║', ' 𝑓', `${oc.operation.why()}`);
179
+ Log.write('║', ' o', `${oc.operation.why()}`);
180
180
  oc.operation.run(this.objectHandle.proxy, argsx);
181
181
  }
182
182
  else {
@@ -184,7 +184,7 @@ export class OperationController extends Controller {
184
184
  if (oc.operation.options.kind === Kind.Transactional || !oc.isUpToDate) {
185
185
  oc = this.edit();
186
186
  if (Log.isOn && Log.opt.operation)
187
- Log.write('║', ' 𝑓', `${oc.operation.why()}`);
187
+ Log.write('║', ' o', `${oc.operation.why()}`);
188
188
  oc.operation.run(this.objectHandle.proxy, argsx);
189
189
  }
190
190
  }
@@ -232,11 +232,11 @@ class Operation extends Observable {
232
232
  why() {
233
233
  let cause;
234
234
  if (this.cause)
235
- cause = ` << ${this.cause}`;
235
+ cause = ` ◀◀ ${this.cause}`;
236
236
  else if (this.controller.options.kind === Kind.Transactional)
237
- cause = ' << operation';
237
+ cause = ' ◀◀ operation';
238
238
  else
239
- cause = ` << T${this.changeset.id}[${this.changeset.hint}]`;
239
+ cause = ` ◀◀ T${this.changeset.id}[${this.changeset.hint}]`;
240
240
  return `${this.hint()}${cause}`;
241
241
  }
242
242
  briefWhy() {
@@ -275,14 +275,14 @@ class Operation extends Observable {
275
275
  const skip = !observable.isOperation &&
276
276
  changeset === this.changeset;
277
277
  if (!skip) {
278
- const why = `${Dump.snapshot2(h, changeset, m, observable)} << ${outer}`;
278
+ const why = `${Dump.snapshot2(h, changeset, m, observable)} ◀◀ ${outer}`;
279
279
  const isReactive = this.options.kind === Kind.Reactive;
280
280
  this.obsoleteDueTo = why;
281
281
  this.obsoleteSince = since;
282
282
  if (Log.isOn && (Log.opt.obsolete || ((_a = this.options.logging) === null || _a === void 0 ? void 0 : _a.obsolete)))
283
283
  Log.write(Log.opt.transaction && !Changeset.current().sealed ? '║' : ' ', isReactive ? '█' : '▒', isReactive && changeset === EMPTY_SNAPSHOT.changeset
284
- ? `${this.hint()} is a reactive and will run automatically (order ${this.options.order})`
285
- : `${this.hint()} is obsolete due to ${Dump.snapshot2(h, changeset, m)} since v${since}${isReactive ? ` and will run automatically (order ${this.options.order})` : ''}`);
284
+ ? `${this.hint()} is reactive and will run automatically (order ${this.options.order})`
285
+ : `${this.hint()} is obsolete due to ${Dump.snapshot2(h, changeset, m)} since s${since}${isReactive ? ` and will run automatically (order ${this.options.order})` : ''}`);
286
286
  this.unsubscribeFromAllObservables();
287
287
  if (isReactive)
288
288
  reactive.push(this);
@@ -465,7 +465,7 @@ class Operation extends Observable {
465
465
  static markEdited(oldValue, newValue, edited, os, m, h) {
466
466
  edited ? os.changes.add(m) : os.changes.delete(m);
467
467
  if (Log.isOn && Log.opt.write)
468
- edited ? Log.write('║', ' ', `${Dump.snapshot2(h, os.changeset, m)} is changed from ${valueHint(oldValue, m)} to ${valueHint(newValue, m)}`) : Log.write('║', ' ', `${Dump.snapshot2(h, os.changeset, m)} is changed from ${valueHint(oldValue, m)} to ${valueHint(newValue, m)}`, undefined, ' (same as previous)');
468
+ edited ? Log.write('║', ' =', `${Dump.snapshot2(h, os.changeset, m)} is changed: ${valueHint(oldValue)} ▸▸ ${valueHint(newValue)}`) : Log.write('║', ' =', `${Dump.snapshot2(h, os.changeset, m)} is changed: ${valueHint(oldValue)} ▸▸ ${valueHint(newValue)}`, undefined, ' (same as previous)');
469
469
  }
470
470
  static isConflicting(oldValue, newValue) {
471
471
  let result = oldValue !== newValue;
@@ -577,14 +577,14 @@ class Operation extends Observable {
577
577
  observable.observers.add(this);
578
578
  this.observables.set(observable, subscription);
579
579
  if (Log.isOn && (Log.opt.read || ((_a = this.options.logging) === null || _a === void 0 ? void 0 : _a.read)))
580
- Log.write('║', ' ∞ ', `${this.hint()} is subscribed to ${Dump.snapshot2(h, os.changeset, m)}${subscription.usageCount > 1 ? ` (${subscription.usageCount} times)` : ''}`);
580
+ Log.write('║', ' ∞', `${this.hint()} is subscribed to ${Dump.snapshot2(h, os.changeset, m)}${subscription.usageCount > 1 ? ` (${subscription.usageCount} times)` : ''}`);
581
581
  }
582
582
  else if (Log.isOn && (Log.opt.read || ((_b = this.options.logging) === null || _b === void 0 ? void 0 : _b.read)))
583
- Log.write('║', ' x ', `${this.hint()} is obsolete and is NOT subscribed to ${Dump.snapshot2(h, os.changeset, m)}`);
583
+ Log.write('║', ' x', `${this.hint()} is obsolete and is NOT subscribed to ${Dump.snapshot2(h, os.changeset, m)}`);
584
584
  }
585
585
  else {
586
586
  if (Log.isOn && (Log.opt.read || ((_c = this.options.logging) === null || _c === void 0 ? void 0 : _c.read)))
587
- Log.write('║', ' x ', `${this.hint()} is NOT subscribed to already obsolete ${Dump.snapshot2(h, os.changeset, m)}`);
587
+ Log.write('║', ' x', `${this.hint()} is NOT subscribed to already obsolete ${Dump.snapshot2(h, os.changeset, m)}`);
588
588
  }
589
589
  return ok;
590
590
  }
@@ -656,7 +656,7 @@ class Operation extends Observable {
656
656
  Operation.current = undefined;
657
657
  Operation.queuedReactiveFunctions = [];
658
658
  Operation.deferredReactiveFunctions = [];
659
- function valueHint(value, m) {
659
+ function valueHint(value) {
660
660
  let result = '';
661
661
  if (Array.isArray(value))
662
662
  result = `Array(${value.length})`;
@@ -665,11 +665,11 @@ function valueHint(value, m) {
665
665
  else if (value instanceof Map)
666
666
  result = `Map(${value.size})`;
667
667
  else if (value instanceof Operation)
668
- result = `${Dump.snapshot2(value.controller.objectHandle, value.changeset, m)}`;
668
+ result = `#${value.controller.objectHandle.id}t${value.changeset.id}s${value.changeset.timestamp}${value.originSnapshotId !== undefined && value.originSnapshotId !== 0 ? `t${value.originSnapshotId}` : ''}`;
669
669
  else if (value === Meta.Undefined)
670
670
  result = 'undefined';
671
671
  else if (typeof (value) === 'string')
672
- result = `"${value.toString().slice(0, 20)}"`;
672
+ result = `"${value.toString().slice(0, 20)}${value.length > 20 ? '...' : ''}"`;
673
673
  else if (value !== undefined && value !== null)
674
674
  result = value.toString().slice(0, 40);
675
675
  else
@@ -1,4 +1,4 @@
1
- export declare type GetItemKey<T = unknown> = (item: T) => string | undefined;
1
+ export type GetItemKey<T = unknown> = (item: T) => string | undefined;
2
2
  export interface CollectionReader<T> {
3
3
  readonly strict: boolean;
4
4
  readonly count: number;
@@ -1,4 +1,4 @@
1
- export declare type F<T> = (...args: any[]) => T;
1
+ export type F<T> = (...args: any[]) => T;
2
2
  export declare class Utils {
3
3
  static freezeSet<T>(obj?: Set<T>): Set<T> | undefined;
4
4
  static freezeMap<K, V>(obj?: Map<K, V>): Map<K, V> | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reactronic",
3
- "version": "0.22.510",
3
+ "version": "0.23.100",
4
4
  "description": "Reactronic - Transactional Reactive State Management",
5
5
  "publisher": "Nezaboodka Software",
6
6
  "license": "Apache-2.0",
@@ -31,16 +31,16 @@
31
31
  },
32
32
  "homepage": "https://github.com/nezaboodka/reactronic/blob/master/README.md#readme",
33
33
  "devDependencies": {
34
- "@types/node": "18.11.9",
35
- "@types/react": "18.0.25",
36
- "@typescript-eslint/eslint-plugin": "5.42.1",
37
- "@typescript-eslint/parser": "5.42.1",
34
+ "@types/node": "18.11.18",
35
+ "@types/react": "18.0.26",
36
+ "@typescript-eslint/eslint-plugin": "5.47.1",
37
+ "@typescript-eslint/parser": "5.47.1",
38
38
  "ava": "4.3.3",
39
39
  "c8": "7.12.0",
40
- "eslint": "8.27.0",
40
+ "eslint": "8.30.0",
41
41
  "react": "18.2.0",
42
42
  "ts-node": "10.9.1",
43
- "typescript": "4.8.4"
43
+ "typescript": "4.9.4"
44
44
  },
45
45
  "scripts": {
46
46
  "build": "eslint source/**/*.ts test/**/*.ts react/**/*.tsx && tsc",