@stratum-hq/mysql 0.3.0 → 0.4.0

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
@@ -82,16 +82,19 @@ await adapter.closeAll();
82
82
  ### TypeORM Subscriber (writes only)
83
83
 
84
84
  ```typescript
85
- import { StratumTypeOrmSubscriber } from "@stratum-hq/mysql";
85
+ import { registerStratumSubscriber } from "@stratum-hq/mysql";
86
86
 
87
- // Register an instance once the data source is initialized. (TypeORM's
88
- // `subscribers` option only loads @EventSubscriber()-decorated classes.)
89
87
  await dataSource.initialize();
90
- dataSource.subscribers.push(new StratumTypeOrmSubscriber());
88
+ // Adds one StratumTypeOrmSubscriber. A second call adds nothing.
89
+ registerStratumSubscriber(dataSource);
91
90
  ```
92
91
 
92
+ Call `registerStratumSubscriber()` after `dataSource.initialize()`. It throws before that, because `initialize()` replaces the subscriber list. Do not put `StratumTypeOrmSubscriber` in the `subscribers` option: TypeORM only loads classes decorated with `@EventSubscriber()` from that option.
93
+
93
94
  Inserts get the current tenant's `tenant_id`. Updates never change `tenant_id`: `save()` keeps the loaded value, and `update()` / query builder updates drop it from the SET values.
94
95
 
96
+ Upserts (`repository.upsert()` and `.orUpdate()`) also get the current tenant's `tenant_id` on insert. If the conflict update writes `tenant_id`, the subscriber rejects the statement before it runs. To upsert, leave `tenant_id` out of the entity values and out of the `orUpdate()` columns.
97
+
95
98
  **Limitation:** TypeORM subscribers can intercept writes but not reads. Use the shared-table adapter's structured methods for tenant-scoped reads.
96
99
 
97
100
  ### Knex Helper
package/dist/index.d.ts CHANGED
@@ -4,8 +4,8 @@ export { MysqlTableAdapter } from "./adapters/table.js";
4
4
  export { MysqlDatabaseAdapter } from "./adapters/database.js";
5
5
  export { MysqlPoolManager } from "./pool-manager.js";
6
6
  export { createTenantView, dropTenantView, setTenantSession } from "./views/manager.js";
7
- export { StratumTypeOrmSubscriber } from "./integrations/typeorm-subscriber.js";
8
- export type { InsertEvent, UpdateEvent, EntitySubscriberInterface } from "./integrations/typeorm-subscriber.js";
7
+ export { StratumTypeOrmSubscriber, registerStratumSubscriber, } from "./integrations/typeorm-subscriber.js";
8
+ export type { InsertEvent, UpdateEvent, BeforeQueryEvent, EntitySubscriberInterface, TypeOrmDataSourceLike, } from "./integrations/typeorm-subscriber.js";
9
9
  export { withTenantScope } from "./integrations/knex.js";
10
10
  export type { KnexLike, KnexQueryBuilderLike } from "./integrations/knex.js";
11
11
  export { withMysqlTenantScope } from "./integrations/sequelize.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,mBAAmB,EACnB,aAAa,EACb,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,yBAAyB,EACzB,wBAAwB,EACxB,2BAA2B,EAC3B,uBAAuB,GACxB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGxF,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAChF,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAChH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,YAAY,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAGjE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,mBAAmB,EACnB,aAAa,EACb,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,yBAAyB,EACzB,wBAAwB,EACxB,2BAA2B,EAC3B,uBAAuB,GACxB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGxF,OAAO,EACL,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,sCAAsC,CAAC;AAC9C,YAAY,EACV,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,YAAY,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAGjE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.aggregatePurgeResults = exports.escapeIdentifier = exports.assertTenantId = exports.withMysqlTenantScope = exports.withTenantScope = exports.StratumTypeOrmSubscriber = exports.setTenantSession = exports.dropTenantView = exports.createTenantView = exports.MysqlPoolManager = exports.MysqlDatabaseAdapter = exports.MysqlTableAdapter = exports.MysqlSharedAdapter = void 0;
