@matter/general 0.12.4-alpha.0-20250211-56b2c53a0 → 0.12.4-alpha.0-20250213-1187f81eb

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.
Files changed (138) hide show
  1. package/dist/cjs/MatterError.d.ts +12 -0
  2. package/dist/cjs/MatterError.d.ts.map +1 -1
  3. package/dist/cjs/MatterError.js +12 -0
  4. package/dist/cjs/MatterError.js.map +1 -1
  5. package/dist/cjs/index.d.ts +1 -0
  6. package/dist/cjs/index.d.ts.map +1 -1
  7. package/dist/cjs/index.js +1 -0
  8. package/dist/cjs/index.js.map +1 -1
  9. package/dist/cjs/log/Logger.d.ts.map +1 -1
  10. package/dist/cjs/log/Logger.js +2 -0
  11. package/dist/cjs/log/Logger.js.map +1 -1
  12. package/dist/cjs/time/Time.d.ts +1 -1
  13. package/dist/cjs/time/Time.d.ts.map +1 -1
  14. package/dist/cjs/time/Time.js +2 -2
  15. package/dist/cjs/time/Time.js.map +1 -1
  16. package/dist/cjs/transaction/Participant.d.ts +47 -0
  17. package/dist/cjs/transaction/Participant.d.ts.map +1 -0
  18. package/dist/cjs/transaction/Participant.js +22 -0
  19. package/dist/cjs/transaction/Participant.js.map +6 -0
  20. package/dist/cjs/transaction/Resource.d.ts +29 -0
  21. package/dist/cjs/transaction/Resource.d.ts.map +1 -0
  22. package/dist/cjs/transaction/Resource.js +40 -0
  23. package/dist/cjs/transaction/Resource.js.map +6 -0
  24. package/dist/cjs/transaction/ResourceSet.d.ts +36 -0
  25. package/dist/cjs/transaction/ResourceSet.d.ts.map +1 -0
  26. package/dist/cjs/transaction/ResourceSet.js +155 -0
  27. package/dist/cjs/transaction/ResourceSet.js.map +6 -0
  28. package/dist/cjs/transaction/Status.d.ts +49 -0
  29. package/dist/cjs/transaction/Status.d.ts.map +1 -0
  30. package/dist/cjs/transaction/Status.js +55 -0
  31. package/dist/cjs/transaction/Status.js.map +6 -0
  32. package/dist/cjs/transaction/Transaction.d.ts +197 -0
  33. package/dist/cjs/transaction/Transaction.d.ts.map +1 -0
  34. package/dist/cjs/transaction/Transaction.js +50 -0
  35. package/dist/cjs/transaction/Transaction.js.map +6 -0
  36. package/dist/cjs/transaction/Tx.d.ts +47 -0
  37. package/dist/cjs/transaction/Tx.d.ts.map +1 -0
  38. package/dist/cjs/transaction/Tx.js +586 -0
  39. package/dist/cjs/transaction/Tx.js.map +6 -0
  40. package/dist/cjs/transaction/errors.d.ts +52 -0
  41. package/dist/cjs/transaction/errors.d.ts.map +1 -0
  42. package/dist/cjs/transaction/errors.js +47 -0
  43. package/dist/cjs/transaction/errors.js.map +6 -0
  44. package/dist/cjs/transaction/index.d.ts +8 -0
  45. package/dist/cjs/transaction/index.d.ts.map +1 -0
  46. package/dist/cjs/transaction/index.js +25 -0
  47. package/dist/cjs/transaction/index.js.map +6 -0
  48. package/dist/cjs/util/Cancelable.d.ts +101 -0
  49. package/dist/cjs/util/Cancelable.d.ts.map +1 -0
  50. package/dist/cjs/util/Cancelable.js +279 -0
  51. package/dist/cjs/util/Cancelable.js.map +6 -0
  52. package/dist/cjs/util/Observable.js +1 -1
  53. package/dist/cjs/util/Observable.js.map +1 -1
  54. package/dist/cjs/util/Promises.d.ts +0 -15
  55. package/dist/cjs/util/Promises.d.ts.map +1 -1
  56. package/dist/cjs/util/Promises.js +0 -33
  57. package/dist/cjs/util/Promises.js.map +1 -1
  58. package/dist/cjs/util/index.d.ts +1 -0
  59. package/dist/cjs/util/index.d.ts.map +1 -1
  60. package/dist/cjs/util/index.js +1 -0
  61. package/dist/cjs/util/index.js.map +1 -1
  62. package/dist/esm/MatterError.d.ts +12 -0
  63. package/dist/esm/MatterError.d.ts.map +1 -1
  64. package/dist/esm/MatterError.js +12 -0
  65. package/dist/esm/MatterError.js.map +1 -1
  66. package/dist/esm/index.d.ts +1 -0
  67. package/dist/esm/index.d.ts.map +1 -1
  68. package/dist/esm/index.js +1 -0
  69. package/dist/esm/index.js.map +1 -1
  70. package/dist/esm/log/Logger.d.ts.map +1 -1
  71. package/dist/esm/log/Logger.js +2 -0
  72. package/dist/esm/log/Logger.js.map +1 -1
  73. package/dist/esm/time/Time.d.ts +1 -1
  74. package/dist/esm/time/Time.d.ts.map +1 -1
  75. package/dist/esm/time/Time.js +1 -1
  76. package/dist/esm/transaction/Participant.d.ts +47 -0
  77. package/dist/esm/transaction/Participant.d.ts.map +1 -0
  78. package/dist/esm/transaction/Participant.js +6 -0
  79. package/dist/esm/transaction/Participant.js.map +6 -0
  80. package/dist/esm/transaction/Resource.d.ts +29 -0
  81. package/dist/esm/transaction/Resource.d.ts.map +1 -0
  82. package/dist/esm/transaction/Resource.js +20 -0
  83. package/dist/esm/transaction/Resource.js.map +6 -0
  84. package/dist/esm/transaction/ResourceSet.d.ts +36 -0
  85. package/dist/esm/transaction/ResourceSet.d.ts.map +1 -0
  86. package/dist/esm/transaction/ResourceSet.js +135 -0
  87. package/dist/esm/transaction/ResourceSet.js.map +6 -0
  88. package/dist/esm/transaction/Status.d.ts +49 -0
  89. package/dist/esm/transaction/Status.d.ts.map +1 -0
  90. package/dist/esm/transaction/Status.js +35 -0
  91. package/dist/esm/transaction/Status.js.map +6 -0
  92. package/dist/esm/transaction/Transaction.d.ts +197 -0
  93. package/dist/esm/transaction/Transaction.d.ts.map +1 -0
  94. package/dist/esm/transaction/Transaction.js +30 -0
  95. package/dist/esm/transaction/Transaction.js.map +6 -0
  96. package/dist/esm/transaction/Tx.d.ts +47 -0
  97. package/dist/esm/transaction/Tx.d.ts.map +1 -0
  98. package/dist/esm/transaction/Tx.js +566 -0
  99. package/dist/esm/transaction/Tx.js.map +6 -0
  100. package/dist/esm/transaction/errors.d.ts +52 -0
  101. package/dist/esm/transaction/errors.d.ts.map +1 -0
  102. package/dist/esm/transaction/errors.js +27 -0
  103. package/dist/esm/transaction/errors.js.map +6 -0
  104. package/dist/esm/transaction/index.d.ts +8 -0
  105. package/dist/esm/transaction/index.d.ts.map +1 -0
  106. package/dist/esm/transaction/index.js +8 -0
  107. package/dist/esm/transaction/index.js.map +6 -0
  108. package/dist/esm/util/Cancelable.d.ts +101 -0
  109. package/dist/esm/util/Cancelable.d.ts.map +1 -0
  110. package/dist/esm/util/Cancelable.js +259 -0
  111. package/dist/esm/util/Cancelable.js.map +6 -0
  112. package/dist/esm/util/Observable.js +1 -1
  113. package/dist/esm/util/Observable.js.map +1 -1
  114. package/dist/esm/util/Promises.d.ts +0 -15
  115. package/dist/esm/util/Promises.d.ts.map +1 -1
  116. package/dist/esm/util/Promises.js +0 -33
  117. package/dist/esm/util/Promises.js.map +1 -1
  118. package/dist/esm/util/index.d.ts +1 -0
  119. package/dist/esm/util/index.d.ts.map +1 -1
  120. package/dist/esm/util/index.js +1 -0
  121. package/dist/esm/util/index.js.map +1 -1
  122. package/package.json +2 -2
  123. package/src/MatterError.ts +18 -0
  124. package/src/index.ts +1 -0
  125. package/src/log/Logger.ts +3 -0
  126. package/src/time/Time.ts +1 -1
  127. package/src/transaction/Participant.ts +54 -0
  128. package/src/transaction/Resource.ts +39 -0
  129. package/src/transaction/ResourceSet.ts +160 -0
  130. package/src/transaction/Status.ts +68 -0
  131. package/src/transaction/Transaction.ts +190 -0
  132. package/src/transaction/Tx.ts +734 -0
  133. package/src/transaction/errors.ts +53 -0
  134. package/src/transaction/index.ts +8 -0
  135. package/src/util/Cancelable.ts +380 -0
  136. package/src/util/Observable.ts +1 -1
  137. package/src/util/Promises.ts +0 -52
  138. package/src/util/index.ts +1 -0
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { MaybePromise } from "#util/Promises.js";
8
+
9
+ /**
10
+ * Components with support for transactionality implement this interface.
11
+ */
12
+ export interface Participant {
13
+ /**
14
+ * Description used in error messages.
15
+ */
16
+ toString(): string;
17
+
18
+ /**
19
+ * The "role" of a participant is an optional key you may use to retrieve
20
+ * a participant from the transaction.
21
+ */
22
+ role?: {};
23
+
24
+ /**
25
+ * Pre-commit logic.
26
+ *
27
+ * Pre-commit logic returns a boolean indicating whether it performed an action that affects state. The transaction
28
+ * will cycle through participants continuously until all participants return false.
29
+ *
30
+ * Thus `preCommit` implementations must be stateful and expect to be invoked more than once for a single
31
+ * transaction.
32
+ */
33
+ preCommit?: () => MaybePromise<boolean>;
34
+
35
+ /**
36
+ * Commit phase one.
37
+ */
38
+ commit1(): MaybePromise;
39
+
40
+ /**
41
+ * Commit phase two.
42
+ */
43
+ commit2(): MaybePromise;
44
+
45
+ /**
46
+ * Post-commit logic.
47
+ */
48
+ postCommit?: () => MaybePromise;
49
+
50
+ /**
51
+ * Drop isolated writes and revert to original canonical source.
52
+ */
53
+ rollback(): MaybePromise;
54
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import type { Transaction } from "./Transaction.js";
8
+
9
+ /**
10
+ * A transaction resource is the target a {@link Participant} is mutating. The {@link Coordinator} tracks the state of
11
+ * resources to ensure only a single transaction ever has exclusive access.
12
+ */
13
+ export interface Resource {
14
+ /**
15
+ * Textual description of the resource used in error messages.
16
+ */
17
+ toString(): string;
18
+
19
+ /**
20
+ * Locking transaction, maintained by {@link Transaction}.
21
+ */
22
+ lockedBy?: Transaction;
23
+
24
+ /**
25
+ * Inform {@link Transaction} this resource is a standin for another resource.
26
+ */
27
+ [Resource.reference]?: Resource;
28
+ }
29
+
30
+ export namespace Resource {
31
+ export const reference = Symbol("reference");
32
+
33
+ export function isLocked(resource: Resource) {
34
+ while (resource[Resource.reference] !== undefined) {
35
+ resource = resource[Resource.reference];
36
+ }
37
+ return resource.lockedBy !== undefined;
38
+ }
39
+ }
@@ -0,0 +1,160 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { Logger } from "#log/Logger.js";
8
+ import { describeList } from "#util/String.js";
9
+ import { SynchronousTransactionConflictError, TransactionDeadlockError, TransactionFlowError } from "./errors.js";
10
+ import { Resource } from "./Resource.js";
11
+ import type { Transaction } from "./Transaction.js";
12
+
13
+ const logger = Logger.get("ResourceSet");
14
+
15
+ /**
16
+ * An internal set of resources supporting bulk operations for {@link Transaction}.
17
+ */
18
+ export class ResourceSet {
19
+ #transaction: Transaction;
20
+ #resources = new Set<Resource>();
21
+
22
+ constructor(transaction: Transaction, resources: Iterable<Resource> = transaction.resources) {
23
+ this.#transaction = transaction;
24
+ for (let resource of resources) {
25
+ while (resource[Resource.reference]) {
26
+ resource = resource[Resource.reference];
27
+ }
28
+ this.#resources.add(resource);
29
+ }
30
+ }
31
+
32
+ /**
33
+ * Wait until the resources have no exclusive transactions and then lock.
34
+ */
35
+ async acquireLocks() {
36
+ while (true) {
37
+ let blockedBy: undefined | Set<Transaction>;
38
+
39
+ for (const resource of this.#resources) {
40
+ const lockedBy = resource.lockedBy;
41
+ if (lockedBy && lockedBy !== this.#transaction) {
42
+ if (!blockedBy) {
43
+ blockedBy = new Set();
44
+ }
45
+ blockedBy.add(lockedBy);
46
+ }
47
+ }
48
+
49
+ if (!blockedBy) {
50
+ break;
51
+ }
52
+
53
+ this.#detectDeadlock(blockedBy);
54
+
55
+ await this.#transaction.waitFor(blockedBy);
56
+ }
57
+
58
+ return this.acquireLocksSync();
59
+ }
60
+
61
+ /**
62
+ * Acquire locks synchronously.
63
+ *
64
+ * Throws an error if resources aren't lockable.
65
+ */
66
+ acquireLocksSync() {
67
+ const toLock = new Set<Resource>();
68
+ const blocked = new Set<Resource>();
69
+ for (const resource of this.#resources) {
70
+ if (resource.lockedBy) {
71
+ if (resource.lockedBy === this.#transaction) {
72
+ continue;
73
+ }
74
+ logger.warn("Transaction", this.#transaction.via, "blocked by", resource.lockedBy.via);
75
+ blocked.add(resource);
76
+ }
77
+ toLock.add(resource);
78
+ }
79
+ if (blocked.size) {
80
+ logger.warn("You may need to await transaction.begin() to acquire locks asynchronously");
81
+ const names = [...blocked].map(s => s.toString());
82
+ throw new SynchronousTransactionConflictError(`Cannot lock ${describeList("and", ...names)} synchronously`);
83
+ }
84
+
85
+ // Update resource status
86
+ for (const resource of toLock) {
87
+ resource.lockedBy = this.#transaction;
88
+ }
89
+
90
+ return toLock;
91
+ }
92
+
93
+ /**
94
+ * Release locks.
95
+ */
96
+ releaseLocks() {
97
+ const unlocked = new Set<Resource>();
98
+
99
+ for (const resource of this.#resources) {
100
+ if (resource.lockedBy === this.#transaction) {
101
+ delete resource.lockedBy;
102
+ unlocked.add(resource);
103
+ }
104
+ }
105
+
106
+ return unlocked;
107
+ }
108
+
109
+ /**
110
+ * Ensure that a transaction that is committing or rolling back has all resources locked.
111
+ *
112
+ * This is just a sanity check.
113
+ */
114
+ assertResourcesAreLocked(transaction: Transaction, why: string) {
115
+ for (const resource of transaction.resources) {
116
+ if (resource.lockedBy !== transaction) {
117
+ throw new TransactionFlowError(`Transaction attempted ${why} but does not have all resources locked`);
118
+ }
119
+ }
120
+ }
121
+
122
+ /**
123
+ * If two transactions would block each other then we would have a deadlock.
124
+ *
125
+ * This is unlikely but not impossible. It can happen if an endpoint is added to an exclusive transaction but a
126
+ * second transaction already has exclusivity on the new endpoint *and* is waiting on the first transaction.
127
+ *
128
+ * So... detect if the wait graph would have cycles if we an endpoint. If so, throw an error.
129
+ */
130
+ #detectDeadlock(blockedBy: Set<Transaction>) {
131
+ // Recursively examine the transaction holding each resource we wish to lock. If any of them are waiting for a
132
+ // resource that I have locked then we've detected deadlock
133
+ const examined = new Set<Transaction>();
134
+ const examineBlocker = (transaction: Transaction) => {
135
+ examined.add(transaction);
136
+ if (transaction === this.#transaction) {
137
+ throw new TransactionDeadlockError(
138
+ "Resource deadlock detected, write operation cannot proceed. " +
139
+ "To prevent this you can await transaction.begin() before modifying state",
140
+ );
141
+ }
142
+
143
+ if (transaction.waitingOn) {
144
+ for (const blocker of transaction.waitingOn) {
145
+ if (!examined.has(blocker)) {
146
+ examineBlocker(blocker);
147
+ }
148
+ }
149
+ }
150
+ };
151
+
152
+ for (const transaction of blockedBy) {
153
+ examineBlocker(transaction);
154
+ }
155
+ }
156
+
157
+ [Symbol.iterator]() {
158
+ return this.#resources[Symbol.iterator]();
159
+ }
160
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { TransactionFlowError } from "./errors.js";
8
+ import type { Transaction } from "./Transaction.js";
9
+
10
+ /**
11
+ * The lifecycle of a transaction adheres to the following discrete stages.
12
+ */
13
+ export enum Status {
14
+ /**
15
+ * Transaction may be used only for read operations.
16
+ */
17
+ ReadOnly = "read only",
18
+
19
+ /**
20
+ * Transaction is registered but there are no ACID guarantees.
21
+ */
22
+ Shared = "shared",
23
+
24
+ /**
25
+ * Transaction is waiting to obtain exclusive access to resources.
26
+ */
27
+ Waiting = "waiting",
28
+
29
+ /**
30
+ * Transaction has exclusive access. Reads will maintain consistency
31
+ * and writes are allowed.
32
+ */
33
+ Exclusive = "exclusive",
34
+
35
+ /**
36
+ * Transaction is in the process of committing, phase one.
37
+ */
38
+ CommittingPhaseOne = "committing phase one",
39
+
40
+ /**
41
+ * Transaction is in the process of committing, phase two.
42
+ */
43
+ CommittingPhaseTwo = "committing phase two",
44
+
45
+ /**
46
+ * Transaction is in the process of rolling back.
47
+ */
48
+ RollingBack = "rolling back",
49
+
50
+ /**
51
+ * Transaction is destroyed, no further operations permitted.
52
+ */
53
+ Destroyed = "destroyed",
54
+ }
55
+
56
+ export namespace Status {
57
+ export function assert(transaction: Transaction, acceptable: Status[], target: Status) {
58
+ if (!acceptable.includes(transaction.status)) {
59
+ throw new TransactionFlowError(
60
+ `Cannot transition transaction from ${formatStatus(transaction.status)} to ${formatStatus(target)}`,
61
+ );
62
+ }
63
+ }
64
+
65
+ export function formatStatus(status: Status) {
66
+ return `<${status}>`;
67
+ }
68
+ }
@@ -0,0 +1,190 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { MaybePromise } from "#util/Promises.js";
8
+ import { Participant } from "./Participant.js";
9
+ import { Resource } from "./Resource.js";
10
+ import { ResourceSet } from "./ResourceSet.js";
11
+ import { Status } from "./Status.js";
12
+ import { ReadOnlyTransaction, act } from "./Tx.js";
13
+
14
+ /**
15
+ * .
16
+ *
17
+ * Transactions are either shared (for reads) or exclusive (for writes). Exclusive transactions do not block shared
18
+ * transactions but state updates will not be visible until the transaction completes.
19
+ *
20
+ * Writes do block other writes. Transactions start automatically when a write occurs. Since this usually happens
21
+ * synchronously, the best Matter.js can do is throw an error if two write transactions would conflict. However, you
22
+ * can avoid this by using {@link begin} which will wait for other transactions to complete before acquiring resource
23
+ * locks.
24
+ *
25
+ * Persistence is implemented by a list of participants. Commits are two phase. If an error throws in phase one all
26
+ * participants roll back. An error in phase 2 could result in data inconsistency as we don't have any form of retry as
27
+ * of yet.
28
+ *
29
+ * TODO - does prevent deadlock but we should probably add a timeout for resource locking
30
+ */
31
+ export interface Transaction {
32
+ /**
33
+ * Diagnostic description of the transaction's source.
34
+ */
35
+ readonly via: string;
36
+
37
+ /**
38
+ * The status of the transaction.
39
+ */
40
+ readonly status: Status;
41
+
42
+ /**
43
+ * Transaction participants.
44
+ */
45
+ readonly participants: Set<Participant>;
46
+
47
+ /**
48
+ * Resources addressed by the participants.
49
+ */
50
+ readonly resources: Set<Resource>;
51
+
52
+ /**
53
+ * The transactions currently blocking this transaction, if any.
54
+ */
55
+ readonly waitingOn: Iterable<Transaction> | undefined;
56
+
57
+ /**
58
+ * Listen for transaction commit or roll back. This may occur more than once for a given.
59
+ */
60
+ onShared(actor: () => void, once?: boolean): void;
61
+
62
+ /**
63
+ * Listen for {@link Transaction.status} close.
64
+ */
65
+ onClose(actor: () => void): void;
66
+
67
+ /**
68
+ * Add {@link Resources} to the transaction.
69
+ *
70
+ * If the transaction is exclusive (writing) the transaction will acquire the lock on each {@link ResourceType},
71
+ * waiting for other writers to finish if necessary.
72
+ */
73
+ addResources(...resources: Resource[]): Promise<void>;
74
+
75
+ /**
76
+ * Add {@link ResourceType}s to the transaction synchronously.
77
+ *
78
+ * Unlike {@link addResources}, this method will throw an error if the
79
+ * transaction is exclusive and the resources cannot be locked.
80
+ */
81
+ addResourcesSync(...resources: Resource[]): void;
82
+
83
+ /**
84
+ * Begin an exclusive transaction.
85
+ *
86
+ * Transactions begin automatically on write but there are a few reasons you may want to use this method to start an
87
+ * exclusive transaction explicitly:
88
+ *
89
+ * 1. Automatic transactions are started in a synchronous context so conflicting transactions will throw an error.
90
+ * If you start a transaction, your code will await any transaction that would otherwise throw an error.
91
+ *
92
+ * 2. Transaction isolation means your view of data may become stale if a write occurs in another transaction.
93
+ * Once you start a transaction you block other writers so can be assured you're dealing with newest state.
94
+ *
95
+ * 3. Say transaction A has an exclusive lock on resource 1 and awaits resource 2. Transaction B has an exclusive
96
+ * lock on resource 2. Transaction B cannot then await resource 1 without causing a deadlock. Matter.js will
97
+ * detect the deadlock and throw an error. One way to prevent this is to begin a transaction and acquire locks
98
+ * in a specific order.
99
+ *
100
+ * None of the issues above are likely and are probably not a concern for your application. If you do encounter
101
+ * these issues the error message will suggest solutions.
102
+ */
103
+ begin(): Promise<void>;
104
+
105
+ /**
106
+ * Begin an exclusive transaction in a synchronous context.
107
+ *
108
+ * Unlike {@link begin}, this method will throw an error if any participant has already joined an exclusive
109
+ * transaction.
110
+ */
111
+ beginSync(): void;
112
+
113
+ /**
114
+ * Add {@link ParticipantType}s to the transaction.
115
+ */
116
+ addParticipants(...participants: Participant[]): void;
117
+
118
+ /**
119
+ * Retrieve a participant with a specific role.
120
+ */
121
+ getParticipant(role: {}): Participant | undefined;
122
+
123
+ /**
124
+ * Commit the transaction.
125
+ *
126
+ * Matter.js commits automatically when an interaction completes. You may commit manually to publish your changes
127
+ * mid-interaction.
128
+ *
129
+ * After commit an exclusive transaction becomes shared and data references refresh to the most recent value.
130
+ */
131
+ commit(): MaybePromise;
132
+
133
+ /**
134
+ * Roll back the transaction.
135
+ *
136
+ * Matter.js rolls back automatically when an interaction fails. You may roll back manually to undo your changes
137
+ * mid-interaction.
138
+ *
139
+ * After rollback an exclusive transaction becomes shared and data references refresh to the most recent value.
140
+ */
141
+ rollback(): MaybePromise;
142
+
143
+ /**
144
+ * Wait for a set of transactions to complete.
145
+ *
146
+ * @param others the set of transactions to await; cleared on return
147
+ */
148
+ waitFor(others: Set<Transaction>): Promise<void>;
149
+ }
150
+
151
+ type StatusType = Status;
152
+ type ResourceType = Resource;
153
+ type ResourceSetType = ResourceSet;
154
+ type ParticipantType = Participant;
155
+
156
+ export const Transaction = {
157
+ /**
158
+ * Perform a transactional operation. This is the only way to obtain a read/write transaction.
159
+ *
160
+ * The transaction will commit automatically if it is exclusive (write mode) after the actor returns.
161
+ *
162
+ * The transaction is destroyed when {@link act} returns. You will receive an error if you access it after it is
163
+ * destroyed.
164
+ */
165
+ act<T>(via: string, actor: (transaction: Transaction) => MaybePromise<T>): MaybePromise<T> {
166
+ // This function is replaced below so do not edit
167
+ return act(via, actor);
168
+ },
169
+
170
+ ReadOnly: ReadOnlyTransaction,
171
+
172
+ Status,
173
+
174
+ Resource,
175
+
176
+ [Symbol.toStringTag]: "Transaction",
177
+ };
178
+
179
+ // This is functionally equivalent to the definition above but removes a stack frame
180
+ Transaction.act = act;
181
+
182
+ export namespace Transaction {
183
+ export type Status = StatusType;
184
+
185
+ export type Resource = ResourceType;
186
+
187
+ export type ResourceSet = ResourceSetType;
188
+
189
+ export type Participant = ParticipantType;
190
+ }