@oktis-works/core 0.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/dist/bootstrap/index.d.ts +7 -0
- package/dist/bootstrap/index.d.ts.map +1 -0
- package/dist/bootstrap/index.js +16 -0
- package/dist/bootstrap/index.js.map +1 -0
- package/dist/build/service.d.ts +28 -0
- package/dist/build/service.d.ts.map +1 -0
- package/dist/build/service.js +71 -0
- package/dist/build/service.js.map +1 -0
- package/dist/cache/index.d.ts +31 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +110 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/category/service.d.ts +21 -0
- package/dist/category/service.d.ts.map +1 -0
- package/dist/category/service.js +67 -0
- package/dist/category/service.js.map +1 -0
- package/dist/content/field-resolver.d.ts +31 -0
- package/dist/content/field-resolver.d.ts.map +1 -0
- package/dist/content/field-resolver.js +40 -0
- package/dist/content/field-resolver.js.map +1 -0
- package/dist/content/post-types.d.ts +28 -0
- package/dist/content/post-types.d.ts.map +1 -0
- package/dist/content/post-types.js +127 -0
- package/dist/content/post-types.js.map +1 -0
- package/dist/content/publisher.d.ts +26 -0
- package/dist/content/publisher.d.ts.map +1 -0
- package/dist/content/publisher.js +156 -0
- package/dist/content/publisher.js.map +1 -0
- package/dist/content/service.d.ts +53 -0
- package/dist/content/service.d.ts.map +1 -0
- package/dist/content/service.js +335 -0
- package/dist/content/service.js.map +1 -0
- package/dist/deployment/service.d.ts +25 -0
- package/dist/deployment/service.d.ts.map +1 -0
- package/dist/deployment/service.js +102 -0
- package/dist/deployment/service.js.map +1 -0
- package/dist/events/bus.d.ts +25 -0
- package/dist/events/bus.d.ts.map +1 -0
- package/dist/events/bus.js +89 -0
- package/dist/events/bus.js.map +1 -0
- package/dist/events/store.d.ts +19 -0
- package/dist/events/store.d.ts.map +1 -0
- package/dist/events/store.js +52 -0
- package/dist/events/store.js.map +1 -0
- package/dist/fields/clone.d.ts +2 -0
- package/dist/fields/clone.d.ts.map +1 -0
- package/dist/fields/clone.js +3 -0
- package/dist/fields/clone.js.map +1 -0
- package/dist/fields/conditional.d.ts +2 -0
- package/dist/fields/conditional.d.ts.map +1 -0
- package/dist/fields/conditional.js +3 -0
- package/dist/fields/conditional.js.map +1 -0
- package/dist/fields/index.d.ts +5 -0
- package/dist/fields/index.d.ts.map +1 -0
- package/dist/fields/index.js +6 -0
- package/dist/fields/index.js.map +1 -0
- package/dist/fields/location-rules.d.ts +16 -0
- package/dist/fields/location-rules.d.ts.map +1 -0
- package/dist/fields/location-rules.js +22 -0
- package/dist/fields/location-rules.js.map +1 -0
- package/dist/fields/service.d.ts +77 -0
- package/dist/fields/service.d.ts.map +1 -0
- package/dist/fields/service.js +278 -0
- package/dist/fields/service.js.map +1 -0
- package/dist/fields/types/registry.d.ts +20 -0
- package/dist/fields/types/registry.d.ts.map +1 -0
- package/dist/fields/types/registry.js +68 -0
- package/dist/fields/types/registry.js.map +1 -0
- package/dist/fields/types/validators/basic.d.ts +2 -0
- package/dist/fields/types/validators/basic.d.ts.map +1 -0
- package/dist/fields/types/validators/basic.js +3 -0
- package/dist/fields/types/validators/basic.js.map +1 -0
- package/dist/fields/types/validators/choice.d.ts +2 -0
- package/dist/fields/types/validators/choice.d.ts.map +1 -0
- package/dist/fields/types/validators/choice.js +3 -0
- package/dist/fields/types/validators/choice.js.map +1 -0
- package/dist/fields/types/validators/client-validate.d.ts +2 -0
- package/dist/fields/types/validators/client-validate.d.ts.map +1 -0
- package/dist/fields/types/validators/client-validate.js +3 -0
- package/dist/fields/types/validators/client-validate.js.map +1 -0
- package/dist/fields/types/validators/index.d.ts +8 -0
- package/dist/fields/types/validators/index.d.ts.map +1 -0
- package/dist/fields/types/validators/index.js +10 -0
- package/dist/fields/types/validators/index.js.map +1 -0
- package/dist/fields/types/validators/media.d.ts +2 -0
- package/dist/fields/types/validators/media.d.ts.map +1 -0
- package/dist/fields/types/validators/media.js +3 -0
- package/dist/fields/types/validators/media.js.map +1 -0
- package/dist/fields/types/validators/relational.d.ts +2 -0
- package/dist/fields/types/validators/relational.d.ts.map +1 -0
- package/dist/fields/types/validators/relational.js +3 -0
- package/dist/fields/types/validators/relational.js.map +1 -0
- package/dist/fields/types/validators/structural.d.ts +2 -0
- package/dist/fields/types/validators/structural.d.ts.map +1 -0
- package/dist/fields/types/validators/structural.js +3 -0
- package/dist/fields/types/validators/structural.js.map +1 -0
- package/dist/fields/validation.d.ts +16 -0
- package/dist/fields/validation.d.ts.map +1 -0
- package/dist/fields/validation.js +123 -0
- package/dist/fields/validation.js.map +1 -0
- package/dist/hooks/catalog.d.ts +20 -0
- package/dist/hooks/catalog.d.ts.map +1 -0
- package/dist/hooks/catalog.js +59 -0
- package/dist/hooks/catalog.js.map +1 -0
- package/dist/hooks/points.d.ts +26 -0
- package/dist/hooks/points.d.ts.map +1 -0
- package/dist/hooks/points.js +33 -0
- package/dist/hooks/points.js.map +1 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle/index.d.ts +17 -0
- package/dist/lifecycle/index.d.ts.map +1 -0
- package/dist/lifecycle/index.js +79 -0
- package/dist/lifecycle/index.js.map +1 -0
- package/dist/media/service.d.ts +32 -0
- package/dist/media/service.d.ts.map +1 -0
- package/dist/media/service.js +87 -0
- package/dist/media/service.js.map +1 -0
- package/dist/menu/service.d.ts +19 -0
- package/dist/menu/service.d.ts.map +1 -0
- package/dist/menu/service.js +64 -0
- package/dist/menu/service.js.map +1 -0
- package/dist/observability/audit.d.ts +26 -0
- package/dist/observability/audit.d.ts.map +1 -0
- package/dist/observability/audit.js +67 -0
- package/dist/observability/audit.js.map +1 -0
- package/dist/observability/event-audit.d.ts +8 -0
- package/dist/observability/event-audit.d.ts.map +1 -0
- package/dist/observability/event-audit.js +20 -0
- package/dist/observability/event-audit.js.map +1 -0
- package/dist/observability/index.d.ts +5 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +6 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/logger.d.ts +13 -0
- package/dist/observability/logger.d.ts.map +1 -0
- package/dist/observability/logger.js +45 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/observability/metrics.d.ts +34 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +56 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/plugin/service.d.ts +32 -0
- package/dist/plugin/service.d.ts.map +1 -0
- package/dist/plugin/service.js +190 -0
- package/dist/plugin/service.js.map +1 -0
- package/dist/role/service.d.ts +19 -0
- package/dist/role/service.d.ts.map +1 -0
- package/dist/role/service.js +65 -0
- package/dist/role/service.js.map +1 -0
- package/dist/settings/service.d.ts +16 -0
- package/dist/settings/service.d.ts.map +1 -0
- package/dist/settings/service.js +64 -0
- package/dist/settings/service.js.map +1 -0
- package/dist/storage/driver.d.ts +20 -0
- package/dist/storage/driver.d.ts.map +1 -0
- package/dist/storage/driver.js +3 -0
- package/dist/storage/driver.js.map +1 -0
- package/dist/storage/drivers/local.d.ts +17 -0
- package/dist/storage/drivers/local.d.ts.map +1 -0
- package/dist/storage/drivers/local.js +88 -0
- package/dist/storage/drivers/local.js.map +1 -0
- package/dist/storage/drivers/s3.d.ts +28 -0
- package/dist/storage/drivers/s3.d.ts.map +1 -0
- package/dist/storage/drivers/s3.js +105 -0
- package/dist/storage/drivers/s3.js.map +1 -0
- package/dist/storage/index.d.ts +16 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +58 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/migrator.d.ts +18 -0
- package/dist/storage/migrator.d.ts.map +1 -0
- package/dist/storage/migrator.js +46 -0
- package/dist/storage/migrator.js.map +1 -0
- package/dist/tag/service.d.ts +13 -0
- package/dist/tag/service.d.ts.map +1 -0
- package/dist/tag/service.js +37 -0
- package/dist/tag/service.js.map +1 -0
- package/dist/taxonomies/service.d.ts +50 -0
- package/dist/taxonomies/service.d.ts.map +1 -0
- package/dist/taxonomies/service.js +179 -0
- package/dist/taxonomies/service.js.map +1 -0
- package/dist/tenant/context.d.ts +9 -0
- package/dist/tenant/context.d.ts.map +1 -0
- package/dist/tenant/context.js +67 -0
- package/dist/tenant/context.js.map +1 -0
- package/dist/tenant/service.d.ts +31 -0
- package/dist/tenant/service.d.ts.map +1 -0
- package/dist/tenant/service.js +90 -0
- package/dist/tenant/service.js.map +1 -0
- package/dist/theme/service.d.ts +16 -0
- package/dist/theme/service.d.ts.map +1 -0
- package/dist/theme/service.js +57 -0
- package/dist/theme/service.js.map +1 -0
- package/dist/user/service.d.ts +31 -0
- package/dist/user/service.d.ts.map +1 -0
- package/dist/user/service.js +95 -0
- package/dist/user/service.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// @oktis-works/core - Tenant Context
|
|
2
|
+
import { setTenantContext, clearTenantContext, getCurrentTenantId } from '@oktis-works/database';
|
|
3
|
+
let _currentContext = null;
|
|
4
|
+
/**
|
|
5
|
+
* O espelho para o RLS do Postgres é opcional: sem conexão inicializada
|
|
6
|
+
* mantemos apenas o contexto em memória (útil em testes e boot antecipado).
|
|
7
|
+
* Outros erros de banco são propagados normalmente.
|
|
8
|
+
*/
|
|
9
|
+
function ignoreIfNoConnection(error) {
|
|
10
|
+
if (error instanceof Error &&
|
|
11
|
+
error.message.startsWith('Database connection not initialized')) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
throw error;
|
|
15
|
+
}
|
|
16
|
+
async function trySetTenantContext(tenantId) {
|
|
17
|
+
try {
|
|
18
|
+
await setTenantContext(tenantId);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
ignoreIfNoConnection(error);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async function tryClearTenantContext() {
|
|
25
|
+
try {
|
|
26
|
+
await clearTenantContext();
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
ignoreIfNoConnection(error);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function tryGetTenantId() {
|
|
33
|
+
try {
|
|
34
|
+
return await getCurrentTenantId();
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
ignoreIfNoConnection(error);
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export async function establishTenantContext(tenantId, userId) {
|
|
42
|
+
await trySetTenantContext(tenantId);
|
|
43
|
+
_currentContext = { tenantId, userId };
|
|
44
|
+
return _currentContext;
|
|
45
|
+
}
|
|
46
|
+
export async function getCurrentContext() {
|
|
47
|
+
if (_currentContext) {
|
|
48
|
+
return _currentContext;
|
|
49
|
+
}
|
|
50
|
+
const tenantId = await tryGetTenantId();
|
|
51
|
+
if (tenantId) {
|
|
52
|
+
_currentContext = { tenantId };
|
|
53
|
+
return _currentContext;
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
export async function clearCurrentContext() {
|
|
58
|
+
await tryClearTenantContext();
|
|
59
|
+
_currentContext = null;
|
|
60
|
+
}
|
|
61
|
+
export function requireTenantContext() {
|
|
62
|
+
if (!_currentContext) {
|
|
63
|
+
throw new Error('Tenant context not established. Call establishTenantContext() first.');
|
|
64
|
+
}
|
|
65
|
+
return _currentContext;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/tenant/context.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAErC,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAOjG,IAAI,eAAe,GAAyB,IAAI,CAAC;AAEjD;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,KAAc;IAC1C,IACE,KAAK,YAAY,KAAK;QACtB,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,qCAAqC,CAAC,EAC/D,CAAC;QACD,OAAO;IACT,CAAC;IACD,MAAM,KAAK,CAAC;AACd,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,QAAgB;IACjD,IAAI,CAAC;QACH,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,KAAK,UAAU,qBAAqB;IAClC,IAAI,CAAC;QACH,MAAM,kBAAkB,EAAE,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,KAAK,UAAU,cAAc;IAC3B,IAAI,CAAC;QACH,OAAO,MAAM,kBAAkB,EAAE,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,QAAgB,EAAE,MAAe;IAC5E,MAAM,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAEpC,eAAe,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACvC,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,cAAc,EAAE,CAAC;IACxC,IAAI,QAAQ,EAAE,CAAC;QACb,eAAe,GAAG,EAAE,QAAQ,EAAE,CAAC;QAC/B,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,MAAM,qBAAqB,EAAE,CAAC;IAC9B,eAAe,GAAG,IAAI,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Tenant } from '@oktis-works/types';
|
|
2
|
+
export declare class TenantService {
|
|
3
|
+
list(options: {
|
|
4
|
+
page?: number;
|
|
5
|
+
limit?: number;
|
|
6
|
+
search?: string;
|
|
7
|
+
}): Promise<{
|
|
8
|
+
data: Tenant[];
|
|
9
|
+
total: number;
|
|
10
|
+
}>;
|
|
11
|
+
getById(id: string): Promise<Tenant | null>;
|
|
12
|
+
getBySlug(slug: string): Promise<Tenant | null>;
|
|
13
|
+
create(input: {
|
|
14
|
+
name: string;
|
|
15
|
+
slug: string;
|
|
16
|
+
domain?: string;
|
|
17
|
+
subdomain?: string;
|
|
18
|
+
settings?: Record<string, unknown>;
|
|
19
|
+
}): Promise<Tenant>;
|
|
20
|
+
update(id: string, input: {
|
|
21
|
+
name?: string;
|
|
22
|
+
slug?: string;
|
|
23
|
+
domain?: string;
|
|
24
|
+
subdomain?: string;
|
|
25
|
+
status?: Tenant['status'];
|
|
26
|
+
settings?: Record<string, unknown>;
|
|
27
|
+
}): Promise<Tenant | null>;
|
|
28
|
+
delete(id: string): Promise<boolean>;
|
|
29
|
+
}
|
|
30
|
+
export declare const tenantService: TenantService;
|
|
31
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/tenant/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,qBAAa,aAAa;IAClB,IAAI,CAAC,OAAO,EAAE;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IA6BxC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAM3C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAM/C,MAAM,CAAC,KAAK,EAAE;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBb,MAAM,CACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE;QACL,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC,GACA,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA+CnB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAU3C;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { getConnection } from '@oktis-works/database';
|
|
3
|
+
export class TenantService {
|
|
4
|
+
async list(options) {
|
|
5
|
+
const sql = getConnection();
|
|
6
|
+
const { page = 1, limit = 20, search } = options;
|
|
7
|
+
const offset = (page - 1) * limit;
|
|
8
|
+
let whereClause = 'WHERE 1=1';
|
|
9
|
+
const params = [];
|
|
10
|
+
if (search) {
|
|
11
|
+
whereClause += ` AND (name ILIKE $${params.length + 1} OR slug ILIKE $${params.length + 2})`;
|
|
12
|
+
params.push(`%${search}%`);
|
|
13
|
+
params.push(`%${search}%`);
|
|
14
|
+
}
|
|
15
|
+
const dataResult = await sql.unsafe(`SELECT * FROM tenants ${whereClause} ORDER BY created_at DESC LIMIT ${limit} OFFSET ${offset}`, params);
|
|
16
|
+
const countResult = await sql.unsafe(`SELECT COUNT(*) as total FROM tenants ${whereClause}`, params);
|
|
17
|
+
return {
|
|
18
|
+
data: dataResult,
|
|
19
|
+
total: Number(countResult[0]?.['total'] ?? 0),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async getById(id) {
|
|
23
|
+
const sql = getConnection();
|
|
24
|
+
const result = await sql.unsafe('SELECT * FROM tenants WHERE id = $1', [id]);
|
|
25
|
+
return result[0] ?? null;
|
|
26
|
+
}
|
|
27
|
+
async getBySlug(slug) {
|
|
28
|
+
const sql = getConnection();
|
|
29
|
+
const result = await sql.unsafe('SELECT * FROM tenants WHERE slug = $1', [slug]);
|
|
30
|
+
return result[0] ?? null;
|
|
31
|
+
}
|
|
32
|
+
async create(input) {
|
|
33
|
+
const sql = getConnection();
|
|
34
|
+
const id = randomUUID();
|
|
35
|
+
const status = 'ACTIVE';
|
|
36
|
+
const settingsJson = input.settings ? JSON.stringify(input.settings) : null;
|
|
37
|
+
const result = await sql.unsafe(`INSERT INTO tenants (id, name, slug, domain, subdomain, status, settings)
|
|
38
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb)
|
|
39
|
+
RETURNING *`, [id, input.name, input.slug, input.domain ?? null, input.subdomain ?? null, status, settingsJson]);
|
|
40
|
+
return result[0];
|
|
41
|
+
}
|
|
42
|
+
async update(id, input) {
|
|
43
|
+
const sql = getConnection();
|
|
44
|
+
const existing = await this.getById(id);
|
|
45
|
+
if (!existing)
|
|
46
|
+
return null;
|
|
47
|
+
const setClauses = [];
|
|
48
|
+
const setParams = [];
|
|
49
|
+
if (input.name !== undefined) {
|
|
50
|
+
setClauses.push(`name = $${setParams.length + 1}`);
|
|
51
|
+
setParams.push(input.name);
|
|
52
|
+
}
|
|
53
|
+
if (input.slug !== undefined) {
|
|
54
|
+
setClauses.push(`slug = $${setParams.length + 1}`);
|
|
55
|
+
setParams.push(input.slug);
|
|
56
|
+
}
|
|
57
|
+
if (input.domain !== undefined) {
|
|
58
|
+
setClauses.push(`domain = $${setParams.length + 1}`);
|
|
59
|
+
setParams.push(input.domain);
|
|
60
|
+
}
|
|
61
|
+
if (input.subdomain !== undefined) {
|
|
62
|
+
setClauses.push(`subdomain = $${setParams.length + 1}`);
|
|
63
|
+
setParams.push(input.subdomain);
|
|
64
|
+
}
|
|
65
|
+
if (input.status !== undefined) {
|
|
66
|
+
setClauses.push(`status = $${setParams.length + 1}`);
|
|
67
|
+
setParams.push(input.status);
|
|
68
|
+
}
|
|
69
|
+
if (input.settings !== undefined) {
|
|
70
|
+
setClauses.push(`settings = $${setParams.length + 1}::jsonb`);
|
|
71
|
+
setParams.push(JSON.stringify(input.settings));
|
|
72
|
+
}
|
|
73
|
+
if (setClauses.length === 0)
|
|
74
|
+
return existing;
|
|
75
|
+
setClauses.push(`updated_at = NOW()`);
|
|
76
|
+
setParams.push(id);
|
|
77
|
+
const result = await sql.unsafe(`UPDATE tenants SET ${setClauses.join(', ')} WHERE id = $${setParams.length} RETURNING *`, setParams);
|
|
78
|
+
return result[0] ?? null;
|
|
79
|
+
}
|
|
80
|
+
async delete(id) {
|
|
81
|
+
const sql = getConnection();
|
|
82
|
+
const existing = await this.getById(id);
|
|
83
|
+
if (!existing)
|
|
84
|
+
return false;
|
|
85
|
+
await sql.unsafe(`UPDATE tenants SET status = $1, updated_at = NOW() WHERE id = $2`, ['DELETED', id]);
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export const tenantService = new TenantService();
|
|
90
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/tenant/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGtD,MAAM,OAAO,aAAa;IACxB,KAAK,CAAC,IAAI,CAAC,OAIV;QACC,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAC5B,MAAM,EAAE,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QACjD,MAAM,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;QAElC,IAAI,WAAW,GAAG,WAAW,CAAC;QAC9B,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,IAAI,MAAM,EAAE,CAAC;YACX,WAAW,IAAI,qBAAqB,MAAM,CAAC,MAAM,GAAG,CAAC,mBAAmB,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC;YAC7F,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC;QAC7B,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,MAAM,CACjC,yBAAyB,WAAW,mCAAmC,KAAK,WAAW,MAAM,EAAE,EAC/F,MAAM,CACP,CAAC;QACF,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,MAAM,CAClC,yCAAyC,WAAW,EAAE,EACtD,MAAM,CACP,CAAC;QAEF,OAAO;YACL,IAAI,EAAE,UAAiC;YACvC,KAAK,EAAE,MAAM,CAAE,WAAW,CAAC,CAAC,CAA6B,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;SAC3E,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,qCAAqC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7E,OAAQ,MAAM,CAAC,CAAC,CAAuB,IAAI,IAAI,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAY;QAC1B,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,uCAAuC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QACjF,OAAQ,MAAM,CAAC,CAAC,CAAuB,IAAI,IAAI,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAMZ;QACC,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAC5B,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,QAAQ,CAAC;QACxB,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAE5E,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAC7B;;mBAEa,EACb,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAClG,CAAC;QAEF,OAAO,MAAM,CAAC,CAAC,CAAsB,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,MAAM,CACV,EAAU,EACV,KAOC;QAED,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAE5B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAE3B,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,MAAM,SAAS,GAAa,EAAE,CAAC;QAE/B,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC7B,UAAU,CAAC,IAAI,CAAC,WAAW,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC;YACnD,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC7B,UAAU,CAAC,IAAI,CAAC,WAAW,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC;YACnD,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC/B,UAAU,CAAC,IAAI,CAAC,aAAa,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC;YACrD,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QACD,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAClC,UAAU,CAAC,IAAI,CAAC,gBAAgB,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC;YACxD,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAClC,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC/B,UAAU,CAAC,IAAI,CAAC,aAAa,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC;YACrD,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QACD,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACjC,UAAU,CAAC,IAAI,CAAC,eAAe,SAAS,CAAC,MAAM,GAAG,CAAC,SAAS,CAAC,CAAC;YAC9D,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,QAAQ,CAAC;QAE7C,UAAU,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACtC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEnB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAC7B,sBAAsB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,SAAS,CAAC,MAAM,cAAc,EACzF,SAAS,CACV,CAAC;QAEF,OAAQ,MAAM,CAAC,CAAC,CAAuB,IAAI,IAAI,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAE5B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;QAE5B,MAAM,GAAG,CAAC,MAAM,CAAC,kEAAkE,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;QAEtG,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Theme } from '@oktis-works/types';
|
|
2
|
+
export declare class ThemeService {
|
|
3
|
+
list(): Promise<Theme[]>;
|
|
4
|
+
getById(id: string): Promise<Theme | null>;
|
|
5
|
+
getByName(name: string): Promise<Theme | null>;
|
|
6
|
+
install(input: {
|
|
7
|
+
name: string;
|
|
8
|
+
version: string;
|
|
9
|
+
manifest: Record<string, unknown>;
|
|
10
|
+
config?: Record<string, unknown>;
|
|
11
|
+
}): Promise<Theme>;
|
|
12
|
+
activate(id: string): Promise<Theme | null>;
|
|
13
|
+
uninstall(id: string): Promise<boolean>;
|
|
14
|
+
}
|
|
15
|
+
export declare const themeService: ThemeService;
|
|
16
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/theme/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,qBAAa,YAAY;IACjB,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAMxB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAM1C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAM9C,OAAO,CAAC,KAAK,EAAE;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,GAAG,OAAO,CAAC,KAAK,CAAC;IAuBZ,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAiB3C,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAU9C;AAED,eAAO,MAAM,YAAY,cAAqB,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { getConnection } from '@oktis-works/database';
|
|
3
|
+
export class ThemeService {
|
|
4
|
+
async list() {
|
|
5
|
+
const sql = getConnection();
|
|
6
|
+
const result = await sql.unsafe('SELECT * FROM themes ORDER BY name ASC');
|
|
7
|
+
return result;
|
|
8
|
+
}
|
|
9
|
+
async getById(id) {
|
|
10
|
+
const sql = getConnection();
|
|
11
|
+
const result = await sql.unsafe('SELECT * FROM themes WHERE id = $1', [id]);
|
|
12
|
+
return result[0] ?? null;
|
|
13
|
+
}
|
|
14
|
+
async getByName(name) {
|
|
15
|
+
const sql = getConnection();
|
|
16
|
+
const result = await sql.unsafe('SELECT * FROM themes WHERE name = $1', [name]);
|
|
17
|
+
return result[0] ?? null;
|
|
18
|
+
}
|
|
19
|
+
async install(input) {
|
|
20
|
+
const sql = getConnection();
|
|
21
|
+
const id = randomUUID();
|
|
22
|
+
const now = new Date().toISOString();
|
|
23
|
+
const result = await sql.unsafe(`INSERT INTO themes (id, name, version, status, manifest, config, created_at, updated_at)
|
|
24
|
+
VALUES ($1, $2, $3, $4, $5::jsonb, $6::jsonb, $7, $7)
|
|
25
|
+
RETURNING *`, [
|
|
26
|
+
id,
|
|
27
|
+
input.name,
|
|
28
|
+
input.version,
|
|
29
|
+
'INSTALLED',
|
|
30
|
+
JSON.stringify(input.manifest),
|
|
31
|
+
input.config ? JSON.stringify(input.config) : '{}',
|
|
32
|
+
now,
|
|
33
|
+
]);
|
|
34
|
+
return result[0];
|
|
35
|
+
}
|
|
36
|
+
async activate(id) {
|
|
37
|
+
const sql = getConnection();
|
|
38
|
+
const existing = await this.getById(id);
|
|
39
|
+
if (!existing)
|
|
40
|
+
return null;
|
|
41
|
+
const result = await sql.unsafe(`UPDATE themes
|
|
42
|
+
SET status = $1, activated_at = NOW(), updated_at = NOW()
|
|
43
|
+
WHERE id = $2
|
|
44
|
+
RETURNING *`, ['ACTIVE', id]);
|
|
45
|
+
return result[0] ?? null;
|
|
46
|
+
}
|
|
47
|
+
async uninstall(id) {
|
|
48
|
+
const sql = getConnection();
|
|
49
|
+
const existing = await this.getById(id);
|
|
50
|
+
if (!existing)
|
|
51
|
+
return false;
|
|
52
|
+
await sql.unsafe('DELETE FROM themes WHERE id = $1', [id]);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export const themeService = new ThemeService();
|
|
57
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/theme/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGtD,MAAM,OAAO,YAAY;IACvB,KAAK,CAAC,IAAI;QACR,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,wCAAwC,CAAC,CAAC;QAC1E,OAAO,MAA4B,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,oCAAoC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5E,OAAQ,MAAM,CAAC,CAAC,CAAsB,IAAI,IAAI,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAY;QAC1B,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,sCAAsC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QAChF,OAAQ,MAAM,CAAC,CAAC,CAAsB,IAAI,IAAI,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAKb;QACC,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAC5B,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAErC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAC7B;;mBAEa,EACb;YACE,EAAE;YACF,KAAK,CAAC,IAAI;YACV,KAAK,CAAC,OAAO;YACb,WAAW;YACX,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC;YAC9B,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI;YAClD,GAAG;SACJ,CACF,CAAC;QAEF,OAAO,MAAM,CAAC,CAAC,CAAqB,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAE5B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAE3B,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAC7B;;;mBAGa,EACb,CAAC,QAAQ,EAAE,EAAE,CAAC,CACf,CAAC;QAEF,OAAQ,MAAM,CAAC,CAAC,CAAsB,IAAI,IAAI,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,EAAU;QACxB,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAE5B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;QAE5B,MAAM,GAAG,CAAC,MAAM,CAAC,kCAAkC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAE3D,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { User } from '@oktis-works/types';
|
|
2
|
+
export declare class UserService {
|
|
3
|
+
list(options: {
|
|
4
|
+
page?: number;
|
|
5
|
+
limit?: number;
|
|
6
|
+
search?: string;
|
|
7
|
+
status?: User['status'];
|
|
8
|
+
}): Promise<{
|
|
9
|
+
data: User[];
|
|
10
|
+
total: number;
|
|
11
|
+
}>;
|
|
12
|
+
getById(id: string): Promise<User | null>;
|
|
13
|
+
getByEmail(email: string): Promise<User | null>;
|
|
14
|
+
create(input: {
|
|
15
|
+
email: string;
|
|
16
|
+
name: string;
|
|
17
|
+
passwordHash: string;
|
|
18
|
+
avatar?: string;
|
|
19
|
+
}): Promise<User>;
|
|
20
|
+
update(id: string, input: {
|
|
21
|
+
name?: string;
|
|
22
|
+
email?: string;
|
|
23
|
+
avatar?: string;
|
|
24
|
+
status?: User['status'];
|
|
25
|
+
}): Promise<User | null>;
|
|
26
|
+
delete(id: string): Promise<boolean>;
|
|
27
|
+
addToTenant(userId: string, tenantId: string, roleId: string): Promise<void>;
|
|
28
|
+
removeFromTenant(userId: string, tenantId: string): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
export declare const userService: UserService;
|
|
31
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/user/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE/C,qBAAa,WAAW;IAChB,IAAI,CAAC,OAAO,EAAE;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;KACzB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAiCtC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAMzC,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAM/C,MAAM,CAAC,KAAK,EAAE;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,IAAI,CAAC;IAeX,MAAM,CACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE;QACL,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;KACzB,GACA,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAuCjB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWpC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW5E,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQxE;AAED,eAAO,MAAM,WAAW,aAAoB,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { getConnection } from '@oktis-works/database';
|
|
3
|
+
export class UserService {
|
|
4
|
+
async list(options) {
|
|
5
|
+
const sql = getConnection();
|
|
6
|
+
const { page = 1, limit = 20, search, status } = options;
|
|
7
|
+
const offset = (page - 1) * limit;
|
|
8
|
+
let whereClause = 'WHERE 1=1';
|
|
9
|
+
const params = [];
|
|
10
|
+
if (status) {
|
|
11
|
+
whereClause += ` AND status = $${params.length + 1}`;
|
|
12
|
+
params.push(status);
|
|
13
|
+
}
|
|
14
|
+
if (search) {
|
|
15
|
+
whereClause += ` AND (name ILIKE $${params.length + 1} OR email ILIKE $${params.length + 2})`;
|
|
16
|
+
params.push(`%${search}%`);
|
|
17
|
+
params.push(`%${search}%`);
|
|
18
|
+
}
|
|
19
|
+
const dataResult = await sql.unsafe(`SELECT * FROM users ${whereClause} ORDER BY created_at DESC LIMIT ${limit} OFFSET ${offset}`, params);
|
|
20
|
+
const countResult = await sql.unsafe(`SELECT COUNT(*) as total FROM users ${whereClause}`, params);
|
|
21
|
+
return {
|
|
22
|
+
data: dataResult,
|
|
23
|
+
total: Number(countResult[0]?.['total'] ?? 0),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async getById(id) {
|
|
27
|
+
const sql = getConnection();
|
|
28
|
+
const result = await sql.unsafe('SELECT * FROM users WHERE id = $1', [id]);
|
|
29
|
+
return result[0] ?? null;
|
|
30
|
+
}
|
|
31
|
+
async getByEmail(email) {
|
|
32
|
+
const sql = getConnection();
|
|
33
|
+
const result = await sql.unsafe('SELECT * FROM users WHERE email = $1', [email]);
|
|
34
|
+
return result[0] ?? null;
|
|
35
|
+
}
|
|
36
|
+
async create(input) {
|
|
37
|
+
const sql = getConnection();
|
|
38
|
+
const id = randomUUID();
|
|
39
|
+
const status = 'ACTIVE';
|
|
40
|
+
const result = await sql.unsafe(`INSERT INTO users (id, email, name, password_hash, avatar, status)
|
|
41
|
+
VALUES ($1, $2, $3, $4, $5, $6)
|
|
42
|
+
RETURNING *`, [id, input.email, input.name, input.passwordHash, input.avatar ?? null, status]);
|
|
43
|
+
return result[0];
|
|
44
|
+
}
|
|
45
|
+
async update(id, input) {
|
|
46
|
+
const sql = getConnection();
|
|
47
|
+
const existing = await this.getById(id);
|
|
48
|
+
if (!existing)
|
|
49
|
+
return null;
|
|
50
|
+
const setClauses = [];
|
|
51
|
+
const setParams = [];
|
|
52
|
+
if (input.name !== undefined) {
|
|
53
|
+
setClauses.push(`name = $${setParams.length + 1}`);
|
|
54
|
+
setParams.push(input.name);
|
|
55
|
+
}
|
|
56
|
+
if (input.email !== undefined) {
|
|
57
|
+
setClauses.push(`email = $${setParams.length + 1}`);
|
|
58
|
+
setParams.push(input.email);
|
|
59
|
+
}
|
|
60
|
+
if (input.avatar !== undefined) {
|
|
61
|
+
setClauses.push(`avatar = $${setParams.length + 1}`);
|
|
62
|
+
setParams.push(input.avatar);
|
|
63
|
+
}
|
|
64
|
+
if (input.status !== undefined) {
|
|
65
|
+
setClauses.push(`status = $${setParams.length + 1}`);
|
|
66
|
+
setParams.push(input.status);
|
|
67
|
+
}
|
|
68
|
+
if (setClauses.length === 0)
|
|
69
|
+
return existing;
|
|
70
|
+
setClauses.push(`updated_at = NOW()`);
|
|
71
|
+
setParams.push(id);
|
|
72
|
+
const result = await sql.unsafe(`UPDATE users SET ${setClauses.join(', ')} WHERE id = $${setParams.length} RETURNING *`, setParams);
|
|
73
|
+
return result[0] ?? null;
|
|
74
|
+
}
|
|
75
|
+
async delete(id) {
|
|
76
|
+
const sql = getConnection();
|
|
77
|
+
const existing = await this.getById(id);
|
|
78
|
+
if (!existing)
|
|
79
|
+
return false;
|
|
80
|
+
await sql.unsafe('DELETE FROM users WHERE id = $1', [id]);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
async addToTenant(userId, tenantId, roleId) {
|
|
84
|
+
const sql = getConnection();
|
|
85
|
+
const id = randomUUID();
|
|
86
|
+
await sql.unsafe(`INSERT INTO tenant_users (id, tenant_id, user_id, role_id, status)
|
|
87
|
+
VALUES ($1, $2, $3, $4, $5)`, [id, tenantId, userId, roleId, 'ACTIVE']);
|
|
88
|
+
}
|
|
89
|
+
async removeFromTenant(userId, tenantId) {
|
|
90
|
+
const sql = getConnection();
|
|
91
|
+
await sql.unsafe('DELETE FROM tenant_users WHERE user_id = $1 AND tenant_id = $2', [userId, tenantId]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export const userService = new UserService();
|
|
95
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/user/service.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@oktis-works/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./validators": {
|
|
14
|
+
"types": "./dist/fields/types/validators/index.d.ts",
|
|
15
|
+
"import": "./dist/fields/types/validators/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"dev": "tsc --watch",
|
|
21
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@oktis-works/types": "0.1.0",
|
|
25
|
+
"@oktis-works/validation": "0.1.0",
|
|
26
|
+
"@oktis-works/config": "0.1.0",
|
|
27
|
+
"@oktis-works/database": "0.1.0",
|
|
28
|
+
"@oktis-works/plugin-runtime": "0.1.0",
|
|
29
|
+
"@aws-sdk/client-s3": "3.700.0",
|
|
30
|
+
"semver": "7"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"typescript": "5.7.3"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist"
|
|
37
|
+
],
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public",
|
|
40
|
+
"registry": "https://registry.npmjs.org/"
|
|
41
|
+
},
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/blacklotus/blacklotus-cms",
|
|
46
|
+
"directory": "packages/core"
|
|
47
|
+
}
|
|
48
|
+
}
|