3
+ exports.aggregatePurgeResults = exports.escapeIdentifier = exports.assertTenantId = exports.withMysqlTenantScope = exports.withTenantScope = exports.registerStratumSubscriber = exports.StratumTypeOrmSubscriber = exports.setTenantSession = exports.dropTenantView = exports.createTenantView = exports.MysqlPoolManager = exports.MysqlDatabaseAdapter = exports.MysqlTableAdapter = exports.MysqlSharedAdapter = void 0;
4
4
  // Adapters
5
5
  var shared_js_1 = require("./adapters/shared.js");
6
6
  Object.defineProperty(exports, "MysqlSharedAdapter", { enumerable: true, get: function () { return shared_js_1.MysqlSharedAdapter; } });
@@ -19,6 +19,7 @@ Object.defineProperty(exports, "setTenantSession", { enumerable: true, get: func
19
19
  // Integrations
20
20
  var typeorm_subscriber_js_1 = require("./integrations/typeorm-subscriber.js");
21
21
  Object.defineProperty(exports, "StratumTypeOrmSubscriber", { enumerable: true, get: function () { return typeorm_subscriber_js_1.StratumTypeOrmSubscriber; } });
22
+ Object.defineProperty(exports, "registerStratumSubscriber", { enumerable: true, get: function () { return typeorm_subscriber_js_1.registerStratumSubscriber; } });
22
23
  var knex_js_1 = require("./integrations/knex.js");
23
24
  Object.defineProperty(exports, "withTenantScope", { enumerable: true, get: function () { return knex_js_1.withTenantScope; } });
24
25
  var sequelize_js_1 = require("./integrations/sequelize.js");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAaA,WAAW;AACX,kDAA0D;AAAjD,+GAAA,kBAAkB,OAAA;AAC3B,gDAAwD;AAA/C,6GAAA,iBAAiB,OAAA;AAC1B,sDAA8D;AAArD,mHAAA,oBAAoB,OAAA;AAE7B,eAAe;AACf,qDAAqD;AAA5C,mHAAA,gBAAgB,OAAA;AAEzB,QAAQ;AACR,iDAAwF;AAA/E,8GAAA,gBAAgB,OAAA;AAAE,4GAAA,cAAc,OAAA;AAAE,8GAAA,gBAAgB,OAAA;AAE3D,eAAe;AACf,8EAAgF;AAAvE,iIAAA,wBAAwB,OAAA;AAEjC,kDAAyD;AAAhD,0GAAA,eAAe,OAAA;AAExB,4DAAmE;AAA1D,oHAAA,oBAAoB,OAAA;AAG7B,YAAY;AACZ,uCAAqF;AAA5E,0GAAA,cAAc,OAAA;AAAE,4GAAA,gBAAgB,OAAA;AAAE,iHAAA,qBAAqB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAaA,WAAW;AACX,kDAA0D;AAAjD,+GAAA,kBAAkB,OAAA;AAC3B,gDAAwD;AAA/C,6GAAA,iBAAiB,OAAA;AAC1B,sDAA8D;AAArD,mHAAA,oBAAoB,OAAA;AAE7B,eAAe;AACf,qDAAqD;AAA5C,mHAAA,gBAAgB,OAAA;AAEzB,QAAQ;AACR,iDAAwF;AAA/E,8GAAA,gBAAgB,OAAA;AAAE,4GAAA,cAAc,OAAA;AAAE,8GAAA,gBAAgB,OAAA;AAE3D,eAAe;AACf,8EAG8C;AAF5C,iIAAA,wBAAwB,OAAA;AACxB,kIAAA,yBAAyB,OAAA;AAS3B,kDAAyD;AAAhD,0GAAA,eAAe,OAAA;AAExB,4DAAmE;AAA1D,oHAAA,oBAAoB,OAAA;AAG7B,YAAY;AACZ,uCAAqF;AAA5E,0GAAA,cAAc,OAAA;AAAE,4GAAA,gBAAgB,OAAA;AAAE,iHAAA,qBAAqB,OAAA"}
@@ -13,17 +13,27 @@ export interface UpdateEvent {
13
13
  }[];
14
14
  };
15
15
  }
