@stonyx/orm 0.3.2-alpha.125 → 0.3.2-alpha.126

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/README.md CHANGED
@@ -1057,6 +1057,8 @@ test('validation hook rejects negative age', async () => {
1057
1057
  | `hasMany` | Define a one-to-many relationship. |
1058
1058
  | `createRecord` | Instantiate a record with proper serialization and relationships. |
1059
1059
  | `updateRecord` | Update an existing record with new data. |
1060
+ | `createRecordAndPersist` | `createRecord`, awaited: resolves once the write has landed, rejects with its error. Not on DynamoDB yet (#299). |
1061
+ | `updateRecordAndPersist` | `updateRecord`, awaited: resolves once the write has landed, rejects with its error. Not on DynamoDB yet (#299). |
1060
1062
  | `store` | Singleton store for all model instances. |
1061
1063
  | `relationships` | Access all relationships (`hasMany`, `belongsTo`, `global`, `pending`). |
1062
1064
  | `beforeHook` | Register a before hook that can halt operations. |
package/dist/index.d.ts CHANGED
@@ -4,13 +4,13 @@ import Serializer from './serializer.js';
4
4
  import attr from './attr.js';
5
5
  import belongsTo from './belongs-to.js';
6
6
  import hasMany from './has-many.js';
7
- import { createRecord, updateRecord } from './manage-record.js';
7
+ import { createRecord, updateRecord, createRecordAndPersist, updateRecordAndPersist } from './manage-record.js';
8
8
  import { count, avg, sum, min, max } from './aggregates.js';
9
9
  export { default } from './main.js';
10
10
  export { store, relationships } from './main.js';
11
11
  export type { PersistErrorDetail } from './main.js';
12
12
  export { Model, View, Serializer };
13
- export { attr, belongsTo, hasMany, createRecord, updateRecord };
13
+ export { attr, belongsTo, hasMany, createRecord, updateRecord, createRecordAndPersist, updateRecordAndPersist };
14
14
  export { count, avg, sum, min, max };
15
15
  export { default as normalizeRecordId } from './normalize-record-id.js';
16
16
  export type { OrmRequest$ as OrmAccessRequest } from './orm-request.js';
package/dist/index.js CHANGED
@@ -19,12 +19,12 @@ import Serializer from './serializer.js';
19
19
  import attr from './attr.js';
20
20
  import belongsTo from './belongs-to.js';
21
21
  import hasMany from './has-many.js';
22
- import { createRecord, updateRecord } from './manage-record.js';
22
+ import { createRecord, updateRecord, createRecordAndPersist, updateRecordAndPersist } from './manage-record.js';
23
23
  import { count, avg, sum, min, max } from './aggregates.js';
24
24
  export { default } from './main.js';
25
25
  export { store, relationships } from './main.js';
26
26
  export { Model, View, Serializer }; // base classes
27
- export { attr, belongsTo, hasMany, createRecord, updateRecord }; // helpers
27
+ export { attr, belongsTo, hasMany, createRecord, updateRecord, createRecordAndPersist, updateRecordAndPersist };
28
28
  export { count, avg, sum, min, max }; // aggregate helpers
29
29
  export { default as normalizeRecordId } from './normalize-record-id.js'; // canonical URL-id -> record-id resolution (#270)
30
30
  export { beforeHook, afterHook, clearHook, clearAllHooks } from './hooks.js'; // middleware hooks
package/dist/main.d.ts CHANGED
@@ -7,6 +7,7 @@ export interface SqlDb {
7
7
  startup(): Promise<void>;
8
8
  shutdown(): Promise<void>;
9
9
  persist(operation: string, model: string, context: unknown, response: unknown): Promise<void>;
10
+ persistResolvesAfterWrite?: boolean;
10
11
  findRecord(modelName: string, id: unknown): Promise<unknown>;
11
12
  findAll(modelName: string, conditions?: Record<string, unknown>): Promise<unknown[]>;
12
13
  }
@@ -11,4 +11,8 @@ export declare function createRecord(modelName: string, rawData?: {
11
11
  [key: string]: unknown;
12
12
  }, userOptions?: CreateRecordOptions): OrmRecord;
13
13
  export declare function updateRecord(record: OrmRecord, rawData: unknown, userOptions?: CreateRecordOptions): void;
14
+ export declare function createRecordAndPersist(modelName: string, rawData?: {
15
+ [key: string]: unknown;
16
+ }, userOptions?: CreateRecordOptions): Promise<OrmRecord>;
17
+ export declare function updateRecordAndPersist(record: OrmRecord, rawData: unknown, userOptions?: CreateRecordOptions): Promise<void>;
14
18
  export {};
@@ -8,7 +8,57 @@ const defaultOptions = {
8
8
  transform: true
9
9
  };
10
10
  let pendingIdCounter = 0;
11
+ const writeNotRequested = Promise.resolve();
12
+ function ignoreReportedFailure() { }
13
+ function persistRequested(options, userOptions) {
14
+ return !options.isDbRecord && !userOptions._relationshipKey && !options._skipAutoPersist;
15
+ }
16
+ function reportPersistFailure(operation, modelName, recordId, failure) {
17
+ const error = failure instanceof Error ? failure : new Error(String(failure));
18
+ Orm.instance.emitPersistError({ operation, modelName, recordId, error });
19
+ return error;
20
+ }
11
21
  export function createRecord(modelName, rawData = {}, userOptions = {}) {
22
+ const { result: record, written } = createRecordWrite(modelName, rawData, userOptions);
23
+ written.catch(ignoreReportedFailure);
24
+ return record;
25
+ }
26
+ export function updateRecord(record, rawData, userOptions = {}) {
27
+ updateRecordWrite(record, rawData, userOptions).written.catch(ignoreReportedFailure);
28
+ }
29
+ export async function createRecordAndPersist(modelName, rawData = {}, userOptions = {}) {
30
+ assertWriteCanBeAwaited();
31
+ const { result: record, written } = createRecordWrite(modelName, rawData, userOptions);
32
+ await written;
33
+ await saveJsonDatabase('create', modelName, record.id, { ...defaultOptions, ...userOptions }, userOptions);
34
+ return record;
35
+ }
36
+ export async function updateRecordAndPersist(record, rawData, userOptions = {}) {
37
+ assertWriteCanBeAwaited();
38
+ await updateRecordWrite(record, rawData, userOptions).written;
39
+ await saveJsonDatabase('update', record?.__model?.__name ?? '', record.id, { ...defaultOptions, ...userOptions }, userOptions);
40
+ }
41
+ function assertWriteCanBeAwaited() {
42
+ const sqlDb = Orm.instance?.sqlDb;
43
+ if (sqlDb && sqlDb.persistResolvesAfterWrite !== true) {
44
+ throw new Error('The configured database adapter cannot confirm a write has landed, so createRecordAndPersist/updateRecordAndPersist are unavailable for it (DynamoDB: abofs/stonyx-orm#299)');
45
+ }
46
+ }
47
+ async function saveJsonDatabase(operation, modelName, recordId, options, userOptions) {
48
+ const orm = Orm.instance;
49
+ if (orm.sqlDb || !persistRequested(options, userOptions))
50
+ return;
51
+ const jsonDatabase = orm.db;
52
+ if (!jsonDatabase?.save)
53
+ return;
54
+ try {
55
+ await jsonDatabase.save();
56
+ }
57
+ catch (failure) {
58
+ throw reportPersistFailure(operation, modelName, recordId, failure);
59
+ }
60
+ }
61
+ function createRecordWrite(modelName, rawData, userOptions) {
12
62
  const orm = Orm.instance;
13
63
  const { initialized } = Orm;
14
64
  const options = { ...defaultOptions, ...userOptions };
@@ -26,9 +76,7 @@ export function createRecord(modelName, rawData = {}, userOptions = {}) {
26
76
  assignRecordId(modelName, rawData);
27
77
  const existingRecord = modelStore.get(rawData.id);
28
78
  if (existingRecord instanceof OrmRecord) {
29
- // Update the existing record with new data so the last entry wins
30
- updateRecord(existingRecord, rawData, { ...options, update: true });
31
- return existingRecord;
79
+ return { result: existingRecord, written: updateRecordWrite(existingRecord, rawData, { ...options, update: true }).written };
32
80
  }
33
81
  const recordClasses = orm.getRecordClasses(modelName);
34
82
  const modelClass = recordClasses.modelClass;
@@ -101,56 +149,38 @@ export function createRecord(modelName, rawData = {}, userOptions = {}) {
101
149
  // Clear the pending queue
102
150
  pendingBelongsTo.length = 0;
103
151
  }
104
- // Auto-persist to SQL — skip for DB loads (isDbRecord) and relationship resolution (_relationshipKey)
105
- const shouldPersist = orm?.sqlDb && !options.isDbRecord && !userOptions._relationshipKey && !options._skipAutoPersist;
106
- if (shouldPersist) {
107
- // Capture ID before persist — SQL adapters re-key pending IDs to real DB IDs,
108
- // but relationship registries were keyed with this original ID
109
- const registryId = record.id;
110
- const response = { data: { id: record.id } };
111
- orm.sqlDb.persist('create', modelName, { rawData }, response)
112
- .catch((err) => {
113
- orm.emitPersistError({
114
- operation: 'create',
115
- modelName,
116
- recordId: record.id,
117
- error: err instanceof Error ? err : new Error(String(err)),
118
- });
119
- })
120
- .finally(() => {
121
- // Evict non-memory records after persist to prevent unbounded heap growth (stonyx#81)
122
- if (store._memoryResolver && !store._memoryResolver(modelName)) {
123
- store.evictRecord(modelName, record.id, registryId);
124
- }
125
- });
126
- }
127
- return record;
152
+ if (!orm?.sqlDb || !persistRequested(options, userOptions))
153
+ return { result: record, written: writeNotRequested };
154
+ const registryIdBeforePersist = record.id;
155
+ const response = { data: { id: record.id } };
156
+ const written = orm.sqlDb.persist('create', modelName, { rawData }, response)
157
+ .catch((failure) => {
158
+ throw reportPersistFailure('create', modelName, record.id, failure);
159
+ })
160
+ .finally(() => {
161
+ if (store._memoryResolver && !store._memoryResolver(modelName)) {
162
+ store.evictRecord(modelName, record.id, registryIdBeforePersist);
163
+ }
164
+ });
165
+ return { result: record, written };
128
166
  }
129
- export function updateRecord(record, rawData, userOptions = {}) {
167
+ function updateRecordWrite(record, rawData, userOptions) {
130
168
  if (!rawData)
131
169
  throw new Error('rawData must be passed in to updateRecord call');
132
- // Guard: read-only views cannot be updated
133
170
  const modelName = record?.__model?.__name;
134
171
  if (modelName && Orm.instance?.isView?.(modelName)) {
135
172
  throw new Error(`Cannot update records for read-only view '${modelName}'`);
136
173
  }
137
174
  const options = { ...defaultOptions, ...userOptions, update: true };
138
- // Capture old state before update for SQL diff
139
175
  const oldState = record.__data ? JSON.parse(JSON.stringify(record.__data)) : {};
140
176
  record.serialize(rawData, options);
141
- // Auto-persist to SQL — skip for DB loads (isDbRecord) and relationship resolution (_relationshipKey)
142
177
  const orm = Orm.instance;
143
- const shouldPersist = orm?.sqlDb && !options.isDbRecord && !userOptions._relationshipKey && !options._skipAutoPersist;
144
- if (shouldPersist && modelName) {
145
- orm.sqlDb.persist('update', modelName, { record, oldState }, {}).catch((err) => {
146
- orm.emitPersistError({
147
- operation: 'update',
148
- modelName,
149
- recordId: record.id,
150
- error: err instanceof Error ? err : new Error(String(err)),
151
- });
152
- });
153
- }
178
+ if (!orm?.sqlDb || !modelName || !persistRequested(options, userOptions))
179
+ return { result: undefined, written: writeNotRequested };
180
+ const written = orm.sqlDb.persist('update', modelName, { record, oldState }, {}).catch((failure) => {
181
+ throw reportPersistFailure('update', modelName, record.id, failure);
182
+ });
183
+ return { result: undefined, written };
154
184
  }
155
185
  /**
156
186
  * gets the next available id based on last record entry.
@@ -70,6 +70,7 @@ export default class MysqlDB {
70
70
  deps: MysqlDBDeps;
71
71
  pool: Pool | null;
72
72
  mysqlConfig: MysqlConfig;
73
+ readonly persistResolvesAfterWrite = true;
73
74
  private _queuedWrites;
74
75
  private _inFlightWrites;
75
76
  private _drainingWrites;
@@ -41,6 +41,7 @@ export default class MysqlDB {
41
41
  deps;
42
42
  pool;
43
43
  mysqlConfig;
44
+ persistResolvesAfterWrite = true;
44
45
  _queuedWrites = [];
45
46
  _inFlightWrites = new Set();
46
47
  _drainingWrites = null;
@@ -85,6 +85,7 @@ export default class PostgresDB {
85
85
  deps: PostgresDeps;
86
86
  pool: Pool | null;
87
87
  pgConfig: Record<string, unknown>;
88
+ readonly persistResolvesAfterWrite = true;
88
89
  private _queuedWrites;
89
90
  private _inFlightWrites;
90
91
  private _drainingWrites;
@@ -48,6 +48,7 @@ export default class PostgresDB {
48
48
  deps;
49
49
  pool;
50
50
  pgConfig;
51
+ persistResolvesAfterWrite = true;
51
52
  _queuedWrites = [];
52
53
  _inFlightWrites = new Set();
53
54
  _drainingWrites = null;
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "stonyx-async",
5
5
  "stonyx-module"
6
6
  ],
7
- "version": "0.3.2-alpha.125",
7
+ "version": "0.3.2-alpha.126",
8
8
  "description": "",
9
9
  "main": "dist/index.js",
10
10
  "type": "module",
package/src/index.ts CHANGED
@@ -21,14 +21,14 @@ import Serializer from './serializer.js';
21
21
  import attr from './attr.js';
22
22
  import belongsTo from './belongs-to.js';
23
23
  import hasMany from './has-many.js';
24
- import { createRecord, updateRecord } from './manage-record.js';
24
+ import { createRecord, updateRecord, createRecordAndPersist, updateRecordAndPersist } from './manage-record.js';
25
25
  import { count, avg, sum, min, max } from './aggregates.js';
26
26
 
27
27
  export { default } from './main.js';
28
28
  export { store, relationships } from './main.js';
29
29
  export type { PersistErrorDetail } from './main.js';
30
30
  export { Model, View, Serializer }; // base classes
31
- export { attr, belongsTo, hasMany, createRecord, updateRecord }; // helpers
31
+ export { attr, belongsTo, hasMany, createRecord, updateRecord, createRecordAndPersist, updateRecordAndPersist };
32
32
  export { count, avg, sum, min, max }; // aggregate helpers
33
33
  export { default as normalizeRecordId } from './normalize-record-id.js'; // canonical URL-id -> record-id resolution (#270)
34
34
  export type { OrmRequest$ as OrmAccessRequest } from './orm-request.js'; // the request access() is handed, incl. recordId (#270)
package/src/main.ts CHANGED
@@ -34,6 +34,7 @@ export interface SqlDb {
34
34
  startup(): Promise<void>;
35
35
  shutdown(): Promise<void>;
36
36
  persist(operation: string, model: string, context: unknown, response: unknown): Promise<void>;
37
+ persistResolvesAfterWrite?: boolean;
37
38
  findRecord(modelName: string, id: unknown): Promise<unknown>;
38
39
  findAll(modelName: string, conditions?: Record<string, unknown>): Promise<unknown[]>;
39
40
  }
@@ -28,7 +28,73 @@ const defaultOptions: CreateRecordOptions = {
28
28
 
29
29
  let pendingIdCounter = 0;
30
30
 
31
+ interface RecordWrite<Result> {
32
+ result: Result;
33
+ written: Promise<void>;
34
+ }
35
+
36
+ type AwaitedOperation = 'create' | 'update';
37
+
38
+ const writeNotRequested = Promise.resolve();
39
+
40
+ function ignoreReportedFailure(): void {}
41
+
42
+ function persistRequested(options: CreateRecordOptions, userOptions: CreateRecordOptions): boolean {
43
+ return !options.isDbRecord && !userOptions._relationshipKey && !options._skipAutoPersist;
44
+ }
45
+
46
+ function reportPersistFailure(operation: AwaitedOperation, modelName: string, recordId: unknown, failure: unknown): Error {
47
+ const error = failure instanceof Error ? failure : new Error(String(failure));
48
+ Orm.instance.emitPersistError({ operation, modelName, recordId, error });
49
+ return error;
50
+ }
51
+
31
52
  export function createRecord(modelName: string, rawData: { [key: string]: unknown } = {}, userOptions: CreateRecordOptions = {}): OrmRecord {
53
+ const { result: record, written } = createRecordWrite(modelName, rawData, userOptions);
54
+ written.catch(ignoreReportedFailure);
55
+ return record;
56
+ }
57
+
58
+ export function updateRecord(record: OrmRecord, rawData: unknown, userOptions: CreateRecordOptions = {}): void {
59
+ updateRecordWrite(record, rawData, userOptions).written.catch(ignoreReportedFailure);
60
+ }
61
+
62
+ export async function createRecordAndPersist(modelName: string, rawData: { [key: string]: unknown } = {}, userOptions: CreateRecordOptions = {}): Promise<OrmRecord> {
63
+ assertWriteCanBeAwaited();
64
+ const { result: record, written } = createRecordWrite(modelName, rawData, userOptions);
65
+ await written;
66
+ await saveJsonDatabase('create', modelName, record.id, { ...defaultOptions, ...userOptions }, userOptions);
67
+ return record;
68
+ }
69
+
70
+ export async function updateRecordAndPersist(record: OrmRecord, rawData: unknown, userOptions: CreateRecordOptions = {}): Promise<void> {
71
+ assertWriteCanBeAwaited();
72
+ await updateRecordWrite(record, rawData, userOptions).written;
73
+ await saveJsonDatabase('update', record?.__model?.__name ?? '', record.id, { ...defaultOptions, ...userOptions }, userOptions);
74
+ }
75
+
76
+ function assertWriteCanBeAwaited(): void {
77
+ const sqlDb = Orm.instance?.sqlDb as { persistResolvesAfterWrite?: boolean } | undefined;
78
+ if (sqlDb && sqlDb.persistResolvesAfterWrite !== true) {
79
+ throw new Error('The configured database adapter cannot confirm a write has landed, so createRecordAndPersist/updateRecordAndPersist are unavailable for it (DynamoDB: abofs/stonyx-orm#299)');
80
+ }
81
+ }
82
+
83
+ async function saveJsonDatabase(operation: AwaitedOperation, modelName: string, recordId: unknown, options: CreateRecordOptions, userOptions: CreateRecordOptions): Promise<void> {
84
+ const orm = Orm.instance;
85
+ if (orm.sqlDb || !persistRequested(options, userOptions)) return;
86
+
87
+ const jsonDatabase = orm.db as { save?: () => Promise<void> } | undefined;
88
+ if (!jsonDatabase?.save) return;
89
+
90
+ try {
91
+ await jsonDatabase.save();
92
+ } catch (failure) {
93
+ throw reportPersistFailure(operation, modelName, recordId, failure);
94
+ }
95
+ }
96
+
97
+ function createRecordWrite(modelName: string, rawData: { [key: string]: unknown }, userOptions: CreateRecordOptions): RecordWrite<OrmRecord> {
32
98
  const orm = Orm.instance;
33
99
  const { initialized } = Orm;
34
100
  const options = { ...defaultOptions, ...userOptions };
@@ -50,9 +116,7 @@ export function createRecord(modelName: string, rawData: { [key: string]: unknow
50
116
  const existingRecord = modelStore.get(rawData.id as number | string);
51
117
 
52
118
  if (existingRecord instanceof OrmRecord) {
53
- // Update the existing record with new data so the last entry wins
54
- updateRecord(existingRecord, rawData, { ...options, update: true });
55
- return existingRecord;
119
+ return { result: existingRecord, written: updateRecordWrite(existingRecord, rawData, { ...options, update: true }).written };
56
120
  }
57
121
 
58
122
  const recordClasses = orm.getRecordClasses(modelName);
@@ -136,37 +200,26 @@ export function createRecord(modelName: string, rawData: { [key: string]: unknow
136
200
  pendingBelongsTo.length = 0;
137
201
  }
138
202
 
139
- // Auto-persist to SQL — skip for DB loads (isDbRecord) and relationship resolution (_relationshipKey)
140
- const shouldPersist = orm?.sqlDb && !options.isDbRecord && !userOptions._relationshipKey && !options._skipAutoPersist;
141
- if (shouldPersist) {
142
- // Capture ID before persist — SQL adapters re-key pending IDs to real DB IDs,
143
- // but relationship registries were keyed with this original ID
144
- const registryId = record.id;
145
- const response = { data: { id: record.id } };
146
- orm!.sqlDb!.persist('create', modelName, { rawData }, response)
147
- .catch((err: unknown) => {
148
- orm!.emitPersistError({
149
- operation: 'create',
150
- modelName,
151
- recordId: record.id,
152
- error: err instanceof Error ? err : new Error(String(err)),
153
- });
154
- })
155
- .finally(() => {
156
- // Evict non-memory records after persist to prevent unbounded heap growth (stonyx#81)
157
- if (store._memoryResolver && !store._memoryResolver(modelName)) {
158
- store.evictRecord(modelName, record.id, registryId);
159
- }
160
- });
161
- }
203
+ if (!orm?.sqlDb || !persistRequested(options, userOptions)) return { result: record, written: writeNotRequested };
204
+
205
+ const registryIdBeforePersist = record.id;
206
+ const response = { data: { id: record.id } };
207
+ const written = orm.sqlDb.persist('create', modelName, { rawData }, response)
208
+ .catch((failure: unknown) => {
209
+ throw reportPersistFailure('create', modelName, record.id, failure);
210
+ })
211
+ .finally(() => {
212
+ if (store._memoryResolver && !store._memoryResolver(modelName)) {
213
+ store.evictRecord(modelName, record.id, registryIdBeforePersist);
214
+ }
215
+ });
162
216
 
163
- return record;
217
+ return { result: record, written };
164
218
  }
165
219
 
166
- export function updateRecord(record: OrmRecord, rawData: unknown, userOptions: CreateRecordOptions = {}): void {
220
+ function updateRecordWrite(record: OrmRecord, rawData: unknown, userOptions: CreateRecordOptions): RecordWrite<void> {
167
221
  if (!rawData) throw new Error('rawData must be passed in to updateRecord call');
168
222
 
169
- // Guard: read-only views cannot be updated
170
223
  const modelName = record?.__model?.__name;
171
224
  if (modelName && Orm.instance?.isView?.(modelName)) {
172
225
  throw new Error(`Cannot update records for read-only view '${modelName}'`);
@@ -174,24 +227,18 @@ export function updateRecord(record: OrmRecord, rawData: unknown, userOptions: C
174
227
 
175
228
  const options = { ...defaultOptions, ...userOptions, update: true };
176
229
 
177
- // Capture old state before update for SQL diff
178
230
  const oldState = record.__data ? JSON.parse(JSON.stringify(record.__data)) : {};
179
231
 
180
232
  record.serialize(rawData, options);
181
233
 
182
- // Auto-persist to SQL — skip for DB loads (isDbRecord) and relationship resolution (_relationshipKey)
183
234
  const orm = Orm.instance;
184
- const shouldPersist = orm?.sqlDb && !options.isDbRecord && !userOptions._relationshipKey && !options._skipAutoPersist;
185
- if (shouldPersist && modelName) {
186
- orm!.sqlDb!.persist('update', modelName, { record, oldState }, {}).catch((err: unknown) => {
187
- orm!.emitPersistError({
188
- operation: 'update',
189
- modelName,
190
- recordId: record.id,
191
- error: err instanceof Error ? err : new Error(String(err)),
192
- });
193
- });
194
- }
235
+ if (!orm?.sqlDb || !modelName || !persistRequested(options, userOptions)) return { result: undefined, written: writeNotRequested };
236
+
237
+ const written = orm.sqlDb.persist('update', modelName, { record, oldState }, {}).catch((failure: unknown) => {
238
+ throw reportPersistFailure('update', modelName, record.id, failure);
239
+ });
240
+
241
+ return { result: undefined, written };
195
242
  }
196
243
 
197
244
  /**
@@ -123,6 +123,7 @@ export default class MysqlDB {
123
123
  pool!: Pool | null;
124
124
  mysqlConfig!: MysqlConfig;
125
125
 
126
+ readonly persistResolvesAfterWrite = true;
126
127
  private _queuedWrites: QueuedWrite[] = [];
127
128
  private _inFlightWrites = new Set<QueuedWrite>();
128
129
  private _drainingWrites: Promise<void> | null = null;
@@ -134,6 +134,7 @@ export default class PostgresDB {
134
134
  pool!: Pool | null;
135
135
  pgConfig!: Record<string, unknown>;
136
136
 
137
+ readonly persistResolvesAfterWrite = true;
137
138
  private _queuedWrites: QueuedWrite[] = [];
138
139
  private _inFlightWrites = new Set<QueuedWrite>();
139
140
  private _drainingWrites: Promise<void> | null = null;