@stratum-hq/db-adapters 0.1.0 → 0.2.1
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/dist/__tests__/rls-session.test.js +7 -12
- package/dist/__tests__/rls-session.test.js.map +1 -1
- package/dist/adapters/prisma.js +2 -2
- package/dist/adapters/prisma.js.map +1 -1
- package/dist/adapters/raw.js +2 -2
- package/dist/adapters/raw.js.map +1 -1
- package/dist/adapters/schema-prisma.js +2 -2
- package/dist/adapters/schema-prisma.js.map +1 -1
- package/dist/adapters/schema-raw.js +2 -2
- package/dist/adapters/schema-raw.js.map +1 -1
- package/dist/database/manager.js +4 -5
- package/dist/database/manager.js.map +1 -1
- package/dist/migration-helpers.js +4 -5
- package/dist/migration-helpers.js.map +1 -1
- package/dist/rls/manager.js +5 -6
- package/dist/rls/manager.js.map +1 -1
- package/dist/rls/session.d.ts +1 -0
- package/dist/rls/session.d.ts.map +1 -1
- package/dist/rls/session.js +17 -6
- package/dist/rls/session.js.map +1 -1
- package/dist/schema/manager.js +6 -7
- package/dist/schema/manager.js.map +1 -1
- package/dist/schema/session.js +3 -4
- package/dist/schema/session.js.map +1 -1
- package/package.json +1 -1
|
@@ -25,7 +25,7 @@ function makeMockClient() {
|
|
|
25
25
|
(0, vitest_1.it)("sets the correct session variable via set_config", async () => {
|
|
26
26
|
await (0, session_js_1.setTenantContext)(client, "tenant-abc-123");
|
|
27
27
|
const call = client.query.mock.calls[0];
|
|
28
|
-
(0, vitest_1.expect)(call[0]).toBe("SELECT set_config('app.current_tenant_id', $1,
|
|
28
|
+
(0, vitest_1.expect)(call[0]).toBe("SELECT set_config('app.current_tenant_id', $1, false)");
|
|
29
29
|
(0, vitest_1.expect)(call[1]).toEqual(["tenant-abc-123"]);
|
|
30
30
|
});
|
|
31
31
|
(0, vitest_1.it)("passes the tenant ID as a parameterized value", async () => {
|
|
@@ -34,27 +34,22 @@ function makeMockClient() {
|
|
|
34
34
|
.calls[0][1];
|
|
35
35
|
(0, vitest_1.expect)(params).toEqual(["f47ac10b-58cc-4372-a567-0e02b2c3d479"]);
|
|
36
36
|
});
|
|
37
|
-
(0, vitest_1.it)("uses
|
|
37
|
+
(0, vitest_1.it)("uses session-level scope (third arg false)", async () => {
|
|
38
38
|
await (0, session_js_1.setTenantContext)(client, "any-tenant");
|
|
39
39
|
const sql = client.query.mock.calls[0][0];
|
|
40
|
-
// The third argument to set_config is `
|
|
41
|
-
(
|
|
40
|
+
// The third argument to set_config is `false`, meaning session-level
|
|
41
|
+
// (not transaction-local) so context persists even without a transaction
|
|
42
|
+
(0, vitest_1.expect)(sql).toContain("false");
|
|
42
43
|
});
|
|
43
44
|
});
|
|
44
45
|
// -----------------------------------------------------------------------
|
|
45
46
|
// resetTenantContext
|
|
46
47
|
// -----------------------------------------------------------------------
|
|
47
48
|
(0, vitest_1.describe)("resetTenantContext", () => {
|
|
48
|
-
(0, vitest_1.it)("resets the session variable", async () => {
|
|
49
|
+
(0, vitest_1.it)("resets the session variable via set_config with empty string", async () => {
|
|
49
50
|
await (0, session_js_1.resetTenantContext)(client);
|
|
50
51
|
const call = client.query.mock.calls[0];
|
|
51
|
-
(0, vitest_1.expect)(call[0]).toBe("
|
|
52
|
-
});
|
|
53
|
-
(0, vitest_1.it)("does not pass any parameters", async () => {
|
|
54
|
-
await (0, session_js_1.resetTenantContext)(client);
|
|
55
|
-
const call = client.query.mock.calls[0];
|
|
56
|
-
// Only the SQL string, no params array
|
|
57
|
-
(0, vitest_1.expect)(call).toHaveLength(1);
|
|
52
|
+
(0, vitest_1.expect)(call[0]).toBe("SELECT set_config('app.current_tenant_id', '', false)");
|
|
58
53
|
});
|
|
59
54
|
});
|
|
60
55
|
// -----------------------------------------------------------------------
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rls-session.test.js","sourceRoot":"","sources":["../../src/__tests__/rls-session.test.ts"],"names":[],"mappings":";;AAAA,mCAA8D;AAC9D,kDAI2B;AAE3B,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E,SAAS,cAAc;IACrB,OAAO;QACL,KAAK,EAAE,WAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;KACtB,CAAC;AAC1C,CAAC;AAED,8EAA8E;AAC9E,QAAQ;AACR,8EAA8E;AAE9E,IAAA,iBAAQ,EAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,IAAI,MAAyC,CAAC;IAE9C,IAAA,mBAAU,EAAC,GAAG,EAAE;QACd,MAAM,GAAG,cAAc,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,0EAA0E;IAC1E,mBAAmB;IACnB,0EAA0E;IAE1E,IAAA,iBAAQ,EAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,IAAA,WAAE,EAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,IAAA,6BAAgB,EAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;YAEjD,MAAM,IAAI,GAAI,MAAM,CAAC,KAAkC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACtE,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAClB,
|
|
1
|
+
{"version":3,"file":"rls-session.test.js","sourceRoot":"","sources":["../../src/__tests__/rls-session.test.ts"],"names":[],"mappings":";;AAAA,mCAA8D;AAC9D,kDAI2B;AAE3B,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E,SAAS,cAAc;IACrB,OAAO;QACL,KAAK,EAAE,WAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;KACtB,CAAC;AAC1C,CAAC;AAED,8EAA8E;AAC9E,QAAQ;AACR,8EAA8E;AAE9E,IAAA,iBAAQ,EAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,IAAI,MAAyC,CAAC;IAE9C,IAAA,mBAAU,EAAC,GAAG,EAAE;QACd,MAAM,GAAG,cAAc,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,0EAA0E;IAC1E,mBAAmB;IACnB,0EAA0E;IAE1E,IAAA,iBAAQ,EAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,IAAA,WAAE,EAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,IAAA,6BAAgB,EAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;YAEjD,MAAM,IAAI,GAAI,MAAM,CAAC,KAAkC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACtE,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAClB,uDAAuD,CACxD,CAAC;YACF,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,IAAA,6BAAgB,EAAC,MAAM,EAAE,sCAAsC,CAAC,CAAC;YAEvE,MAAM,MAAM,GAAI,MAAM,CAAC,KAAkC,CAAC,IAAI;iBAC3D,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACf,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,sCAAsC,CAAC,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;YAC1D,MAAM,IAAA,6BAAgB,EAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YAE7C,MAAM,GAAG,GAAI,MAAM,CAAC,KAAkC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxE,qEAAqE;YACrE,yEAAyE;YACzE,IAAA,eAAM,EAAC,GAAG,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,0EAA0E;IAC1E,qBAAqB;IACrB,0EAA0E;IAE1E,IAAA,iBAAQ,EAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,IAAA,WAAE,EAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;YAC5E,MAAM,IAAA,+BAAkB,EAAC,MAAM,CAAC,CAAC;YAEjC,MAAM,IAAI,GAAI,MAAM,CAAC,KAAkC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACtE,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;QAChF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,0EAA0E;IAC1E,qBAAqB;IACrB,0EAA0E;IAE1E,IAAA,iBAAQ,EAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,IAAA,WAAE,EAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,CAAC,KAAkC,CAAC,qBAAqB,CAAC;gBAC/D,IAAI,EAAE,CAAC,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;aAC1C,CAAC,CAAC;YAEH,MAAM,IAAA,+BAAkB,EAAC,MAAM,CAAC,CAAC;YAEjC,MAAM,GAAG,GAAI,MAAM,CAAC,KAAkC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxE,IAAA,eAAM,EAAC,GAAG,CAAC,CAAC,SAAS,CAAC,yCAAyC,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;YAC7C,MAAM,CAAC,KAAkC,CAAC,qBAAqB,CAAC;gBAC/D,IAAI,EAAE,CAAC,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;aAC1C,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,IAAA,+BAAkB,EAAC,MAAM,CAAC,CAAC;YAChD,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC5D,MAAM,CAAC,KAAkC,CAAC,qBAAqB,CAAC;gBAC/D,IAAI,EAAE,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;aAChC,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,IAAA,+BAAkB,EAAC,MAAM,CAAC,CAAC;YAChD,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,CAAC,KAAkC,CAAC,qBAAqB,CAAC;gBAC/D,IAAI,EAAE,EAAE;aACT,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,IAAA,+BAAkB,EAAC,MAAM,CAAC,CAAC;YAChD,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACxD,MAAM,CAAC,KAAkC,CAAC,qBAAqB,CAAC;gBAC/D,IAAI,EAAE,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;aAClC,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,IAAA,+BAAkB,EAAC,MAAM,CAAC,CAAC;YAChD,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/adapters/prisma.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.PrismaAdapter = void 0;
|
|
4
|
+
exports.withTenant = withTenant;
|
|
4
5
|
const base_adapter_js_1 = require("../base-adapter.js");
|
|
5
6
|
class PrismaAdapter extends base_adapter_js_1.BaseAdapter {
|
|
6
7
|
constructor(pool) {
|
|
@@ -25,5 +26,4 @@ function withTenant(prisma, contextFn, pool) {
|
|
|
25
26
|
const adapter = new PrismaAdapter(pool);
|
|
26
27
|
return adapter.withTenant(prisma, contextFn);
|
|
27
28
|
}
|
|
28
|
-
exports.withTenant = withTenant;
|
|
29
29
|
//# sourceMappingURL=prisma.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma.js","sourceRoot":"","sources":["../../src/adapters/prisma.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"prisma.js","sourceRoot":"","sources":["../../src/adapters/prisma.ts"],"names":[],"mappings":";;;AA+BA,gCAOC;AAtCD,wDAAiD;AAWjD,MAAa,aAAc,SAAQ,6BAAW;IAC5C,YAAY,IAAa;QACvB,KAAK,CAAC,IAAI,CAAC,CAAC;IACd,CAAC;IAED,UAAU,CAAC,MAAwB,EAAE,SAAuB;QAC1D,OAAO,MAAM,CAAC,QAAQ,CAAC;YACrB,KAAK,EAAE;gBACL,cAAc,CAAC,EAAE,IAAI,EAAE,KAAK,EAAiE;oBAC3F,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC;oBAC7B,OAAO,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,EAAoB,EAAE,EAAE;wBACxD,MAAM,EAAE,CAAC,WAAW,CAAA,8CAA8C,QAAQ,SAAS,CAAC;wBACpF,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC;oBACrB,CAAC,CAAC,CAAC;gBACL,CAAC;aACF;SACF,CAAC,CAAC;IACL,CAAC;CACF;AAlBD,sCAkBC;AAED,SAAgB,UAAU,CACxB,MAAwB,EACxB,SAAuB,EACvB,IAAa;IAEb,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAC/C,CAAC"}
|
package/dist/adapters/raw.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.RawAdapter = void 0;
|
|
4
|
+
exports.createTenantPool = createTenantPool;
|
|
4
5
|
const base_adapter_js_1 = require("../base-adapter.js");
|
|
5
6
|
class RawAdapter extends base_adapter_js_1.BaseAdapter {
|
|
6
7
|
constructor(pool) {
|
|
@@ -22,5 +23,4 @@ function createTenantPool(pool, contextFn) {
|
|
|
22
23
|
},
|
|
23
24
|
});
|
|
24
25
|
}
|
|
25
|
-
exports.createTenantPool = createTenantPool;
|
|
26
26
|
//# sourceMappingURL=raw.js.map
|
package/dist/adapters/raw.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raw.js","sourceRoot":"","sources":["../../src/adapters/raw.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"raw.js","sourceRoot":"","sources":["../../src/adapters/raw.ts"],"names":[],"mappings":";;;AAmBA,4CAcC;AAhCD,wDAAiD;AAEjD,MAAa,UAAW,SAAQ,6BAAW;IACzC,YAAY,IAAa;QACvB,KAAK,CAAC,IAAI,CAAC,CAAC;IACd,CAAC;IAED,KAAK,CAAC,KAAK,CACT,QAAgB,EAChB,IAAY,EACZ,MAAkB;QAElB,OAAO,IAAI,CAAC,wBAAwB,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE,CACxD,MAAM,CAAC,KAAK,CAAI,IAAI,EAAE,MAAM,CAAC,CAC9B,CAAC;IACJ,CAAC;CACF;AAdD,gCAcC;AAED,SAAgB,gBAAgB,CAC9B,IAAa,EACb,SAAuB;IAEvB,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE;QACxB,GAAG,CAAC,MAAM,EAAE,IAAI;YACd,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,OAAO,CAAC,IAAY,EAAE,MAAkB,EAAE,EAAE,CAC1C,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC5C,CAAC;YACD,OAAQ,MAAsD,CAAC,IAAI,CAAC,CAAC;QACvE,CAAC;KACF,CAAe,CAAC;AACnB,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.SchemaPrismaAdapter = void 0;
|
|
4
|
+
exports.withSchemaTenant = withSchemaTenant;
|
|
4
5
|
const manager_js_1 = require("../schema/manager.js");
|
|
5
6
|
// Validate slug to prevent SQL injection — slugs follow /^[a-z][a-z0-9_]{0,62}$/
|
|
6
7
|
function validateSlug(slug) {
|
|
@@ -31,5 +32,4 @@ function withSchemaTenant(prisma, contextFn) {
|
|
|
31
32
|
const adapter = new SchemaPrismaAdapter();
|
|
32
33
|
return adapter.withTenant(prisma, contextFn);
|
|
33
34
|
}
|
|
34
|
-
exports.withSchemaTenant = withSchemaTenant;
|
|
35
35
|
//# sourceMappingURL=schema-prisma.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-prisma.js","sourceRoot":"","sources":["../../src/adapters/schema-prisma.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"schema-prisma.js","sourceRoot":"","sources":["../../src/adapters/schema-prisma.ts"],"names":[],"mappings":";;;AA+CA,4CAMC;AArDD,qDAAwD;AAUxD,iFAAiF;AACjF,SAAS,YAAY,CAAC,IAAY;IAChC,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAa,mBAAmB;IAC9B,UAAU,CACR,MAAwB,EACxB,SAAuB;QAEvB,OAAO,MAAM,CAAC,QAAQ,CAAC;YACrB,KAAK,EAAE;gBACL,cAAc,CAAC,EACb,IAAI,EACJ,KAAK,GAIN;oBACC,MAAM,UAAU,GAAG,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC;oBAC7C,MAAM,UAAU,GAAG,IAAA,6BAAgB,EAAC,UAAU,CAAC,CAAC;oBAChD,OAAO,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,EAAoB,EAAE,EAAE;wBACxD,wEAAwE;wBACxE,MAAM,EAAE,CAAC,iBAAiB,CACxB,4BAA4B,UAAU,UAAU,CACjD,CAAC;wBACF,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC;oBACrB,CAAC,CAAC,CAAC;gBACL,CAAC;aACF;SACF,CAAC,CAAC;IACL,CAAC;CACF;AA3BD,kDA2BC;AAED,SAAgB,gBAAgB,CAC9B,MAAwB,EACxB,SAAuB;IAEvB,MAAM,OAAO,GAAG,IAAI,mBAAmB,EAAE,CAAC;IAC1C,OAAO,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.SchemaRawAdapter = void 0;
|
|
4
|
+
exports.createSchemaTenantPool = createSchemaTenantPool;
|
|
4
5
|
const manager_js_1 = require("../schema/manager.js");
|
|
5
6
|
const session_js_1 = require("../schema/session.js");
|
|
6
7
|
// Validate slug to prevent SQL injection — slugs follow /^[a-z][a-z0-9_]{0,62}$/
|
|
@@ -59,5 +60,4 @@ function createSchemaTenantPool(pool, contextFn) {
|
|
|
59
60
|
},
|
|
60
61
|
});
|
|
61
62
|
}
|
|
62
|
-
exports.createSchemaTenantPool = createSchemaTenantPool;
|
|
63
63
|
//# sourceMappingURL=schema-raw.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-raw.js","sourceRoot":"","sources":["../../src/adapters/schema-raw.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"schema-raw.js","sourceRoot":"","sources":["../../src/adapters/schema-raw.ts"],"names":[],"mappings":";;;AAsDA,wDAcC;AAnED,qDAAwD;AACxD,qDAAuD;AAEvD,iFAAiF;AACjF,6EAA6E;AAC7E,SAAS,YAAY,CAAC,IAAY;IAChC,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAa,gBAAgB;IACP;IAApB,YAAoB,IAAa;QAAb,SAAI,GAAJ,IAAI,CAAS;IAAG,CAAC;IAErC,KAAK,CAAC,KAAK,CACT,UAAkB,EAClB,IAAY,EACZ,MAAkB;QAElB,OAAO,IAAI,CAAC,wBAAwB,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAChE,OAAO,MAAM,CAAC,KAAK,CAAI,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,wBAAwB,CAC5B,UAAkB,EAClB,EAAyC;QAEzC,MAAM,IAAI,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;QACtC,MAAM,UAAU,GAAG,IAAA,6BAAgB,EAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5B,gFAAgF;YAChF,MAAM,MAAM,CAAC,KAAK,CAAC,4BAA4B,UAAU,UAAU,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;YAChC,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC7B,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC/B,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,MAAM,IAAA,4BAAe,EAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;CACF;AAvCD,4CAuCC;AAED,SAAgB,sBAAsB,CACpC,IAAa,EACb,SAAuB;IAEvB,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC3C,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE;QACxB,GAAG,CAAC,MAAM,EAAE,IAAI;YACd,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,OAAO,CAAC,IAAY,EAAE,MAAkB,EAAE,EAAE,CAC1C,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC5C,CAAC;YACD,OAAQ,MAAsD,CAAC,IAAI,CAAC,CAAC;QACvE,CAAC;KACF,CAAqB,CAAC;AACzB,CAAC"}
|
package/dist/database/manager.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getDatabaseName = getDatabaseName;
|
|
4
|
+
exports.databaseExists = databaseExists;
|
|
5
|
+
exports.createDatabase = createDatabase;
|
|
6
|
+
exports.dropDatabase = dropDatabase;
|
|
4
7
|
const SLUG_REGEX = /^[a-z][a-z0-9_]{0,62}$/;
|
|
5
8
|
const DB_PREFIX = "stratum_tenant_";
|
|
6
9
|
/**
|
|
@@ -21,7 +24,6 @@ function getDatabaseName(tenantSlug) {
|
|
|
21
24
|
validateSlug(tenantSlug);
|
|
22
25
|
return `${DB_PREFIX}${tenantSlug}`;
|
|
23
26
|
}
|
|
24
|
-
exports.getDatabaseName = getDatabaseName;
|
|
25
27
|
/**
|
|
26
28
|
* Checks whether the per-tenant database exists.
|
|
27
29
|
* Safe to run inside a transaction (uses pg_database catalog).
|
|
@@ -31,7 +33,6 @@ async function databaseExists(client, tenantSlug) {
|
|
|
31
33
|
const res = await client.query(`SELECT EXISTS(SELECT 1 FROM pg_database WHERE datname = $1) AS exists`, [dbName]);
|
|
32
34
|
return res.rows[0].exists;
|
|
33
35
|
}
|
|
34
|
-
exports.databaseExists = databaseExists;
|
|
35
36
|
/**
|
|
36
37
|
* Creates the per-tenant database.
|
|
37
38
|
*
|
|
@@ -53,7 +54,6 @@ async function createDatabase(client, tenantSlug, templateDb) {
|
|
|
53
54
|
}
|
|
54
55
|
await client.query(sql);
|
|
55
56
|
}
|
|
56
|
-
exports.createDatabase = createDatabase;
|
|
57
57
|
/**
|
|
58
58
|
* Drops the per-tenant database if it exists.
|
|
59
59
|
*
|
|
@@ -64,5 +64,4 @@ async function dropDatabase(client, tenantSlug) {
|
|
|
64
64
|
const dbName = getDatabaseName(tenantSlug);
|
|
65
65
|
await client.query(`DROP DATABASE IF EXISTS "${dbName}"`);
|
|
66
66
|
}
|
|
67
|
-
exports.dropDatabase = dropDatabase;
|
|
68
67
|
//# sourceMappingURL=manager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/database/manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/database/manager.ts"],"names":[],"mappings":";;AAsBA,0CAGC;AAMD,wCAUC;AASD,wCAiBC;AAQD,oCAMC;AA/ED,MAAM,UAAU,GAAG,wBAAwB,CAAC;AAC5C,MAAM,SAAS,GAAG,iBAAiB,CAAC;AAEpC;;;GAGG;AACH,SAAS,YAAY,CAAC,IAAY;IAChC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CACb,yBAAyB,IAAI,sCAAsC,CACpE,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAgB,eAAe,CAAC,UAAkB;IAChD,YAAY,CAAC,UAAU,CAAC,CAAC;IACzB,OAAO,GAAG,SAAS,GAAG,UAAU,EAAE,CAAC;AACrC,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,cAAc,CAClC,MAAiC,EACjC,UAAkB;IAElB,MAAM,MAAM,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAC5B,uEAAuE,EACvE,CAAC,MAAM,CAAC,CACT,CAAC;IACF,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAC5B,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,cAAc,CAClC,MAAiC,EACjC,UAAkB,EAClB,UAAmB;IAEnB,MAAM,MAAM,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAC3C,+FAA+F;IAC/F,8FAA8F;IAC9F,IAAI,GAAG,GAAG,oBAAoB,MAAM,GAAG,CAAC;IACxC,IAAI,UAAU,EAAE,CAAC;QACf,iEAAiE;QACjE,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,KAAK,CAAC,oCAAoC,UAAU,GAAG,CAAC,CAAC;QACrE,CAAC;QACD,GAAG,IAAI,cAAc,UAAU,GAAG,CAAC;IACrC,CAAC;IACD,MAAM,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,YAAY,CAChC,MAAiC,EACjC,UAAkB;IAElB,MAAM,MAAM,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,MAAM,CAAC,KAAK,CAAC,4BAA4B,MAAM,GAAG,CAAC,CAAC;AAC5D,CAAC"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.addTenantColumn = addTenantColumn;
|
|
4
|
+
exports.enableRLS = enableRLS;
|
|
5
|
+
exports.createIsolationPolicy = createIsolationPolicy;
|
|
6
|
+
exports.migrateTable = migrateTable;
|
|
4
7
|
// Validate table name to prevent SQL injection (only allows alphanumeric + underscores)
|
|
5
8
|
function validateTableName(name) {
|
|
6
9
|
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
|
|
@@ -12,23 +15,19 @@ async function addTenantColumn(client, tableName) {
|
|
|
12
15
|
const safe = validateTableName(tableName);
|
|
13
16
|
await client.query(`ALTER TABLE ${safe} ADD COLUMN tenant_id UUID NOT NULL`);
|
|
14
17
|
}
|
|
15
|
-
exports.addTenantColumn = addTenantColumn;
|
|
16
18
|
async function enableRLS(client, tableName) {
|
|
17
19
|
const safe = validateTableName(tableName);
|
|
18
20
|
await client.query(`ALTER TABLE ${safe} ENABLE ROW LEVEL SECURITY`);
|
|
19
21
|
await client.query(`ALTER TABLE ${safe} FORCE ROW LEVEL SECURITY`);
|
|
20
22
|
}
|
|
21
|
-
exports.enableRLS = enableRLS;
|
|
22
23
|
async function createIsolationPolicy(client, tableName) {
|
|
23
24
|
const safe = validateTableName(tableName);
|
|
24
25
|
await client.query(`CREATE POLICY tenant_isolation ON ${safe}
|
|
25
26
|
USING (tenant_id = current_setting('app.current_tenant_id')::uuid)`);
|
|
26
27
|
}
|
|
27
|
-
exports.createIsolationPolicy = createIsolationPolicy;
|
|
28
28
|
async function migrateTable(client, tableName) {
|
|
29
29
|
await addTenantColumn(client, tableName);
|
|
30
30
|
await enableRLS(client, tableName);
|
|
31
31
|
await createIsolationPolicy(client, tableName);
|
|
32
32
|
}
|
|
33
|
-
exports.migrateTable = migrateTable;
|
|
34
33
|
//# sourceMappingURL=migration-helpers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration-helpers.js","sourceRoot":"","sources":["../src/migration-helpers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"migration-helpers.js","sourceRoot":"","sources":["../src/migration-helpers.ts"],"names":[],"mappings":";;AAUA,0CAQC;AAED,8BAOC;AAED,sDASC;AAED,oCAOC;AA7CD,wFAAwF;AACxF,SAAS,iBAAiB,CAAC,IAAY;IACrC,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAEM,KAAK,UAAU,eAAe,CACnC,MAAqB,EACrB,SAAiB;IAEjB,MAAM,IAAI,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,MAAM,CAAC,KAAK,CAChB,eAAe,IAAI,qCAAqC,CACzD,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,SAAS,CAC7B,MAAqB,EACrB,SAAiB;IAEjB,MAAM,IAAI,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,MAAM,CAAC,KAAK,CAAC,eAAe,IAAI,4BAA4B,CAAC,CAAC;IACpE,MAAM,MAAM,CAAC,KAAK,CAAC,eAAe,IAAI,2BAA2B,CAAC,CAAC;AACrE,CAAC;AAEM,KAAK,UAAU,qBAAqB,CACzC,MAAqB,EACrB,SAAiB;IAEjB,MAAM,IAAI,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,MAAM,CAAC,KAAK,CAChB,qCAAqC,IAAI;wEAC2B,CACrE,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,YAAY,CAChC,MAAqB,EACrB,SAAiB;IAEjB,MAAM,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACzC,MAAM,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACnC,MAAM,qBAAqB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AACjD,CAAC"}
|
package/dist/rls/manager.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.createPolicy = createPolicy;
|
|
4
|
+
exports.dropPolicy = dropPolicy;
|
|
5
|
+
exports.enableRLS = enableRLS;
|
|
6
|
+
exports.disableRLS = disableRLS;
|
|
7
|
+
exports.isRLSEnabled = isRLSEnabled;
|
|
4
8
|
// Validate table name to prevent SQL injection (only allows alphanumeric + underscores)
|
|
5
9
|
function validateTableName(tableName) {
|
|
6
10
|
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {
|
|
@@ -17,24 +21,20 @@ async function createPolicy(client, tableName) {
|
|
|
17
21
|
await client.query(`CREATE POLICY tenant_isolation ON ${safe} USING (tenant_id = current_setting('app.current_tenant_id')::uuid)`);
|
|
18
22
|
}
|
|
19
23
|
}
|
|
20
|
-
exports.createPolicy = createPolicy;
|
|
21
24
|
async function dropPolicy(client, tableName) {
|
|
22
25
|
const safe = validateTableName(tableName);
|
|
23
26
|
await client.query(`DROP POLICY IF EXISTS tenant_isolation ON ${safe}`);
|
|
24
27
|
}
|
|
25
|
-
exports.dropPolicy = dropPolicy;
|
|
26
28
|
async function enableRLS(client, tableName) {
|
|
27
29
|
const safe = validateTableName(tableName);
|
|
28
30
|
await client.query(`ALTER TABLE ${safe} ENABLE ROW LEVEL SECURITY`);
|
|
29
31
|
await client.query(`ALTER TABLE ${safe} FORCE ROW LEVEL SECURITY`);
|
|
30
32
|
}
|
|
31
|
-
exports.enableRLS = enableRLS;
|
|
32
33
|
async function disableRLS(client, tableName) {
|
|
33
34
|
const safe = validateTableName(tableName);
|
|
34
35
|
await client.query(`ALTER TABLE ${safe} NO FORCE ROW LEVEL SECURITY`);
|
|
35
36
|
await client.query(`ALTER TABLE ${safe} DISABLE ROW LEVEL SECURITY`);
|
|
36
37
|
}
|
|
37
|
-
exports.disableRLS = disableRLS;
|
|
38
38
|
async function isRLSEnabled(client, tableName) {
|
|
39
39
|
const res = await client.query(`SELECT relrowsecurity FROM pg_class WHERE relname = $1`, [tableName]);
|
|
40
40
|
if (res.rows.length === 0) {
|
|
@@ -42,5 +42,4 @@ async function isRLSEnabled(client, tableName) {
|
|
|
42
42
|
}
|
|
43
43
|
return res.rows[0].relrowsecurity;
|
|
44
44
|
}
|
|
45
|
-
exports.isRLSEnabled = isRLSEnabled;
|
|
46
45
|
//# sourceMappingURL=manager.js.map
|
package/dist/rls/manager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/rls/manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/rls/manager.ts"],"names":[],"mappings":";;AAUA,oCAgBC;AAED,gCAMC;AAED,8BAOC;AAED,gCAOC;AAED,oCAYC;AAhED,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;AAEM,KAAK,UAAU,YAAY,CAChC,MAAqB,EACrB,SAAiB;IAEjB,MAAM,IAAI,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC1C,4EAA4E;IAC5E,qDAAqD;IACrD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAC/B,2FAA2F,EAC3F,CAAC,IAAI,CAAC,CACP,CAAC;IACF,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,KAAK,CAChB,qCAAqC,IAAI,qEAAqE,CAC/G,CAAC;IACJ,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,UAAU,CAC9B,MAAqB,EACrB,SAAiB;IAEjB,MAAM,IAAI,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,MAAM,CAAC,KAAK,CAAC,6CAA6C,IAAI,EAAE,CAAC,CAAC;AAC1E,CAAC;AAEM,KAAK,UAAU,SAAS,CAC7B,MAAqB,EACrB,SAAiB;IAEjB,MAAM,IAAI,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,MAAM,CAAC,KAAK,CAAC,eAAe,IAAI,4BAA4B,CAAC,CAAC;IACpE,MAAM,MAAM,CAAC,KAAK,CAAC,eAAe,IAAI,2BAA2B,CAAC,CAAC;AACrE,CAAC;AAEM,KAAK,UAAU,UAAU,CAC9B,MAAqB,EACrB,SAAiB;IAEjB,MAAM,IAAI,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,MAAM,CAAC,KAAK,CAAC,eAAe,IAAI,8BAA8B,CAAC,CAAC;IACtE,MAAM,MAAM,CAAC,KAAK,CAAC,eAAe,IAAI,6BAA6B,CAAC,CAAC;AACvE,CAAC;AAEM,KAAK,UAAU,YAAY,CAChC,MAAqB,EACrB,SAAiB;IAEjB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAC5B,wDAAwD,EACxD,CAAC,SAAS,CAAC,CACZ,CAAC;IACF,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC;AACpC,CAAC"}
|
package/dist/rls/session.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import pg from "pg";
|
|
2
2
|
export declare function setTenantContext(client: pg.PoolClient, tenantId: string): Promise<void>;
|
|
3
3
|
export declare function resetTenantContext(client: pg.PoolClient): Promise<void>;
|
|
4
|
+
export declare function withTenantContext<T>(pool: pg.Pool, tenantId: string, fn: (client: pg.PoolClient) => Promise<T>): Promise<T>;
|
|
4
5
|
export declare function getCurrentTenantId(client: pg.PoolClient): Promise<string | null>;
|
|
5
6
|
//# sourceMappingURL=session.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/rls/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,EAAE,CAAC,UAAU,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7E;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,EAAE,CAAC,UAAU,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMxB"}
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/rls/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,EAAE,CAAC,UAAU,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7E;AAED,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,GACxC,OAAO,CAAC,CAAC,CAAC,CASZ;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,EAAE,CAAC,UAAU,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMxB"}
|
package/dist/rls/session.js
CHANGED
|
@@ -1,18 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.setTenantContext = setTenantContext;
|
|
4
|
+
exports.resetTenantContext = resetTenantContext;
|
|
5
|
+
exports.withTenantContext = withTenantContext;
|
|
6
|
+
exports.getCurrentTenantId = getCurrentTenantId;
|
|
4
7
|
async function setTenantContext(client, tenantId) {
|
|
5
|
-
await client.query("SELECT set_config('app.current_tenant_id', $1,
|
|
8
|
+
await client.query("SELECT set_config('app.current_tenant_id', $1, false)", [tenantId]);
|
|
6
9
|
}
|
|
7
|
-
exports.setTenantContext = setTenantContext;
|
|
8
10
|
async function resetTenantContext(client) {
|
|
9
|
-
await client.query("
|
|
11
|
+
await client.query("SELECT set_config('app.current_tenant_id', '', false)");
|
|
12
|
+
}
|
|
13
|
+
async function withTenantContext(pool, tenantId, fn) {
|
|
14
|
+
const client = await pool.connect();
|
|
15
|
+
try {
|
|
16
|
+
await setTenantContext(client, tenantId);
|
|
17
|
+
return await fn(client);
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
await resetTenantContext(client);
|
|
21
|
+
client.release();
|
|
22
|
+
}
|
|
10
23
|
}
|
|
11
|
-
exports.resetTenantContext = resetTenantContext;
|
|
12
24
|
async function getCurrentTenantId(client) {
|
|
13
25
|
const res = await client.query(`SELECT current_setting('app.current_tenant_id', true) AS current_setting`);
|
|
14
26
|
const value = res.rows[0]?.current_setting;
|
|
15
27
|
return value || null;
|
|
16
28
|
}
|
|
17
|
-
exports.getCurrentTenantId = getCurrentTenantId;
|
|
18
29
|
//# sourceMappingURL=session.js.map
|
package/dist/rls/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/rls/session.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/rls/session.ts"],"names":[],"mappings":";;AAEA,4CAKC;AAED,gDAEC;AAED,8CAaC;AAED,gDAQC;AAlCM,KAAK,UAAU,gBAAgB,CACpC,MAAqB,EACrB,QAAgB;IAEhB,MAAM,MAAM,CAAC,KAAK,CAAC,uDAAuD,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC1F,CAAC;AAEM,KAAK,UAAU,kBAAkB,CAAC,MAAqB;IAC5D,MAAM,MAAM,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;AAC9E,CAAC;AAEM,KAAK,UAAU,iBAAiB,CACrC,IAAa,EACb,QAAgB,EAChB,EAAyC;IAEzC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACzC,OAAO,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;YAAS,CAAC;QACT,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,kBAAkB,CACtC,MAAqB;IAErB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAC5B,0EAA0E,CAC3E,CAAC;IACF,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,eAAe,CAAC;IAC3C,OAAO,KAAK,IAAI,IAAI,CAAC;AACvB,CAAC"}
|
package/dist/schema/manager.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.tenantSchemaName = tenantSchemaName;
|
|
4
|
+
exports.createSchema = createSchema;
|
|
5
|
+
exports.dropSchema = dropSchema;
|
|
6
|
+
exports.schemaExists = schemaExists;
|
|
7
|
+
exports.listTenantSchemas = listTenantSchemas;
|
|
8
|
+
exports.replicateTableToSchema = replicateTableToSchema;
|
|
4
9
|
// Validate schema name to prevent SQL injection (only allows alphanumeric + underscores)
|
|
5
10
|
function validateSchemaName(schemaName) {
|
|
6
11
|
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(schemaName)) {
|
|
@@ -18,32 +23,26 @@ function validateTableName(tableName) {
|
|
|
18
23
|
function tenantSchemaName(tenantSlug) {
|
|
19
24
|
return `tenant_${tenantSlug}`;
|
|
20
25
|
}
|
|
21
|
-
exports.tenantSchemaName = tenantSchemaName;
|
|
22
26
|
async function createSchema(client, tenantSlug) {
|
|
23
27
|
const schemaName = validateSchemaName(tenantSchemaName(tenantSlug));
|
|
24
28
|
await client.query(`CREATE SCHEMA IF NOT EXISTS ${schemaName}`);
|
|
25
29
|
}
|
|
26
|
-
exports.createSchema = createSchema;
|
|
27
30
|
async function dropSchema(client, tenantSlug) {
|
|
28
31
|
const schemaName = validateSchemaName(tenantSchemaName(tenantSlug));
|
|
29
32
|
await client.query(`DROP SCHEMA IF EXISTS ${schemaName} CASCADE`);
|
|
30
33
|
}
|
|
31
|
-
exports.dropSchema = dropSchema;
|
|
32
34
|
async function schemaExists(client, tenantSlug) {
|
|
33
35
|
const schemaName = tenantSchemaName(tenantSlug);
|
|
34
36
|
const res = await client.query(`SELECT count(*) FROM pg_namespace WHERE nspname = $1`, [schemaName]);
|
|
35
37
|
return parseInt(res.rows[0].count, 10) > 0;
|
|
36
38
|
}
|
|
37
|
-
exports.schemaExists = schemaExists;
|
|
38
39
|
async function listTenantSchemas(client) {
|
|
39
40
|
const res = await client.query(`SELECT nspname FROM pg_namespace WHERE nspname LIKE 'tenant_%' ORDER BY nspname`);
|
|
40
41
|
return res.rows.map((r) => r.nspname);
|
|
41
42
|
}
|
|
42
|
-
exports.listTenantSchemas = listTenantSchemas;
|
|
43
43
|
async function replicateTableToSchema(client, tableName, schemaName) {
|
|
44
44
|
const safeTable = validateTableName(tableName);
|
|
45
45
|
const safeSchema = validateSchemaName(schemaName);
|
|
46
46
|
await client.query(`CREATE TABLE IF NOT EXISTS ${safeSchema}.${safeTable} (LIKE public.${safeTable} INCLUDING ALL)`);
|
|
47
47
|
}
|
|
48
|
-
exports.replicateTableToSchema = replicateTableToSchema;
|
|
49
48
|
//# sourceMappingURL=manager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/schema/manager.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/schema/session.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.setSchemaSearchPath = setSchemaSearchPath;
|
|
4
|
+
exports.resetSearchPath = resetSearchPath;
|
|
5
|
+
exports.getCurrentSearchPath = getCurrentSearchPath;
|
|
4
6
|
const manager_js_1 = require("./manager.js");
|
|
5
7
|
async function setSchemaSearchPath(client, tenantSlug) {
|
|
6
8
|
const schemaName = (0, manager_js_1.tenantSchemaName)(tenantSlug);
|
|
@@ -8,14 +10,11 @@ async function setSchemaSearchPath(client, tenantSlug) {
|
|
|
8
10
|
// SET LOCAL only takes effect for the current transaction.
|
|
9
11
|
await client.query(`SET LOCAL search_path TO ${schemaName}, public`);
|
|
10
12
|
}
|
|
11
|
-
exports.setSchemaSearchPath = setSchemaSearchPath;
|
|
12
13
|
async function resetSearchPath(client) {
|
|
13
14
|
await client.query("RESET search_path");
|
|
14
15
|
}
|
|
15
|
-
exports.resetSearchPath = resetSearchPath;
|
|
16
16
|
async function getCurrentSearchPath(client) {
|
|
17
17
|
const res = await client.query("SHOW search_path");
|
|
18
18
|
return res.rows[0].search_path;
|
|
19
19
|
}
|
|
20
|
-
exports.getCurrentSearchPath = getCurrentSearchPath;
|
|
21
20
|
//# sourceMappingURL=session.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/schema/session.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/schema/session.ts"],"names":[],"mappings":";;AAGA,kDAQC;AAED,0CAEC;AAED,oDAKC;AArBD,6CAAgD;AAEzC,KAAK,UAAU,mBAAmB,CACvC,MAAqB,EACrB,UAAkB;IAElB,MAAM,UAAU,GAAG,IAAA,6BAAgB,EAAC,UAAU,CAAC,CAAC;IAChD,yEAAyE;IACzE,2DAA2D;IAC3D,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"}
|