@stratum-hq/db-adapters 0.4.0 → 1.1.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.
Files changed (76) hide show
  1. package/README.md +22 -4
  2. package/dist/adapters/database-prisma.d.ts +4 -2
  3. package/dist/adapters/database-prisma.d.ts.map +1 -1
  4. package/dist/adapters/database-prisma.js +19 -6
  5. package/dist/adapters/database-prisma.js.map +1 -1
  6. package/dist/adapters/drizzle.d.ts +2 -2
  7. package/dist/adapters/drizzle.d.ts.map +1 -1
  8. package/dist/adapters/drizzle.js +9 -8
  9. package/dist/adapters/drizzle.js.map +1 -1
  10. package/dist/adapters/prisma.d.ts +1 -1
  11. package/dist/adapters/prisma.d.ts.map +1 -1
  12. package/dist/adapters/prisma.js +12 -5
  13. package/dist/adapters/prisma.js.map +1 -1
  14. package/dist/adapters/schema-prisma.d.ts +36 -4
  15. package/dist/adapters/schema-prisma.d.ts.map +1 -1
  16. package/dist/adapters/schema-prisma.js +55 -17
  17. package/dist/adapters/schema-prisma.js.map +1 -1
  18. package/dist/adapters/schema-raw.d.ts +14 -3
  19. package/dist/adapters/schema-raw.d.ts.map +1 -1
  20. package/dist/adapters/schema-raw.js +9 -5
  21. package/dist/adapters/schema-raw.js.map +1 -1
  22. package/dist/database/manager.d.ts.map +1 -1
  23. package/dist/database/manager.js +7 -1
  24. package/dist/database/manager.js.map +1 -1
  25. package/dist/database/pool-manager.d.ts.map +1 -1
  26. package/dist/database/pool-manager.js +2 -3
  27. package/dist/database/pool-manager.js.map +1 -1
  28. package/dist/index.d.ts +5 -4
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +6 -6
  31. package/dist/index.js.map +1 -1
  32. package/dist/schema/manager.d.ts +1 -0
  33. package/dist/schema/manager.d.ts.map +1 -1
  34. package/dist/schema/manager.js +11 -2
  35. package/dist/schema/manager.js.map +1 -1
  36. package/dist/schema/session.d.ts +10 -1
  37. package/dist/schema/session.d.ts.map +1 -1
  38. package/dist/schema/session.js +24 -4
  39. package/dist/schema/session.js.map +1 -1
  40. package/package.json +10 -2
  41. package/dist/__tests__/base-adapter.test.d.ts +0 -2
  42. package/dist/__tests__/base-adapter.test.d.ts.map +0 -1
  43. package/dist/__tests__/base-adapter.test.js +0 -194
  44. package/dist/__tests__/base-adapter.test.js.map +0 -1
  45. package/dist/__tests__/database-manager.test.d.ts +0 -2
  46. package/dist/__tests__/database-manager.test.d.ts.map +0 -1
  47. package/dist/__tests__/database-manager.test.js +0 -110
  48. package/dist/__tests__/database-manager.test.js.map +0 -1
  49. package/dist/__tests__/drizzle.test.d.ts +0 -2
  50. package/dist/__tests__/drizzle.test.d.ts.map +0 -1
  51. package/dist/__tests__/drizzle.test.js +0 -177
  52. package/dist/__tests__/drizzle.test.js.map +0 -1
  53. package/dist/__tests__/pool-manager.test.d.ts +0 -2
  54. package/dist/__tests__/pool-manager.test.d.ts.map +0 -1
  55. package/dist/__tests__/pool-manager.test.js +0 -171
  56. package/dist/__tests__/pool-manager.test.js.map +0 -1
  57. package/dist/__tests__/rls-manager.test.d.ts +0 -2
  58. package/dist/__tests__/rls-manager.test.d.ts.map +0 -1
  59. package/dist/__tests__/rls-manager.test.js +0 -180
  60. package/dist/__tests__/rls-manager.test.js.map +0 -1
  61. package/dist/__tests__/rls-session.test.d.ts +0 -2
  62. package/dist/__tests__/rls-session.test.d.ts.map +0 -1
  63. package/dist/__tests__/rls-session.test.js +0 -97
  64. package/dist/__tests__/rls-session.test.js.map +0 -1
  65. package/dist/__tests__/schema-manager.test.d.ts +0 -2
  66. package/dist/__tests__/schema-manager.test.d.ts.map +0 -1
  67. package/dist/__tests__/schema-manager.test.js +0 -116
  68. package/dist/__tests__/schema-manager.test.js.map +0 -1
  69. package/dist/__tests__/schema-session.test.d.ts +0 -2
  70. package/dist/__tests__/schema-session.test.d.ts.map +0 -1
  71. package/dist/__tests__/schema-session.test.js +0 -23
  72. package/dist/__tests__/schema-session.test.js.map +0 -1
  73. package/dist/__tests__/sequelize.test.d.ts +0 -2
  74. package/dist/__tests__/sequelize.test.d.ts.map +0 -1
  75. package/dist/__tests__/sequelize.test.js +0 -150
  76. package/dist/__tests__/sequelize.test.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,19 +1,20 @@
1
1
  export { BaseAdapter } from "./base-adapter.js";
2
2
  export { RawAdapter, createTenantPool } from "./adapters/raw.js";
3
- export { PrismaAdapter, withTenant } from "./adapters/prisma.js";
3
+ export { PrismaAdapter, withTenant as prismaWithTenant } from "./adapters/prisma.js";
4
4
  export { SchemaRawAdapter, createSchemaTenantPool, } from "./adapters/schema-raw.js";
5
+ export type { SchemaAdapterOptions } from "./adapters/schema-raw.js";
5
6
  export { SchemaPrismaAdapter, withSchemaTenant, } from "./adapters/schema-prisma.js";
6
7
  export { createPolicy, dropPolicy, enableRLS, disableRLS, isRLSEnabled, } from "./rls/manager.js";
7
8
  export { setTenantContext, resetTenantContext, withTenantContext, withRlsBypass, getCurrentTenantId, } from "./rls/session.js";
8
9
  export { createSchema, dropSchema, schemaExists, listTenantSchemas, replicateTableToSchema, tenantSchemaName, } from "./schema/manager.js";
9
10
  export { setSchemaSearchPath, resetSearchPath, getCurrentSearchPath, } from "./schema/session.js";
10
- export { addTenantColumn, enableRLS as enableRLSMigration, createIsolationPolicy, migrateTable, } from "./migration-helpers.js";
11
+ export { addTenantColumn, enableRLS as enableRLSForMigration, createIsolationPolicy, migrateTable, } from "./migration-helpers.js";
11
12
  export { getDatabaseName, databaseExists, createDatabase, dropDatabase, } from "./database/manager.js";