16
+ export interface BeforeQueryEvent {
17
+ /** The SQL text that TypeORM is about to send to MySQL. */
18
+ query: string;
19
+ }
16
20
  export interface EntitySubscriberInterface {
17
21
  beforeInsert?(event: InsertEvent): void | Promise<void>;
18
22
  beforeUpdate?(event: UpdateEvent): void | Promise<void>;
23
+ beforeQuery?(event: BeforeQueryEvent): void | Promise<void>;
24
+ }
25
+ /** The part of a TypeORM `DataSource` that the registration helper uses. */
26
+ export interface TypeOrmDataSourceLike {
27
+ readonly isInitialized: boolean;
28
+ readonly subscribers: unknown[];
19
29
  }
20
30
  /**
21
31
  * TypeORM subscriber that injects tenant_id into inserted entities via ALS and
22
32
  * never lets an update change tenant_id.
23
33
  *
24
- * Register an instance after the data source is initialized:
25
- * `dataSource.subscribers.push(new StratumTypeOrmSubscriber())`. TypeORM's
26
- * `subscribers` option only loads classes decorated with `@EventSubscriber()`.
34
+ * Register it with `registerStratumSubscriber(dataSource)` after
35
+ * `dataSource.initialize()`. TypeORM's `subscribers` option only loads classes
36
+ * decorated with `@EventSubscriber()`, so it does not load this class.
27
37
  *
28
38
  * Known limitation: TypeORM subscribers cannot intercept query filtering.
29
39
  * This subscriber handles writes only. Use the shared-table adapter's
@@ -39,5 +49,26 @@ export declare class StratumTypeOrmSubscriber implements EntitySubscriberInterfa
39
49
  * case-insensitive, so any letter case is dropped).
40
50
  */
41
51
  beforeUpdate(event: UpdateEvent): void;
52
+ /**
53
+ * Rejects an upsert that writes tenant_id on a key conflict.
54
+ *
55
+ * A conflict update must never change the tenant of an existing row. A
56
+ * subscriber cannot remove one column from the conflict update, so the
57
+ * statement fails before it runs.
58
+ *
59
+ * @throws Error when the ON DUPLICATE KEY UPDATE clause assigns tenant_id.
60
+ */
61
+ beforeQuery(event: BeforeQueryEvent): void;
42
62
  }
63
+ /**
64
+ * Returns the one StratumTypeOrmSubscriber on the data source, and adds it first when it is missing.
65
+ *
66
+ * A second call returns the subscriber that the first call added, so the
67
+ * data source never runs the subscriber twice.
68
+ *
69
+ * @param dataSource - An initialized TypeORM `DataSource`.
70
+ * @throws Error when the data source is not initialized. `initialize()` replaces
71
+ * the subscriber list, so an earlier registration has no effect.
72
+ */
73
+ export declare function registerStratumSubscriber(dataSource: TypeOrmDataSourceLike): StratumTypeOrmSubscriber;
43
74
  //# sourceMappingURL=typeorm-subscriber.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"typeorm-subscriber.d.ts","sourceRoot":"","sources":["../../src/integrations/typeorm-subscriber.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B,wFAAwF;IACxF,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE;YAAE,YAAY,EAAE,MAAM,CAAC;YAAC,YAAY,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,CAAC;CAC1E;AAED,MAAM,WAAW,yBAAyB;IACxC,YAAY,CAAC,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,YAAY,CAAC,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,wBAAyB,YAAW,yBAAyB;IACxE,qEAAqE;IACrE,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAMtC;;;;;OAKG;IACH,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;CAsBvC"}
