@stonyx/orm 0.3.2-alpha.6 → 0.3.2-alpha.61

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 (53) hide show
  1. package/README.md +580 -10
  2. package/config/{environment.ts → environment.js} +8 -0
  3. package/dist/commands.js +34 -0
  4. package/dist/dynamodb/connection.d.ts +31 -0
  5. package/dist/dynamodb/connection.js +28 -0
  6. package/dist/dynamodb/dynamodb-db.d.ts +142 -0
  7. package/dist/dynamodb/dynamodb-db.js +596 -0
  8. package/dist/dynamodb/operation-builder.d.ts +76 -0
  9. package/dist/dynamodb/operation-builder.js +116 -0
  10. package/dist/dynamodb/type-map.d.ts +31 -0
  11. package/dist/dynamodb/type-map.js +48 -0
  12. package/dist/index.d.ts +1 -0
  13. package/dist/main.d.ts +116 -0
  14. package/dist/main.js +129 -0
  15. package/dist/manage-record.js +137 -11
  16. package/dist/mysql/connection.d.ts +1 -0
  17. package/dist/mysql/mysql-db.d.ts +8 -0
  18. package/dist/mysql/mysql-db.js +44 -10
  19. package/dist/orm-request.d.ts +181 -3
  20. package/dist/orm-request.js +794 -47
  21. package/dist/postgres/connection.d.ts +1 -0
  22. package/dist/postgres/connection.js +8 -6
  23. package/dist/postgres/postgres-db.d.ts +8 -0
  24. package/dist/postgres/postgres-db.js +44 -10
  25. package/dist/record.js +7 -5
  26. package/dist/relationships.js +1 -1
  27. package/dist/serializer.js +38 -2
  28. package/dist/setup-rest-server.js +51 -5
  29. package/dist/store.d.ts +13 -1
  30. package/dist/store.js +65 -6
  31. package/dist/types/orm-types.d.ts +112 -0
  32. package/package.json +16 -7
  33. package/src/commands.ts +43 -0
  34. package/src/dynamodb/connection.ts +50 -0
  35. package/src/dynamodb/dynamodb-db.ts +811 -0
  36. package/src/dynamodb/operation-builder.ts +202 -0
  37. package/src/dynamodb/type-map.ts +54 -0
  38. package/src/index.ts +1 -0
  39. package/src/main.ts +133 -0
  40. package/src/manage-record.ts +154 -17
  41. package/src/mysql/connection.ts +1 -0
  42. package/src/mysql/mysql-db.ts +44 -12
  43. package/src/orm-request.ts +809 -50
  44. package/src/postgres/connection.ts +10 -6
  45. package/src/postgres/postgres-db.ts +44 -12
  46. package/src/record.ts +8 -5
  47. package/src/relationships.ts +1 -1
  48. package/src/serializer.ts +39 -2
  49. package/src/setup-rest-server.ts +59 -6
  50. package/src/store.ts +68 -6
  51. package/src/types/orm-types.ts +118 -0
  52. package/src/types/stonyx-rest-server.d.ts +14 -1
  53. package/src/types/stonyx.d.ts +7 -1
@@ -84,6 +84,15 @@ export default class MysqlDB {
84
84
  pool!: Pool | null;
85
85
  mysqlConfig!: MysqlConfig;
86
86
 
87
+ /**
88
+ * Promise-chain mutex for write serialization (#156).
89
+ * All persist() calls chain through this single queue so concurrent
90
+ * fire-and-forget writes never produce parallel InnoDB transactions
91
+ * on FK-linked rows (which cause deadlocks).
92
+ * Reads are NOT affected — only persist() serializes.
93
+ */
94
+ private _writeQueue: Promise<void> = Promise.resolve();
95
+
87
96
  constructor(deps: Partial<MysqlDBDeps> = {}) {
88
97
  if (MysqlDB.instance) return MysqlDB.instance;
89
98
  MysqlDB.instance = this;
@@ -118,7 +127,15 @@ export default class MysqlDB {
118
127
  if (pending.length > 0) {
119
128
  this.deps.log.db?.(`${pending.length} pending migration(s) found.`);
120
129
 
121
- const shouldApply = await this.deps.confirm(`${pending.length} pending migration(s) found. Apply now?`);
130
+ let shouldApply: boolean;
131
+ if (this.mysqlConfig.autoMigrate === true) {
132
+ shouldApply = true;
133
+ } else if (this.mysqlConfig.autoMigrate === false) {
134
+ shouldApply = false;
135
+ this.deps.log.warn?.(`autoMigrate is false — skipping ${pending.length} pending migration(s).`);
136
+ } else {
137
+ shouldApply = await this.deps.confirm(`${pending.length} pending migration(s) found. Apply now?`);
138
+ }
122
139
 
123
140
  if (shouldApply) {
124
141
  for (const filename of pending) {
@@ -139,9 +156,17 @@ export default class MysqlDB {
139
156
  const modelCount = Object.keys(schemas).length;
140
157
 
141
158
  if (modelCount > 0) {
142
- const shouldGenerate = await this.deps.confirm(
143
- `No migrations found but ${modelCount} model(s) detected. Generate and apply initial migration?`
144
- );
159
+ let shouldGenerate: boolean;
160
+ if (this.mysqlConfig.autoMigrate === true) {
161
+ shouldGenerate = true;
162
+ } else if (this.mysqlConfig.autoMigrate === false) {
163
+ shouldGenerate = false;
164
+ this.deps.log.warn?.(`autoMigrate is false — skipping initial migration generation for ${modelCount} model(s).`);
165
+ } else {
166
+ shouldGenerate = await this.deps.confirm(
167
+ `No migrations found but ${modelCount} model(s) detected. Generate and apply initial migration?`
168
+ );
169
+ }
145
170
 
146
171
  if (shouldGenerate) {
147
172
  const { generateMigration } = await import('./migration-generator.js');
@@ -398,14 +423,21 @@ export default class MysqlDB {
398
423
  const Orm = (await import('@stonyx/orm')).default;
399
424
  if ((Orm as unknown as { instance?: { isView?: (name: string) => boolean } }).instance?.isView?.(modelName)) return;
400
425
 
401
- switch (operation) {
402
- case 'create':
403
- return this._persistCreate(modelName, context, response);
404
- case 'update':
405
- return this._persistUpdate(modelName, context, response);
406
- case 'delete':
407
- return this._persistDelete(modelName, context);
408
- }
426
+ const work = async () => {
427
+ switch (operation) {
428
+ case 'create':
429
+ return this._persistCreate(modelName, context, response);
430
+ case 'update':
431
+ return this._persistUpdate(modelName, context, response);
432
+ case 'delete':
433
+ return this._persistDelete(modelName, context);
434
+ }
435
+ };
436
+
437
+ // Chain through the write queue — .then(work, work) ensures the queue
438
+ // advances even when a previous persist rejects (#156).
439
+ this._writeQueue = this._writeQueue.then(work, work);
440
+ return this._writeQueue;
409
441
  }
410
442
 
411
443
  private async _persistCreate(modelName: string, context: PersistContext, response: PersistResponse): Promise<void> {