@webiny/api-core-sql 0.0.0-unstable.9f53ea597d
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/LICENSE +21 -0
- package/README.md +11 -0
- package/TableManager.d.ts +16 -0
- package/TableManager.js +26 -0
- package/TableManager.js.map +1 -0
- package/adminUsers/index.d.ts +9 -0
- package/adminUsers/index.js +117 -0
- package/adminUsers/index.js.map +1 -0
- package/createApiCoreSql.d.ts +8 -0
- package/createApiCoreSql.js +32 -0
- package/createApiCoreSql.js.map +1 -0
- package/feature/KnexClient/KnexClient.d.ts +9 -0
- package/feature/KnexClient/KnexClient.js +8 -0
- package/feature/KnexClient/KnexClient.js.map +1 -0
- package/feature/KnexClient/abstractions.d.ts +8 -0
- package/feature/KnexClient/abstractions.js +5 -0
- package/feature/KnexClient/abstractions.js.map +1 -0
- package/feature/KnexClient/index.d.ts +6 -0
- package/feature/KnexClient/index.js +15 -0
- package/feature/KnexClient/index.js.map +1 -0
- package/getSqlTablePrefix.d.ts +1 -0
- package/getSqlTablePrefix.js +4 -0
- package/getSqlTablePrefix.js.map +1 -0
- package/index.d.ts +9 -0
- package/index.js +11 -0
- package/index.js.map +1 -0
- package/keyValueStore/index.d.ts +9 -0
- package/keyValueStore/index.js +84 -0
- package/keyValueStore/index.js.map +1 -0
- package/package.json +43 -0
- package/security/index.d.ts +9 -0
- package/security/index.js +345 -0
- package/security/index.js.map +1 -0
- package/serviceDiscovery/SqlServiceManifestLoader.d.ts +13 -0
- package/serviceDiscovery/SqlServiceManifestLoader.js +25 -0
- package/serviceDiscovery/SqlServiceManifestLoader.js.map +1 -0
- package/serviceDiscovery/index.d.ts +1 -0
- package/serviceDiscovery/index.js +1 -0
- package/sortItems.d.ts +1 -0
- package/sortItems.js +31 -0
- package/sortItems.js.map +1 -0
- package/tenancy/index.d.ts +9 -0
- package/tenancy/index.js +111 -0
- package/tenancy/index.js.map +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Webiny
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# @webiny/api-core-sql
|
|
2
|
+
|
|
3
|
+
> [!NOTE]
|
|
4
|
+
> This package is part of the [Webiny](https://www.webiny.com) monorepo.
|
|
5
|
+
> It’s **included in every Webiny project by default** and is not meant to be used as a standalone package.
|
|
6
|
+
|
|
7
|
+
📘 **Documentation:** [https://www.webiny.com/docs](https://www.webiny.com/docs)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
_This README file is automatically generated during the publish process._
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Knex } from "knex";
|
|
2
|
+
interface ITableManager {
|
|
3
|
+
reset(): void;
|
|
4
|
+
resolve(tableName: string): string;
|
|
5
|
+
ensure(tableName: string, creator: (table: Knex.CreateTableBuilder) => void): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
export declare class TableManager implements ITableManager {
|
|
8
|
+
private readonly knex;
|
|
9
|
+
private readonly prefix;
|
|
10
|
+
private readonly verified;
|
|
11
|
+
constructor(knex: Knex, prefix?: string);
|
|
12
|
+
reset(): void;
|
|
13
|
+
resolve(tableName: string): string;
|
|
14
|
+
ensure(tableName: string, creator: (table: Knex.CreateTableBuilder) => void): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
package/TableManager.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class TableManager {
|
|
2
|
+
constructor(knex, prefix = ""){
|
|
3
|
+
this.verified = new Set();
|
|
4
|
+
this.knex = knex;
|
|
5
|
+
this.prefix = prefix ? `${prefix}_` : "";
|
|
6
|
+
const g = globalThis;
|
|
7
|
+
const managers = g.__sqlTableManagers ??= [];
|
|
8
|
+
managers.push(this);
|
|
9
|
+
}
|
|
10
|
+
reset() {
|
|
11
|
+
this.verified.clear();
|
|
12
|
+
}
|
|
13
|
+
resolve(tableName) {
|
|
14
|
+
return `${this.prefix}${tableName}`;
|
|
15
|
+
}
|
|
16
|
+
async ensure(tableName, creator) {
|
|
17
|
+
const resolved = this.resolve(tableName);
|
|
18
|
+
if (this.verified.has(resolved)) return;
|
|
19
|
+
const exists = await this.knex.schema.hasTable(resolved);
|
|
20
|
+
if (!exists) await this.knex.schema.createTable(resolved, creator);
|
|
21
|
+
this.verified.add(resolved);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export { TableManager };
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=TableManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TableManager.js","sources":["../src/TableManager.ts"],"sourcesContent":["import type { Knex } from \"knex\";\n\ninterface ITableManager {\n reset(): void;\n resolve(tableName: string): string;\n ensure(tableName: string, creator: (table: Knex.CreateTableBuilder) => void): Promise<void>;\n}\n\nexport class TableManager implements ITableManager {\n private readonly knex: Knex;\n private readonly prefix: string;\n private readonly verified = new Set<string>();\n\n constructor(knex: Knex, prefix: string = \"\") {\n this.knex = knex;\n this.prefix = prefix ? `${prefix}_` : \"\";\n\n const g = globalThis as Record<string, unknown>;\n const managers = (g.__sqlTableManagers ??= []) as ITableManager[];\n managers.push(this);\n }\n\n public reset(): void {\n this.verified.clear();\n }\n\n public resolve(tableName: string): string {\n return `${this.prefix}${tableName}`;\n }\n\n public async ensure(\n tableName: string,\n creator: (table: Knex.CreateTableBuilder) => void\n ): Promise<void> {\n const resolved = this.resolve(tableName);\n\n if (this.verified.has(resolved)) {\n return;\n }\n\n const exists = await this.knex.schema.hasTable(resolved);\n\n if (!exists) {\n await this.knex.schema.createTable(resolved, creator);\n }\n\n this.verified.add(resolved);\n }\n}\n"],"names":["TableManager","knex","prefix","Set","g","globalThis","managers","tableName","creator","resolved","exists"],"mappings":"AAQO,MAAMA;IAKT,YAAYC,IAAU,EAAEC,SAAiB,EAAE,CAAE;aAF5B,QAAQ,GAAG,IAAIC;QAG5B,IAAI,CAAC,IAAI,GAAGF;QACZ,IAAI,CAAC,MAAM,GAAGC,SAAS,GAAGA,OAAO,CAAC,CAAC,GAAG;QAEtC,MAAME,IAAIC;QACV,MAAMC,WAAYF,EAAE,kBAAkB,KAAK,EAAE;QAC7CE,SAAS,IAAI,CAAC,IAAI;IACtB;IAEO,QAAc;QACjB,IAAI,CAAC,QAAQ,CAAC,KAAK;IACvB;IAEO,QAAQC,SAAiB,EAAU;QACtC,OAAO,GAAG,IAAI,CAAC,MAAM,GAAGA,WAAW;IACvC;IAEA,MAAa,OACTA,SAAiB,EACjBC,OAAiD,EACpC;QACb,MAAMC,WAAW,IAAI,CAAC,OAAO,CAACF;QAE9B,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAACE,WAClB;QAGJ,MAAMC,SAAS,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAACD;QAE/C,IAAI,CAACC,QACD,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAACD,UAAUD;QAGjD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAACC;IACtB;AACJ"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Knex } from "knex";
|
|
2
|
+
import type { AdminUsersStorageOperations } from "@webiny/api-core/types/users.js";
|
|
3
|
+
import type { TableManager } from "../TableManager.js";
|
|
4
|
+
interface CreateStorageOperationsParams {
|
|
5
|
+
knex: Knex;
|
|
6
|
+
tableManager: TableManager;
|
|
7
|
+
}
|
|
8
|
+
export declare const createStorageOperations: (params: CreateStorageOperationsParams) => AdminUsersStorageOperations;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import error from "@webiny/error";
|
|
2
|
+
import { sortItems } from "../sortItems.js";
|
|
3
|
+
const TABLE_NAME = "webiny_core_admin_users";
|
|
4
|
+
const userToRow = (user)=>({
|
|
5
|
+
id: user.id,
|
|
6
|
+
tenant: user.tenant,
|
|
7
|
+
email: user.email,
|
|
8
|
+
data: JSON.stringify(user)
|
|
9
|
+
});
|
|
10
|
+
const rowToUser = (row)=>JSON.parse(row.data);
|
|
11
|
+
const createStorageOperations = (params)=>{
|
|
12
|
+
const { knex, tableManager } = params;
|
|
13
|
+
const ensureTable = ()=>tableManager.ensure(TABLE_NAME, (table)=>{
|
|
14
|
+
table.text("id").notNullable();
|
|
15
|
+
table.text("tenant").notNullable();
|
|
16
|
+
table.text("email").notNullable();
|
|
17
|
+
table.text("data").notNullable();
|
|
18
|
+
table.primary([
|
|
19
|
+
"tenant",
|
|
20
|
+
"id"
|
|
21
|
+
]);
|
|
22
|
+
table.unique([
|
|
23
|
+
"tenant",
|
|
24
|
+
"email"
|
|
25
|
+
]);
|
|
26
|
+
});
|
|
27
|
+
const query = ()=>knex(tableManager.resolve(TABLE_NAME));
|
|
28
|
+
return {
|
|
29
|
+
async getUser (params) {
|
|
30
|
+
await ensureTable();
|
|
31
|
+
const { where: { tenant, id, email } } = params;
|
|
32
|
+
try {
|
|
33
|
+
if (id) {
|
|
34
|
+
const row = await query().where("tenant", tenant).andWhere("id", id).first();
|
|
35
|
+
return row ? rowToUser(row) : null;
|
|
36
|
+
}
|
|
37
|
+
const row = await query().where("tenant", tenant).andWhere("email", email).first();
|
|
38
|
+
return row ? rowToUser(row) : null;
|
|
39
|
+
} catch (err) {
|
|
40
|
+
throw error.from(err, {
|
|
41
|
+
message: "Could not load user.",
|
|
42
|
+
code: "GET_ADMIN_USERS_ERROR",
|
|
43
|
+
data: {
|
|
44
|
+
id,
|
|
45
|
+
email
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
async listUsers (params) {
|
|
51
|
+
await ensureTable();
|
|
52
|
+
const { where, sort } = params;
|
|
53
|
+
try {
|
|
54
|
+
const rows = await query().where("tenant", where.tenant);
|
|
55
|
+
let items = rows.map((row)=>rowToUser(row));
|
|
56
|
+
items = sortItems(items, sort);
|
|
57
|
+
const { id_in } = where;
|
|
58
|
+
if (Array.isArray(id_in)) return items.filter((item)=>id_in.includes(item.id));
|
|
59
|
+
return items;
|
|
60
|
+
} catch (err) {
|
|
61
|
+
throw error.from(err, {
|
|
62
|
+
message: "Could not list users.",
|
|
63
|
+
code: "LIST_ADMIN_USERS_ERROR"
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
async createUser ({ user }) {
|
|
68
|
+
await ensureTable();
|
|
69
|
+
try {
|
|
70
|
+
const row = userToRow(user);
|
|
71
|
+
await query().insert(row);
|
|
72
|
+
return user;
|
|
73
|
+
} catch (err) {
|
|
74
|
+
throw error.from(err, {
|
|
75
|
+
message: "Could not create admin user.",
|
|
76
|
+
code: "CREATE_ADMIN_USER_ERROR",
|
|
77
|
+
data: {
|
|
78
|
+
user
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
async updateUser ({ user }) {
|
|
84
|
+
await ensureTable();
|
|
85
|
+
try {
|
|
86
|
+
const row = userToRow(user);
|
|
87
|
+
await query().where("tenant", user.tenant).andWhere("id", user.id).update(row);
|
|
88
|
+
return user;
|
|
89
|
+
} catch (err) {
|
|
90
|
+
throw error.from(err, {
|
|
91
|
+
message: "Could not update user.",
|
|
92
|
+
code: "UPDATE_ADMIN_USER_ERROR",
|
|
93
|
+
data: {
|
|
94
|
+
user
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
async deleteUser ({ user }) {
|
|
100
|
+
await ensureTable();
|
|
101
|
+
try {
|
|
102
|
+
await query().where("tenant", user.tenant).andWhere("id", user.id).delete();
|
|
103
|
+
} catch (err) {
|
|
104
|
+
throw error.from(err, {
|
|
105
|
+
message: "Could not delete user.",
|
|
106
|
+
code: "DELETE_ADMIN_USER_ERROR",
|
|
107
|
+
data: {
|
|
108
|
+
user
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
export { createStorageOperations };
|
|
116
|
+
|
|
117
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adminUsers/index.js","sources":["../../src/adminUsers/index.ts"],"sourcesContent":["import type { Knex } from \"knex\";\nimport type {\n AdminUser,\n AdminUsersStorageOperations,\n StorageOperationsGetUserParams,\n StorageOperationsListUsersParams\n} from \"@webiny/api-core/types/users.js\";\nimport WebinyError from \"@webiny/error\";\nimport type { TableManager } from \"~/TableManager.js\";\nimport { sortItems } from \"~/sortItems.js\";\n\nconst TABLE_NAME = \"webiny_core_admin_users\";\n\ninterface IAdminUserRow {\n id: string;\n tenant: string;\n email: string;\n data: string;\n}\n\nconst userToRow = (user: AdminUser): IAdminUserRow => {\n return {\n id: user.id,\n tenant: user.tenant,\n email: user.email,\n data: JSON.stringify(user)\n };\n};\n\nconst rowToUser = <TUser extends AdminUser = AdminUser>(row: IAdminUserRow): TUser => {\n return JSON.parse(row.data) as TUser;\n};\n\ninterface CreateStorageOperationsParams {\n knex: Knex;\n tableManager: TableManager;\n}\n\nexport const createStorageOperations = (\n params: CreateStorageOperationsParams\n): AdminUsersStorageOperations => {\n const { knex, tableManager } = params;\n\n const ensureTable = () => {\n return tableManager.ensure(TABLE_NAME, table => {\n table.text(\"id\").notNullable();\n table.text(\"tenant\").notNullable();\n table.text(\"email\").notNullable();\n table.text(\"data\").notNullable();\n\n table.primary([\"tenant\", \"id\"]);\n table.unique([\"tenant\", \"email\"]);\n });\n };\n\n const query = () => {\n return knex<IAdminUserRow>(tableManager.resolve(TABLE_NAME));\n };\n\n return {\n async getUser<TUser extends AdminUser = AdminUser>(\n params: StorageOperationsGetUserParams\n ): Promise<TUser | null> {\n await ensureTable();\n\n const {\n where: { tenant, id, email }\n } = params;\n\n try {\n if (id) {\n const row = await query().where(\"tenant\", tenant).andWhere(\"id\", id).first();\n\n return row ? rowToUser<TUser>(row) : null;\n }\n\n const row = await query()\n .where(\"tenant\", tenant)\n .andWhere(\"email\", email as string)\n .first();\n\n return row ? rowToUser<TUser>(row) : null;\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not load user.\",\n code: \"GET_ADMIN_USERS_ERROR\",\n data: { id, email }\n });\n }\n },\n\n async listUsers<TUser extends AdminUser = AdminUser>(\n params: StorageOperationsListUsersParams\n ): Promise<TUser[]> {\n await ensureTable();\n\n const { where, sort } = params;\n\n try {\n const rows = await query().where(\"tenant\", where.tenant);\n\n let items = rows.map(row => rowToUser<TUser>(row));\n\n items = sortItems(items, sort);\n\n const { id_in } = where;\n\n if (Array.isArray(id_in)) {\n return items.filter(item => id_in.includes(item.id));\n }\n\n return items;\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list users.\",\n code: \"LIST_ADMIN_USERS_ERROR\"\n });\n }\n },\n\n async createUser<TUser extends AdminUser = AdminUser>({\n user\n }: {\n user: TUser;\n }): Promise<TUser> {\n await ensureTable();\n\n try {\n const row = userToRow(user);\n await query().insert(row);\n\n return user;\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not create admin user.\",\n code: \"CREATE_ADMIN_USER_ERROR\",\n data: { user }\n });\n }\n },\n\n async updateUser<TUser extends AdminUser = AdminUser>({\n user\n }: {\n user: TUser;\n }): Promise<TUser> {\n await ensureTable();\n\n try {\n const row = userToRow(user);\n await query().where(\"tenant\", user.tenant).andWhere(\"id\", user.id).update(row);\n\n return user;\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not update user.\",\n code: \"UPDATE_ADMIN_USER_ERROR\",\n data: { user }\n });\n }\n },\n\n async deleteUser<TUser extends AdminUser = AdminUser>({\n user\n }: {\n user: TUser;\n }): Promise<void> {\n await ensureTable();\n\n try {\n await query().where(\"tenant\", user.tenant).andWhere(\"id\", user.id).delete();\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not delete user.\",\n code: \"DELETE_ADMIN_USER_ERROR\",\n data: { user }\n });\n }\n }\n };\n};\n"],"names":["TABLE_NAME","userToRow","user","JSON","rowToUser","row","createStorageOperations","params","knex","tableManager","ensureTable","table","query","tenant","id","email","err","WebinyError","where","sort","rows","items","sortItems","id_in","Array","item"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Knex } from "knex";
|
|
2
|
+
import type { ApiCoreStorageOperations } from "@webiny/api-core/types/core.js";
|
|
3
|
+
interface CreateApiCoreSqlParams {
|
|
4
|
+
knex: Knex;
|
|
5
|
+
tableNamePrefix?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const createApiCoreSql: ({ knex, tableNamePrefix }: CreateApiCoreSqlParams) => ApiCoreStorageOperations;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ServiceDiscovery } from "@webiny/api-core/features/serviceDiscovery/index.js";
|
|
2
|
+
import { createStorageOperations } from "./adminUsers/index.js";
|
|
3
|
+
import { createStorageOperations as index_js_createStorageOperations } from "./tenancy/index.js";
|
|
4
|
+
import { createStorageOperations as external_security_index_js_createStorageOperations } from "./security/index.js";
|
|
5
|
+
import { createStorageOperations as external_keyValueStore_index_js_createStorageOperations } from "./keyValueStore/index.js";
|
|
6
|
+
import { TableManager } from "./TableManager.js";
|
|
7
|
+
import { SqlServiceManifestLoader } from "./serviceDiscovery/index.js";
|
|
8
|
+
const createApiCoreSql = ({ knex, tableNamePrefix })=>{
|
|
9
|
+
const tableManager = new TableManager(knex, tableNamePrefix);
|
|
10
|
+
ServiceDiscovery.setLoader(new SqlServiceManifestLoader(knex, tableManager));
|
|
11
|
+
return {
|
|
12
|
+
usersStorageOperations: createStorageOperations({
|
|
13
|
+
knex,
|
|
14
|
+
tableManager
|
|
15
|
+
}),
|
|
16
|
+
tenancyStorageOperations: index_js_createStorageOperations({
|
|
17
|
+
knex,
|
|
18
|
+
tableManager
|
|
19
|
+
}),
|
|
20
|
+
securityStorageOperations: external_security_index_js_createStorageOperations({
|
|
21
|
+
knex,
|
|
22
|
+
tableManager
|
|
23
|
+
}),
|
|
24
|
+
keyValueStorageOperations: external_keyValueStore_index_js_createStorageOperations({
|
|
25
|
+
knex,
|
|
26
|
+
tableManager
|
|
27
|
+
})
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export { createApiCoreSql };
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=createApiCoreSql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createApiCoreSql.js","sources":["../src/createApiCoreSql.ts"],"sourcesContent":["import type { Knex } from \"knex\";\nimport type { ApiCoreStorageOperations } from \"@webiny/api-core/types/core.js\";\nimport { ServiceDiscovery } from \"@webiny/api-core/features/serviceDiscovery/index.js\";\nimport { createStorageOperations as createUsersStorageOperations } from \"./adminUsers/index.js\";\nimport { createStorageOperations as createTenancyStorageOperations } from \"./tenancy/index.js\";\nimport { createStorageOperations as createSecurityStorageOperations } from \"./security/index.js\";\nimport { createStorageOperations as createKeyValueStorageOperations } from \"./keyValueStore/index.js\";\nimport { TableManager } from \"./TableManager.js\";\nimport { SqlServiceManifestLoader } from \"./serviceDiscovery/index.js\";\n\ninterface CreateApiCoreSqlParams {\n knex: Knex;\n tableNamePrefix?: string;\n}\n\nexport const createApiCoreSql = ({\n knex,\n tableNamePrefix\n}: CreateApiCoreSqlParams): ApiCoreStorageOperations => {\n const tableManager = new TableManager(knex, tableNamePrefix);\n\n ServiceDiscovery.setLoader(new SqlServiceManifestLoader(knex, tableManager));\n\n return {\n usersStorageOperations: createUsersStorageOperations({\n knex,\n tableManager\n }),\n tenancyStorageOperations: createTenancyStorageOperations({\n knex,\n tableManager\n }),\n securityStorageOperations: createSecurityStorageOperations({\n knex,\n tableManager\n }),\n keyValueStorageOperations: createKeyValueStorageOperations({\n knex,\n tableManager\n })\n };\n};\n"],"names":["createApiCoreSql","knex","tableNamePrefix","tableManager","TableManager","ServiceDiscovery","SqlServiceManifestLoader","createUsersStorageOperations","createTenancyStorageOperations","createSecurityStorageOperations","createKeyValueStorageOperations"],"mappings":";;;;;;;AAeO,MAAMA,mBAAmB,CAAC,EAC7BC,IAAI,EACJC,eAAe,EACM;IACrB,MAAMC,eAAe,IAAIC,aAAaH,MAAMC;IAE5CG,iBAAiB,SAAS,CAAC,IAAIC,yBAAyBL,MAAME;IAE9D,OAAO;QACH,wBAAwBI,wBAA6B;YACjDN;YACAE;QACJ;QACA,0BAA0BK,iCAA+B;YACrDP;YACAE;QACJ;QACA,2BAA2BM,mDAAgC;YACvDR;YACAE;QACJ;QACA,2BAA2BO,wDAAgC;YACvDT;YACAE;QACJ;IACJ;AACJ"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Knex } from "knex";
|
|
2
|
+
import type { KnexClient as Abstraction } from "./abstractions.js";
|
|
3
|
+
export interface IKnexClientParams {
|
|
4
|
+
knex: Knex;
|
|
5
|
+
}
|
|
6
|
+
export declare class KnexClient implements Abstraction.Interface {
|
|
7
|
+
readonly client: Knex<any, any[]>;
|
|
8
|
+
constructor(params: IKnexClientParams);
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature/KnexClient/KnexClient.js","sources":["../../../src/feature/KnexClient/KnexClient.ts"],"sourcesContent":["import type { Knex } from \"knex\";\nimport type { KnexClient as Abstraction } from \"./abstractions.js\";\n\nexport interface IKnexClientParams {\n knex: Knex;\n}\n\nexport class KnexClient implements Abstraction.Interface {\n public readonly client;\n\n public constructor(params: IKnexClientParams) {\n this.client = params.knex;\n }\n}\n"],"names":["KnexClient","params"],"mappings":"AAOO,MAAMA;IAGT,YAAmBC,MAAyB,CAAE;QAC1C,IAAI,CAAC,MAAM,GAAGA,OAAO,IAAI;IAC7B;AACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature/KnexClient/abstractions.js","sources":["../../../src/feature/KnexClient/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport type { Knex } from \"knex\";\n\nexport interface IKnexClient {\n readonly client: Knex;\n}\n\nexport const KnexClient = createAbstraction<IKnexClient>(\"Db/Sql/KnexClient\");\n\nexport namespace KnexClient {\n export type Interface = IKnexClient;\n}\n"],"names":["KnexClient","createAbstraction"],"mappings":";AAOO,MAAMA,aAAaC,kBAA+B"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createFeature } from "@webiny/feature/api";
|
|
2
|
+
import { KnexClient } from "./abstractions.js";
|
|
3
|
+
import { KnexClient as external_KnexClient_js_KnexClient } from "./KnexClient.js";
|
|
4
|
+
const KnexClientFeature = createFeature({
|
|
5
|
+
name: "Db/Sql/KnexClientFeature",
|
|
6
|
+
register (container, knex) {
|
|
7
|
+
const client = new external_KnexClient_js_KnexClient({
|
|
8
|
+
knex
|
|
9
|
+
});
|
|
10
|
+
container.registerInstance(KnexClient, client);
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
export { KnexClient, KnexClientFeature };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature/KnexClient/index.js","sources":["../../../src/feature/KnexClient/index.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport type { Knex } from \"knex\";\nimport { KnexClient as KnexClientAbstraction } from \"./abstractions.js\";\nimport { KnexClient } from \"./KnexClient.js\";\n\nexport { KnexClient } from \"./abstractions.js\";\n\nexport const KnexClientFeature = createFeature<Knex>({\n name: \"Db/Sql/KnexClientFeature\",\n register(container, knex) {\n const client = new KnexClient({ knex });\n container.registerInstance(KnexClientAbstraction, client);\n }\n});\n"],"names":["KnexClientFeature","createFeature","container","knex","client","KnexClient","KnexClientAbstraction"],"mappings":";;;AAOO,MAAMA,oBAAoBC,cAAoB;IACjD,MAAM;IACN,UAASC,SAAS,EAAEC,IAAI;QACpB,MAAMC,SAAS,IAAIC,kCAAW;YAAEF;QAAK;QACrCD,UAAU,gBAAgB,CAACI,YAAuBF;IACtD;AACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getSqlTablePrefix: () => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getSqlTablePrefix.js","sources":["../src/getSqlTablePrefix.ts"],"sourcesContent":["export const getSqlTablePrefix = (): string => {\n return process.env.SQL_TABLE_PREFIX || process.env.WEBINY_SQL_TABLE_PREFIX || \"\";\n};\n"],"names":["getSqlTablePrefix","process"],"mappings":"AAAO,MAAMA,oBAAoB,IACtBC,QAAQ,GAAG,CAAC,gBAAgB,IAAIA,QAAQ,GAAG,CAAC,uBAAuB,IAAI"}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Knex } from "knex";
|
|
2
|
+
export { createApiCoreSql } from "./createApiCoreSql.js";
|
|
3
|
+
export { getSqlTablePrefix } from "./getSqlTablePrefix.js";
|
|
4
|
+
export { SqlServiceManifestLoader } from "./serviceDiscovery/index.js";
|
|
5
|
+
export { KnexClient } from "./feature/KnexClient/index.js";
|
|
6
|
+
interface IRegisterApiCoreSqlExtension {
|
|
7
|
+
knex: Knex;
|
|
8
|
+
}
|
|
9
|
+
export declare const registerSQLCore: ({ knex }: IRegisterApiCoreSqlExtension) => import("@webiny/handler").RegisterExtensionPlugin<import("@webiny/handler/types.js").Context>;
|
package/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createRegisterExtensionPlugin } from "@webiny/handler";
|
|
2
|
+
import { KnexClient, KnexClientFeature } from "./feature/KnexClient/index.js";
|
|
3
|
+
const registerSQLCore = ({ knex })=>createRegisterExtensionPlugin(async (context)=>{
|
|
4
|
+
KnexClientFeature.register(context.container, knex);
|
|
5
|
+
});
|
|
6
|
+
export { createApiCoreSql } from "./createApiCoreSql.js";
|
|
7
|
+
export { getSqlTablePrefix } from "./getSqlTablePrefix.js";
|
|
8
|
+
export { SqlServiceManifestLoader } from "./serviceDiscovery/index.js";
|
|
9
|
+
export { KnexClient, registerSQLCore };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
package/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { createRegisterExtensionPlugin } from \"@webiny/handler\";\nimport type { Knex } from \"knex\";\nimport { KnexClientFeature } from \"./feature/KnexClient/index.js\";\n\nexport { createApiCoreSql } from \"./createApiCoreSql.js\";\nexport { getSqlTablePrefix } from \"./getSqlTablePrefix.js\";\nexport { SqlServiceManifestLoader } from \"./serviceDiscovery/index.js\";\n\nexport { KnexClient } from \"./feature/KnexClient/index.js\";\n\ninterface IRegisterApiCoreSqlExtension {\n knex: Knex;\n}\n\nexport const registerSQLCore = ({ knex }: IRegisterApiCoreSqlExtension) => {\n return createRegisterExtensionPlugin(async context => {\n KnexClientFeature.register(context.container, knex);\n });\n};\n"],"names":["registerSQLCore","knex","createRegisterExtensionPlugin","context","KnexClientFeature"],"mappings":";;AAcO,MAAMA,kBAAkB,CAAC,EAAEC,IAAI,EAAgC,GAC3DC,8BAA8B,OAAMC;QACvCC,kBAAkB,QAAQ,CAACD,QAAQ,SAAS,EAAEF;IAClD"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Knex } from "knex";
|
|
2
|
+
import type { IKeyValueStorageOperations } from "@webiny/api-core/features/keyValueStore/abstractions.js";
|
|
3
|
+
import type { TableManager } from "../TableManager.js";
|
|
4
|
+
interface CreateStorageOperationsParams {
|
|
5
|
+
knex: Knex;
|
|
6
|
+
tableManager: TableManager;
|
|
7
|
+
}
|
|
8
|
+
export declare const createStorageOperations: (params: CreateStorageOperationsParams) => IKeyValueStorageOperations;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { WebinyError } from "@webiny/error";
|
|
2
|
+
const TABLE_NAME = "webiny_core_key_value";
|
|
3
|
+
const createStorageOperations = (params)=>{
|
|
4
|
+
const { knex, tableManager } = params;
|
|
5
|
+
const ensureTable = ()=>tableManager.ensure(TABLE_NAME, (table)=>{
|
|
6
|
+
table.text("scopedKey").primary().notNullable();
|
|
7
|
+
table.text("key").notNullable();
|
|
8
|
+
table.text("scope").notNullable();
|
|
9
|
+
table.text("value").notNullable();
|
|
10
|
+
table.datetime("expiresAt");
|
|
11
|
+
});
|
|
12
|
+
const query = ()=>knex(tableManager.resolve(TABLE_NAME));
|
|
13
|
+
const createScopedKey = (key, scope)=>`${scope}:${key}`;
|
|
14
|
+
return {
|
|
15
|
+
async get (key, scope) {
|
|
16
|
+
await ensureTable();
|
|
17
|
+
try {
|
|
18
|
+
const scopedKey = createScopedKey(key, scope);
|
|
19
|
+
const row = await query().where("scopedKey", scopedKey).first();
|
|
20
|
+
if (!row) return null;
|
|
21
|
+
if (row.expiresAt && new Date(row.expiresAt) <= new Date()) {
|
|
22
|
+
await query().where("scopedKey", scopedKey).delete();
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
key,
|
|
27
|
+
value: JSON.parse(row.value)
|
|
28
|
+
};
|
|
29
|
+
} catch (err) {
|
|
30
|
+
throw WebinyError.from(err, {
|
|
31
|
+
message: "Could not get key-value record.",
|
|
32
|
+
code: "GET_KEY_VALUE_ERROR",
|
|
33
|
+
data: {
|
|
34
|
+
key,
|
|
35
|
+
scope
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
async set (key, value, scope, options) {
|
|
41
|
+
await ensureTable();
|
|
42
|
+
try {
|
|
43
|
+
const scopedKey = createScopedKey(key, scope);
|
|
44
|
+
const expiresAt = options?.expiresAt ?? null;
|
|
45
|
+
const row = {
|
|
46
|
+
scopedKey,
|
|
47
|
+
key,
|
|
48
|
+
scope,
|
|
49
|
+
value: JSON.stringify(value),
|
|
50
|
+
expiresAt
|
|
51
|
+
};
|
|
52
|
+
await query().insert(row).onConflict("scopedKey").merge();
|
|
53
|
+
} catch (err) {
|
|
54
|
+
throw WebinyError.from(err, {
|
|
55
|
+
message: "Could not set key-value record.",
|
|
56
|
+
code: "SET_KEY_VALUE_ERROR",
|
|
57
|
+
data: {
|
|
58
|
+
key,
|
|
59
|
+
scope
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
async delete (key, scope) {
|
|
65
|
+
await ensureTable();
|
|
66
|
+
try {
|
|
67
|
+
const scopedKey = createScopedKey(key, scope);
|
|
68
|
+
await query().where("scopedKey", scopedKey).delete();
|
|
69
|
+
} catch (err) {
|
|
70
|
+
throw WebinyError.from(err, {
|
|
71
|
+
message: "Could not delete key-value record.",
|
|
72
|
+
code: "DELETE_KEY_VALUE_ERROR",
|
|
73
|
+
data: {
|
|
74
|
+
key,
|
|
75
|
+
scope
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
export { createStorageOperations };
|
|
83
|
+
|
|
84
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyValueStore/index.js","sources":["../../src/keyValueStore/index.ts"],"sourcesContent":["import type { Knex } from \"knex\";\nimport type {\n IKeyValueStorageOperations,\n IKeyValueStoreSetOptions\n} from \"@webiny/api-core/features/keyValueStore/abstractions.js\";\nimport { WebinyError } from \"@webiny/error\";\nimport type { TableManager } from \"~/TableManager.js\";\n\nconst TABLE_NAME = \"webiny_core_key_value\";\n\ninterface IKeyValueRow {\n scopedKey: string;\n key: string;\n scope: string;\n value: string;\n expiresAt: Date | null;\n}\n\ninterface CreateStorageOperationsParams {\n knex: Knex;\n tableManager: TableManager;\n}\n\nexport const createStorageOperations = (\n params: CreateStorageOperationsParams\n): IKeyValueStorageOperations => {\n const { knex, tableManager } = params;\n\n const ensureTable = () => {\n return tableManager.ensure(TABLE_NAME, table => {\n table.text(\"scopedKey\").primary().notNullable();\n table.text(\"key\").notNullable();\n table.text(\"scope\").notNullable();\n table.text(\"value\").notNullable();\n table.datetime(\"expiresAt\");\n });\n };\n\n const query = () => {\n return knex<IKeyValueRow>(tableManager.resolve(TABLE_NAME));\n };\n\n const createScopedKey = (key: string, scope: string): string => {\n return `${scope}:${key}`;\n };\n\n return {\n async get(key: string, scope: string) {\n await ensureTable();\n\n try {\n const scopedKey = createScopedKey(key, scope);\n const row = await query().where(\"scopedKey\", scopedKey).first();\n\n if (!row) {\n return null;\n }\n\n if (row.expiresAt && new Date(row.expiresAt) <= new Date()) {\n await query().where(\"scopedKey\", scopedKey).delete();\n return null;\n }\n\n return {\n key,\n value: JSON.parse(row.value)\n };\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not get key-value record.\",\n code: \"GET_KEY_VALUE_ERROR\",\n data: { key, scope }\n });\n }\n },\n\n async set(key: string, value: any, scope: string, options?: IKeyValueStoreSetOptions) {\n await ensureTable();\n\n try {\n const scopedKey = createScopedKey(key, scope);\n const expiresAt = options?.expiresAt ?? null;\n\n const row: IKeyValueRow = {\n scopedKey,\n key,\n scope,\n value: JSON.stringify(value),\n expiresAt\n };\n\n await query().insert(row).onConflict(\"scopedKey\").merge();\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not set key-value record.\",\n code: \"SET_KEY_VALUE_ERROR\",\n data: { key, scope }\n });\n }\n },\n\n async delete(key: string, scope: string) {\n await ensureTable();\n\n try {\n const scopedKey = createScopedKey(key, scope);\n await query().where(\"scopedKey\", scopedKey).delete();\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not delete key-value record.\",\n code: \"DELETE_KEY_VALUE_ERROR\",\n data: { key, scope }\n });\n }\n }\n };\n};\n"],"names":["TABLE_NAME","createStorageOperations","params","knex","tableManager","ensureTable","table","query","createScopedKey","key","scope","scopedKey","row","Date","JSON","err","WebinyError","value","options","expiresAt"],"mappings":";AAQA,MAAMA,aAAa;AAeZ,MAAMC,0BAA0B,CACnCC;IAEA,MAAM,EAAEC,IAAI,EAAEC,YAAY,EAAE,GAAGF;IAE/B,MAAMG,cAAc,IACTD,aAAa,MAAM,CAACJ,YAAYM,CAAAA;YACnCA,MAAM,IAAI,CAAC,aAAa,OAAO,GAAG,WAAW;YAC7CA,MAAM,IAAI,CAAC,OAAO,WAAW;YAC7BA,MAAM,IAAI,CAAC,SAAS,WAAW;YAC/BA,MAAM,IAAI,CAAC,SAAS,WAAW;YAC/BA,MAAM,QAAQ,CAAC;QACnB;IAGJ,MAAMC,QAAQ,IACHJ,KAAmBC,aAAa,OAAO,CAACJ;IAGnD,MAAMQ,kBAAkB,CAACC,KAAaC,QAC3B,GAAGA,MAAM,CAAC,EAAED,KAAK;IAG5B,OAAO;QACH,MAAM,KAAIA,GAAW,EAAEC,KAAa;YAChC,MAAML;YAEN,IAAI;gBACA,MAAMM,YAAYH,gBAAgBC,KAAKC;gBACvC,MAAME,MAAM,MAAML,QAAQ,KAAK,CAAC,aAAaI,WAAW,KAAK;gBAE7D,IAAI,CAACC,KACD,OAAO;gBAGX,IAAIA,IAAI,SAAS,IAAI,IAAIC,KAAKD,IAAI,SAAS,KAAK,IAAIC,QAAQ;oBACxD,MAAMN,QAAQ,KAAK,CAAC,aAAaI,WAAW,MAAM;oBAClD,OAAO;gBACX;gBAEA,OAAO;oBACHF;oBACA,OAAOK,KAAK,KAAK,CAACF,IAAI,KAAK;gBAC/B;YACJ,EAAE,OAAOG,KAAK;gBACV,MAAMC,YAAY,IAAI,CAACD,KAAK;oBACxB,SAAS;oBACT,MAAM;oBACN,MAAM;wBAAEN;wBAAKC;oBAAM;gBACvB;YACJ;QACJ;QAEA,MAAM,KAAID,GAAW,EAAEQ,KAAU,EAAEP,KAAa,EAAEQ,OAAkC;YAChF,MAAMb;YAEN,IAAI;gBACA,MAAMM,YAAYH,gBAAgBC,KAAKC;gBACvC,MAAMS,YAAYD,SAAS,aAAa;gBAExC,MAAMN,MAAoB;oBACtBD;oBACAF;oBACAC;oBACA,OAAOI,KAAK,SAAS,CAACG;oBACtBE;gBACJ;gBAEA,MAAMZ,QAAQ,MAAM,CAACK,KAAK,UAAU,CAAC,aAAa,KAAK;YAC3D,EAAE,OAAOG,KAAK;gBACV,MAAMC,YAAY,IAAI,CAACD,KAAK;oBACxB,SAAS;oBACT,MAAM;oBACN,MAAM;wBAAEN;wBAAKC;oBAAM;gBACvB;YACJ;QACJ;QAEA,MAAM,QAAOD,GAAW,EAAEC,KAAa;YACnC,MAAML;YAEN,IAAI;gBACA,MAAMM,YAAYH,gBAAgBC,KAAKC;gBACvC,MAAMH,QAAQ,KAAK,CAAC,aAAaI,WAAW,MAAM;YACtD,EAAE,OAAOI,KAAK;gBACV,MAAMC,YAAY,IAAI,CAACD,KAAK;oBACxB,SAAS;oBACT,MAAM;oBACN,MAAM;wBAAEN;wBAAKC;oBAAM;gBACvB;YACJ;QACJ;IACJ;AACJ"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@webiny/api-core-sql",
|
|
3
|
+
"version": "0.0.0-unstable.9f53ea597d",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./index.js",
|
|
7
|
+
"./*": "./*"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/webiny/webiny-js.git"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"@webiny/api-core",
|
|
15
|
+
"storage-operations",
|
|
16
|
+
"sql",
|
|
17
|
+
"knex",
|
|
18
|
+
"sau:sql"
|
|
19
|
+
],
|
|
20
|
+
"description": "SQL-specific dependencies for @webiny/api-core.",
|
|
21
|
+
"author": "Webiny Ltd.",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@webiny/api-core": "0.0.0-unstable.9f53ea597d",
|
|
25
|
+
"@webiny/error": "0.0.0-unstable.9f53ea597d",
|
|
26
|
+
"@webiny/feature": "0.0.0-unstable.9f53ea597d",
|
|
27
|
+
"@webiny/handler": "0.0.0-unstable.9f53ea597d",
|
|
28
|
+
"knex": "3.3.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@webiny/build-tools": "0.0.0-unstable.9f53ea597d",
|
|
32
|
+
"@webiny/project-utils": "0.0.0-unstable.9f53ea597d",
|
|
33
|
+
"better-sqlite3": "13.0.1",
|
|
34
|
+
"typescript": "7.0.2",
|
|
35
|
+
"vitest": "4.1.10"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"webiny": {
|
|
41
|
+
"publishFrom": "dist"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Knex } from "knex";
|
|
2
|
+
import type { SecurityStorageOperations } from "@webiny/api-core/types/security.js";
|
|
3
|
+
import type { TableManager } from "../TableManager.js";
|
|
4
|
+
interface CreateStorageOperationsParams {
|
|
5
|
+
knex: Knex;
|
|
6
|
+
tableManager: TableManager;
|
|
7
|
+
}
|
|
8
|
+
export declare const createStorageOperations: (params: CreateStorageOperationsParams) => SecurityStorageOperations;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import error from "@webiny/error";
|
|
2
|
+
import { sortItems } from "../sortItems.js";
|
|
3
|
+
const ROLES_TABLE = "webiny_core_roles";
|
|
4
|
+
const TEAMS_TABLE = "webiny_core_teams";
|
|
5
|
+
const API_KEYS_TABLE = "webiny_core_api_keys";
|
|
6
|
+
const createStorageOperations = (params)=>{
|
|
7
|
+
const { knex, tableManager } = params;
|
|
8
|
+
const ensureRolesTable = ()=>tableManager.ensure(ROLES_TABLE, (table)=>{
|
|
9
|
+
table.text("id").notNullable();
|
|
10
|
+
table.text("tenant").notNullable();
|
|
11
|
+
table.text("slug").notNullable();
|
|
12
|
+
table.text("data").notNullable();
|
|
13
|
+
table.primary([
|
|
14
|
+
"tenant",
|
|
15
|
+
"id"
|
|
16
|
+
]);
|
|
17
|
+
table.unique([
|
|
18
|
+
"tenant",
|
|
19
|
+
"slug"
|
|
20
|
+
]);
|
|
21
|
+
});
|
|
22
|
+
const ensureTeamsTable = ()=>tableManager.ensure(TEAMS_TABLE, (table)=>{
|
|
23
|
+
table.text("id").notNullable();
|
|
24
|
+
table.text("tenant").notNullable();
|
|
25
|
+
table.text("slug").notNullable();
|
|
26
|
+
table.text("data").notNullable();
|
|
27
|
+
table.primary([
|
|
28
|
+
"tenant",
|
|
29
|
+
"id"
|
|
30
|
+
]);
|
|
31
|
+
table.unique([
|
|
32
|
+
"tenant",
|
|
33
|
+
"slug"
|
|
34
|
+
]);
|
|
35
|
+
});
|
|
36
|
+
const ensureApiKeysTable = ()=>tableManager.ensure(API_KEYS_TABLE, (table)=>{
|
|
37
|
+
table.text("id").notNullable();
|
|
38
|
+
table.text("tenant").notNullable();
|
|
39
|
+
table.text("token").notNullable();
|
|
40
|
+
table.text("slug").notNullable();
|
|
41
|
+
table.text("data").notNullable();
|
|
42
|
+
table.primary([
|
|
43
|
+
"tenant",
|
|
44
|
+
"id"
|
|
45
|
+
]);
|
|
46
|
+
table.unique([
|
|
47
|
+
"tenant",
|
|
48
|
+
"token"
|
|
49
|
+
]);
|
|
50
|
+
table.unique([
|
|
51
|
+
"tenant",
|
|
52
|
+
"slug"
|
|
53
|
+
]);
|
|
54
|
+
});
|
|
55
|
+
const rolesQuery = ()=>knex(tableManager.resolve(ROLES_TABLE));
|
|
56
|
+
const teamsQuery = ()=>knex(tableManager.resolve(TEAMS_TABLE));
|
|
57
|
+
const apiKeysQuery = ()=>knex(tableManager.resolve(API_KEYS_TABLE));
|
|
58
|
+
return {
|
|
59
|
+
async getRole ({ where: { tenant, id, slug } }) {
|
|
60
|
+
await ensureRolesTable();
|
|
61
|
+
try {
|
|
62
|
+
if (id) {
|
|
63
|
+
const row = await rolesQuery().where("tenant", tenant).andWhere("id", id).first();
|
|
64
|
+
return row ? JSON.parse(row.data) : null;
|
|
65
|
+
}
|
|
66
|
+
const row = await rolesQuery().where("tenant", tenant).andWhere("slug", slug).first();
|
|
67
|
+
return row ? JSON.parse(row.data) : null;
|
|
68
|
+
} catch (err) {
|
|
69
|
+
throw error.from(err, {
|
|
70
|
+
message: "Could not load role.",
|
|
71
|
+
code: "GET_ROLE_ERROR",
|
|
72
|
+
data: {
|
|
73
|
+
id,
|
|
74
|
+
slug
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
async listRoles ({ where: { tenant, id_in, slug_in }, sort }) {
|
|
80
|
+
await ensureRolesTable();
|
|
81
|
+
try {
|
|
82
|
+
const qb = rolesQuery().where("tenant", tenant);
|
|
83
|
+
if (Array.isArray(id_in)) qb.whereIn("id", id_in);
|
|
84
|
+
else if (Array.isArray(slug_in)) qb.whereIn("slug", slug_in);
|
|
85
|
+
const rows = await qb;
|
|
86
|
+
const items = rows.map((row)=>JSON.parse(row.data));
|
|
87
|
+
return sortItems(items, sort);
|
|
88
|
+
} catch (err) {
|
|
89
|
+
throw error.from(err, {
|
|
90
|
+
message: "Could not list roles.",
|
|
91
|
+
code: "LIST_ROLE_ERROR"
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
async createRole ({ role }) {
|
|
96
|
+
await ensureRolesTable();
|
|
97
|
+
try {
|
|
98
|
+
await rolesQuery().insert({
|
|
99
|
+
id: role.id,
|
|
100
|
+
tenant: role.tenant,
|
|
101
|
+
slug: role.slug,
|
|
102
|
+
data: JSON.stringify(role)
|
|
103
|
+
});
|
|
104
|
+
} catch (err) {
|
|
105
|
+
throw error.from(err, {
|
|
106
|
+
message: "Could not create role.",
|
|
107
|
+
code: "CREATE_ROLE_ERROR",
|
|
108
|
+
data: {
|
|
109
|
+
role
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
async updateRole ({ role }) {
|
|
115
|
+
await ensureRolesTable();
|
|
116
|
+
try {
|
|
117
|
+
await rolesQuery().where("tenant", role.tenant).andWhere("id", role.id).update({
|
|
118
|
+
slug: role.slug,
|
|
119
|
+
data: JSON.stringify(role)
|
|
120
|
+
});
|
|
121
|
+
} catch (err) {
|
|
122
|
+
throw error.from(err, {
|
|
123
|
+
message: "Could not update role.",
|
|
124
|
+
code: "UPDATE_ROLE_ERROR",
|
|
125
|
+
data: {
|
|
126
|
+
role
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
async deleteRole ({ role }) {
|
|
132
|
+
await ensureRolesTable();
|
|
133
|
+
try {
|
|
134
|
+
await rolesQuery().where("tenant", role.tenant).andWhere("id", role.id).delete();
|
|
135
|
+
} catch (err) {
|
|
136
|
+
throw error.from(err, {
|
|
137
|
+
message: "Could not delete role.",
|
|
138
|
+
code: "DELETE_ROLE_ERROR",
|
|
139
|
+
data: {
|
|
140
|
+
role
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
async getTeam ({ where: { tenant, id, slug } }) {
|
|
146
|
+
await ensureTeamsTable();
|
|
147
|
+
try {
|
|
148
|
+
if (id) {
|
|
149
|
+
const row = await teamsQuery().where("tenant", tenant).andWhere("id", id).first();
|
|
150
|
+
return row ? JSON.parse(row.data) : null;
|
|
151
|
+
}
|
|
152
|
+
const row = await teamsQuery().where("tenant", tenant).andWhere("slug", slug).first();
|
|
153
|
+
return row ? JSON.parse(row.data) : null;
|
|
154
|
+
} catch (err) {
|
|
155
|
+
throw error.from(err, {
|
|
156
|
+
message: "Could not load team.",
|
|
157
|
+
code: "GET_TEAM_ERROR",
|
|
158
|
+
data: {
|
|
159
|
+
id,
|
|
160
|
+
slug
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
async listTeams ({ where: { tenant, id_in, slug_in }, sort }) {
|
|
166
|
+
await ensureTeamsTable();
|
|
167
|
+
try {
|
|
168
|
+
const qb = teamsQuery().where("tenant", tenant);
|
|
169
|
+
if (Array.isArray(id_in)) qb.whereIn("id", id_in);
|
|
170
|
+
else if (Array.isArray(slug_in)) qb.whereIn("slug", slug_in);
|
|
171
|
+
const rows = await qb;
|
|
172
|
+
const items = rows.map((row)=>JSON.parse(row.data));
|
|
173
|
+
return sortItems(items, sort);
|
|
174
|
+
} catch (err) {
|
|
175
|
+
throw error.from(err, {
|
|
176
|
+
message: "Could not list teams.",
|
|
177
|
+
code: "LIST_TEAM_ERROR"
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
async createTeam ({ team }) {
|
|
182
|
+
await ensureTeamsTable();
|
|
183
|
+
try {
|
|
184
|
+
await teamsQuery().insert({
|
|
185
|
+
id: team.id,
|
|
186
|
+
tenant: team.tenant,
|
|
187
|
+
slug: team.slug,
|
|
188
|
+
data: JSON.stringify(team)
|
|
189
|
+
});
|
|
190
|
+
} catch (err) {
|
|
191
|
+
throw error.from(err, {
|
|
192
|
+
message: "Could not create team.",
|
|
193
|
+
code: "CREATE_TEAM_ERROR",
|
|
194
|
+
data: {
|
|
195
|
+
team
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
async updateTeam ({ team }) {
|
|
201
|
+
await ensureTeamsTable();
|
|
202
|
+
try {
|
|
203
|
+
await teamsQuery().where("tenant", team.tenant).andWhere("id", team.id).update({
|
|
204
|
+
slug: team.slug,
|
|
205
|
+
data: JSON.stringify(team)
|
|
206
|
+
});
|
|
207
|
+
} catch (err) {
|
|
208
|
+
throw error.from(err, {
|
|
209
|
+
message: "Could not update team.",
|
|
210
|
+
code: "UPDATE_TEAM_ERROR",
|
|
211
|
+
data: {
|
|
212
|
+
team
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
async deleteTeam ({ team }) {
|
|
218
|
+
await ensureTeamsTable();
|
|
219
|
+
try {
|
|
220
|
+
await teamsQuery().where("tenant", team.tenant).andWhere("id", team.id).delete();
|
|
221
|
+
} catch (err) {
|
|
222
|
+
throw error.from(err, {
|
|
223
|
+
message: "Could not delete team.",
|
|
224
|
+
code: "DELETE_TEAM_ERROR",
|
|
225
|
+
data: {
|
|
226
|
+
team
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
async getApiKey ({ id, tenant }) {
|
|
232
|
+
await ensureApiKeysTable();
|
|
233
|
+
try {
|
|
234
|
+
const row = await apiKeysQuery().where("tenant", tenant).andWhere("id", id).first();
|
|
235
|
+
return row ? JSON.parse(row.data) : null;
|
|
236
|
+
} catch (err) {
|
|
237
|
+
throw error.from(err, {
|
|
238
|
+
message: "Could not load api key.",
|
|
239
|
+
code: "GET_API_KEY_ERROR",
|
|
240
|
+
data: {
|
|
241
|
+
id
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
async getApiKeyByToken ({ tenant, token }) {
|
|
247
|
+
await ensureApiKeysTable();
|
|
248
|
+
try {
|
|
249
|
+
const row = await apiKeysQuery().where("tenant", tenant).andWhere("token", token).first();
|
|
250
|
+
return row ? JSON.parse(row.data) : null;
|
|
251
|
+
} catch (err) {
|
|
252
|
+
throw error.from(err, {
|
|
253
|
+
message: "Could not load api key by token.",
|
|
254
|
+
code: "GET_BY_TOKEN_API_KEY_ERROR",
|
|
255
|
+
data: {
|
|
256
|
+
token
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
async getApiKeyBySlug ({ tenant, slug }) {
|
|
262
|
+
await ensureApiKeysTable();
|
|
263
|
+
try {
|
|
264
|
+
const row = await apiKeysQuery().where("tenant", tenant).andWhere("slug", slug).first();
|
|
265
|
+
return row ? JSON.parse(row.data) : null;
|
|
266
|
+
} catch (err) {
|
|
267
|
+
throw error.from(err, {
|
|
268
|
+
message: "Could not load api key by slug.",
|
|
269
|
+
code: "GET_BY_SLUG_API_KEY_ERROR",
|
|
270
|
+
data: {
|
|
271
|
+
slug
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
async listApiKeys ({ where: { tenant }, sort }) {
|
|
277
|
+
await ensureApiKeysTable();
|
|
278
|
+
try {
|
|
279
|
+
const rows = await apiKeysQuery().where("tenant", tenant);
|
|
280
|
+
const items = rows.map((row)=>JSON.parse(row.data));
|
|
281
|
+
return sortItems(items, sort);
|
|
282
|
+
} catch (err) {
|
|
283
|
+
throw error.from(err, {
|
|
284
|
+
message: "Could not list api keys.",
|
|
285
|
+
code: "LIST_API_KEY_ERROR"
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
async createApiKey ({ apiKey }) {
|
|
290
|
+
await ensureApiKeysTable();
|
|
291
|
+
try {
|
|
292
|
+
await apiKeysQuery().insert({
|
|
293
|
+
id: apiKey.id,
|
|
294
|
+
tenant: apiKey.tenant,
|
|
295
|
+
token: apiKey.token,
|
|
296
|
+
slug: apiKey.slug,
|
|
297
|
+
data: JSON.stringify(apiKey)
|
|
298
|
+
});
|
|
299
|
+
} catch (err) {
|
|
300
|
+
throw error.from(err, {
|
|
301
|
+
message: "Could not create api key.",
|
|
302
|
+
code: "CREATE_API_KEY_ERROR",
|
|
303
|
+
data: {
|
|
304
|
+
apiKey
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
async updateApiKey ({ apiKey }) {
|
|
310
|
+
await ensureApiKeysTable();
|
|
311
|
+
try {
|
|
312
|
+
await apiKeysQuery().where("tenant", apiKey.tenant).andWhere("id", apiKey.id).update({
|
|
313
|
+
token: apiKey.token,
|
|
314
|
+
slug: apiKey.slug,
|
|
315
|
+
data: JSON.stringify(apiKey)
|
|
316
|
+
});
|
|
317
|
+
} catch (err) {
|
|
318
|
+
throw error.from(err, {
|
|
319
|
+
message: "Could not update api key.",
|
|
320
|
+
code: "UPDATE_API_KEY_ERROR",
|
|
321
|
+
data: {
|
|
322
|
+
apiKey
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
async deleteApiKey ({ apiKey }) {
|
|
328
|
+
await ensureApiKeysTable();
|
|
329
|
+
try {
|
|
330
|
+
await apiKeysQuery().where("tenant", apiKey.tenant).andWhere("id", apiKey.id).delete();
|
|
331
|
+
} catch (err) {
|
|
332
|
+
throw error.from(err, {
|
|
333
|
+
message: "Could not delete api key.",
|
|
334
|
+
code: "DELETE_API_KEY_ERROR",
|
|
335
|
+
data: {
|
|
336
|
+
apiKey
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
};
|
|
343
|
+
export { createStorageOperations };
|
|
344
|
+
|
|
345
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security/index.js","sources":["../../src/security/index.ts"],"sourcesContent":["import type { Knex } from \"knex\";\nimport type {\n SecurityStorageOperations,\n StorageApiKey,\n StorageRole,\n StorageTeam\n} from \"@webiny/api-core/types/security.js\";\nimport WebinyError from \"@webiny/error\";\nimport type { TableManager } from \"~/TableManager.js\";\nimport { sortItems } from \"~/sortItems.js\";\n\nconst ROLES_TABLE = \"webiny_core_roles\";\nconst TEAMS_TABLE = \"webiny_core_teams\";\nconst API_KEYS_TABLE = \"webiny_core_api_keys\";\n\ninterface IRoleRow {\n id: string;\n tenant: string;\n slug: string;\n data: string;\n}\n\ninterface ITeamRow {\n id: string;\n tenant: string;\n slug: string;\n data: string;\n}\n\ninterface IApiKeyRow {\n id: string;\n tenant: string;\n token: string;\n slug: string;\n data: string;\n}\n\ninterface CreateStorageOperationsParams {\n knex: Knex;\n tableManager: TableManager;\n}\n\nexport const createStorageOperations = (\n params: CreateStorageOperationsParams\n): SecurityStorageOperations => {\n const { knex, tableManager } = params;\n\n const ensureRolesTable = () => {\n return tableManager.ensure(ROLES_TABLE, table => {\n table.text(\"id\").notNullable();\n table.text(\"tenant\").notNullable();\n table.text(\"slug\").notNullable();\n table.text(\"data\").notNullable();\n\n table.primary([\"tenant\", \"id\"]);\n table.unique([\"tenant\", \"slug\"]);\n });\n };\n\n const ensureTeamsTable = () => {\n return tableManager.ensure(TEAMS_TABLE, table => {\n table.text(\"id\").notNullable();\n table.text(\"tenant\").notNullable();\n table.text(\"slug\").notNullable();\n table.text(\"data\").notNullable();\n\n table.primary([\"tenant\", \"id\"]);\n table.unique([\"tenant\", \"slug\"]);\n });\n };\n\n const ensureApiKeysTable = () => {\n return tableManager.ensure(API_KEYS_TABLE, table => {\n table.text(\"id\").notNullable();\n table.text(\"tenant\").notNullable();\n table.text(\"token\").notNullable();\n table.text(\"slug\").notNullable();\n table.text(\"data\").notNullable();\n\n table.primary([\"tenant\", \"id\"]);\n table.unique([\"tenant\", \"token\"]);\n table.unique([\"tenant\", \"slug\"]);\n });\n };\n\n const rolesQuery = () => knex<IRoleRow>(tableManager.resolve(ROLES_TABLE));\n const teamsQuery = () => knex<ITeamRow>(tableManager.resolve(TEAMS_TABLE));\n const apiKeysQuery = () => knex<IApiKeyRow>(tableManager.resolve(API_KEYS_TABLE));\n\n return {\n /* Roles */\n async getRole({ where: { tenant, id, slug } }) {\n await ensureRolesTable();\n\n try {\n if (id) {\n const row = await rolesQuery()\n .where(\"tenant\", tenant)\n .andWhere(\"id\", id)\n .first();\n\n return row ? (JSON.parse(row.data) as StorageRole) : null;\n }\n\n const row = await rolesQuery()\n .where(\"tenant\", tenant)\n .andWhere(\"slug\", slug as string)\n .first();\n\n return row ? (JSON.parse(row.data) as StorageRole) : null;\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not load role.\",\n code: \"GET_ROLE_ERROR\",\n data: { id, slug }\n });\n }\n },\n\n async listRoles({ where: { tenant, id_in, slug_in }, sort }) {\n await ensureRolesTable();\n\n try {\n const qb = rolesQuery().where(\"tenant\", tenant);\n\n if (Array.isArray(id_in)) {\n qb.whereIn(\"id\", id_in);\n } else if (Array.isArray(slug_in)) {\n qb.whereIn(\"slug\", slug_in);\n }\n\n const rows = await qb;\n const items = rows.map(row => JSON.parse(row.data) as StorageRole);\n\n return sortItems(items, sort);\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list roles.\",\n code: \"LIST_ROLE_ERROR\"\n });\n }\n },\n\n async createRole({ role }) {\n await ensureRolesTable();\n\n try {\n await rolesQuery().insert({\n id: role.id,\n tenant: role.tenant,\n slug: role.slug,\n data: JSON.stringify(role)\n });\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not create role.\",\n code: \"CREATE_ROLE_ERROR\",\n data: { role }\n });\n }\n },\n\n async updateRole({ role }) {\n await ensureRolesTable();\n\n try {\n await rolesQuery()\n .where(\"tenant\", role.tenant)\n .andWhere(\"id\", role.id)\n .update({\n slug: role.slug,\n data: JSON.stringify(role)\n });\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not update role.\",\n code: \"UPDATE_ROLE_ERROR\",\n data: { role }\n });\n }\n },\n\n async deleteRole({ role }) {\n await ensureRolesTable();\n\n try {\n await rolesQuery().where(\"tenant\", role.tenant).andWhere(\"id\", role.id).delete();\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not delete role.\",\n code: \"DELETE_ROLE_ERROR\",\n data: { role }\n });\n }\n },\n\n /* Teams */\n async getTeam({ where: { tenant, id, slug } }) {\n await ensureTeamsTable();\n\n try {\n if (id) {\n const row = await teamsQuery()\n .where(\"tenant\", tenant)\n .andWhere(\"id\", id)\n .first();\n\n return row ? (JSON.parse(row.data) as StorageTeam) : null;\n }\n\n const row = await teamsQuery()\n .where(\"tenant\", tenant)\n .andWhere(\"slug\", slug as string)\n .first();\n\n return row ? (JSON.parse(row.data) as StorageTeam) : null;\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not load team.\",\n code: \"GET_TEAM_ERROR\",\n data: { id, slug }\n });\n }\n },\n\n async listTeams({ where: { tenant, id_in, slug_in }, sort }) {\n await ensureTeamsTable();\n\n try {\n const qb = teamsQuery().where(\"tenant\", tenant);\n\n if (Array.isArray(id_in)) {\n qb.whereIn(\"id\", id_in);\n } else if (Array.isArray(slug_in)) {\n qb.whereIn(\"slug\", slug_in);\n }\n\n const rows = await qb;\n const items = rows.map(row => JSON.parse(row.data) as StorageTeam);\n\n return sortItems(items, sort);\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list teams.\",\n code: \"LIST_TEAM_ERROR\"\n });\n }\n },\n\n async createTeam({ team }) {\n await ensureTeamsTable();\n\n try {\n await teamsQuery().insert({\n id: team.id,\n tenant: team.tenant,\n slug: team.slug,\n data: JSON.stringify(team)\n });\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not create team.\",\n code: \"CREATE_TEAM_ERROR\",\n data: { team }\n });\n }\n },\n\n async updateTeam({ team }) {\n await ensureTeamsTable();\n\n try {\n await teamsQuery()\n .where(\"tenant\", team.tenant)\n .andWhere(\"id\", team.id)\n .update({\n slug: team.slug,\n data: JSON.stringify(team)\n });\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not update team.\",\n code: \"UPDATE_TEAM_ERROR\",\n data: { team }\n });\n }\n },\n\n async deleteTeam({ team }) {\n await ensureTeamsTable();\n\n try {\n await teamsQuery().where(\"tenant\", team.tenant).andWhere(\"id\", team.id).delete();\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not delete team.\",\n code: \"DELETE_TEAM_ERROR\",\n data: { team }\n });\n }\n },\n\n /* API Keys */\n async getApiKey({ id, tenant }) {\n await ensureApiKeysTable();\n\n try {\n const row = await apiKeysQuery().where(\"tenant\", tenant).andWhere(\"id\", id).first();\n\n return row ? (JSON.parse(row.data) as StorageApiKey) : null;\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not load api key.\",\n code: \"GET_API_KEY_ERROR\",\n data: { id }\n });\n }\n },\n\n async getApiKeyByToken({ tenant, token }) {\n await ensureApiKeysTable();\n\n try {\n const row = await apiKeysQuery()\n .where(\"tenant\", tenant)\n .andWhere(\"token\", token)\n .first();\n\n return row ? (JSON.parse(row.data) as StorageApiKey) : null;\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not load api key by token.\",\n code: \"GET_BY_TOKEN_API_KEY_ERROR\",\n data: { token }\n });\n }\n },\n\n async getApiKeyBySlug({ tenant, slug }) {\n await ensureApiKeysTable();\n\n try {\n const row = await apiKeysQuery()\n .where(\"tenant\", tenant)\n .andWhere(\"slug\", slug)\n .first();\n\n return row ? (JSON.parse(row.data) as StorageApiKey) : null;\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not load api key by slug.\",\n code: \"GET_BY_SLUG_API_KEY_ERROR\",\n data: { slug }\n });\n }\n },\n\n async listApiKeys({ where: { tenant }, sort }) {\n await ensureApiKeysTable();\n\n try {\n const rows = await apiKeysQuery().where(\"tenant\", tenant);\n const items = rows.map(row => JSON.parse(row.data) as StorageApiKey);\n\n return sortItems(items, sort);\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list api keys.\",\n code: \"LIST_API_KEY_ERROR\"\n });\n }\n },\n\n async createApiKey({ apiKey }) {\n await ensureApiKeysTable();\n\n try {\n await apiKeysQuery().insert({\n id: apiKey.id,\n tenant: apiKey.tenant,\n token: apiKey.token,\n slug: apiKey.slug,\n data: JSON.stringify(apiKey)\n });\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not create api key.\",\n code: \"CREATE_API_KEY_ERROR\",\n data: { apiKey }\n });\n }\n },\n\n async updateApiKey({ apiKey }) {\n await ensureApiKeysTable();\n\n try {\n await apiKeysQuery()\n .where(\"tenant\", apiKey.tenant)\n .andWhere(\"id\", apiKey.id)\n .update({\n token: apiKey.token,\n slug: apiKey.slug,\n data: JSON.stringify(apiKey)\n });\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not update api key.\",\n code: \"UPDATE_API_KEY_ERROR\",\n data: { apiKey }\n });\n }\n },\n\n async deleteApiKey({ apiKey }) {\n await ensureApiKeysTable();\n\n try {\n await apiKeysQuery()\n .where(\"tenant\", apiKey.tenant)\n .andWhere(\"id\", apiKey.id)\n .delete();\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not delete api key.\",\n code: \"DELETE_API_KEY_ERROR\",\n data: { apiKey }\n });\n }\n }\n };\n};\n"],"names":["ROLES_TABLE","TEAMS_TABLE","API_KEYS_TABLE","createStorageOperations","params","knex","tableManager","ensureRolesTable","table","ensureTeamsTable","ensureApiKeysTable","rolesQuery","teamsQuery","apiKeysQuery","tenant","id","slug","row","JSON","err","WebinyError","id_in","slug_in","sort","qb","Array","rows","items","sortItems","role","team","token","apiKey"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Knex } from "knex";
|
|
2
|
+
import type { IServiceManifestLoader } from "@webiny/api-core/features/serviceDiscovery/index.js";
|
|
3
|
+
import type { TableManager } from "../TableManager.js";
|
|
4
|
+
export declare class SqlServiceManifestLoader implements IServiceManifestLoader {
|
|
5
|
+
private readonly knex;
|
|
6
|
+
private readonly tableManager;
|
|
7
|
+
constructor(knex: Knex, tableManager: TableManager);
|
|
8
|
+
load(): Promise<{
|
|
9
|
+
name: string;
|
|
10
|
+
manifest: any;
|
|
11
|
+
}[] | undefined>;
|
|
12
|
+
private ensureTable;
|
|
13
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const TABLE_NAME = "webiny_service_manifests";
|
|
2
|
+
class SqlServiceManifestLoader {
|
|
3
|
+
constructor(knex, tableManager){
|
|
4
|
+
this.knex = knex;
|
|
5
|
+
this.tableManager = tableManager;
|
|
6
|
+
}
|
|
7
|
+
async load() {
|
|
8
|
+
await this.ensureTable();
|
|
9
|
+
const rows = await this.knex(this.tableManager.resolve(TABLE_NAME)).select("name", "manifest");
|
|
10
|
+
if (!rows.length) return;
|
|
11
|
+
return rows.map((row)=>({
|
|
12
|
+
name: row.name,
|
|
13
|
+
manifest: JSON.parse(row.manifest)
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
async ensureTable() {
|
|
17
|
+
await this.tableManager.ensure(TABLE_NAME, (table)=>{
|
|
18
|
+
table.text("name").primary().notNullable();
|
|
19
|
+
table.text("manifest").notNullable();
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export { SqlServiceManifestLoader };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=SqlServiceManifestLoader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serviceDiscovery/SqlServiceManifestLoader.js","sources":["../../src/serviceDiscovery/SqlServiceManifestLoader.ts"],"sourcesContent":["import type { Knex } from \"knex\";\nimport type { IServiceManifestLoader } from \"@webiny/api-core/features/serviceDiscovery/index.js\";\nimport type { TableManager } from \"~/TableManager.js\";\n\nconst TABLE_NAME = \"webiny_service_manifests\";\n\ninterface IServiceManifestRow {\n name: string;\n manifest: string;\n}\n\nexport class SqlServiceManifestLoader implements IServiceManifestLoader {\n private readonly knex: Knex;\n private readonly tableManager: TableManager;\n\n constructor(knex: Knex, tableManager: TableManager) {\n this.knex = knex;\n this.tableManager = tableManager;\n }\n\n async load() {\n await this.ensureTable();\n\n const rows = await this.knex<IServiceManifestRow>(\n this.tableManager.resolve(TABLE_NAME)\n ).select(\"name\", \"manifest\");\n\n if (!rows.length) {\n return undefined;\n }\n\n return rows.map(row => ({\n name: row.name,\n manifest: JSON.parse(row.manifest)\n }));\n }\n\n private async ensureTable() {\n await this.tableManager.ensure(TABLE_NAME, table => {\n table.text(\"name\").primary().notNullable();\n table.text(\"manifest\").notNullable();\n });\n }\n}\n"],"names":["TABLE_NAME","SqlServiceManifestLoader","knex","tableManager","rows","row","JSON","table"],"mappings":"AAIA,MAAMA,aAAa;AAOZ,MAAMC;IAIT,YAAYC,IAAU,EAAEC,YAA0B,CAAE;QAChD,IAAI,CAAC,IAAI,GAAGD;QACZ,IAAI,CAAC,YAAY,GAAGC;IACxB;IAEA,MAAM,OAAO;QACT,MAAM,IAAI,CAAC,WAAW;QAEtB,MAAMC,OAAO,MAAM,IAAI,CAAC,IAAI,CACxB,IAAI,CAAC,YAAY,CAAC,OAAO,CAACJ,aAC5B,MAAM,CAAC,QAAQ;QAEjB,IAAI,CAACI,KAAK,MAAM,EACZ;QAGJ,OAAOA,KAAK,GAAG,CAACC,CAAAA,MAAQ;gBACpB,MAAMA,IAAI,IAAI;gBACd,UAAUC,KAAK,KAAK,CAACD,IAAI,QAAQ;YACrC;IACJ;IAEA,MAAc,cAAc;QACxB,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAACL,YAAYO,CAAAA;YACvCA,MAAM,IAAI,CAAC,QAAQ,OAAO,GAAG,WAAW;YACxCA,MAAM,IAAI,CAAC,YAAY,WAAW;QACtC;IACJ;AACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SqlServiceManifestLoader } from "./SqlServiceManifestLoader.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SqlServiceManifestLoader } from "./SqlServiceManifestLoader.js";
|
package/sortItems.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const sortItems: <T>(items: T[], sort?: string[]) => T[];
|
package/sortItems.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const sortItems = (items, sort)=>{
|
|
2
|
+
if (!sort?.length || items.length <= 1) return items;
|
|
3
|
+
const parsed = sort.filter(Boolean).map((s)=>{
|
|
4
|
+
const parts = s.split("_");
|
|
5
|
+
const direction = parts.pop()?.toUpperCase() === "ASC" ? 1 : -1;
|
|
6
|
+
const field = parts.join("_");
|
|
7
|
+
return {
|
|
8
|
+
field,
|
|
9
|
+
direction
|
|
10
|
+
};
|
|
11
|
+
}).filter(({ field })=>field.length > 0);
|
|
12
|
+
if (0 === parsed.length) return items;
|
|
13
|
+
return [
|
|
14
|
+
...items
|
|
15
|
+
].sort((a, b)=>{
|
|
16
|
+
for (const { field, direction } of parsed){
|
|
17
|
+
const va = a[field];
|
|
18
|
+
const vb = b[field];
|
|
19
|
+
if (null != va || null != vb) {
|
|
20
|
+
if (null == va) return direction;
|
|
21
|
+
if (null == vb) return -direction;
|
|
22
|
+
if (va < vb) return -1 * direction;
|
|
23
|
+
if (va > vb) return +direction;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return 0;
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
export { sortItems };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=sortItems.js.map
|
package/sortItems.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sortItems.js","sources":["../src/sortItems.ts"],"sourcesContent":["export const sortItems = <T>(items: T[], sort?: string[]): T[] => {\n if (!sort?.length || items.length <= 1) {\n return items;\n }\n\n const parsed = sort\n .filter(Boolean)\n .map(s => {\n const parts = s.split(\"_\");\n const direction = parts.pop()?.toUpperCase() === \"ASC\" ? 1 : -1;\n const field = parts.join(\"_\");\n return { field, direction };\n })\n .filter(({ field }) => field.length > 0);\n\n if (parsed.length === 0) {\n return items;\n }\n\n return [...items].sort((a, b) => {\n for (const { field, direction } of parsed) {\n const va = (a as Record<string, unknown>)[field];\n const vb = (b as Record<string, unknown>)[field];\n\n if (va == null && vb == null) {\n continue;\n }\n if (va == null) {\n return direction;\n }\n if (vb == null) {\n return -direction;\n }\n if (va < vb) {\n return -1 * direction;\n }\n if (va > vb) {\n return 1 * direction;\n }\n }\n return 0;\n });\n};\n"],"names":["sortItems","items","sort","parsed","Boolean","s","parts","direction","field","a","b","va","vb"],"mappings":"AAAO,MAAMA,YAAY,CAAIC,OAAYC;IACrC,IAAI,CAACA,MAAM,UAAUD,MAAM,MAAM,IAAI,GACjC,OAAOA;IAGX,MAAME,SAASD,KACV,MAAM,CAACE,SACP,GAAG,CAACC,CAAAA;QACD,MAAMC,QAAQD,EAAE,KAAK,CAAC;QACtB,MAAME,YAAYD,MAAM,GAAG,IAAI,kBAAkB,QAAQ,IAAI;QAC7D,MAAME,QAAQF,MAAM,IAAI,CAAC;QACzB,OAAO;YAAEE;YAAOD;QAAU;IAC9B,GACC,MAAM,CAAC,CAAC,EAAEC,KAAK,EAAE,GAAKA,MAAM,MAAM,GAAG;IAE1C,IAAIL,AAAkB,MAAlBA,OAAO,MAAM,EACb,OAAOF;IAGX,OAAO;WAAIA;KAAM,CAAC,IAAI,CAAC,CAACQ,GAAGC;QACvB,KAAK,MAAM,EAAEF,KAAK,EAAED,SAAS,EAAE,IAAIJ,OAAQ;YACvC,MAAMQ,KAAMF,CAA6B,CAACD,MAAM;YAChD,MAAMI,KAAMF,CAA6B,CAACF,MAAM;YAEhD,IAAIG,AAAM,QAANA,MAAcC,AAAM,QAANA;gBAGlB,IAAID,AAAM,QAANA,IACA,OAAOJ;gBAEX,IAAIK,AAAM,QAANA,IACA,OAAO,CAACL;gBAEZ,IAAII,KAAKC,IACL,OAAO,KAAKL;gBAEhB,IAAII,KAAKC,IACL,OAAO,CAAIL;;QAEnB;QACA,OAAO;IACX;AACJ"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Knex } from "knex";
|
|
2
|
+
import type { TenancyStorageOperations } from "@webiny/api-core/types/tenancy.js";
|
|
3
|
+
import type { TableManager } from "../TableManager.js";
|
|
4
|
+
interface CreateStorageOperationsParams {
|
|
5
|
+
knex: Knex;
|
|
6
|
+
tableManager: TableManager;
|
|
7
|
+
}
|
|
8
|
+
export declare const createStorageOperations: (params: CreateStorageOperationsParams) => TenancyStorageOperations;
|
|
9
|
+
export {};
|
package/tenancy/index.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import error from "@webiny/error";
|
|
2
|
+
const TABLE_NAME = "webiny_core_tenants";
|
|
3
|
+
const tenantToRow = (tenant)=>({
|
|
4
|
+
id: tenant.id,
|
|
5
|
+
parent: tenant.parent,
|
|
6
|
+
createdOn: tenant.createdOn,
|
|
7
|
+
data: JSON.stringify(tenant)
|
|
8
|
+
});
|
|
9
|
+
const rowToTenant = (row)=>{
|
|
10
|
+
const tenant = JSON.parse(row.data);
|
|
11
|
+
if (!tenant.tags) tenant.tags = [];
|
|
12
|
+
if (!tenant.description) tenant.description = "";
|
|
13
|
+
return tenant;
|
|
14
|
+
};
|
|
15
|
+
const createStorageOperations = (params)=>{
|
|
16
|
+
const { knex, tableManager } = params;
|
|
17
|
+
const ensureTable = ()=>tableManager.ensure(TABLE_NAME, (table)=>{
|
|
18
|
+
table.text("id").primary().notNullable();
|
|
19
|
+
table.text("parent");
|
|
20
|
+
table.text("createdOn").notNullable();
|
|
21
|
+
table.text("data").notNullable();
|
|
22
|
+
table.index([
|
|
23
|
+
"parent"
|
|
24
|
+
]);
|
|
25
|
+
});
|
|
26
|
+
const query = ()=>knex(tableManager.resolve(TABLE_NAME));
|
|
27
|
+
return {
|
|
28
|
+
async getTenantsByIds (ids) {
|
|
29
|
+
await ensureTable();
|
|
30
|
+
try {
|
|
31
|
+
const rows = await query().whereIn("id", ids);
|
|
32
|
+
return rows.map(rowToTenant);
|
|
33
|
+
} catch (err) {
|
|
34
|
+
throw error.from(err, {
|
|
35
|
+
message: "Could not get tenants by IDs.",
|
|
36
|
+
code: "GET_TENANTS_BY_IDS_ERROR",
|
|
37
|
+
data: {
|
|
38
|
+
ids
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
async listTenants (params = {}) {
|
|
44
|
+
await ensureTable();
|
|
45
|
+
try {
|
|
46
|
+
const qb = query();
|
|
47
|
+
if (params.parent) qb.where("parent", params.parent);
|
|
48
|
+
qb.orderBy("createdOn", "asc");
|
|
49
|
+
const rows = await qb;
|
|
50
|
+
return rows.map(rowToTenant);
|
|
51
|
+
} catch (err) {
|
|
52
|
+
throw error.from(err, {
|
|
53
|
+
message: "Could not list tenants.",
|
|
54
|
+
code: "LIST_TENANTS_ERROR",
|
|
55
|
+
data: {
|
|
56
|
+
params
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
async createTenant (data) {
|
|
62
|
+
await ensureTable();
|
|
63
|
+
try {
|
|
64
|
+
const row = tenantToRow(data);
|
|
65
|
+
await query().insert(row);
|
|
66
|
+
return data;
|
|
67
|
+
} catch (err) {
|
|
68
|
+
throw error.from(err, {
|
|
69
|
+
message: "Could not create tenant record.",
|
|
70
|
+
code: "CREATE_TENANT_ERROR",
|
|
71
|
+
data: {
|
|
72
|
+
tenant: data
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
async updateTenant (data) {
|
|
78
|
+
await ensureTable();
|
|
79
|
+
try {
|
|
80
|
+
const row = tenantToRow(data);
|
|
81
|
+
await query().where("id", data.id).update(row);
|
|
82
|
+
return data;
|
|
83
|
+
} catch (err) {
|
|
84
|
+
throw error.from(err, {
|
|
85
|
+
message: "Could not update tenant record.",
|
|
86
|
+
code: "UPDATE_TENANT_ERROR",
|
|
87
|
+
data: {
|
|
88
|
+
tenant: data
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
async deleteTenant (id) {
|
|
94
|
+
await ensureTable();
|
|
95
|
+
try {
|
|
96
|
+
await query().where("id", id).delete();
|
|
97
|
+
} catch (err) {
|
|
98
|
+
throw error.from(err, {
|
|
99
|
+
message: "Could not delete tenant record.",
|
|
100
|
+
code: "DELETE_TENANT_ERROR",
|
|
101
|
+
data: {
|
|
102
|
+
id
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
export { createStorageOperations };
|
|
110
|
+
|
|
111
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenancy/index.js","sources":["../../src/tenancy/index.ts"],"sourcesContent":["import type { Knex } from \"knex\";\nimport type {\n ListTenantsParams,\n TenancyStorageOperations,\n Tenant\n} from \"@webiny/api-core/types/tenancy.js\";\nimport WebinyError from \"@webiny/error\";\nimport type { TableManager } from \"~/TableManager.js\";\n\nconst TABLE_NAME = \"webiny_core_tenants\";\n\ninterface ITenantRow {\n id: string;\n parent: string | null;\n createdOn: string;\n data: string;\n}\n\nconst tenantToRow = (tenant: Tenant): ITenantRow => {\n return {\n id: tenant.id,\n parent: tenant.parent,\n createdOn: tenant.createdOn,\n data: JSON.stringify(tenant)\n };\n};\n\nconst rowToTenant = (row: ITenantRow): Tenant => {\n const tenant = JSON.parse(row.data) as Tenant;\n\n if (!tenant.tags) {\n tenant.tags = [];\n }\n\n if (!tenant.description) {\n tenant.description = \"\";\n }\n\n return tenant;\n};\n\ninterface CreateStorageOperationsParams {\n knex: Knex;\n tableManager: TableManager;\n}\n\nexport const createStorageOperations = (\n params: CreateStorageOperationsParams\n): TenancyStorageOperations => {\n const { knex, tableManager } = params;\n\n const ensureTable = () => {\n return tableManager.ensure(TABLE_NAME, table => {\n table.text(\"id\").primary().notNullable();\n table.text(\"parent\");\n table.text(\"createdOn\").notNullable();\n table.text(\"data\").notNullable();\n\n table.index([\"parent\"]);\n });\n };\n\n const query = () => {\n return knex<ITenantRow>(tableManager.resolve(TABLE_NAME));\n };\n\n return {\n async getTenantsByIds(ids: readonly string[]): Promise<Tenant[]> {\n await ensureTable();\n\n try {\n const rows = await query().whereIn(\"id\", ids);\n\n return rows.map(rowToTenant);\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not get tenants by IDs.\",\n code: \"GET_TENANTS_BY_IDS_ERROR\",\n data: {\n ids\n }\n });\n }\n },\n\n async listTenants(params: ListTenantsParams = {}): Promise<Tenant[]> {\n await ensureTable();\n\n try {\n const qb = query();\n\n if (params.parent) {\n qb.where(\"parent\", params.parent);\n }\n\n qb.orderBy(\"createdOn\", \"asc\");\n\n const rows = await qb;\n\n return rows.map(rowToTenant);\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list tenants.\",\n code: \"LIST_TENANTS_ERROR\",\n data: { params }\n });\n }\n },\n\n async createTenant(data: Tenant): Promise<Tenant> {\n await ensureTable();\n\n try {\n const row = tenantToRow(data);\n await query().insert(row);\n\n return data;\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not create tenant record.\",\n code: \"CREATE_TENANT_ERROR\",\n data: { tenant: data }\n });\n }\n },\n\n async updateTenant(data: Tenant): Promise<Tenant> {\n await ensureTable();\n\n try {\n const row = tenantToRow(data);\n await query().where(\"id\", data.id).update(row);\n\n return data;\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not update tenant record.\",\n code: \"UPDATE_TENANT_ERROR\",\n data: { tenant: data }\n });\n }\n },\n\n async deleteTenant(id: string): Promise<void> {\n await ensureTable();\n\n try {\n await query().where(\"id\", id).delete();\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not delete tenant record.\",\n code: \"DELETE_TENANT_ERROR\",\n data: { id }\n });\n }\n }\n };\n};\n"],"names":["TABLE_NAME","tenantToRow","tenant","JSON","rowToTenant","row","createStorageOperations","params","knex","tableManager","ensureTable","table","query","ids","rows","err","WebinyError","qb","data","id"],"mappings":";AASA,MAAMA,aAAa;AASnB,MAAMC,cAAc,CAACC,SACV;QACH,IAAIA,OAAO,EAAE;QACb,QAAQA,OAAO,MAAM;QACrB,WAAWA,OAAO,SAAS;QAC3B,MAAMC,KAAK,SAAS,CAACD;IACzB;AAGJ,MAAME,cAAc,CAACC;IACjB,MAAMH,SAASC,KAAK,KAAK,CAACE,IAAI,IAAI;IAElC,IAAI,CAACH,OAAO,IAAI,EACZA,OAAO,IAAI,GAAG,EAAE;IAGpB,IAAI,CAACA,OAAO,WAAW,EACnBA,OAAO,WAAW,GAAG;IAGzB,OAAOA;AACX;AAOO,MAAMI,0BAA0B,CACnCC;IAEA,MAAM,EAAEC,IAAI,EAAEC,YAAY,EAAE,GAAGF;IAE/B,MAAMG,cAAc,IACTD,aAAa,MAAM,CAACT,YAAYW,CAAAA;YACnCA,MAAM,IAAI,CAAC,MAAM,OAAO,GAAG,WAAW;YACtCA,MAAM,IAAI,CAAC;YACXA,MAAM,IAAI,CAAC,aAAa,WAAW;YACnCA,MAAM,IAAI,CAAC,QAAQ,WAAW;YAE9BA,MAAM,KAAK,CAAC;gBAAC;aAAS;QAC1B;IAGJ,MAAMC,QAAQ,IACHJ,KAAiBC,aAAa,OAAO,CAACT;IAGjD,OAAO;QACH,MAAM,iBAAgBa,GAAsB;YACxC,MAAMH;YAEN,IAAI;gBACA,MAAMI,OAAO,MAAMF,QAAQ,OAAO,CAAC,MAAMC;gBAEzC,OAAOC,KAAK,GAAG,CAACV;YACpB,EAAE,OAAOW,KAAK;gBACV,MAAMC,MAAAA,IAAgB,CAACD,KAAK;oBACxB,SAAS;oBACT,MAAM;oBACN,MAAM;wBACFF;oBACJ;gBACJ;YACJ;QACJ;QAEA,MAAM,aAAYN,SAA4B,CAAC,CAAC;YAC5C,MAAMG;YAEN,IAAI;gBACA,MAAMO,KAAKL;gBAEX,IAAIL,OAAO,MAAM,EACbU,GAAG,KAAK,CAAC,UAAUV,OAAO,MAAM;gBAGpCU,GAAG,OAAO,CAAC,aAAa;gBAExB,MAAMH,OAAO,MAAMG;gBAEnB,OAAOH,KAAK,GAAG,CAACV;YACpB,EAAE,OAAOW,KAAK;gBACV,MAAMC,MAAAA,IAAgB,CAACD,KAAK;oBACxB,SAAS;oBACT,MAAM;oBACN,MAAM;wBAAER;oBAAO;gBACnB;YACJ;QACJ;QAEA,MAAM,cAAaW,IAAY;YAC3B,MAAMR;YAEN,IAAI;gBACA,MAAML,MAAMJ,YAAYiB;gBACxB,MAAMN,QAAQ,MAAM,CAACP;gBAErB,OAAOa;YACX,EAAE,OAAOH,KAAK;gBACV,MAAMC,MAAAA,IAAgB,CAACD,KAAK;oBACxB,SAAS;oBACT,MAAM;oBACN,MAAM;wBAAE,QAAQG;oBAAK;gBACzB;YACJ;QACJ;QAEA,MAAM,cAAaA,IAAY;YAC3B,MAAMR;YAEN,IAAI;gBACA,MAAML,MAAMJ,YAAYiB;gBACxB,MAAMN,QAAQ,KAAK,CAAC,MAAMM,KAAK,EAAE,EAAE,MAAM,CAACb;gBAE1C,OAAOa;YACX,EAAE,OAAOH,KAAK;gBACV,MAAMC,MAAAA,IAAgB,CAACD,KAAK;oBACxB,SAAS;oBACT,MAAM;oBACN,MAAM;wBAAE,QAAQG;oBAAK;gBACzB;YACJ;QACJ;QAEA,MAAM,cAAaC,EAAU;YACzB,MAAMT;YAEN,IAAI;gBACA,MAAME,QAAQ,KAAK,CAAC,MAAMO,IAAI,MAAM;YACxC,EAAE,OAAOJ,KAAK;gBACV,MAAMC,MAAAA,IAAgB,CAACD,KAAK;oBACxB,SAAS;oBACT,MAAM;oBACN,MAAM;wBAAEI;oBAAG;gBACf;YACJ;QACJ;IACJ;AACJ"}
|