1
+ {"version":3,"file":"typeorm-subscriber.d.ts","sourceRoot":"","sources":["../../src/integrations/typeorm-subscriber.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B,wFAAwF;IACxF,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE;YAAE,YAAY,EAAE,MAAM,CAAC;YAAC,YAAY,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,CAAC;CAC1E;AAED,MAAM,WAAW,gBAAgB;IAC/B,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,yBAAyB;IACxC,YAAY,CAAC,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,YAAY,CAAC,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,WAAW,CAAC,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAED,4EAA4E;AAC5E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,OAAO,EAAE,CAAC;CACjC;AAOD;;;;;;;;;;;GAWG;AACH,qBAAa,wBAAyB,YAAW,yBAAyB;IACxE,qEAAqE;IACrE,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAMtC;;;;;OAKG;IACH,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAuBtC;;;;;;;;OAQG;IACH,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;CAS3C;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,qBAAqB,GAChC,wBAAwB,CAgB1B"}
@@ -1,15 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.StratumTypeOrmSubscriber = void 0;
4
+ exports.registerStratumSubscriber = registerStratumSubscriber;
4
5
  const sdk_1 = require("@stratum-hq/sdk");
5
6
  const utils_js_1 = require("../utils.js");
7
+ // TypeORM writes an upsert on MySQL as INSERT ... ON DUPLICATE KEY UPDATE and
8
+ // quotes each column with backticks.
9
+ const UPSERT_CLAUSE = /\bON\s+DUPLICATE\s+KEY\s+UPDATE\b/i;
10
+ const TENANT_ASSIGNMENT = /`tenant_id`\s*=/i;
6
11
  /**
7
12
  * TypeORM subscriber that injects tenant_id into inserted entities via ALS and
8
13
  * never lets an update change tenant_id.
9
14
  *
10
- * Register an instance after the data source is initialized:
11
- * `dataSource.subscribers.push(new StratumTypeOrmSubscriber())`. TypeORM's
12
- * `subscribers` option only loads classes decorated with `@EventSubscriber()`.
15
+ * Register it with `registerStratumSubscriber(dataSource)` after
16
+ * `dataSource.initialize()`. TypeORM's `subscribers` option only loads classes
17
+ * decorated with `@EventSubscriber()`, so it does not load this class.
13
18
  *
14
19
  * Known limitation: TypeORM subscribers cannot intercept query filtering.
15
20
  * This subscriber handles writes only. Use the shared-table adapter's
@@ -48,6 +53,44 @@ class StratumTypeOrmSubscriber {
48
53
  }
49
54
  }
50
55
  }
56
+ /**
57
+ * Rejects an upsert that writes tenant_id on a key conflict.
58
+ *
59
+ * A conflict update must never change the tenant of an existing row. A
60
+ * subscriber cannot remove one column from the conflict update, so the
61
+ * statement fails before it runs.
62
+ *
63
+ * @throws Error when the ON DUPLICATE KEY UPDATE clause assigns tenant_id.
64
+ */
65
+ beforeQuery(event) {
66
+ const clause = event.query.split(UPSERT_CLAUSE)[1];
67
+ if (clause !== undefined && TENANT_ASSIGNMENT.test(clause)) {
68
+ throw new Error("Stratum: an upsert must not update tenant_id on conflict. " +
69
+ "Remove tenant_id from the entity values or from the orUpdate() columns.");
70
+ }
71
+ }
51
72
  }
52
73
  exports.StratumTypeOrmSubscriber = StratumTypeOrmSubscriber;