12
13
  export { DatabasePoolManager } from "./database/pool-manager.js";
13
14
  export type { DatabasePoolManagerOptions } from "./database/pool-manager.js";
14
15
  export { DatabaseRawAdapter } from "./adapters/database-raw.js";
15
16
  export { DatabasePrismaAdapter } from "./adapters/database-prisma.js";
16
- export { SequelizeAdapter, withTenantScope } from "./adapters/sequelize.js";
17
- export { DrizzleAdapter, withTenant as withDrizzleTenant, withTenantScope as withDrizzleTenantScope, } from "./adapters/drizzle.js";
17
+ export { SequelizeAdapter, withTenantScope as sequelizeWithTenantScope } from "./adapters/sequelize.js";
18
+ export { DrizzleAdapter, withTenant as drizzleWithTenant, withTenantScope as drizzleWithTenantScope, } from "./adapters/drizzle.js";
18
19
  export type { DrizzleLike } from "./adapters/drizzle.js";
19
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EACL,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,YAAY,EACZ,UAAU,EACV,SAAS,EACT,UAAU,EACV,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,eAAe,EACf,SAAS,IAAI,kBAAkB,EAC/B,qBAAqB,EACrB,YAAY,GACb,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,eAAe,EACf,cAAc,EACd,cAAc,EACd,YAAY,GACb,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,YAAY,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAE7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EACL,cAAc,EACd,UAAU,IAAI,iBAAiB,EAC/B,eAAe,IAAI,sBAAsB,GAC1C,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,UAAU,IAAI,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,EACL,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EACL,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,YAAY,EACZ,UAAU,EACV,SAAS,EACT,UAAU,EACV,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,eAAe,EACf,SAAS,IAAI,qBAAqB,EAClC,qBAAqB,EACrB,YAAY,GACb,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,eAAe,EACf,cAAc,EACd,cAAc,EACd,YAAY,GACb,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,YAAY,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAE7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,eAAe,IAAI,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxG,OAAO,EACL,cAAc,EACd,UAAU,IAAI,iBAAiB,EAC/B,eAAe,IAAI,sBAAsB,GAC1C,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.withDrizzleTenantScope = exports.withDrizzleTenant = exports.DrizzleAdapter = exports.withTenantScope = exports.SequelizeAdapter = exports.DatabasePrismaAdapter = exports.DatabaseRawAdapter = exports.DatabasePoolManager = exports.dropDatabase = exports.createDatabase = exports.databaseExists = exports.getDatabaseName = exports.migrateTable = exports.createIsolationPolicy = exports.enableRLSMigration = exports.addTenantColumn = exports.getCurrentSearchPath = exports.resetSearchPath = exports.setSchemaSearchPath = exports.tenantSchemaName = exports.replicateTableToSchema = exports.listTenantSchemas = exports.schemaExists = exports.dropSchema = exports.createSchema = exports.getCurrentTenantId = exports.withRlsBypass = exports.withTenantContext = exports.resetTenantContext = exports.setTenantContext = exports.isRLSEnabled = exports.disableRLS = exports.enableRLS = exports.dropPolicy = exports.createPolicy = exports.withSchemaTenant = exports.SchemaPrismaAdapter = exports.createSchemaTenantPool = exports.SchemaRawAdapter = exports.withTenant = exports.PrismaAdapter = exports.createTenantPool = exports.RawAdapter = exports.BaseAdapter = void 0;
3
+ exports.drizzleWithTenantScope = exports.drizzleWithTenant = exports.DrizzleAdapter = exports.sequelizeWithTenantScope = exports.SequelizeAdapter = exports.DatabasePrismaAdapter = exports.DatabaseRawAdapter = exports.DatabasePoolManager = exports.dropDatabase = exports.createDatabase = exports.databaseExists = exports.getDatabaseName = exports.migrateTable = exports.createIsolationPolicy = exports.enableRLSForMigration = exports.addTenantColumn = exports.getCurrentSearchPath = exports.resetSearchPath = exports.setSchemaSearchPath = exports.tenantSchemaName = exports.replicateTableToSchema = exports.listTenantSchemas = exports.schemaExists = exports.dropSchema = exports.createSchema = exports.getCurrentTenantId = exports.withRlsBypass = exports.withTenantContext = exports.resetTenantContext = exports.setTenantContext = exports.isRLSEnabled = exports.disableRLS = exports.enableRLS = exports.dropPolicy = exports.createPolicy = exports.withSchemaTenant = exports.SchemaPrismaAdapter = exports.createSchemaTenantPool = exports.SchemaRawAdapter = exports.prismaWithTenant = exports.PrismaAdapter = exports.createTenantPool = exports.RawAdapter = exports.BaseAdapter = void 0;
4
4
  var base_adapter_js_1 = require("./base-adapter.js");
5
5
  Object.defineProperty(exports, "BaseAdapter", { enumerable: true, get: function () { return base_adapter_js_1.BaseAdapter; } });
6
6
  var raw_js_1 = require("./adapters/raw.js");
