@zetra/citrineos-tenant 1.8.3-fork.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/module/DataApi.d.ts +40 -0
- package/dist/module/DataApi.js +66 -0
- package/dist/module/DataApi.js.map +1 -0
- package/dist/module/interface.d.ts +6 -0
- package/dist/module/interface.js +5 -0
- package/dist/module/interface.js.map +1 -0
- package/dist/module/module.d.ts +58 -0
- package/dist/module/module.js +185 -0
- package/dist/module/module.js.map +1 -0
- package/package.json +25 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,sCAAsC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AbstractModuleApi, Namespace, OCPP1_6_Namespace, OCPP2_0_1_Namespace } from '@citrineos/base';
|
|
2
|
+
import { TenantModule } from './module.js';
|
|
3
|
+
import type { ITenantModuleApi } from './interface.js';
|
|
4
|
+
import type { FastifyInstance, FastifyRequest } from 'fastify';
|
|
5
|
+
import type { ILogObj } from 'tslog';
|
|
6
|
+
import { Logger } from 'tslog';
|
|
7
|
+
import { Tenant } from '@citrineos/data';
|
|
8
|
+
/**
|
|
9
|
+
* Server API for the Tenant module.
|
|
10
|
+
*/
|
|
11
|
+
export declare class TenantDataApi extends AbstractModuleApi<TenantModule> implements ITenantModuleApi {
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
* Constructs a new instance of the class.
|
|
15
|
+
*
|
|
16
|
+
* @param {TenantModule} tenantModule - The Tenant module.
|
|
17
|
+
* @param {FastifyInstance} server - The Fastify server instance.
|
|
18
|
+
* @param {Logger<ILogObj>} [logger] - The logger instance.
|
|
19
|
+
*/
|
|
20
|
+
constructor(tenantModule: TenantModule, server: FastifyInstance, logger?: Logger<ILogObj>);
|
|
21
|
+
createTenant(request: FastifyRequest<{
|
|
22
|
+
Body: Tenant & {
|
|
23
|
+
tenantPath?: string;
|
|
24
|
+
websocketServerId?: string;
|
|
25
|
+
};
|
|
26
|
+
}>): Promise<Tenant>;
|
|
27
|
+
deleteTenant(request: FastifyRequest<{
|
|
28
|
+
Querystring: {
|
|
29
|
+
tenantId: number;
|
|
30
|
+
};
|
|
31
|
+
}>): Promise<boolean>;
|
|
32
|
+
/**
|
|
33
|
+
* Overrides superclass method to generate the URL path based on the input {@link Namespace}
|
|
34
|
+
* and the module's endpoint prefix configuration.
|
|
35
|
+
*
|
|
36
|
+
* @param {Namespace} input - The input {@link Namespace}.
|
|
37
|
+
* @return {string} - The generated URL path.
|
|
38
|
+
*/
|
|
39
|
+
protected _toDataPath(input: OCPP2_0_1_Namespace | OCPP1_6_Namespace | Namespace): string;
|
|
40
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
5
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
6
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
7
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
8
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
9
|
+
};
|
|
10
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
11
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
12
|
+
};
|
|
13
|
+
import { AbstractModuleApi, AsDataEndpoint, HttpMethod, Namespace, OCPP1_6_Namespace, OCPP2_0_1_Namespace, } from '@citrineos/base';
|
|
14
|
+
import { TenantModule } from './module.js';
|
|
15
|
+
import { Logger } from 'tslog';
|
|
16
|
+
import { Tenant, CreateTenantQuerySchema, TenantQuerySchema } from '@citrineos/data';
|
|
17
|
+
/**
|
|
18
|
+
* Server API for the Tenant module.
|
|
19
|
+
*/
|
|
20
|
+
export class TenantDataApi extends AbstractModuleApi {
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
* Constructs a new instance of the class.
|
|
24
|
+
*
|
|
25
|
+
* @param {TenantModule} tenantModule - The Tenant module.
|
|
26
|
+
* @param {FastifyInstance} server - The Fastify server instance.
|
|
27
|
+
* @param {Logger<ILogObj>} [logger] - The logger instance.
|
|
28
|
+
*/
|
|
29
|
+
constructor(tenantModule, server, logger) {
|
|
30
|
+
super(tenantModule, server, null, logger);
|
|
31
|
+
}
|
|
32
|
+
async createTenant(request) {
|
|
33
|
+
const { tenantPath, websocketServerId, ...tenantData } = request.body;
|
|
34
|
+
const createdTenant = await this._module.createTenant(tenantData, tenantPath, websocketServerId);
|
|
35
|
+
this._logger?.info(`Tenant created: ${createdTenant.id}`);
|
|
36
|
+
return createdTenant;
|
|
37
|
+
}
|
|
38
|
+
async deleteTenant(request) {
|
|
39
|
+
const deletedTenant = await this._module.deleteTenant(request.query.tenantId);
|
|
40
|
+
return !!deletedTenant;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Overrides superclass method to generate the URL path based on the input {@link Namespace}
|
|
44
|
+
* and the module's endpoint prefix configuration.
|
|
45
|
+
*
|
|
46
|
+
* @param {Namespace} input - The input {@link Namespace}.
|
|
47
|
+
* @return {string} - The generated URL path.
|
|
48
|
+
*/
|
|
49
|
+
_toDataPath(input) {
|
|
50
|
+
const endpointPrefix = this._module.config.modules.tenant.endpointPrefix;
|
|
51
|
+
return super._toDataPath(input, endpointPrefix);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
__decorate([
|
|
55
|
+
AsDataEndpoint(Namespace.Tenant, HttpMethod.Post, undefined, CreateTenantQuerySchema),
|
|
56
|
+
__metadata("design:type", Function),
|
|
57
|
+
__metadata("design:paramtypes", [Object]),
|
|
58
|
+
__metadata("design:returntype", Promise)
|
|
59
|
+
], TenantDataApi.prototype, "createTenant", null);
|
|
60
|
+
__decorate([
|
|
61
|
+
AsDataEndpoint(Namespace.Tenant, HttpMethod.Delete, TenantQuerySchema),
|
|
62
|
+
__metadata("design:type", Function),
|
|
63
|
+
__metadata("design:paramtypes", [Object]),
|
|
64
|
+
__metadata("design:returntype", Promise)
|
|
65
|
+
], TenantDataApi.prototype, "deleteTenant", null);
|
|
66
|
+
//# sourceMappingURL=DataApi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataApi.js","sourceRoot":"","sources":["../../src/module/DataApi.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,sCAAsC;;;;;;;;;;AAEtC,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrF;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,iBAA+B;IAChE;;;;;;;OAOG;IACH,YAAY,YAA0B,EAAE,MAAuB,EAAE,MAAwB;QACvF,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAGK,AAAN,KAAK,CAAC,YAAY,CAChB,OAKE;QAEF,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;QACtE,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CACnD,UAAoB,EACpB,UAAU,EACV,iBAAiB,CAClB,CAAC;QAEF,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,mBAAmB,aAAa,CAAC,EAAE,EAAE,CAAC,CAAC;QAE1D,OAAO,aAAa,CAAC;IACvB,CAAC;IAGK,AAAN,KAAK,CAAC,YAAY,CAChB,OAA8D;QAE9D,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC9E,OAAO,CAAC,CAAC,aAAa,CAAC;IACzB,CAAC;IAED;;;;;;OAMG;IACO,WAAW,CAAC,KAA0D;QAC9E,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC;QACzE,OAAO,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;IAClD,CAAC;CACF;AAvCO;IADL,cAAc,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,uBAAuB,CAAC;;;;iDAmBrF;AAGK;IADL,cAAc,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,iBAAiB,CAAC;;;;iDAMtE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interface.js","sourceRoot":"","sources":["../../src/module/interface.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,sCAAsC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { BootstrapConfig, CallAction, ICache, IMessageHandler, IMessageSender, SystemConfig } from '@citrineos/base';
|
|
2
|
+
import { AbstractModule, OCPPValidator } from '@citrineos/base';
|
|
3
|
+
import type { ILogObj } from 'tslog';
|
|
4
|
+
import { Logger } from 'tslog';
|
|
5
|
+
import { type ITenantRepository, Tenant } from '@citrineos/data';
|
|
6
|
+
export declare class TenantModule extends AbstractModule {
|
|
7
|
+
/**
|
|
8
|
+
* Fields
|
|
9
|
+
*/
|
|
10
|
+
_requests: CallAction[];
|
|
11
|
+
_responses: CallAction[];
|
|
12
|
+
protected _tenantRepository: ITenantRepository;
|
|
13
|
+
/**
|
|
14
|
+
* Constructor
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* This is the constructor function that initializes the {@link TenantModule}.
|
|
18
|
+
*
|
|
19
|
+
* @param {BootstrapConfig & SystemConfig} config - The `config` contains configuration settings for the module.
|
|
20
|
+
*
|
|
21
|
+
* @param {ICache} [cache] - The cache instance which is shared among the modules & Central System to pass information such as blacklisted actions or boot status.
|
|
22
|
+
*
|
|
23
|
+
* @param {IMessageSender} [sender] - The `sender` parameter is an optional parameter that represents an instance of the {@link IMessageSender} interface.
|
|
24
|
+
* It is used to send messages from the central system to external systems or devices. If no `sender` is provided, a default {@link RabbitMqSender} instance is created and used.
|
|
25
|
+
*
|
|
26
|
+
* @param {IMessageHandler} [handler] - The `handler` parameter is an optional parameter that represents an instance of the {@link IMessageHandler} interface.
|
|
27
|
+
* It is used to handle incoming messages and dispatch them to the appropriate methods or functions. If no `handler` is provided, a default {@link RabbitMqReceiver} instance is created and used.
|
|
28
|
+
*
|
|
29
|
+
* @param {Logger<ILogObj>} [logger] - The `logger` parameter is an optional parameter that represents an instance of {@link Logger<ILogObj>}.
|
|
30
|
+
* It is used to propagate system wide logger settings and will serve as the parent logger for any sub-component logging. If no `logger` is provided, a default {@link Logger<ILogObj>} instance is created and used.
|
|
31
|
+
*
|
|
32
|
+
* @param {ITenantRepository} [tenantRepository] - An optional parameter of type {@link ITenantRepository}
|
|
33
|
+
* which represents a repository for tenant data.
|
|
34
|
+
* If no `tenantRepository` is provided, a default {@link sequelize:tenantRepository} instance is created and used.
|
|
35
|
+
*/
|
|
36
|
+
constructor(config: BootstrapConfig & SystemConfig, cache: ICache, sender?: IMessageSender, handler?: IMessageHandler, logger?: Logger<ILogObj>, ocppValidator?: OCPPValidator, tenantRepository?: ITenantRepository);
|
|
37
|
+
get tenantRepository(): ITenantRepository;
|
|
38
|
+
/**
|
|
39
|
+
* Creates a tenant and adds a mapping to a websocket server if provided
|
|
40
|
+
*/
|
|
41
|
+
createTenant(tenant: Tenant, tenantPath?: string, websocketServerId?: string): Promise<Tenant>;
|
|
42
|
+
/**
|
|
43
|
+
* Deletes a tenant and removes all associated mappings from websocket servers
|
|
44
|
+
*/
|
|
45
|
+
deleteTenant(id: number): Promise<Tenant | undefined>;
|
|
46
|
+
/**
|
|
47
|
+
* Helper to resolve the OcppRouter Base URL
|
|
48
|
+
*/
|
|
49
|
+
private _getOcppRouterBaseUrl;
|
|
50
|
+
/**
|
|
51
|
+
* Helper to get system headers for internal communication
|
|
52
|
+
*/
|
|
53
|
+
private _getSystemHeaders;
|
|
54
|
+
/**
|
|
55
|
+
* Simple slugifier for tenant paths
|
|
56
|
+
*/
|
|
57
|
+
private _slugify;
|
|
58
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { AbstractModule, EventGroup, BadRequestError, DEFAULT_TENANT_ID, OCPPValidator, } from '@citrineos/base';
|
|
2
|
+
import { RabbitMqReceiver, RabbitMqSender } from '@citrineos/util';
|
|
3
|
+
import { Logger } from 'tslog';
|
|
4
|
+
import { SequelizeTenantRepository, Tenant } from '@citrineos/data';
|
|
5
|
+
export class TenantModule extends AbstractModule {
|
|
6
|
+
/**
|
|
7
|
+
* Fields
|
|
8
|
+
*/
|
|
9
|
+
_requests = [];
|
|
10
|
+
_responses = [];
|
|
11
|
+
_tenantRepository;
|
|
12
|
+
/**
|
|
13
|
+
* Constructor
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* This is the constructor function that initializes the {@link TenantModule}.
|
|
17
|
+
*
|
|
18
|
+
* @param {BootstrapConfig & SystemConfig} config - The `config` contains configuration settings for the module.
|
|
19
|
+
*
|
|
20
|
+
* @param {ICache} [cache] - The cache instance which is shared among the modules & Central System to pass information such as blacklisted actions or boot status.
|
|
21
|
+
*
|
|
22
|
+
* @param {IMessageSender} [sender] - The `sender` parameter is an optional parameter that represents an instance of the {@link IMessageSender} interface.
|
|
23
|
+
* It is used to send messages from the central system to external systems or devices. If no `sender` is provided, a default {@link RabbitMqSender} instance is created and used.
|
|
24
|
+
*
|
|
25
|
+
* @param {IMessageHandler} [handler] - The `handler` parameter is an optional parameter that represents an instance of the {@link IMessageHandler} interface.
|
|
26
|
+
* It is used to handle incoming messages and dispatch them to the appropriate methods or functions. If no `handler` is provided, a default {@link RabbitMqReceiver} instance is created and used.
|
|
27
|
+
*
|
|
28
|
+
* @param {Logger<ILogObj>} [logger] - The `logger` parameter is an optional parameter that represents an instance of {@link Logger<ILogObj>}.
|
|
29
|
+
* It is used to propagate system wide logger settings and will serve as the parent logger for any sub-component logging. If no `logger` is provided, a default {@link Logger<ILogObj>} instance is created and used.
|
|
30
|
+
*
|
|
31
|
+
* @param {ITenantRepository} [tenantRepository] - An optional parameter of type {@link ITenantRepository}
|
|
32
|
+
* which represents a repository for tenant data.
|
|
33
|
+
* If no `tenantRepository` is provided, a default {@link sequelize:tenantRepository} instance is created and used.
|
|
34
|
+
*/
|
|
35
|
+
constructor(config, cache, sender, handler, logger, ocppValidator, tenantRepository) {
|
|
36
|
+
super(config, cache, handler || new RabbitMqReceiver(config, logger), sender || new RabbitMqSender(config, logger), EventGroup.Tenant, logger, ocppValidator);
|
|
37
|
+
this._requests = config.modules.tenant.requests;
|
|
38
|
+
this._responses = config.modules.tenant.responses;
|
|
39
|
+
this._tenantRepository = tenantRepository || new SequelizeTenantRepository(config, logger);
|
|
40
|
+
}
|
|
41
|
+
get tenantRepository() {
|
|
42
|
+
return this._tenantRepository;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Creates a tenant and adds a mapping to a websocket server if provided
|
|
46
|
+
*/
|
|
47
|
+
async createTenant(tenant, tenantPath, websocketServerId) {
|
|
48
|
+
let effectivePath = tenantPath;
|
|
49
|
+
if (!effectivePath && tenant.name) {
|
|
50
|
+
const hasDynamicEnabled = this._config.util.networkConnection.websocketServers.some((ws) => ws.dynamicTenantResolution);
|
|
51
|
+
if (hasDynamicEnabled) {
|
|
52
|
+
effectivePath = this._slugify(tenant.name);
|
|
53
|
+
this._logger?.info(`No tenant path provided; generated slug '${effectivePath}' from name '${tenant.name}'`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (effectivePath) {
|
|
57
|
+
const serverIds = websocketServerId
|
|
58
|
+
? [websocketServerId]
|
|
59
|
+
: this._config.util.networkConnection.websocketServers
|
|
60
|
+
.filter((ws) => ws.dynamicTenantResolution)
|
|
61
|
+
.map((ws) => ws.id)
|
|
62
|
+
.filter((id) => !!id);
|
|
63
|
+
const baseUrl = this._getOcppRouterBaseUrl();
|
|
64
|
+
for (const id of serverIds) {
|
|
65
|
+
const routerUrl = `${baseUrl}/data/ocpprouter/websocket?id=${id}`;
|
|
66
|
+
try {
|
|
67
|
+
const response = await fetch(routerUrl, {
|
|
68
|
+
headers: this._getSystemHeaders(),
|
|
69
|
+
});
|
|
70
|
+
if (response.ok) {
|
|
71
|
+
const config = (await response.json());
|
|
72
|
+
if (config.tenantPathMapping && config.tenantPathMapping[effectivePath]) {
|
|
73
|
+
throw new BadRequestError(`Tenant path '${effectivePath}' is already taken on server '${id}'`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (error instanceof BadRequestError) {
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
this._logger?.warn(`Could not verify path availability on server ${id}: ${error instanceof Error ? error.message : error}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const createdTenant = await this._tenantRepository.createTenant(tenant);
|
|
86
|
+
if (effectivePath) {
|
|
87
|
+
const serverIds = websocketServerId
|
|
88
|
+
? [websocketServerId]
|
|
89
|
+
: this._config.util.networkConnection.websocketServers
|
|
90
|
+
.filter((ws) => ws.dynamicTenantResolution)
|
|
91
|
+
.map((ws) => ws.id)
|
|
92
|
+
.filter((id) => !!id);
|
|
93
|
+
const baseUrl = this._getOcppRouterBaseUrl();
|
|
94
|
+
for (const id of serverIds) {
|
|
95
|
+
const routerUrl = `${baseUrl}/data/ocpprouter/websocketMapping?id=${id}`;
|
|
96
|
+
try {
|
|
97
|
+
const response = await fetch(routerUrl, {
|
|
98
|
+
method: 'PUT',
|
|
99
|
+
headers: this._getSystemHeaders(),
|
|
100
|
+
body: JSON.stringify({
|
|
101
|
+
path: effectivePath,
|
|
102
|
+
tenantId: createdTenant.id,
|
|
103
|
+
}),
|
|
104
|
+
});
|
|
105
|
+
if (!response.ok) {
|
|
106
|
+
const errorBody = await response.text();
|
|
107
|
+
this._logger?.error(`Failed to add websocket mapping on server ${id}: ${response.status} ${errorBody}`);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
this._logger?.info(`Successfully added websocket mapping for tenant ${createdTenant.id} to path ${effectivePath} on server ${id}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
this._logger?.error(`Error calling OcppRouter API at ${routerUrl}:`, error);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
this._logger?.info(`Tenant created: ${createdTenant.id}`);
|
|
119
|
+
return createdTenant;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Deletes a tenant and removes all associated mappings from websocket servers
|
|
123
|
+
*/
|
|
124
|
+
async deleteTenant(id) {
|
|
125
|
+
const serverIds = this._config.util.networkConnection.websocketServers
|
|
126
|
+
.map((ws) => ws.id)
|
|
127
|
+
.filter((id) => !!id);
|
|
128
|
+
const baseUrl = this._getOcppRouterBaseUrl();
|
|
129
|
+
for (const serverId of serverIds) {
|
|
130
|
+
const routerUrl = `${baseUrl}/data/ocpprouter/websocketMapping?id=${serverId}&tenantId=${id}`;
|
|
131
|
+
try {
|
|
132
|
+
const response = await fetch(routerUrl, {
|
|
133
|
+
method: 'DELETE',
|
|
134
|
+
headers: this._getSystemHeaders(),
|
|
135
|
+
});
|
|
136
|
+
if (!response.ok) {
|
|
137
|
+
this._logger?.error(`Failed to cleanup websocket mapping for tenant ${id} on server ${serverId}: ${response.status}`);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
this._logger?.info(`Cleaned up websocket mappings for tenant ${id} on server ${serverId}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
this._logger?.error(`Error cleaning up mapping at ${routerUrl}:`, error);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const deletedTenant = await this._tenantRepository.deleteByKey(DEFAULT_TENANT_ID, id.toString()); // DEFAULT_TENANT_ID for global tenant table
|
|
148
|
+
if (deletedTenant) {
|
|
149
|
+
this._logger?.info(`Tenant deleted: ${id}`);
|
|
150
|
+
}
|
|
151
|
+
return deletedTenant;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Helper to resolve the OcppRouter Base URL
|
|
155
|
+
*/
|
|
156
|
+
_getOcppRouterBaseUrl() {
|
|
157
|
+
return (this._config.modules.tenant.ocppRouterBaseUrl ||
|
|
158
|
+
`http://${this._config.centralSystem.host}:${this._config.centralSystem.port}`);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Helper to get system headers for internal communication
|
|
162
|
+
*/
|
|
163
|
+
_getSystemHeaders() {
|
|
164
|
+
const headers = {
|
|
165
|
+
'Content-Type': 'application/json',
|
|
166
|
+
};
|
|
167
|
+
if (this._config.centralSystem.systemApiToken) {
|
|
168
|
+
headers['x-system-token'] = this._config.centralSystem.systemApiToken;
|
|
169
|
+
}
|
|
170
|
+
return headers;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Simple slugifier for tenant paths
|
|
174
|
+
*/
|
|
175
|
+
_slugify(text) {
|
|
176
|
+
return text
|
|
177
|
+
.toString()
|
|
178
|
+
.toLowerCase()
|
|
179
|
+
.trim()
|
|
180
|
+
.replace(/\s+/g, '-') // Replace spaces with -
|
|
181
|
+
.replace(/[^\w-]+/g, '') // Remove all non-word chars
|
|
182
|
+
.replace(/--+/g, '-'); // Replace multiple - with single -
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/module/module.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zetra/citrineos-tenant",
|
|
3
|
+
"version": "1.8.3-fork.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "The tenant module for OCPP v2.0.1. This module is not intended to be used directly, but rather as a dependency for other modules.",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"prepublish": "npx eslint",
|
|
13
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"ocpp",
|
|
17
|
+
"ocpp_v201"
|
|
18
|
+
],
|
|
19
|
+
"license": "Apache-2.0",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@zetra/citrineos-base": "1.8.3-fork.1",
|
|
22
|
+
"@zetra/citrineos-data": "1.8.3-fork.1",
|
|
23
|
+
"@zetra/citrineos-util": "1.8.3-fork.1"
|
|
24
|
+
}
|
|
25
|
+
}
|