74
+ /**
75
+ * Returns the one StratumTypeOrmSubscriber on the data source, and adds it first when it is missing.
76
+ *
77
+ * A second call returns the subscriber that the first call added, so the
78
+ * data source never runs the subscriber twice.
79
+ *
80
+ * @param dataSource - An initialized TypeORM `DataSource`.
81
+ * @throws Error when the data source is not initialized. `initialize()` replaces
82
+ * the subscriber list, so an earlier registration has no effect.
83
+ */
84
+ function registerStratumSubscriber(dataSource) {
85
+ if (!dataSource.isInitialized) {
86
+ throw new Error("Stratum: call registerStratumSubscriber() after dataSource.initialize(). " +
87
+ "initialize() replaces the subscriber list.");
88
+ }
89
+ const existing = dataSource.subscribers.find((subscriber) => subscriber instanceof StratumTypeOrmSubscriber);
90
+ if (existing)
91
+ return existing;
92
+ const subscriber = new StratumTypeOrmSubscriber();
93
+ dataSource.subscribers.push(subscriber);
94
+ return subscriber;
95
+ }
53
96
  //# sourceMappingURL=typeorm-subscriber.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"typeorm-subscriber.js","sourceRoot":"","sources":["../../src/integrations/typeorm-subscriber.ts"],"names":[],"mappings":";;;AAAA,yCAAmD;AACnD,0CAA6C;AAqB7C;;;;;;;;;;;GAWG;AACH,MAAa,wBAAwB;IACnC,qEAAqE;IACrE,YAAY,CAAC,KAAkB;QAC7B,MAAM,OAAO,GAAG,IAAA,sBAAgB,GAAE,CAAC;QACnC,IAAA,yBAAc,EAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAClC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;IAChD,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,KAAkB;QAC7B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,MAAM,WAAW,GAAG,IAAI,GAAG,CACzB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,WAAW,CAAC,CACvE,CAAC;QACF,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC;YACnD,IAAI,MAAM,CAAC,YAAY,CAAC,WAAW,EAAE,KAAK,WAAW,IAAI,MAAM,CAAC,YAAY,IAAI,MAAM,EAAE,CAAC;gBACvF,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC;YACpC,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,EAAE,CAAC;gBAC7B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;CACF;AApCD,4DAoCC"}