@@ -8,7 +8,7 @@ Object.defineProperty(exports, "RawAdapter", { enumerable: true, get: function (
8
8
  Object.defineProperty(exports, "createTenantPool", { enumerable: true, get: function () { return raw_js_1.createTenantPool; } });
9
9
  var prisma_js_1 = require("./adapters/prisma.js");
10
10
  Object.defineProperty(exports, "PrismaAdapter", { enumerable: true, get: function () { return prisma_js_1.PrismaAdapter; } });
11
- Object.defineProperty(exports, "withTenant", { enumerable: true, get: function () { return prisma_js_1.withTenant; } });
11
+ Object.defineProperty(exports, "prismaWithTenant", { enumerable: true, get: function () { return prisma_js_1.withTenant; } });
12
12
  var schema_raw_js_1 = require("./adapters/schema-raw.js");
13
13
  Object.defineProperty(exports, "SchemaRawAdapter", { enumerable: true, get: function () { return schema_raw_js_1.SchemaRawAdapter; } });
14
14
  Object.defineProperty(exports, "createSchemaTenantPool", { enumerable: true, get: function () { return schema_raw_js_1.createSchemaTenantPool; } });
@@ -40,7 +40,7 @@ Object.defineProperty(exports, "resetSearchPath", { enumerable: true, get: funct
40
40
  Object.defineProperty(exports, "getCurrentSearchPath", { enumerable: true, get: function () { return session_js_2.getCurrentSearchPath; } });
41
41
  var migration_helpers_js_1 = require("./migration-helpers.js");
42
42
  Object.defineProperty(exports, "addTenantColumn", { enumerable: true, get: function () { return migration_helpers_js_1.addTenantColumn; } });
43
- Object.defineProperty(exports, "enableRLSMigration", { enumerable: true, get: function () { return migration_helpers_js_1.enableRLS; } });
43
+ Object.defineProperty(exports, "enableRLSForMigration", { enumerable: true, get: function () { return migration_helpers_js_1.enableRLS; } });
44
44
  Object.defineProperty(exports, "createIsolationPolicy", { enumerable: true, get: function () { return migration_helpers_js_1.createIsolationPolicy; } });
45
45
  Object.defineProperty(exports, "migrateTable", { enumerable: true, get: function () { return migration_helpers_js_1.migrateTable; } });
46
46
  // DB_PER_TENANT isolation
@@ -57,9 +57,9 @@ var database_prisma_js_1 = require("./adapters/database-prisma.js");
57
57
  Object.defineProperty(exports, "DatabasePrismaAdapter", { enumerable: true, get: function () { return database_prisma_js_1.DatabasePrismaAdapter; } });
58
58
  var sequelize_js_1 = require("./adapters/sequelize.js");
59
59
  Object.defineProperty(exports, "SequelizeAdapter", { enumerable: true, get: function () { return sequelize_js_1.SequelizeAdapter; } });
60
- Object.defineProperty(exports, "withTenantScope", { enumerable: true, get: function () { return sequelize_js_1.withTenantScope; } });
60
+ Object.defineProperty(exports, "sequelizeWithTenantScope", { enumerable: true, get: function () { return sequelize_js_1.withTenantScope; } });
61
61
  var drizzle_js_1 = require("./adapters/drizzle.js");
62
62
  Object.defineProperty(exports, "DrizzleAdapter", { enumerable: true, get: function () { return drizzle_js_1.DrizzleAdapter; } });
63
- Object.defineProperty(exports, "withDrizzleTenant", { enumerable: true, get: function () { return drizzle_js_1.withTenant; } });
64
- Object.defineProperty(exports, "withDrizzleTenantScope", { enumerable: true, get: function () { return drizzle_js_1.withTenantScope; } });
63
+ Object.defineProperty(exports, "drizzleWithTenant", { enumerable: true, get: function () { return drizzle_js_1.withTenant; } });
64
+ Object.defineProperty(exports, "drizzleWithTenantScope", { enumerable: true, get: function () { return drizzle_js_1.withTenantScope; } });
65
65
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,qDAAgD;AAAvC,8GAAA,WAAW,OAAA;AAEpB,4CAAiE;AAAxD,oGAAA,UAAU,OAAA;AAAE,0GAAA,gBAAgB,OAAA;AACrC,kDAAiE;AAAxD,0GAAA,aAAa,OAAA;AAAE,uGAAA,UAAU,OAAA;AAClC,0DAGkC;AAFhC,iHAAA,gBAAgB,OAAA;AAChB,uHAAA,sBAAsB,OAAA;AAExB,gEAGqC;AAFnC,uHAAA,mBAAmB,OAAA;AACnB,oHAAA,gBAAgB,OAAA;AAGlB,+CAM0B;AALxB,0GAAA,YAAY,OAAA;AACZ,wGAAA,UAAU,OAAA;AACV,uGAAA,SAAS,OAAA;AACT,wGAAA,UAAU,OAAA;AACV,0GAAA,YAAY,OAAA;AAGd,+CAM0B;AALxB,8GAAA,gBAAgB,OAAA;AAChB,gHAAA,kBAAkB,OAAA;AAClB,+GAAA,iBAAiB,OAAA;AACjB,2GAAA,aAAa,OAAA;AACb,gHAAA,kBAAkB,OAAA;AAGpB,kDAO6B;AAN3B,0GAAA,YAAY,OAAA;AACZ,wGAAA,UAAU,OAAA;AACV,0GAAA,YAAY,OAAA;AACZ,+GAAA,iBAAiB,OAAA;AACjB,oHAAA,sBAAsB,OAAA;AACtB,8GAAA,gBAAgB,OAAA;AAGlB,kDAI6B;AAH3B,iHAAA,mBAAmB,OAAA;AACnB,6GAAA,eAAe,OAAA;AACf,kHAAA,oBAAoB,OAAA;AAGtB,+DAKgC;AAJ9B,uHAAA,eAAe,OAAA;AACf,0HAAA,SAAS,OAAsB;AAC/B,6HAAA,qBAAqB,OAAA;AACrB,oHAAA,YAAY,OAAA;AAGd,0BAA0B;AAC1B,oDAK+B;AAJ7B,6GAAA,eAAe,OAAA;AACf,4GAAA,cAAc,OAAA;AACd,4GAAA,cAAc,OAAA;AACd,0GAAA,YAAY,OAAA;AAGd,8DAAiE;AAAxD,sHAAA,mBAAmB,OAAA;AAG5B,8DAAgE;AAAvD,qHAAA,kBAAkB,OAAA;AAC3B,oEAAsE;AAA7D,2HAAA,qBAAqB,OAAA;AAC9B,wDAA4E;AAAnE,gHAAA,gBAAgB,OAAA;AAAE,+GAAA,eAAe,OAAA;AAC1C,oDAI+B;AAH7B,4GAAA,cAAc,OAAA;AACd,+GAAA,UAAU,OAAqB;AAC/B,oHAAA,eAAe,OAA0B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,qDAAgD;AAAvC,8GAAA,WAAW,OAAA;AAEpB,4CAAiE;AAAxD,oGAAA,UAAU,OAAA;AAAE,0GAAA,gBAAgB,OAAA;AACrC,kDAAqF;AAA5E,0GAAA,aAAa,OAAA;AAAE,6GAAA,UAAU,OAAoB;AACtD,0DAGkC;AAFhC,iHAAA,gBAAgB,OAAA;AAChB,uHAAA,sBAAsB,OAAA;AAGxB,gEAGqC;AAFnC,uHAAA,mBAAmB,OAAA;AACnB,oHAAA,gBAAgB,OAAA;AAGlB,+CAM0B;AALxB,0GAAA,YAAY,OAAA;AACZ,wGAAA,UAAU,OAAA;AACV,uGAAA,SAAS,OAAA;AACT,wGAAA,UAAU,OAAA;AACV,0GAAA,YAAY,OAAA;AAGd,+CAM0B;AALxB,8GAAA,gBAAgB,OAAA;AAChB,gHAAA,kBAAkB,OAAA;AAClB,+GAAA,iBAAiB,OAAA;AACjB,2GAAA,aAAa,OAAA;AACb,gHAAA,kBAAkB,OAAA;AAGpB,kDAO6B;AAN3B,0GAAA,YAAY,OAAA;AACZ,wGAAA,UAAU,OAAA;AACV,0GAAA,YAAY,OAAA;AACZ,+GAAA,iBAAiB,OAAA;AACjB,oHAAA,sBAAsB,OAAA;AACtB,8GAAA,gBAAgB,OAAA;AAGlB,kDAI6B;AAH3B,iHAAA,mBAAmB,OAAA;AACnB,6GAAA,eAAe,OAAA;AACf,kHAAA,oBAAoB,OAAA;AAGtB,+DAKgC;AAJ9B,uHAAA,eAAe,OAAA;AACf,6HAAA,SAAS,OAAyB;AAClC,6HAAA,qBAAqB,OAAA;AACrB,oHAAA,YAAY,OAAA;AAGd,0BAA0B;AAC1B,oDAK+B;AAJ7B,6GAAA,eAAe,OAAA;AACf,4GAAA,cAAc,OAAA;AACd,4GAAA,cAAc,OAAA;AACd,0GAAA,YAAY,OAAA;AAGd,8DAAiE;AAAxD,sHAAA,mBAAmB,OAAA;AAG5B,8DAAgE;AAAvD,qHAAA,kBAAkB,OAAA;AAC3B,oEAAsE;AAA7D,2HAAA,qBAAqB,OAAA;AAC9B,wDAAwG;AAA/F,gHAAA,gBAAgB,OAAA;AAAE,wHAAA,eAAe,OAA4B;AACtE,oDAI+B;AAH7B,4GAAA,cAAc,OAAA;AACd,+GAAA,UAAU,OAAqB;AAC/B,oHAAA,eAAe,OAA0B"}
@@ -1,4 +1,5 @@
1
1
  import pg from "pg";
2
+ export declare function validateSchemaName(schemaName: string): string;
2
3
  export declare function tenantSchemaName(tenantSlug: string): string;
3
4
  export declare function createSchema(client: pg.PoolClient, tenantSlug: string): Promise<void>;
4
5
  export declare function dropSchema(client: pg.PoolClient, tenantSlug: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/schema/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAkBpB,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,EAAE,CAAC,UAAU,EACrB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,EAAE,CAAC,UAAU,EACrB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,EAAE,CAAC,UAAU,EACrB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,EAAE,CAAC,UAAU,GACpB,OAAO,CAAC,MAAM,EAAE,CAAC,CAKnB;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,EAAE,CAAC,UAAU,EACrB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAMf"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/schema/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAGpB,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAK7D;AAaD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAQ3D;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,EAAE,CAAC,UAAU,EACrB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAKf;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,EAAE,CAAC,UAAU,EACrB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,EAAE,CAAC,UAAU,EACrB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,EAAE,CAAC,UAAU,GACpB,OAAO,CAAC,MAAM,EAAE,CAAC,CAKnB;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,EAAE,CAAC,UAAU,EACrB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAMf"}
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateSchemaName = validateSchemaName;
3
4
  exports.tenantSchemaName = tenantSchemaName;
4
5
  exports.createSchema = createSchema;
5
6
  exports.dropSchema = dropSchema;
@@ -20,12 +21,20 @@ function validateTableName(tableName) {
20
21
  }
21
22
  return tableName;
22
23
  }
24
+ // PostgreSQL silently truncates identifiers longer than this many bytes.
25
+ const MAX_IDENTIFIER_BYTES = 63;
23
26
  function tenantSchemaName(tenantSlug) {
24
- return `tenant_${tenantSlug}`;
27
+ const schemaName = `tenant_${tenantSlug}`;
28
+ if (Buffer.byteLength(schemaName) > MAX_IDENTIFIER_BYTES) {
29
+ throw new Error(`Schema name for tenant slug "${tenantSlug}" exceeds ${MAX_IDENTIFIER_BYTES} bytes`);
30
+ }
31
+ return schemaName;
25
32
  }
26
33
  async function createSchema(client, tenantSlug) {
27
34
  const schemaName = validateSchemaName(tenantSchemaName(tenantSlug));
28
- await client.query(`CREATE SCHEMA IF NOT EXISTS ${schemaName}`);
35
+ // No IF NOT EXISTS: an existing schema may hold another tenant's data, so
36
+ // provisioning must fail rather than adopt it.
37
+ await client.query(`CREATE SCHEMA ${schemaName}`);
29
38
  }
30
39
  async function dropSchema(client, tenantSlug) {
31
40
  const schemaName = validateSchemaName(tenantSchemaName(tenantSlug));
@@ -1 +1 @@
1
- {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/schema/manager.ts"],"names":[],"mappings":";;AAkBA,4CAEC;AAED,oCAMC;AAED,gCAMC;AAED,oCAUC;AAED,8CAOC;AAED,wDAUC;AAnED,yFAAyF;AACzF,SAAS,kBAAkB,CAAC,UAAkB;IAC5C,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,wFAAwF;AACxF,SAAS,iBAAiB,CAAC,SAAiB;IAC1C,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,uBAAuB,SAAS,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAgB,gBAAgB,CAAC,UAAkB;IACjD,OAAO,UAAU,UAAU,EAAE,CAAC;AAChC,CAAC;AAEM,KAAK,UAAU,YAAY,CAChC,MAAqB,EACrB,UAAkB;IAElB,MAAM,UAAU,GAAG,kBAAkB,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC;IACpE,MAAM,MAAM,CAAC,KAAK,CAAC,+BAA+B,UAAU,EAAE,CAAC,CAAC;AAClE,CAAC;AAEM,KAAK,UAAU,UAAU,CAC9B,MAAqB,EACrB,UAAkB;IAElB,MAAM,UAAU,GAAG,kBAAkB,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC;IACpE,MAAM,MAAM,CAAC,KAAK,CAAC,yBAAyB,UAAU,UAAU,CAAC,CAAC;AACpE,CAAC;AAEM,KAAK,UAAU,YAAY,CAChC,MAAqB,EACrB,UAAkB;IAElB,MAAM,UAAU,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAC5B,sDAAsD,EACtD,CAAC,UAAU,CAAC,CACb,CAAC;IACF,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;AAC7C,CAAC;AAEM,KAAK,UAAU,iBAAiB,CACrC,MAAqB;IAErB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAC5B,iFAAiF,CAClF,CAAC;IACF,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC;AAEM,KAAK,UAAU,sBAAsB,CAC1C,MAAqB,EACrB,SAAiB,EACjB,UAAkB;IAElB,MAAM,SAAS,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAClD,MAAM,MAAM,CAAC,KAAK,CAChB,8BAA8B,UAAU,IAAI,SAAS,iBAAiB,SAAS,iBAAiB,CACjG,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/schema/manager.ts"],"names":[],"mappings":";;AAGA,gDAKC;AAaD,4CAQC;AAED,oCAQC;AAED,gCAMC;AAED,oCAUC;AAED,8CAOC;AAED,wDAUC;AA9ED,yFAAyF;AACzF,SAAgB,kBAAkB,CAAC,UAAkB;IACnD,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,wFAAwF;AACxF,SAAS,iBAAiB,CAAC,SAAiB;IAC1C,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,uBAAuB,SAAS,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,yEAAyE;AACzE,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEhC,SAAgB,gBAAgB,CAAC,UAAkB;IACjD,MAAM,UAAU,GAAG,UAAU,UAAU,EAAE,CAAC;IAC1C,IAAI,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,oBAAoB,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CACb,gCAAgC,UAAU,aAAa,oBAAoB,QAAQ,CACpF,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAEM,KAAK,UAAU,YAAY,CAChC,MAAqB,EACrB,UAAkB;IAElB,MAAM,UAAU,GAAG,kBAAkB,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC;IACpE,0EAA0E;IAC1E,+CAA+C;IAC/C,MAAM,MAAM,CAAC,KAAK,CAAC,iBAAiB,UAAU,EAAE,CAAC,CAAC;AACpD,CAAC;AAEM,KAAK,UAAU,UAAU,CAC9B,MAAqB,EACrB,UAAkB;IAElB,MAAM,UAAU,GAAG,kBAAkB,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC;IACpE,MAAM,MAAM,CAAC,KAAK,CAAC,yBAAyB,UAAU,UAAU,CAAC,CAAC;AACpE,CAAC;AAEM,KAAK,UAAU,YAAY,CAChC,MAAqB,EACrB,UAAkB;IAElB,MAAM,UAAU,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAC5B,sDAAsD,EACtD,CAAC,UAAU,CAAC,CACb,CAAC;IACF,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;AAC7C,CAAC;AAEM,KAAK,UAAU,iBAAiB,CACrC,MAAqB;IAErB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAC5B,iFAAiF,CAClF,CAAC;IACF,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC;AAEM,KAAK,UAAU,sBAAsB,CAC1C,MAAqB,EACrB,SAAiB,EACjB,UAAkB;IAElB,MAAM,SAAS,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAClD,MAAM,MAAM,CAAC,KAAK,CAChB,8BAA8B,UAAU,IAAI,SAAS,iBAAiB,SAAS,iBAAiB,CACjG,CAAC;AACJ,CAAC"}
@@ -1,5 +1,14 @@
1
1
  import pg from "pg";
2
- export declare function setSchemaSearchPath(client: pg.PoolClient, tenantSlug: string): Promise<void>;
2
+ /**
3
+ * Builds the search_path list for a tenant: the tenant schema first, then any
4
+ * explicitly opted-in extra schemas (for example one holding extension
5
+ * functions). Every extra entry is validated as a plain identifier, the same
6
+ * way tenant schema names are. Note that an unqualified table missing from the
7
+ * tenant schema resolves in the extra schemas, so list only schemas that hold
8
+ * no tenant data.
9
+ */
10
+ export declare function tenantSearchPath(schemaName: string, extraSearchPath?: string[]): string;
11
+ export declare function setSchemaSearchPath(client: pg.PoolClient, tenantSlug: string, extraSearchPath?: string[]): Promise<void>;
3
12
  export declare function resetSearchPath(client: pg.PoolClient): Promise<void>;
4
13
  export declare function getCurrentSearchPath(client: pg.PoolClient): Promise<string>;
5
14
  //# sourceMappingURL=session.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/schema/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAIpB,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,EAAE,CAAC,UAAU,EACrB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1E;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,EAAE,CAAC,UAAU,GACpB,OAAO,CAAC,MAAM,CAAC,CAGjB"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/schema/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAIpB;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,eAAe,GAAE,MAAM,EAAO,GAAG,MAAM,CAE3F;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,EAAE,CAAC,UAAU,EACrB,UAAU,EAAE,MAAM,EAClB,eAAe,GAAE,MAAM,EAAO,GAC7B,OAAO,CAAC,IAAI,CAAC,CAef;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1E;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,EAAE,CAAC,UAAU,GACpB,OAAO,CAAC,MAAM,CAAC,CAGjB"}
@@ -1,17 +1,37 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tenantSearchPath = tenantSearchPath;
3
4
  exports.setSchemaSearchPath = setSchemaSearchPath;
4
5
  exports.resetSearchPath = resetSearchPath;
5
6
  exports.getCurrentSearchPath = getCurrentSearchPath;
6
7
  const core_1 = require("@stratum-hq/core");
7
8
  const manager_js_1 = require("./manager.js");
8
- async function setSchemaSearchPath(client, tenantSlug) {
9
+ /**
10
+ * Builds the search_path list for a tenant: the tenant schema first, then any
11
+ * explicitly opted-in extra schemas (for example one holding extension
12
+ * functions). Every extra entry is validated as a plain identifier, the same
13
+ * way tenant schema names are. Note that an unqualified table missing from the
14
+ * tenant schema resolves in the extra schemas, so list only schemas that hold
15
+ * no tenant data.
16
+ */
17
+ function tenantSearchPath(schemaName, extraSearchPath = []) {
18
+ return [schemaName, ...extraSearchPath.map(manager_js_1.validateSchemaName)].join(", ");
19
+ }
20
+ async function setSchemaSearchPath(client, tenantSlug, extraSearchPath = []) {
9
21
  // The schema name is interpolated (identifiers cannot be bound), so the slug
10
22
  // must be validated against the canonical slug charset first; validateSlug
11
23
  // throws on anything else. SET LOCAL only takes effect for the current
12
- // transaction.
13
- const schemaName = (0, manager_js_1.tenantSchemaName)((0, core_1.validateSlug)(tenantSlug));
14
- await client.query(`SET LOCAL search_path TO ${schemaName}, public`);
24
+ // transaction. The path is the tenant schema alone (pg_catalog is always
25
+ // searched), so a table missing from it errors instead of resolving to a
26
+ // shared table in public. Extra schemas are appended only when opted in.
27
+ const searchPath = tenantSearchPath((0, manager_js_1.tenantSchemaName)((0, core_1.validateSlug)(tenantSlug)), extraSearchPath);
28
+ await client.query(`SET LOCAL search_path TO ${searchPath}`);
29
+ // Outside a transaction SET LOCAL is a no-op with only a warning. SHOW
30
+ // reports unquoted identifiers folded to lower case.
31
+ const res = await client.query("SHOW search_path");
32
+ if (res.rows[0].search_path !== searchPath.toLowerCase()) {
33
+ throw new Error("setSchemaSearchPath must be called inside a transaction");
34
+ }
15
35
  }
16
36
  async function resetSearchPath(client) {
17
37
  await client.query("RESET search_path");
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/schema/session.ts"],"names":[],"mappings":";;AAIA,kDAUC;AAED,0CAEC;AAED,oDAKC;AAxBD,2CAAgD;AAChD,6CAAgD;AAEzC,KAAK,UAAU,mBAAmB,CACvC,MAAqB,EACrB,UAAkB;IAElB,6EAA6E;IAC7E,2EAA2E;IAC3E,uEAAuE;IACvE,eAAe;IACf,MAAM,UAAU,GAAG,IAAA,6BAAgB,EAAC,IAAA,mBAAY,EAAC,UAAU,CAAC,CAAC,CAAC;IAC9D,MAAM,MAAM,CAAC,KAAK,CAAC,4BAA4B,UAAU,UAAU,CAAC,CAAC;AACvE,CAAC;AAEM,KAAK,UAAU,eAAe,CAAC,MAAqB;IACzD,MAAM,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;AAC1C,CAAC;AAEM,KAAK,UAAU,oBAAoB,CACxC,MAAqB;IAErB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAA0B,kBAAkB,CAAC,CAAC;IAC5E,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/schema/session.ts"],"names":[],"mappings":";;AAYA,4CAEC;AAED,kDAmBC;AAED,0CAEC;AAED,oDAKC;AA7CD,2CAAgD;AAChD,6CAAoE;AAEpE;;;;;;;GAOG;AACH,SAAgB,gBAAgB,CAAC,UAAkB,EAAE,kBAA4B,EAAE;IACjF,OAAO,CAAC,UAAU,EAAE,GAAG,eAAe,CAAC,GAAG,CAAC,+BAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7E,CAAC;AAEM,KAAK,UAAU,mBAAmB,CACvC,MAAqB,EACrB,UAAkB,EAClB,kBAA4B,EAAE;IAE9B,6EAA6E;IAC7E,2EAA2E;IAC3E,uEAAuE;IACvE,yEAAyE;IACzE,yEAAyE;IACzE,yEAAyE;IACzE,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAA,6BAAgB,EAAC,IAAA,mBAAY,EAAC,UAAU,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC;IACjG,MAAM,MAAM,CAAC,KAAK,CAAC,4BAA4B,UAAU,EAAE,CAAC,CAAC;IAC7D,uEAAuE;IACvE,qDAAqD;IACrD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAA0B,kBAAkB,CAAC,CAAC;IAC5E,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,KAAK,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,eAAe,CAAC,MAAqB;IACzD,MAAM,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;AAC1C,CAAC;AAEM,KAAK,UAAU,oBAAoB,CACxC,MAAqB;IAErB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAA0B,kBAAkB,CAAC,CAAC;IAC5E,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;AACjC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stratum-hq/db-adapters",
3
- "version": "0.4.0",
3
+ "version": "1.1.0",
4
4
  "description": "Stratum PostgreSQL adapters for tenant-scoped query isolation",
5
5
  "keywords": [
6
6
  "multi-tenancy",
@@ -55,8 +55,16 @@
55
55
  "devDependencies": {
56
56
  "@prisma/client": "^5.10.0",
57
57
  "@types/pg": "^8.11.0",
58
+ "drizzle-orm": "^0.45.3",
58
59
  "typescript": "^5.4.0",
59
- "vitest": "^1.6.0"
60
+ "vitest": "^4.1.11"
61
+ },
62
+ "license": "MIT",
63
+ "author": "Christian Crank",
64
+ "homepage": "https://github.com/stratum-hq/Stratum/tree/main/packages/db-adapters#readme",
65
+ "bugs": "https://github.com/stratum-hq/Stratum/issues",
66
+ "engines": {
67
+ "node": ">=20.0.0"
60
68
  },
61
69
  "repository": {
62
70
  "type": "git",
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=base-adapter.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"base-adapter.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/base-adapter.test.ts"],"names":[],"mappings":""}
@@ -1,194 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
- const base_adapter_js_1 = require("../base-adapter.js");
5
- // ---------------------------------------------------------------------------
6
- // Mock pg
7
- // ---------------------------------------------------------------------------
8
- const mockQuery = vitest_1.vi.fn();
9
- const mockRelease = vitest_1.vi.fn();
10
- const mockConnect = vitest_1.vi.fn();
11
- // Create a mock Pool class that will be used directly
12
- class MockPool {
13
- connect = mockConnect;
14
- }
15
- vitest_1.vi.mock("pg", () => {
16
- return { default: { Pool: MockPool }, Pool: MockPool };
17
- });
18
- // ---------------------------------------------------------------------------
19
- // Concrete subclass for testing the abstract BaseAdapter
20
- // ---------------------------------------------------------------------------
21
- class TestAdapter extends base_adapter_js_1.BaseAdapter {
22
- // Expose executeWithTenantContext publicly for testing
23
- async runWithTenant(tenantId, fn) {
24
- return this.executeWithTenantContext(tenantId, fn);
25
- }
26
- }
27
- // ---------------------------------------------------------------------------
28
- // Helpers
29
- // ---------------------------------------------------------------------------
30
- function makeMockClient() {
31
- const client = {
32
- query: mockQuery,
33
- release: mockRelease,
34
- };
35
- return client;
36
- }
37
- // ---------------------------------------------------------------------------
38
- // Tests
39
- // ---------------------------------------------------------------------------
40
- (0, vitest_1.describe)("BaseAdapter", () => {
41
- let adapter;
42
- (0, vitest_1.beforeEach)(() => {
43
- vitest_1.vi.clearAllMocks();
44
- const mockClient = makeMockClient();
45
- mockConnect.mockResolvedValue(mockClient);
46
- mockQuery.mockResolvedValue({ rows: [] });
47
- const pool = new MockPool();
48
- adapter = new TestAdapter(pool);
49
- });
50
- (0, vitest_1.describe)("executeWithTenantContext", () => {
51
- (0, vitest_1.it)("acquires a client from the pool", async () => {
52
- await adapter.runWithTenant("tenant-1", async () => "result");
53
- (0, vitest_1.expect)(mockConnect).toHaveBeenCalledTimes(1);
54
- });
55
- (0, vitest_1.it)("begins a transaction", async () => {
56
- await adapter.runWithTenant("tenant-1", async () => "result");
57
- (0, vitest_1.expect)(mockQuery).toHaveBeenCalledWith("BEGIN");
58
- });
59
- (0, vitest_1.it)("sets tenant context with correct SQL and parameters", async () => {
60
- await adapter.runWithTenant("tenant-abc", async () => "ok");
61
- (0, vitest_1.expect)(mockQuery).toHaveBeenCalledWith("SELECT set_config('app.current_tenant_id', $1, true)", ["tenant-abc"]);
62
- });
63
- (0, vitest_1.it)("executes the provided query function", async () => {
64
- const queryFn = vitest_1.vi.fn().mockResolvedValue("my-result");
65
- await adapter.runWithTenant("tenant-1", queryFn);
66
- (0, vitest_1.expect)(queryFn).toHaveBeenCalledTimes(1);
67
- });
68
- (0, vitest_1.it)("passes the client to the query function", async () => {
69
- const queryFn = vitest_1.vi.fn().mockResolvedValue("ok");
70
- await adapter.runWithTenant("tenant-1", queryFn);
71
- // The queryFn receives the mock client
72
- const passedClient = queryFn.mock.calls[0][0];
73
- (0, vitest_1.expect)(passedClient.query).toBeDefined();
74
- (0, vitest_1.expect)(passedClient.release).toBeDefined();
75
- });
76
- (0, vitest_1.it)("commits the transaction on success", async () => {
77
- await adapter.runWithTenant("tenant-1", async () => "ok");
78
- const queryCalls = mockQuery.mock.calls.map((c) => c[0]);
79
- (0, vitest_1.expect)(queryCalls).toContain("COMMIT");
80
- });
81
- (0, vitest_1.it)("returns the result from the query function", async () => {
82
- const result = await adapter.runWithTenant("tenant-1", async () => ({ data: [1, 2, 3] }));
83
- (0, vitest_1.expect)(result).toEqual({ data: [1, 2, 3] });
84
- });
85
- (0, vitest_1.it)("executes in the correct order: BEGIN, set_config, queryFn, COMMIT", async () => {
86
- const callOrder = [];
87
- mockQuery.mockImplementation(async (sql) => {
88
- if (typeof sql === "string") {
89
- if (sql === "BEGIN")
90
- callOrder.push("BEGIN");
91
- else if (sql.includes("set_config"))
92
- callOrder.push("SET_CONFIG");
93
- else if (sql === "COMMIT")
94
- callOrder.push("COMMIT");
95
- else if (sql === "ROLLBACK")
96
- callOrder.push("ROLLBACK");
97
- else if (sql === "RESET app.current_tenant_id")
98
- callOrder.push("RESET");
99
- }
100
- return { rows: [] };
101
- });
102
- await adapter.runWithTenant("tenant-1", async () => {
103
- callOrder.push("QUERY_FN");
104
- return "done";
105
- });
106
- (0, vitest_1.expect)(callOrder).toEqual([
107
- "BEGIN",
108
- "SET_CONFIG",
109
- "QUERY_FN",
110
- "COMMIT",
111
- "RESET",
112
- ]);
113
- });
114
- (0, vitest_1.it)("rolls back on error from query function", async () => {
115
- const error = new Error("query failed");
116
- await (0, vitest_1.expect)(adapter.runWithTenant("tenant-1", async () => {
117
- throw error;
118
- })).rejects.toThrow("query failed");
119
- (0, vitest_1.expect)(mockQuery).toHaveBeenCalledWith("ROLLBACK");
120
- });
121
- (0, vitest_1.it)("does not commit when query function throws", async () => {
122
- try {
123
- await adapter.runWithTenant("tenant-1", async () => {
124
- throw new Error("fail");
125
- });
126
- }
127
- catch {
128
- // expected
129
- }
130
- const queryCalls = mockQuery.mock.calls.map((c) => c[0]);
131
- (0, vitest_1.expect)(queryCalls).not.toContain("COMMIT");
132
- });
133
- (0, vitest_1.it)("resets tenant context in finally block on success", async () => {
134
- await adapter.runWithTenant("tenant-1", async () => "ok");
135
- (0, vitest_1.expect)(mockQuery).toHaveBeenCalledWith("RESET app.current_tenant_id");
136
- });
137
- (0, vitest_1.it)("resets tenant context in finally block on error", async () => {
138
- try {
139
- await adapter.runWithTenant("tenant-1", async () => {
140
- throw new Error("boom");
141
- });
142
- }
143
- catch {
144
- // expected
145
- }
146
- (0, vitest_1.expect)(mockQuery).toHaveBeenCalledWith("RESET app.current_tenant_id");
147
- });
148
- (0, vitest_1.it)("releases the client on success", async () => {
149
- await adapter.runWithTenant("tenant-1", async () => "ok");
150
- (0, vitest_1.expect)(mockRelease).toHaveBeenCalledTimes(1);
151
- });
152
- (0, vitest_1.it)("releases the client on error", async () => {
153
- try {
154
- await adapter.runWithTenant("tenant-1", async () => {
155
- throw new Error("fail");
156
- });
157
- }
158
- catch {
159
- // expected
160
- }
161
- (0, vitest_1.expect)(mockRelease).toHaveBeenCalledTimes(1);
162
- });
163
- (0, vitest_1.it)("still releases client if RESET query fails", async () => {
164
- let callCount = 0;
165
- mockQuery.mockImplementation(async (sql) => {
166
- callCount++;
167
- if (typeof sql === "string" && sql.includes("RESET")) {
168
- throw new Error("connection broken");
169
- }
170
- return { rows: [] };
171
- });
172
- await adapter.runWithTenant("tenant-1", async () => "ok");
173
- // Client should still be released even though RESET threw
174
- (0, vitest_1.expect)(mockRelease).toHaveBeenCalledTimes(1);
175
- });
176
- (0, vitest_1.it)("propagates the original error even if ROLLBACK fails", async () => {
177
- mockQuery.mockImplementation(async (sql) => {
178
- if (typeof sql === "string" && sql === "ROLLBACK") {
179
- throw new Error("rollback failed");
180
- }
181
- return { rows: [] };
182
- });
183
- // The queryFn throws — we want the original error, but ROLLBACK also throws.
184
- // In the current implementation, ROLLBACK failure replaces the original error
185
- // because there's no catch around ROLLBACK. Let's verify behavior:
186
- await (0, vitest_1.expect)(adapter.runWithTenant("tenant-1", async () => {
187
- throw new Error("original error");
188
- })).rejects.toThrow();
189
- // Client should still be released
190
- (0, vitest_1.expect)(mockRelease).toHaveBeenCalledTimes(1);
191
- });
192
- });
193
- });
194
- //# sourceMappingURL=base-adapter.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"base-adapter.test.js","sourceRoot":"","sources":["../../src/__tests__/base-adapter.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=database-manager.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"database-manager.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/database-manager.test.ts"],"names":[],"mappings":""}
@@ -1,110 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
- const manager_js_1 = require("../database/manager.js");
5
- // ---------------------------------------------------------------------------
6
- // getDatabaseName
7
- // ---------------------------------------------------------------------------
8
- (0, vitest_1.describe)("getDatabaseName", () => {
9
- (0, vitest_1.it)("returns correct name for a simple slug", () => {
10
- (0, vitest_1.expect)((0, manager_js_1.getDatabaseName)("acme")).toBe("stratum_tenant_acme");
11
- });
12
- (0, vitest_1.it)("handles slugs with numbers and underscores", () => {
13
- (0, vitest_1.expect)((0, manager_js_1.getDatabaseName)("acme_corp_2")).toBe("stratum_tenant_acme_corp_2");
14
- });
15
- (0, vitest_1.it)("throws on slug with hyphens", () => {
16
- (0, vitest_1.expect)(() => (0, manager_js_1.getDatabaseName)("acme-corp")).toThrow(/Invalid tenant slug/);
17
- });
18
- (0, vitest_1.it)("throws on slug starting with a number", () => {
19
- (0, vitest_1.expect)(() => (0, manager_js_1.getDatabaseName)("1acme")).toThrow(/Invalid tenant slug/);
20
- });
21
- (0, vitest_1.it)("throws on empty slug", () => {
22
- (0, vitest_1.expect)(() => (0, manager_js_1.getDatabaseName)("")).toThrow(/Invalid tenant slug/);
23
- });
24
- (0, vitest_1.it)("throws on slug with uppercase letters", () => {
25
- (0, vitest_1.expect)(() => (0, manager_js_1.getDatabaseName)("Acme")).toThrow(/Invalid tenant slug/);
26
- });
27
- (0, vitest_1.it)("throws on slug that is too long (> 63 chars)", () => {
28
- // 64 chars: 'a' + 63 'x'
29
- const longSlug = "a" + "x".repeat(63);
30
- (0, vitest_1.expect)(() => (0, manager_js_1.getDatabaseName)(longSlug)).toThrow(/Invalid tenant slug/);
31
- });
32
- (0, vitest_1.it)("accepts maximum-length slug (63 chars)", () => {
33
- const maxSlug = "a" + "x".repeat(62); // 63 chars total
34
- (0, vitest_1.expect)((0, manager_js_1.getDatabaseName)(maxSlug)).toBe(`stratum_tenant_${maxSlug}`);
35
- });
36
- });
37
- // ---------------------------------------------------------------------------
38
- // databaseExists
39
- // ---------------------------------------------------------------------------
40
- (0, vitest_1.describe)("databaseExists", () => {
41
- function makeClient(exists) {
42
- return {
43
- query: vitest_1.vi.fn().mockResolvedValue({ rows: [{ exists }] }),
44
- };
45
- }
46
- (0, vitest_1.it)("returns true when database exists", async () => {
47
- const client = makeClient(true);
48
- const result = await (0, manager_js_1.databaseExists)(client, "acme");
49
- (0, vitest_1.expect)(result).toBe(true);
50
- (0, vitest_1.expect)(client.query).toHaveBeenCalledWith(vitest_1.expect.stringContaining("pg_database"), ["stratum_tenant_acme"]);
51
- });
52
- (0, vitest_1.it)("returns false when database does not exist", async () => {
53
- const client = makeClient(false);
54
- const result = await (0, manager_js_1.databaseExists)(client, "acme");
55
- (0, vitest_1.expect)(result).toBe(false);
56
- });
57
- (0, vitest_1.it)("throws on invalid slug", async () => {
58
- const client = makeClient(false);
59
- await (0, vitest_1.expect)((0, manager_js_1.databaseExists)(client, "bad-slug")).rejects.toThrow(/Invalid tenant slug/);
60
- });
61
- });
62
- // ---------------------------------------------------------------------------
63
- // createDatabase
64
- // ---------------------------------------------------------------------------
65
- (0, vitest_1.describe)("createDatabase", () => {
66
- function makeClient() {
67
- return {
68
- query: vitest_1.vi.fn().mockResolvedValue({}),
69
- };
70
- }
71
- (0, vitest_1.it)("issues CREATE DATABASE with correct name", async () => {
72
- const client = makeClient();
73
- await (0, manager_js_1.createDatabase)(client, "acme");
74
- (0, vitest_1.expect)(client.query).toHaveBeenCalledWith('CREATE DATABASE "stratum_tenant_acme"');
75
- });
76
- (0, vitest_1.it)("includes TEMPLATE clause when templateDb is provided", async () => {
77
- const client = makeClient();
78
- await (0, manager_js_1.createDatabase)(client, "acme", "stratum_base");
79
- (0, vitest_1.expect)(client.query).toHaveBeenCalledWith('CREATE DATABASE "stratum_tenant_acme" TEMPLATE "stratum_base"');
80
- });
81
- (0, vitest_1.it)("throws on invalid template database name", async () => {
82
- const client = makeClient();
83
- await (0, vitest_1.expect)((0, manager_js_1.createDatabase)(client, "acme", "bad-template!")).rejects.toThrow(/Invalid template database name/);
84
- (0, vitest_1.expect)(client.query).not.toHaveBeenCalled();
85
- });
86
- (0, vitest_1.it)("throws on invalid slug", async () => {
87
- const client = makeClient();
88
- await (0, vitest_1.expect)((0, manager_js_1.createDatabase)(client, "bad-slug")).rejects.toThrow(/Invalid tenant slug/);
89
- });
90
- });
91
- // ---------------------------------------------------------------------------
92
- // dropDatabase
93
- // ---------------------------------------------------------------------------
94
- (0, vitest_1.describe)("dropDatabase", () => {
95
- function makeClient() {
96
- return {
97
- query: vitest_1.vi.fn().mockResolvedValue({}),
98
- };
99
- }
100
- (0, vitest_1.it)("issues DROP DATABASE IF EXISTS with correct name", async () => {
101
- const client = makeClient();
102
- await (0, manager_js_1.dropDatabase)(client, "acme");
103
- (0, vitest_1.expect)(client.query).toHaveBeenCalledWith('DROP DATABASE IF EXISTS "stratum_tenant_acme"');
104
- });
105
- (0, vitest_1.it)("throws on invalid slug", async () => {
106
- const client = makeClient();
107
- await (0, vitest_1.expect)((0, manager_js_1.dropDatabase)(client, "bad slug")).rejects.toThrow(/Invalid tenant slug/);
108
- });
109
- });
110
- //# sourceMappingURL=database-manager.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"database-manager.test.js","sourceRoot":"","sources":["../../src/__tests__/database-manager.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=drizzle.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"drizzle.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/drizzle.test.ts"],"names":[],"mappings":""}