@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.
- package/README.md +22 -4
- package/dist/adapters/database-prisma.d.ts +4 -2
- package/dist/adapters/database-prisma.d.ts.map +1 -1
- package/dist/adapters/database-prisma.js +19 -6
- package/dist/adapters/database-prisma.js.map +1 -1
- package/dist/adapters/drizzle.d.ts +2 -2
- package/dist/adapters/drizzle.d.ts.map +1 -1
- package/dist/adapters/drizzle.js +9 -8
- package/dist/adapters/drizzle.js.map +1 -1
- package/dist/adapters/prisma.d.ts +1 -1
- package/dist/adapters/prisma.d.ts.map +1 -1
- package/dist/adapters/prisma.js +12 -5
- package/dist/adapters/prisma.js.map +1 -1
- package/dist/adapters/schema-prisma.d.ts +36 -4
- package/dist/adapters/schema-prisma.d.ts.map +1 -1
- package/dist/adapters/schema-prisma.js +55 -17
- package/dist/adapters/schema-prisma.js.map +1 -1
- package/dist/adapters/schema-raw.d.ts +14 -3
- package/dist/adapters/schema-raw.d.ts.map +1 -1
- package/dist/adapters/schema-raw.js +9 -5
- package/dist/adapters/schema-raw.js.map +1 -1
- package/dist/database/manager.d.ts.map +1 -1
- package/dist/database/manager.js +7 -1
- package/dist/database/manager.js.map +1 -1
- package/dist/database/pool-manager.d.ts.map +1 -1
- package/dist/database/pool-manager.js +2 -3
- package/dist/database/pool-manager.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/schema/manager.d.ts +1 -0
- package/dist/schema/manager.d.ts.map +1 -1
- package/dist/schema/manager.js +11 -2
- package/dist/schema/manager.js.map +1 -1
- package/dist/schema/session.d.ts +10 -1
- package/dist/schema/session.d.ts.map +1 -1
- package/dist/schema/session.js +24 -4
- package/dist/schema/session.js.map +1 -1
- package/package.json +10 -2
- package/dist/__tests__/base-adapter.test.d.ts +0 -2
- package/dist/__tests__/base-adapter.test.d.ts.map +0 -1
- package/dist/__tests__/base-adapter.test.js +0 -194
- package/dist/__tests__/base-adapter.test.js.map +0 -1
- package/dist/__tests__/database-manager.test.d.ts +0 -2
- package/dist/__tests__/database-manager.test.d.ts.map +0 -1
- package/dist/__tests__/database-manager.test.js +0 -110
- package/dist/__tests__/database-manager.test.js.map +0 -1
- package/dist/__tests__/drizzle.test.d.ts +0 -2
- package/dist/__tests__/drizzle.test.d.ts.map +0 -1
- package/dist/__tests__/drizzle.test.js +0 -177
- package/dist/__tests__/drizzle.test.js.map +0 -1
- package/dist/__tests__/pool-manager.test.d.ts +0 -2
- package/dist/__tests__/pool-manager.test.d.ts.map +0 -1
- package/dist/__tests__/pool-manager.test.js +0 -171
- package/dist/__tests__/pool-manager.test.js.map +0 -1
- package/dist/__tests__/rls-manager.test.d.ts +0 -2
- package/dist/__tests__/rls-manager.test.d.ts.map +0 -1
- package/dist/__tests__/rls-manager.test.js +0 -180
- package/dist/__tests__/rls-manager.test.js.map +0 -1
- package/dist/__tests__/rls-session.test.d.ts +0 -2
- package/dist/__tests__/rls-session.test.d.ts.map +0 -1
- package/dist/__tests__/rls-session.test.js +0 -97
- package/dist/__tests__/rls-session.test.js.map +0 -1
- package/dist/__tests__/schema-manager.test.d.ts +0 -2
- package/dist/__tests__/schema-manager.test.d.ts.map +0 -1
- package/dist/__tests__/schema-manager.test.js +0 -116
- package/dist/__tests__/schema-manager.test.js.map +0 -1
- package/dist/__tests__/schema-session.test.d.ts +0 -2
- package/dist/__tests__/schema-session.test.d.ts.map +0 -1
- package/dist/__tests__/schema-session.test.js +0 -23
- package/dist/__tests__/schema-session.test.js.map +0 -1
- package/dist/__tests__/sequelize.test.d.ts +0 -2
- package/dist/__tests__/sequelize.test.d.ts.map +0 -1
- package/dist/__tests__/sequelize.test.js +0 -150
- package/dist/__tests__/sequelize.test.js.map +0 -1
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vitest_1 = require("vitest");
|
|
4
|
-
const drizzle_js_1 = require("../adapters/drizzle.js");
|
|
5
|
-
const base_adapter_js_1 = require("../base-adapter.js");
|
|
6
|
-
// ---------------------------------------------------------------------------
|
|
7
|
-
// Mock pg
|
|
8
|
-
// ---------------------------------------------------------------------------
|
|
9
|
-
class MockPool {
|
|
10
|
-
}
|
|
11
|
-
vitest_1.vi.mock("pg", () => {
|
|
12
|
-
return { default: { Pool: MockPool }, Pool: MockPool };
|
|
13
|
-
});
|
|
14
|
-
function createMockDrizzle() {
|
|
15
|
-
const executions = [];
|
|
16
|
-
return {
|
|
17
|
-
executions,
|
|
18
|
-
execute: async (query) => {
|
|
19
|
-
executions.push({ query });
|
|
20
|
-
return { rows: [] };
|
|
21
|
-
},
|
|
22
|
-
transaction: async (fn) => {
|
|
23
|
-
// Create a nested mock for the transaction context that shares the
|
|
24
|
-
// executions array so tests can inspect what ran inside the tx.
|
|
25
|
-
const txMock = {
|
|
26
|
-
execute: async (query) => {
|
|
27
|
-
executions.push({ query });
|
|
28
|
-
return { rows: [] };
|
|
29
|
-
},
|
|
30
|
-
transaction: async (innerFn) => innerFn(txMock),
|
|
31
|
-
};
|
|
32
|
-
return fn(txMock);
|
|
33
|
-
},
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
// ---------------------------------------------------------------------------
|
|
37
|
-
// Tests
|
|
38
|
-
// ---------------------------------------------------------------------------
|
|
39
|
-
(0, vitest_1.describe)("DrizzleAdapter", () => {
|
|
40
|
-
let pool;
|
|
41
|
-
let adapter;
|
|
42
|
-
(0, vitest_1.beforeEach)(() => {
|
|
43
|
-
vitest_1.vi.clearAllMocks();
|
|
44
|
-
pool = new MockPool();
|
|
45
|
-
adapter = new drizzle_js_1.DrizzleAdapter(pool);
|
|
46
|
-
});
|
|
47
|
-
(0, vitest_1.it)("extends BaseAdapter", () => {
|
|
48
|
-
(0, vitest_1.expect)(adapter).toBeInstanceOf(base_adapter_js_1.BaseAdapter);
|
|
49
|
-
});
|
|
50
|
-
(0, vitest_1.describe)("withTenant (method)", () => {
|
|
51
|
-
(0, vitest_1.it)("returns a new wrapped object, not the original instance", () => {
|
|
52
|
-
const mock = createMockDrizzle();
|
|
53
|
-
const result = adapter.withTenant(mock, () => "tenant-1");
|
|
54
|
-
(0, vitest_1.expect)(result).not.toBe(mock);
|
|
55
|
-
});
|
|
56
|
-
(0, vitest_1.it)("returned object exposes execute and transaction", () => {
|
|
57
|
-
const mock = createMockDrizzle();
|
|
58
|
-
const result = adapter.withTenant(mock, () => "tenant-1");
|
|
59
|
-
(0, vitest_1.expect)(typeof result.execute).toBe("function");
|
|
60
|
-
(0, vitest_1.expect)(typeof result.transaction).toBe("function");
|
|
61
|
-
});
|
|
62
|
-
(0, vitest_1.it)("wrapped execute calls transaction() and sets set_config inside it", async () => {
|
|
63
|
-
const mock = createMockDrizzle();
|
|
64
|
-
const transactionSpy = vitest_1.vi.spyOn(mock, "transaction");
|
|
65
|
-
const wrapped = adapter.withTenant(mock, () => "tenant-abc");
|
|
66
|
-
await wrapped.execute({ sql: "SELECT 1" });
|
|
67
|
-
(0, vitest_1.expect)(transactionSpy).toHaveBeenCalledTimes(1);
|
|
68
|
-
(0, vitest_1.expect)(mock.executions).toHaveLength(2);
|
|
69
|
-
(0, vitest_1.expect)(mock.executions[0].query.sql).toContain("set_config");
|
|
70
|
-
(0, vitest_1.expect)(mock.executions[0].query.sql).toContain("app.current_tenant_id");
|
|
71
|
-
(0, vitest_1.expect)(mock.executions[1].query.sql).toBe("SELECT 1");
|
|
72
|
-
});
|
|
73
|
-
(0, vitest_1.it)("set_config receives tenant ID as params", async () => {
|
|
74
|
-
const mock = createMockDrizzle();
|
|
75
|
-
const wrapped = adapter.withTenant(mock, () => "tenant-xyz");
|
|
76
|
-
await wrapped.execute({ sql: "SELECT 1" });
|
|
77
|
-
(0, vitest_1.expect)(mock.executions[0].query.params).toEqual(["tenant-xyz"]);
|
|
78
|
-
});
|
|
79
|
-
(0, vitest_1.it)("wrapped transaction injects set_config before user callback", async () => {
|
|
80
|
-
const mock = createMockDrizzle();
|
|
81
|
-
const transactionSpy = vitest_1.vi.spyOn(mock, "transaction");
|
|
82
|
-
const wrapped = adapter.withTenant(mock, () => "tenant-abc");
|
|
83
|
-
await wrapped.transaction(async (tx) => {
|
|
84
|
-
await tx.execute({ sql: "INSERT INTO foo VALUES (1)" });
|
|
85
|
-
});
|
|
86
|
-
(0, vitest_1.expect)(transactionSpy).toHaveBeenCalledTimes(1);
|
|
87
|
-
(0, vitest_1.expect)(mock.executions).toHaveLength(2);
|
|
88
|
-
(0, vitest_1.expect)(mock.executions[0].query.sql).toContain("set_config");
|
|
89
|
-
(0, vitest_1.expect)(mock.executions[1].query.sql).toBe("INSERT INTO foo VALUES (1)");
|
|
90
|
-
});
|
|
91
|
-
(0, vitest_1.it)("reads tenant ID lazily from contextFn on each call", async () => {
|
|
92
|
-
let currentTenant = "tenant-1";
|
|
93
|
-
const mock = createMockDrizzle();
|
|
94
|
-
const wrapped = adapter.withTenant(mock, () => currentTenant);
|
|
95
|
-
await wrapped.execute({ sql: "SELECT 1" });
|
|
96
|
-
(0, vitest_1.expect)(mock.executions[0].query.params).toEqual(["tenant-1"]);
|
|
97
|
-
currentTenant = "tenant-2";
|
|
98
|
-
mock.executions.length = 0;
|
|
99
|
-
await wrapped.execute({ sql: "SELECT 2" });
|
|
100
|
-
(0, vitest_1.expect)(mock.executions[0].query.params).toEqual(["tenant-2"]);
|
|
101
|
-
});
|
|
102
|
-
(0, vitest_1.it)("throws when contextFn returns empty string (execute)", async () => {
|
|
103
|
-
const mock = createMockDrizzle();
|
|
104
|
-
const wrapped = adapter.withTenant(mock, () => "");
|
|
105
|
-
await (0, vitest_1.expect)(wrapped.execute({ sql: "SELECT 1" })).rejects.toThrow("Tenant context is required for database operations.");
|
|
106
|
-
});
|
|
107
|
-
(0, vitest_1.it)("throws when contextFn returns empty string (transaction)", async () => {
|
|
108
|
-
const mock = createMockDrizzle();
|
|
109
|
-
const wrapped = adapter.withTenant(mock, () => "");
|
|
110
|
-
await (0, vitest_1.expect)(wrapped.transaction(async (tx) => {
|
|
111
|
-
await tx.execute({ sql: "SELECT 1" });
|
|
112
|
-
})).rejects.toThrow("Tenant context is required for database operations.");
|
|
113
|
-
});
|
|
114
|
-
(0, vitest_1.it)("propagates errors thrown by set_config (execute path)", async () => {
|
|
115
|
-
const mock = createMockDrizzle();
|
|
116
|
-
// Override transaction to use a tx whose execute throws
|
|
117
|
-
mock.transaction = async (fn) => {
|
|
118
|
-
const failTx = {
|
|
119
|
-
execute: vitest_1.vi.fn().mockRejectedValueOnce(new Error("set_config failed")),
|
|
120
|
-
transaction: async (innerFn) => innerFn(failTx),
|
|
121
|
-
};
|
|
122
|
-
return fn(failTx);
|
|
123
|
-
};
|
|
124
|
-
const wrapped = adapter.withTenant(mock, () => "tenant-1");
|
|
125
|
-
await (0, vitest_1.expect)(wrapped.execute({ sql: "SELECT 1" })).rejects.toThrow("set_config failed");
|
|
126
|
-
});
|
|
127
|
-
(0, vitest_1.it)("propagates errors thrown by set_config (transaction path)", async () => {
|
|
128
|
-
const mock = createMockDrizzle();
|
|
129
|
-
mock.transaction = async (fn) => {
|
|
130
|
-
const failTx = {
|
|
131
|
-
execute: vitest_1.vi.fn().mockRejectedValueOnce(new Error("set_config failed")),
|
|
132
|
-
transaction: async (innerFn) => innerFn(failTx),
|
|
133
|
-
};
|
|
134
|
-
return fn(failTx);
|
|
135
|
-
};
|
|
136
|
-
const wrapped = adapter.withTenant(mock, () => "tenant-1");
|
|
137
|
-
await (0, vitest_1.expect)(wrapped.transaction(async (tx) => {
|
|
138
|
-
await tx.execute({ sql: "SELECT 1" });
|
|
139
|
-
})).rejects.toThrow("set_config failed");
|
|
140
|
-
});
|
|
141
|
-
(0, vitest_1.it)("throws when execute() called with no tenant", async () => {
|
|
142
|
-
const mock = createMockDrizzle();
|
|
143
|
-
const wrapped = adapter.withTenant(mock, () => "");
|
|
144
|
-
const query = { sql: "SELECT 1" };
|
|
145
|
-
await (0, vitest_1.expect)(wrapped.execute(query)).rejects.toThrow("Tenant context is required for database operations.");
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
(0, vitest_1.describe)("withTenant (convenience function)", () => {
|
|
150
|
-
(0, vitest_1.it)("returns a new wrapped object, not the original instance", () => {
|
|
151
|
-
const mock = createMockDrizzle();
|
|
152
|
-
const pool = new MockPool();
|
|
153
|
-
const result = (0, drizzle_js_1.withTenant)(mock, () => "tenant-1", pool);
|
|
154
|
-
(0, vitest_1.expect)(result).not.toBe(mock);
|
|
155
|
-
});
|
|
156
|
-
(0, vitest_1.it)("wrapped execute calls transaction() with set_config", async () => {
|
|
157
|
-
const mock = createMockDrizzle();
|
|
158
|
-
const transactionSpy = vitest_1.vi.spyOn(mock, "transaction");
|
|
159
|
-
const pool = new MockPool();
|
|
160
|
-
const wrapped = (0, drizzle_js_1.withTenant)(mock, () => "fn-tenant", pool);
|
|
161
|
-
await wrapped.execute({ sql: "SELECT 1" });
|
|
162
|
-
(0, vitest_1.expect)(transactionSpy).toHaveBeenCalledTimes(1);
|
|
163
|
-
(0, vitest_1.expect)(mock.executions[0].query.params).toEqual(["fn-tenant"]);
|
|
164
|
-
});
|
|
165
|
-
(0, vitest_1.it)("throws when contextFn returns empty string", async () => {
|
|
166
|
-
const mock = createMockDrizzle();
|
|
167
|
-
const pool = new MockPool();
|
|
168
|
-
const wrapped = (0, drizzle_js_1.withTenant)(mock, () => "", pool);
|
|
169
|
-
await (0, vitest_1.expect)(wrapped.execute({ sql: "SELECT 1" })).rejects.toThrow("Tenant context is required for database operations.");
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
(0, vitest_1.describe)("withTenantScope (deprecated alias)", () => {
|
|
173
|
-
(0, vitest_1.it)("is the same function as withTenant", () => {
|
|
174
|
-
(0, vitest_1.expect)(drizzle_js_1.withTenantScope).toBe(drizzle_js_1.withTenant);
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
//# sourceMappingURL=drizzle.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"drizzle.test.js","sourceRoot":"","sources":["../../src/__tests__/drizzle.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pool-manager.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/pool-manager.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vitest_1 = require("vitest");
|
|
4
|
-
const pool_manager_js_1 = require("../database/pool-manager.js");
|
|
5
|
-
// ---------------------------------------------------------------------------
|
|
6
|
-
// Mock pg.Pool
|
|
7
|
-
// ---------------------------------------------------------------------------
|
|
8
|
-
const mockPoolEnd = vitest_1.vi.fn().mockResolvedValue(undefined);
|
|
9
|
-
vitest_1.vi.mock("pg", () => {
|
|
10
|
-
class Pool {
|
|
11
|
-
database;
|
|
12
|
-
totalCount = 0;
|
|
13
|
-
idleCount = 0;
|
|
14
|
-
end = mockPoolEnd;
|
|
15
|
-
constructor(config) {
|
|
16
|
-
this.database = config.database;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return { default: { Pool } };
|
|
20
|
-
});
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
// Helpers
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
function makeManager(maxPools = 3) {
|
|
25
|
-
return new pool_manager_js_1.DatabasePoolManager({
|
|
26
|
-
baseConnectionConfig: {
|
|
27
|
-
host: "localhost",
|
|
28
|
-
port: 5432,
|
|
29
|
-
user: "stratum",
|
|
30
|
-
password: "secret",
|
|
31
|
-
},
|
|
32
|
-
maxPools,
|
|
33
|
-
idleTimeoutMs: 30_000,
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
// ---------------------------------------------------------------------------
|
|
37
|
-
// Tests
|
|
38
|
-
// ---------------------------------------------------------------------------
|
|
39
|
-
(0, vitest_1.describe)("DatabasePoolManager", () => {
|
|
40
|
-
(0, vitest_1.beforeEach)(() => {
|
|
41
|
-
mockPoolEnd.mockClear();
|
|
42
|
-
});
|
|
43
|
-
(0, vitest_1.describe)("slug validation", () => {
|
|
44
|
-
(0, vitest_1.it)("rejects slugs starting with a number", async () => {
|
|
45
|
-
const mgr = makeManager();
|
|
46
|
-
await (0, vitest_1.expect)(mgr.getPool("123acme")).rejects.toThrow("Invalid tenant slug");
|
|
47
|
-
});
|
|
48
|
-
(0, vitest_1.it)("rejects slugs with uppercase letters", async () => {
|
|
49
|
-
const mgr = makeManager();
|
|
50
|
-
await (0, vitest_1.expect)(mgr.getPool("Acme")).rejects.toThrow("Invalid tenant slug");
|
|
51
|
-
});
|
|
52
|
-
(0, vitest_1.it)("rejects slugs with hyphens", async () => {
|
|
53
|
-
const mgr = makeManager();
|
|
54
|
-
await (0, vitest_1.expect)(mgr.getPool("acme-corp")).rejects.toThrow("Invalid tenant slug");
|
|
55
|
-
});
|
|
56
|
-
(0, vitest_1.it)("rejects slugs with special characters", async () => {
|
|
57
|
-
const mgr = makeManager();
|
|
58
|
-
await (0, vitest_1.expect)(mgr.getPool("acme; DROP TABLE")).rejects.toThrow("Invalid tenant slug");
|
|
59
|
-
});
|
|
60
|
-
(0, vitest_1.it)("rejects empty slugs", async () => {
|
|
61
|
-
const mgr = makeManager();
|
|
62
|
-
await (0, vitest_1.expect)(mgr.getPool("")).rejects.toThrow("Invalid tenant slug");
|
|
63
|
-
});
|
|
64
|
-
(0, vitest_1.it)("accepts valid lowercase slugs with underscores", async () => {
|
|
65
|
-
const mgr = makeManager();
|
|
66
|
-
await (0, vitest_1.expect)(mgr.getPool("acme_corp")).resolves.toBeDefined();
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
(0, vitest_1.describe)("getPool", () => {
|
|
70
|
-
(0, vitest_1.it)("creates a new pool for an unseen tenant slug", async () => {
|
|
71
|
-
const mgr = makeManager();
|
|
72
|
-
const pool = await mgr.getPool("acme");
|
|
73
|
-
(0, vitest_1.expect)(pool).toBeDefined();
|
|
74
|
-
(0, vitest_1.expect)(mgr.getStats().poolCount).toBe(1);
|
|
75
|
-
});
|
|
76
|
-
(0, vitest_1.it)("returns the same pool instance on subsequent calls", async () => {
|
|
77
|
-
const mgr = makeManager();
|
|
78
|
-
const pool1 = await mgr.getPool("acme");
|
|
79
|
-
const pool2 = await mgr.getPool("acme");
|
|
80
|
-
(0, vitest_1.expect)(pool1).toBe(pool2);
|
|
81
|
-
(0, vitest_1.expect)(mgr.getStats().poolCount).toBe(1);
|
|
82
|
-
});
|
|
83
|
-
(0, vitest_1.it)("creates separate pools for different slugs", async () => {
|
|
84
|
-
const mgr = makeManager();
|
|
85
|
-
const pool1 = await mgr.getPool("acme");
|
|
86
|
-
const pool2 = await mgr.getPool("globex");
|
|
87
|
-
(0, vitest_1.expect)(pool1).not.toBe(pool2);
|
|
88
|
-
(0, vitest_1.expect)(mgr.getStats().poolCount).toBe(2);
|
|
89
|
-
});
|
|
90
|
-
(0, vitest_1.it)("connects to the correct database name", async () => {
|
|
91
|
-
const mgr = makeManager();
|
|
92
|
-
const pool = (await mgr.getPool("acme"));
|
|
93
|
-
(0, vitest_1.expect)(pool.database).toBe("stratum_tenant_acme");
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
(0, vitest_1.describe)("LRU eviction", () => {
|
|
97
|
-
(0, vitest_1.it)("evicts the least recently used pool when maxPools is exceeded", async () => {
|
|
98
|
-
const mgr = makeManager(2);
|
|
99
|
-
await mgr.getPool("tenant_a");
|
|
100
|
-
// Small delay to ensure different timestamps
|
|
101
|
-
await new Promise((r) => setTimeout(r, 2));
|
|
102
|
-
await mgr.getPool("tenant_b");
|
|
103
|
-
// tenant_a is now the LRU entry; adding tenant_c should evict it.
|
|
104
|
-
await new Promise((r) => setTimeout(r, 2));
|
|
105
|
-
await mgr.getPool("tenant_c");
|
|
106
|
-
(0, vitest_1.expect)(mockPoolEnd).toHaveBeenCalledTimes(1);
|
|
107
|
-
// poolCount should be back to maxPools (2) after eviction.
|
|
108
|
-
(0, vitest_1.expect)(mgr.getStats().poolCount).toBe(2);
|
|
109
|
-
});
|
|
110
|
-
(0, vitest_1.it)("updates lastUsed when an existing pool is accessed", async () => {
|
|
111
|
-
const mgr = makeManager(2);
|
|
112
|
-
await mgr.getPool("tenant_a");
|
|
113
|
-
await new Promise((r) => setTimeout(r, 2));
|
|
114
|
-
await mgr.getPool("tenant_b");
|
|
115
|
-
await new Promise((r) => setTimeout(r, 2));
|
|
116
|
-
// Re-access tenant_a to make it the most recently used.
|
|
117
|
-
await mgr.getPool("tenant_a");
|
|
118
|
-
await new Promise((r) => setTimeout(r, 2));
|
|
119
|
-
// Now tenant_b is the LRU; adding tenant_c should evict tenant_b.
|
|
120
|
-
await mgr.getPool("tenant_c");
|
|
121
|
-
(0, vitest_1.expect)(mockPoolEnd).toHaveBeenCalledTimes(1);
|
|
122
|
-
// tenant_a and tenant_c should remain.
|
|
123
|
-
(0, vitest_1.expect)(mgr.getStats().poolCount).toBe(2);
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
(0, vitest_1.describe)("closePool", () => {
|
|
127
|
-
(0, vitest_1.it)("closes and removes the specified pool", async () => {
|
|
128
|
-
const mgr = makeManager();
|
|
129
|
-
await mgr.getPool("acme");
|
|
130
|
-
(0, vitest_1.expect)(mgr.getStats().poolCount).toBe(1);
|
|
131
|
-
await mgr.closePool("acme");
|
|
132
|
-
(0, vitest_1.expect)(mockPoolEnd).toHaveBeenCalledTimes(1);
|
|
133
|
-
(0, vitest_1.expect)(mgr.getStats().poolCount).toBe(0);
|
|
134
|
-
});
|
|
135
|
-
(0, vitest_1.it)("is a no-op for unknown slug", async () => {
|
|
136
|
-
const mgr = makeManager();
|
|
137
|
-
await mgr.closePool("nonexistent");
|
|
138
|
-
(0, vitest_1.expect)(mockPoolEnd).not.toHaveBeenCalled();
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
(0, vitest_1.describe)("closeAll", () => {
|
|
142
|
-
(0, vitest_1.it)("closes all pools", async () => {
|
|
143
|
-
const mgr = makeManager(10);
|
|
144
|
-
await mgr.getPool("a");
|
|
145
|
-
await mgr.getPool("b");
|
|
146
|
-
await mgr.getPool("c");
|
|
147
|
-
(0, vitest_1.expect)(mgr.getStats().poolCount).toBe(3);
|
|
148
|
-
await mgr.closeAll();
|
|
149
|
-
(0, vitest_1.expect)(mockPoolEnd).toHaveBeenCalledTimes(3);
|
|
150
|
-
(0, vitest_1.expect)(mgr.getStats().poolCount).toBe(0);
|
|
151
|
-
});
|
|
152
|
-
(0, vitest_1.it)("is safe to call when no pools exist", async () => {
|
|
153
|
-
const mgr = makeManager();
|
|
154
|
-
await (0, vitest_1.expect)(mgr.closeAll()).resolves.toBeUndefined();
|
|
155
|
-
(0, vitest_1.expect)(mockPoolEnd).not.toHaveBeenCalled();
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
(0, vitest_1.describe)("getStats", () => {
|
|
159
|
-
(0, vitest_1.it)("returns zero counts for a fresh manager", () => {
|
|
160
|
-
const mgr = makeManager();
|
|
161
|
-
(0, vitest_1.expect)(mgr.getStats()).toEqual({ poolCount: 0, activeConnections: 0 });
|
|
162
|
-
});
|
|
163
|
-
(0, vitest_1.it)("reflects current pool count", async () => {
|
|
164
|
-
const mgr = makeManager(10);
|
|
165
|
-
await mgr.getPool("x");
|
|
166
|
-
await mgr.getPool("y");
|
|
167
|
-
(0, vitest_1.expect)(mgr.getStats().poolCount).toBe(2);
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
//# sourceMappingURL=pool-manager.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pool-manager.test.js","sourceRoot":"","sources":["../../src/__tests__/pool-manager.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rls-manager.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/rls-manager.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vitest_1 = require("vitest");
|
|
4
|
-
const manager_js_1 = require("../rls/manager.js");
|
|
5
|
-
// ---------------------------------------------------------------------------
|
|
6
|
-
// Mock pg.PoolClient
|
|
7
|
-
// ---------------------------------------------------------------------------
|
|
8
|
-
function makeMockClient() {
|
|
9
|
-
return {
|
|
10
|
-
query: vitest_1.vi.fn().mockResolvedValue({ rows: [], rowCount: 0 }),
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
// Tests
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
|
-
(0, vitest_1.describe)("RLS Manager", () => {
|
|
17
|
-
let client;
|
|
18
|
-
(0, vitest_1.beforeEach)(() => {
|
|
19
|
-
client = makeMockClient();
|
|
20
|
-
});
|
|
21
|
-
// -----------------------------------------------------------------------
|
|
22
|
-
// Table name validation
|
|
23
|
-
// -----------------------------------------------------------------------
|
|
24
|
-
(0, vitest_1.describe)("table name validation", () => {
|
|
25
|
-
(0, vitest_1.it)("rejects names containing SQL injection attempts", async () => {
|
|
26
|
-
await (0, vitest_1.expect)((0, manager_js_1.createPolicy)(client, "users; DROP TABLE")).rejects.toThrow("Invalid table name");
|
|
27
|
-
await (0, vitest_1.expect)((0, manager_js_1.dropPolicy)(client, "users; DROP TABLE")).rejects.toThrow("Invalid table name");
|
|
28
|
-
await (0, vitest_1.expect)((0, manager_js_1.enableRLS)(client, "users; DROP TABLE")).rejects.toThrow("Invalid table name");
|
|
29
|
-
await (0, vitest_1.expect)((0, manager_js_1.disableRLS)(client, "users; DROP TABLE")).rejects.toThrow("Invalid table name");
|
|
30
|
-
});
|
|
31
|
-
(0, vitest_1.it)("rejects names with spaces", async () => {
|
|
32
|
-
await (0, vitest_1.expect)((0, manager_js_1.createPolicy)(client, "my table")).rejects.toThrow("Invalid table name");
|
|
33
|
-
});
|
|
34
|
-
(0, vitest_1.it)("rejects names starting with a digit", async () => {
|
|
35
|
-
await (0, vitest_1.expect)((0, manager_js_1.createPolicy)(client, "1users")).rejects.toThrow("Invalid table name");
|
|
36
|
-
});
|
|
37
|
-
(0, vitest_1.it)("rejects names with hyphens", async () => {
|
|
38
|
-
await (0, vitest_1.expect)((0, manager_js_1.createPolicy)(client, "my-table")).rejects.toThrow("Invalid table name");
|
|
39
|
-
});
|
|
40
|
-
(0, vitest_1.it)("rejects names with parentheses", async () => {
|
|
41
|
-
await (0, vitest_1.expect)((0, manager_js_1.createPolicy)(client, "users()")).rejects.toThrow("Invalid table name");
|
|
42
|
-
});
|
|
43
|
-
(0, vitest_1.it)("rejects empty string", async () => {
|
|
44
|
-
await (0, vitest_1.expect)((0, manager_js_1.createPolicy)(client, "")).rejects.toThrow("Invalid table name");
|
|
45
|
-
});
|
|
46
|
-
(0, vitest_1.it)("accepts simple alphanumeric names", async () => {
|
|
47
|
-
client.query.mockResolvedValueOnce({
|
|
48
|
-
rows: [{ count: "0" }],
|
|
49
|
-
});
|
|
50
|
-
await (0, vitest_1.expect)((0, manager_js_1.createPolicy)(client, "users")).resolves.toBeUndefined();
|
|
51
|
-
});
|
|
52
|
-
(0, vitest_1.it)("accepts names with underscores", async () => {
|
|
53
|
-
client.query.mockResolvedValueOnce({
|
|
54
|
-
rows: [{ count: "0" }],
|
|
55
|
-
});
|
|
56
|
-
await (0, vitest_1.expect)((0, manager_js_1.createPolicy)(client, "tenant_data")).resolves.toBeUndefined();
|
|
57
|
-
});
|
|
58
|
-
(0, vitest_1.it)("accepts names starting with underscore", async () => {
|
|
59
|
-
client.query.mockResolvedValueOnce({
|
|
60
|
-
rows: [{ count: "0" }],
|
|
61
|
-
});
|
|
62
|
-
await (0, vitest_1.expect)((0, manager_js_1.createPolicy)(client, "_internal")).resolves.toBeUndefined();
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
// -----------------------------------------------------------------------
|
|
66
|
-
// createPolicy
|
|
67
|
-
// -----------------------------------------------------------------------
|
|
68
|
-
(0, vitest_1.describe)("createPolicy", () => {
|
|
69
|
-
(0, vitest_1.it)("checks for existing policy before creating", async () => {
|
|
70
|
-
client.query.mockResolvedValueOnce({
|
|
71
|
-
rows: [{ count: "0" }],
|
|
72
|
-
});
|
|
73
|
-
await (0, manager_js_1.createPolicy)(client, "orders");
|
|
74
|
-
const calls = client.query.mock.calls;
|
|
75
|
-
(0, vitest_1.expect)(calls).toHaveLength(2);
|
|
76
|
-
// First call: check pg_policies
|
|
77
|
-
(0, vitest_1.expect)(calls[0][0]).toContain("pg_policies");
|
|
78
|
-
(0, vitest_1.expect)(calls[0][0]).toContain("tenant_isolation");
|
|
79
|
-
(0, vitest_1.expect)(calls[0][1]).toEqual(["orders"]);
|
|
80
|
-
// Second call: CREATE POLICY
|
|
81
|
-
(0, vitest_1.expect)(calls[1][0]).toContain("CREATE POLICY tenant_isolation ON orders");
|
|
82
|
-
(0, vitest_1.expect)(calls[1][0]).toContain("current_setting('app.current_tenant_id')");
|
|
83
|
-
});
|
|
84
|
-
(0, vitest_1.it)("skips creation when policy already exists", async () => {
|
|
85
|
-
client.query.mockResolvedValueOnce({
|
|
86
|
-
rows: [{ count: "1" }],
|
|
87
|
-
});
|
|
88
|
-
await (0, manager_js_1.createPolicy)(client, "orders");
|
|
89
|
-
const calls = client.query.mock.calls;
|
|
90
|
-
// Only the SELECT check, no CREATE POLICY
|
|
91
|
-
(0, vitest_1.expect)(calls).toHaveLength(1);
|
|
92
|
-
(0, vitest_1.expect)(calls[0][0]).toContain("pg_policies");
|
|
93
|
-
});
|
|
94
|
-
(0, vitest_1.it)("uses the validated table name in the SQL", async () => {
|
|
95
|
-
client.query.mockResolvedValueOnce({
|
|
96
|
-
rows: [{ count: "0" }],
|
|
97
|
-
});
|
|
98
|
-
await (0, manager_js_1.createPolicy)(client, "user_accounts");
|
|
99
|
-
const createCall = client.query.mock
|
|
100
|
-
.calls[1][0];
|
|
101
|
-
(0, vitest_1.expect)(createCall).toContain("ON user_accounts USING");
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
// -----------------------------------------------------------------------
|
|
105
|
-
// dropPolicy
|
|
106
|
-
// -----------------------------------------------------------------------
|
|
107
|
-
(0, vitest_1.describe)("dropPolicy", () => {
|
|
108
|
-
(0, vitest_1.it)("generates correct DROP POLICY SQL", async () => {
|
|
109
|
-
await (0, manager_js_1.dropPolicy)(client, "orders");
|
|
110
|
-
const call = client.query.mock.calls[0];
|
|
111
|
-
(0, vitest_1.expect)(call[0]).toBe("DROP POLICY IF EXISTS tenant_isolation ON orders");
|
|
112
|
-
});
|
|
113
|
-
(0, vitest_1.it)("uses the validated table name", async () => {
|
|
114
|
-
await (0, manager_js_1.dropPolicy)(client, "tenant_invoices");
|
|
115
|
-
const sql = client.query.mock.calls[0][0];
|
|
116
|
-
(0, vitest_1.expect)(sql).toContain("ON tenant_invoices");
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
// -----------------------------------------------------------------------
|
|
120
|
-
// enableRLS
|
|
121
|
-
// -----------------------------------------------------------------------
|
|
122
|
-
(0, vitest_1.describe)("enableRLS", () => {
|
|
123
|
-
(0, vitest_1.it)("generates correct ALTER TABLE statements", async () => {
|
|
124
|
-
await (0, manager_js_1.enableRLS)(client, "products");
|
|
125
|
-
const calls = client.query.mock.calls;
|
|
126
|
-
(0, vitest_1.expect)(calls).toHaveLength(2);
|
|
127
|
-
(0, vitest_1.expect)(calls[0][0]).toBe("ALTER TABLE products ENABLE ROW LEVEL SECURITY");
|
|
128
|
-
(0, vitest_1.expect)(calls[1][0]).toBe("ALTER TABLE products FORCE ROW LEVEL SECURITY");
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
// -----------------------------------------------------------------------
|
|
132
|
-
// disableRLS
|
|
133
|
-
// -----------------------------------------------------------------------
|
|
134
|
-
(0, vitest_1.describe)("disableRLS", () => {
|
|
135
|
-
(0, vitest_1.it)("generates correct ALTER TABLE statements for disabling", async () => {
|
|
136
|
-
await (0, manager_js_1.disableRLS)(client, "products");
|
|
137
|
-
const calls = client.query.mock.calls;
|
|
138
|
-
(0, vitest_1.expect)(calls).toHaveLength(2);
|
|
139
|
-
(0, vitest_1.expect)(calls[0][0]).toBe("ALTER TABLE products NO FORCE ROW LEVEL SECURITY");
|
|
140
|
-
(0, vitest_1.expect)(calls[1][0]).toBe("ALTER TABLE products DISABLE ROW LEVEL SECURITY");
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
// -----------------------------------------------------------------------
|
|
144
|
-
// isRLSEnabled
|
|
145
|
-
// -----------------------------------------------------------------------
|
|
146
|
-
(0, vitest_1.describe)("isRLSEnabled", () => {
|
|
147
|
-
(0, vitest_1.it)("queries pg_class with the table name as a parameter", async () => {
|
|
148
|
-
client.query.mockResolvedValueOnce({
|
|
149
|
-
rows: [{ relrowsecurity: true }],
|
|
150
|
-
});
|
|
151
|
-
await (0, manager_js_1.isRLSEnabled)(client, "orders");
|
|
152
|
-
const call = client.query.mock.calls[0];
|
|
153
|
-
(0, vitest_1.expect)(call[0]).toContain("pg_class");
|
|
154
|
-
(0, vitest_1.expect)(call[0]).toContain("relrowsecurity");
|
|
155
|
-
(0, vitest_1.expect)(call[1]).toEqual(["orders"]);
|
|
156
|
-
});
|
|
157
|
-
(0, vitest_1.it)("returns true when RLS is enabled", async () => {
|
|
158
|
-
client.query.mockResolvedValueOnce({
|
|
159
|
-
rows: [{ relrowsecurity: true }],
|
|
160
|
-
});
|
|
161
|
-
const result = await (0, manager_js_1.isRLSEnabled)(client, "orders");
|
|
162
|
-
(0, vitest_1.expect)(result).toBe(true);
|
|
163
|
-
});
|
|
164
|
-
(0, vitest_1.it)("returns false when RLS is disabled", async () => {
|
|
165
|
-
client.query.mockResolvedValueOnce({
|
|
166
|
-
rows: [{ relrowsecurity: false }],
|
|
167
|
-
});
|
|
168
|
-
const result = await (0, manager_js_1.isRLSEnabled)(client, "orders");
|
|
169
|
-
(0, vitest_1.expect)(result).toBe(false);
|
|
170
|
-
});
|
|
171
|
-
(0, vitest_1.it)("returns false when table does not exist (no rows)", async () => {
|
|
172
|
-
client.query.mockResolvedValueOnce({
|
|
173
|
-
rows: [],
|
|
174
|
-
});
|
|
175
|
-
const result = await (0, manager_js_1.isRLSEnabled)(client, "nonexistent");
|
|
176
|
-
(0, vitest_1.expect)(result).toBe(false);
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
//# sourceMappingURL=rls-manager.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rls-manager.test.js","sourceRoot":"","sources":["../../src/__tests__/rls-manager.test.ts"],"names":[],"mappings":";;AAAA,mCAA8D;AAC9D,kDAM2B;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,wBAAwB;IACxB,0EAA0E;IAE1E,IAAA,iBAAQ,EAAC,uBAAuB,EAAE,GAAG,EAAE;QACrC,IAAA,WAAE,EAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;YAC/D,MAAM,IAAA,eAAM,EAAC,IAAA,yBAAY,EAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CACrE,oBAAoB,CACrB,CAAC;YACF,MAAM,IAAA,eAAM,EAAC,IAAA,uBAAU,EAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CACnE,oBAAoB,CACrB,CAAC;YACF,MAAM,IAAA,eAAM,EAAC,IAAA,sBAAS,EAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAClE,oBAAoB,CACrB,CAAC;YACF,MAAM,IAAA,eAAM,EAAC,IAAA,uBAAU,EAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CACnE,oBAAoB,CACrB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;YACzC,MAAM,IAAA,eAAM,EAAC,IAAA,yBAAY,EAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAC5D,oBAAoB,CACrB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;YACnD,MAAM,IAAA,eAAM,EAAC,IAAA,yBAAY,EAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAC1D,oBAAoB,CACrB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;YAC1C,MAAM,IAAA,eAAM,EAAC,IAAA,yBAAY,EAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAC5D,oBAAoB,CACrB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;YAC9C,MAAM,IAAA,eAAM,EAAC,IAAA,yBAAY,EAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAC3D,oBAAoB,CACrB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;YACpC,MAAM,IAAA,eAAM,EAAC,IAAA,yBAAY,EAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CACpD,oBAAoB,CACrB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;YAChD,MAAM,CAAC,KAAkC,CAAC,qBAAqB,CAAC;gBAC/D,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;aACvB,CAAC,CAAC;YACH,MAAM,IAAA,eAAM,EAAC,IAAA,yBAAY,EAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QACvE,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,KAAK,EAAE,GAAG,EAAE,CAAC;aACvB,CAAC,CAAC;YACH,MAAM,IAAA,eAAM,EACV,IAAA,yBAAY,EAAC,MAAM,EAAE,aAAa,CAAC,CACpC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACrD,MAAM,CAAC,KAAkC,CAAC,qBAAqB,CAAC;gBAC/D,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;aACvB,CAAC,CAAC;YACH,MAAM,IAAA,eAAM,EAAC,IAAA,yBAAY,EAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC3E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,0EAA0E;IAC1E,eAAe;IACf,0EAA0E;IAE1E,IAAA,iBAAQ,EAAC,cAAc,EAAE,GAAG,EAAE;QAC5B,IAAA,WAAE,EAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;YACzD,MAAM,CAAC,KAAkC,CAAC,qBAAqB,CAAC;gBAC/D,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;aACvB,CAAC,CAAC;YAEH,MAAM,IAAA,yBAAY,EAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAErC,MAAM,KAAK,GAAI,MAAM,CAAC,KAAkC,CAAC,IAAI,CAAC,KAAK,CAAC;YACpE,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAE9B,gCAAgC;YAChC,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;YAC7C,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;YAClD,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;YAExC,6BAA6B;YAC7B,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,0CAA0C,CAAC,CAAC;YAC1E,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,0CAA0C,CAAC,CAAC;QAC5E,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,KAAK,EAAE,GAAG,EAAE,CAAC;aACvB,CAAC,CAAC;YAEH,MAAM,IAAA,yBAAY,EAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAErC,MAAM,KAAK,GAAI,MAAM,CAAC,KAAkC,CAAC,IAAI,CAAC,KAAK,CAAC;YACpE,0CAA0C;YAC1C,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,CAAC,KAAkC,CAAC,qBAAqB,CAAC;gBAC/D,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;aACvB,CAAC,CAAC;YAEH,MAAM,IAAA,yBAAY,EAAC,MAAM,EAAE,eAAe,CAAC,CAAC;YAE5C,MAAM,UAAU,GAAI,MAAM,CAAC,KAAkC,CAAC,IAAI;iBAC/D,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACf,IAAA,eAAM,EAAC,UAAU,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,0EAA0E;IAC1E,aAAa;IACb,0EAA0E;IAE1E,IAAA,iBAAQ,EAAC,YAAY,EAAE,GAAG,EAAE;QAC1B,IAAA,WAAE,EAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;YACjD,MAAM,IAAA,uBAAU,EAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAEnC,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,kDAAkD,CACnD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;YAC7C,MAAM,IAAA,uBAAU,EAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;YAE5C,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,oBAAoB,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,0EAA0E;IAC1E,YAAY;IACZ,0EAA0E;IAE1E,IAAA,iBAAQ,EAAC,WAAW,EAAE,GAAG,EAAE;QACzB,IAAA,WAAE,EAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;YACxD,MAAM,IAAA,sBAAS,EAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAEpC,MAAM,KAAK,GAAI,MAAM,CAAC,KAAkC,CAAC,IAAI,CAAC,KAAK,CAAC;YACpE,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACtB,gDAAgD,CACjD,CAAC;YACF,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACtB,+CAA+C,CAChD,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,0EAA0E;IAC1E,aAAa;IACb,0EAA0E;IAE1E,IAAA,iBAAQ,EAAC,YAAY,EAAE,GAAG,EAAE;QAC1B,IAAA,WAAE,EAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;YACtE,MAAM,IAAA,uBAAU,EAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAErC,MAAM,KAAK,GAAI,MAAM,CAAC,KAAkC,CAAC,IAAI,CAAC,KAAK,CAAC;YACpE,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACtB,kDAAkD,CACnD,CAAC;YACF,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACtB,iDAAiD,CAClD,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,0EAA0E;IAC1E,eAAe;IACf,0EAA0E;IAE1E,IAAA,iBAAQ,EAAC,cAAc,EAAE,GAAG,EAAE;QAC5B,IAAA,WAAE,EAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YAClE,MAAM,CAAC,KAAkC,CAAC,qBAAqB,CAAC;gBAC/D,IAAI,EAAE,CAAC,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;aACjC,CAAC,CAAC;YAEH,MAAM,IAAA,yBAAY,EAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAErC,MAAM,IAAI,GAAI,MAAM,CAAC,KAAkC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACtE,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACtC,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;YAC5C,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,CAAC,KAAkC,CAAC,qBAAqB,CAAC;gBAC/D,IAAI,EAAE,CAAC,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;aACjC,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAY,EAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACpD,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;YACjD,MAAM,CAAC,KAAkC,CAAC,qBAAqB,CAAC;gBAC/D,IAAI,EAAE,CAAC,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;aAClC,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAY,EAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACpD,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,CAAC,KAAkC,CAAC,qBAAqB,CAAC;gBAC/D,IAAI,EAAE,EAAE;aACT,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAY,EAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YACzD,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rls-session.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/rls-session.test.ts"],"names":[],"mappings":""}
|