1
+ {"version":3,"file":"typeorm-subscriber.js","sourceRoot":"","sources":["../../src/integrations/typeorm-subscriber.ts"],"names":[],"mappings":";;;AAsHA,8DAkBC;AAxID,yCAAmD;AACnD,0CAA6C;AAiC7C,8EAA8E;AAC9E,qCAAqC;AACrC,MAAM,aAAa,GAAG,oCAAoC,CAAC;AAC3D,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AAE7C;;;;;;;;;;;GAWG;AACH,MAAa,wBAAwB;IACnC,qEAAqE;IACrE,YAAY,CAAC,KAAkB;QAC7B,MAAM,OAAO,GAAG,IAAA,sBAAgB,GAAE,CAAC;QACnC,IAAA,yBAAc,EAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAClC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;IAChD,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,KAAkB;QAC7B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,MAAM,WAAW,GAAG,IAAI,GAAG,CACzB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,WAAW,CAAC,CACvE,CAAC;QACF,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC;YACnD,IAAI,MAAM,CAAC,YAAY,CAAC,WAAW,EAAE,KAAK,WAAW,IAAI,MAAM,CAAC,YAAY,IAAI,MAAM,EAAE,CAAC;gBACvF,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC;YACpC,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,EAAE,CAAC;gBAC7B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,WAAW,CAAC,KAAuB;QACjC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QACnD,IAAI,MAAM,KAAK,SAAS,IAAI,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CACb,4DAA4D;gBAC1D,yEAAyE,CAC5E,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AAvDD,4DAuDC;AAED;;;;;;;;;GASG;AACH,SAAgB,yBAAyB,CACvC,UAAiC;IAEjC,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,2EAA2E;YACzE,4CAA4C,CAC/C,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC,IAAI,CAC1C,CAAC,UAAU,EAA0C,EAAE,CACrD,UAAU,YAAY,wBAAwB,CACjD,CAAC;IACF,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,UAAU,GAAG,IAAI,wBAAwB,EAAE,CAAC;IAClD,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACxC,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -10,7 +10,8 @@ import type { MysqlPoolLike, MysqlPoolManagerOptions } from "./types.js";
10
10
  */
11
11
  export declare class MysqlPoolManager {
12
12
  private readonly pools;
13
- private readonly pending;
13
+ /** Pools that closePool or closeAll removed while a caller held them, by slug. */
14
+ private readonly closedEntries;
14
15
  private readonly createPool;
15
16
  private readonly baseUri;
16
17
  private readonly maxPools;
@@ -38,8 +39,17 @@ export declare class MysqlPoolManager {
38
39
  getStats(): {
39
40
  poolCount: number;
40
41
  };
41
- /** Evicts the pool that has been idle the longest and has no active references. */
42
- private evictLRU;
42
+ /** Keeps a removed pool that callers still hold, so that their releases do not reach a later pool for the slug. */
43
+ private recordClosedHolds;
44
+ /** Stops tracking a removed pool after its last hold ends. */
45
+ private forgetClosedIfReleased;
46
+ /** Ends the evicted pool first, then creates the pool for the slug. */
47
+ private openPool;
48
+ /**
49
+ * Removes the least-recently-used pool that no caller holds from the map and
50
+ * returns its entry. The caller ends it. Returns undefined when every pool is held.
51
+ */
52
+ private takeLRU;
43
53
  /** Closes pools that have been idle longer than idleTimeoutMs and have no active references. */
44
54
  private closeIdlePools;
45
55
  /** Builds the MySQL connection URI with the given database name. */
@@ -1 +1 @@
1
- {"version":3,"file":"pool-manager.d.ts","sourceRoot":"","sources":["../src/pool-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AASzE;;;;;;;;GAQG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkD;IAC1E,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0D;IACrF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;IAC3D,0EAA0E;IAC1E,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAqB;gBAEpC,OAAO,EAAE,uBAAuB;IAgB5C;;;;OAIG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAwCnD;;;OAGG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQ/B,0EAA0E;IACpE,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5C,2FAA2F;IACrF,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAO/B,qDAAqD;IACrD,QAAQ,IAAI;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE;IAIjC,mFAAmF;YACrE,QAAQ;IAgBtB,gGAAgG;YAClF,cAAc;IAa5B,oEAAoE;IACpE,OAAO,CAAC,QAAQ;CAYjB"}
1
+ {"version":3,"file":"pool-manager.d.ts","sourceRoot":"","sources":["../src/pool-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAUzE;;;;;;;;GAQG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAC3D,kFAAkF;IAClF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA0C;IACxE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0D;IACrF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;IAC3D,0EAA0E;IAC1E,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAqB;gBAEpC,OAAO,EAAE,uBAAuB;IAgB5C;;;;OAIG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA2BnD;;;OAGG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAqB/B,0EAA0E;IACpE,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ5C,2FAA2F;IACrF,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ/B,qDAAqD;IACrD,QAAQ,IAAI;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE;IAIjC,mHAAmH;IACnH,OAAO,CAAC,iBAAiB;IAUzB,8DAA8D;IAC9D,OAAO,CAAC,sBAAsB;IAO9B,uEAAuE;YACzD,QAAQ;IAOtB;;;OAGG;IACH,OAAO,CAAC,OAAO;IAiBf,gGAAgG;YAClF,cAAc;IAe5B,oEAAoE;IACpE,OAAO,CAAC,QAAQ;CAYjB"}
@@ -13,7 +13,8 @@ const core_1 = require("@stratum-hq/core");
13
13
  */
14
14
  class MysqlPoolManager {
15
15
  pools = new Map();
16
- pending = new Map();
16
+ /** Pools that closePool or closeAll removed while a caller held them, by slug. */
17
+ closedEntries = new Map();
17
18
  createPool;
18
19
  baseUri;
19
20
  maxPools;
@@ -41,37 +42,28 @@ class MysqlPoolManager {
41
42
  */
42
43
  async getPool(slug) {
43
44
  (0, core_1.validateSlug)(slug);
44
- const existing = this.pools.get(slug);
45
- if (existing) {
46
- existing.lastUsed = Date.now();
47
- existing.refCount++;
48
- return existing.pool;
45
+ // The lookup, the eviction choice and the insert run with no await between
46
+ // them. Thus a concurrent call for the same slug always finds this entry and
47
+ // waits for the same pool.
48
+ let entry = this.pools.get(slug);
49
+ if (!entry) {
50
+ const victim = this.pools.size >= this.maxPools ? this.takeLRU() : undefined;
51
+ entry = { ready: this.openPool(slug, victim), lastUsed: Date.now(), refCount: 0 };
52
+ this.pools.set(slug, entry);
49
53
  }
50
- // Deduplicate concurrent creation requests for the same slug.
51
- const inflight = this.pending.get(slug);
52
- if (inflight) {
53
- const pool = await inflight;
54
- const entry = this.pools.get(slug);
55
- if (entry) {
56
- entry.refCount++;
57
- }
58
- return pool;
59
- }
60
- // Evict before adding so we never exceed maxPools.
61
- if (this.pools.size >= this.maxPools) {
62
- await this.evictLRU();
63
- }
64
- const dbName = `stratum_tenant_${slug}`;
65
- const uri = this.buildUri(dbName);
66
- const createPromise = Promise.resolve(this.createPool(uri));
67
- this.pending.set(slug, createPromise);
54
+ entry.lastUsed = Date.now();
55
+ entry.refCount++;
68
56
  try {
69
- const pool = await createPromise;
70
- this.pools.set(slug, { pool, lastUsed: Date.now(), refCount: 1 });
71
- return pool;
57
+ return await entry.ready;
72
58
  }
73
- finally {
74
- this.pending.delete(slug);
59
+ catch (err) {
60
+ // Remove the failed entry so that the next call tries again. The caller
61
+ // gets no pool, so it will not call releasePool.
62
+ if (this.pools.get(slug) === entry)
63
+ this.pools.delete(slug);
64
+ entry.refCount--;
65
+ this.forgetClosedIfReleased(slug, entry);
66
+ throw err;
75
67
  }
76
68
  }
77
69
  /**
@@ -79,12 +71,24 @@ class MysqlPoolManager {
79
71
  * No-op if the slug is not tracked.
80
72
  */
81
73
  releasePool(slug) {
74
+ // The caller passes a slug, not the pool, so the manager cannot tell a
75
+ // hold on a closed pool from a hold on its replacement. It ends holds on
76
+ // closed pools first. The replacement then counts as held for longer than
77
+ // it is, which is safe: eviction never ends a pool in use.
78
+ const closed = this.closedEntries.get(slug)?.values().next().value;
79
+ if (closed) {
80
+ closed.refCount--;
81
+ this.forgetClosedIfReleased(slug, closed);
82
+ return;
83
+ }
82
84
  const entry = this.pools.get(slug);
83
85
  if (!entry)
84
86
  return;
85
87
  if (entry.refCount > 0) {
86
88
  entry.refCount--;
87
89
  }
90
+ // The idle timeout counts from the end of the last use, not from its start.
91
+ entry.lastUsed = Date.now();
88
92
  }
89
93
  /** Closes and removes the pool for the given slug. No-op if not found. */
90
94
  async closePool(slug) {
@@ -92,21 +96,55 @@ class MysqlPoolManager {
92
96
  if (!entry)
93
97
  return;
94
98
  this.pools.delete(slug);
95
- await entry.pool.end();
99
+ this.recordClosedHolds(slug, entry);
100
+ await endEntry(entry);
96
101
  }
97
102
  /** Closes all managed pools and stops the idle timer. Call during application shutdown. */
98
103
  async closeAll() {
99
104
  clearInterval(this.idleTimer);
100
105
  const entries = Array.from(this.pools.entries());
101
106
  this.pools.clear();
102
- await Promise.all(entries.map(([, entry]) => entry.pool.end()));
107
+ for (const [slug, entry] of entries)
108
+ this.recordClosedHolds(slug, entry);
109
+ await Promise.all(entries.map(([, entry]) => endEntry(entry)));
103
110
  }
104
111
  /** Returns a snapshot of current pool statistics. */
105
112
  getStats() {
106
113
  return { poolCount: this.pools.size };
107
114
  }
108
- /** Evicts the pool that has been idle the longest and has no active references. */
109
- async evictLRU() {
115
+ /** Keeps a removed pool that callers still hold, so that their releases do not reach a later pool for the slug. */
116
+ recordClosedHolds(slug, entry) {
117
+ if (entry.refCount === 0)
118
+ return;
119
+ let closed = this.closedEntries.get(slug);
120
+ if (!closed) {
121
+ closed = new Set();
122
+ this.closedEntries.set(slug, closed);
123
+ }
124
+ closed.add(entry);
125
+ }
126
+ /** Stops tracking a removed pool after its last hold ends. */
127
+ forgetClosedIfReleased(slug, entry) {
128
+ const closed = this.closedEntries.get(slug);
129
+ if (!closed || entry.refCount > 0)
130
+ return;
131
+ closed.delete(entry);
132
+ if (closed.size === 0)
133
+ this.closedEntries.delete(slug);
134
+ }
135
+ /** Ends the evicted pool first, then creates the pool for the slug. */
136
+ async openPool(slug, victim) {
137
+ // The evicted pool belongs to a different tenant. Its end error must not
138
+ // fail this request.
139
+ if (victim)
140
+ await endEntry(victim).catch(() => undefined);
141
+ return this.createPool(this.buildUri(`stratum_tenant_${slug}`));
142
+ }
143
+ /**
144
+ * Removes the least-recently-used pool that no caller holds from the map and
145
+ * returns its entry. The caller ends it. Returns undefined when every pool is held.
146
+ */
147
+ takeLRU() {
110
148
  let oldestKey;
111
149
  let oldestTime = Infinity;
112
150
  for (const [key, entry] of this.pools.entries()) {
@@ -115,9 +153,11 @@ class MysqlPoolManager {
115
153
  oldestKey = key;
116
154
  }
117
155
  }
118
- if (oldestKey !== undefined) {
119
- await this.closePool(oldestKey);
120
- }
156
+ if (oldestKey === undefined)
157
+ return undefined;
158
+ const entry = this.pools.get(oldestKey);
159
+ this.pools.delete(oldestKey);
160
+ return entry;
121
161
  }
122
162
  /** Closes pools that have been idle longer than idleTimeoutMs and have no active references. */
123
163
  async closeIdlePools() {
@@ -128,7 +168,9 @@ class MysqlPoolManager {
128
168
  toClose.push(key);
129
169
  }
130
170
  }
131
- await Promise.all(toClose.map((slug) => this.closePool(slug)));
171
+ // The timer awaits nothing, so a rejection here would be unhandled. One
172
+ // pool that fails to end must not stop the others from closing.
173
+ await Promise.allSettled(toClose.map((slug) => this.closePool(slug)));
132
174
  }
133
175
  /** Builds the MySQL connection URI with the given database name. */
134
176
  buildUri(dbName) {
@@ -146,4 +188,9 @@ class MysqlPoolManager {
146
188
  }
147
189
  }
148
190
  exports.MysqlPoolManager = MysqlPoolManager;
191
+ /** Ends the entry's pool. A pool that failed to be created has nothing to end. */
192
+ async function endEntry(entry) {
193
+ const pool = await entry.ready.catch(() => undefined);
194
+ await pool?.end();
195
+ }
149
196
  //# sourceMappingURL=pool-manager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pool-manager.js","sourceRoot":"","sources":["../src/pool-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pool-manager.js","sourceRoot":"","sources":["../src/pool-manager.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stratum-hq/mysql",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "MySQL tenant isolation for Stratum — shared table, table-per-tenant, and database-per-tenant strategies",
5
5
  "keywords": [
6
6
  "multi-tenancy",
@@ -38,12 +38,14 @@
38
38
  "clean": "rm -rf dist"
39
39
  },
40
40
  "dependencies": {
41
- "@stratum-hq/core": "*",
42
- "@stratum-hq/sdk": "*"
41
+ "@stratum-hq/core": "^1.4.0",
42
+ "@stratum-hq/sdk": "^1.2.0"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "mysql2": "^3.0.0",
46
- "knex": ">=3.0.0"
46
+ "knex": ">=3.0.0",
47
+ "typeorm": "^1.0.0",
48
+ "sequelize": "^6.0.0"
47
49
  },
48
50
  "peerDependenciesMeta": {
49
51
  "typeorm": {