mcp-creatio 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +252 -212
- package/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +18 -11
- package/dist/cli.js.map +1 -1
- package/dist/creatio/auth/auth.d.ts +2 -0
- package/dist/creatio/auth/auth.d.ts.map +1 -1
- package/dist/creatio/auth/auth.js.map +1 -1
- package/dist/creatio/auth/providers/base-provider.d.ts +1 -0
- package/dist/creatio/auth/providers/base-provider.d.ts.map +1 -1
- package/dist/creatio/auth/providers/base-provider.js +3 -0
- package/dist/creatio/auth/providers/base-provider.js.map +1 -1
- package/dist/creatio/auth/providers/oauth2-code-provider.d.ts +3 -0
- package/dist/creatio/auth/providers/oauth2-code-provider.d.ts.map +1 -1
- package/dist/creatio/auth/providers/oauth2-code-provider.js +30 -24
- package/dist/creatio/auth/providers/oauth2-code-provider.js.map +1 -1
- package/dist/creatio/providers/configuration-provider.d.ts +3 -2
- package/dist/creatio/providers/configuration-provider.d.ts.map +1 -1
- package/dist/creatio/providers/crud-provider.d.ts +2 -0
- package/dist/creatio/providers/crud-provider.d.ts.map +1 -1
- package/dist/creatio/services/configuration-service-provider.d.ts.map +1 -1
- package/dist/creatio/services/configuration-service-provider.js +11 -3
- package/dist/creatio/services/configuration-service-provider.js.map +1 -1
- package/dist/creatio/services/http-client.d.ts.map +1 -1
- package/dist/creatio/services/http-client.js +0 -1
- package/dist/creatio/services/http-client.js.map +1 -1
- package/dist/creatio/services/metadata-store.d.ts +5 -0
- package/dist/creatio/services/metadata-store.d.ts.map +1 -1
- package/dist/creatio/services/metadata-store.js +18 -6
- package/dist/creatio/services/metadata-store.js.map +1 -1
- package/dist/creatio/services/odata-crud-provider.d.ts +3 -1
- package/dist/creatio/services/odata-crud-provider.d.ts.map +1 -1
- package/dist/creatio/services/odata-crud-provider.js +31 -8
- package/dist/creatio/services/odata-crud-provider.js.map +1 -1
- package/dist/server/http/creatio-oauth-handlers.d.ts +0 -1
- package/dist/server/http/creatio-oauth-handlers.d.ts.map +1 -1
- package/dist/server/http/creatio-oauth-handlers.js +30 -23
- package/dist/server/http/creatio-oauth-handlers.js.map +1 -1
- package/dist/server/http/httpServer.d.ts +9 -0
- package/dist/server/http/httpServer.d.ts.map +1 -1
- package/dist/server/http/httpServer.js +34 -11
- package/dist/server/http/httpServer.js.map +1 -1
- package/dist/server/http/mcp-handlers.d.ts.map +1 -1
- package/dist/server/http/mcp-handlers.js +4 -1
- package/dist/server/http/mcp-handlers.js.map +1 -1
- package/dist/server/http/mcp-oauth-handlers.d.ts.map +1 -1
- package/dist/server/http/mcp-oauth-handlers.js +18 -6
- package/dist/server/http/mcp-oauth-handlers.js.map +1 -1
- package/dist/server/http/middleware.d.ts +7 -0
- package/dist/server/http/middleware.d.ts.map +1 -1
- package/dist/server/http/middleware.js +23 -0
- package/dist/server/http/middleware.js.map +1 -1
- package/dist/server/http/rate-limiter.d.ts +24 -0
- package/dist/server/http/rate-limiter.d.ts.map +1 -0
- package/dist/server/http/rate-limiter.js +42 -0
- package/dist/server/http/rate-limiter.js.map +1 -0
- package/dist/server/mcp/creatio-rest.d.ts +44 -0
- package/dist/server/mcp/creatio-rest.d.ts.map +1 -0
- package/dist/server/mcp/creatio-rest.js +26 -0
- package/dist/server/mcp/creatio-rest.js.map +1 -0
- package/dist/server/mcp/crtmcp/crt-mcp-client.d.ts +55 -0
- package/dist/server/mcp/crtmcp/crt-mcp-client.d.ts.map +1 -0
- package/dist/server/mcp/crtmcp/crt-mcp-client.js +67 -0
- package/dist/server/mcp/crtmcp/crt-mcp-client.js.map +1 -0
- package/dist/server/mcp/crtmcp/crt-mcp-tool-preparer.d.ts +20 -0
- package/dist/server/mcp/crtmcp/crt-mcp-tool-preparer.d.ts.map +1 -0
- package/dist/server/mcp/crtmcp/crt-mcp-tool-preparer.js +74 -0
- package/dist/server/mcp/crtmcp/crt-mcp-tool-preparer.js.map +1 -0
- package/dist/server/mcp/dataforge/dataforge-client.d.ts +64 -0
- package/dist/server/mcp/dataforge/dataforge-client.d.ts.map +1 -0
- package/dist/server/mcp/dataforge/dataforge-client.js +130 -0
- package/dist/server/mcp/dataforge/dataforge-client.js.map +1 -0
- package/dist/server/mcp/dataforge/dataforge-tool-preparer.d.ts +17 -0
- package/dist/server/mcp/dataforge/dataforge-tool-preparer.d.ts.map +1 -0
- package/dist/server/mcp/dataforge/dataforge-tool-preparer.js +42 -0
- package/dist/server/mcp/dataforge/dataforge-tool-preparer.js.map +1 -0
- package/dist/server/mcp/filters.d.ts.map +1 -1
- package/dist/server/mcp/filters.js +20 -4
- package/dist/server/mcp/filters.js.map +1 -1
- package/dist/server/mcp/globalsearch/globalsearch-client.d.ts +50 -0
- package/dist/server/mcp/globalsearch/globalsearch-client.d.ts.map +1 -0
- package/dist/server/mcp/globalsearch/globalsearch-client.js +118 -0
- package/dist/server/mcp/globalsearch/globalsearch-client.js.map +1 -0
- package/dist/server/mcp/globalsearch/globalsearch-tool-preparer.d.ts +16 -0
- package/dist/server/mcp/globalsearch/globalsearch-tool-preparer.d.ts.map +1 -0
- package/dist/server/mcp/globalsearch/globalsearch-tool-preparer.js +34 -0
- package/dist/server/mcp/globalsearch/globalsearch-tool-preparer.js.map +1 -0
- package/dist/server/mcp/json-schema-to-zod.d.ts +3 -0
- package/dist/server/mcp/json-schema-to-zod.d.ts.map +1 -0
- package/dist/server/mcp/json-schema-to-zod.js +54 -0
- package/dist/server/mcp/json-schema-to-zod.js.map +1 -0
- package/dist/server/mcp/server.d.ts +18 -0
- package/dist/server/mcp/server.d.ts.map +1 -1
- package/dist/server/mcp/server.js +93 -25
- package/dist/server/mcp/server.js.map +1 -1
- package/dist/server/mcp/tool-preparer.d.ts +26 -0
- package/dist/server/mcp/tool-preparer.d.ts.map +1 -0
- package/dist/server/mcp/tool-preparer.js +11 -0
- package/dist/server/mcp/tool-preparer.js.map +1 -0
- package/dist/server/mcp/tools-data.d.ts +69 -10
- package/dist/server/mcp/tools-data.d.ts.map +1 -1
- package/dist/server/mcp/tools-data.js +222 -32
- package/dist/server/mcp/tools-data.js.map +1 -1
- package/dist/server/oauth/oauth-server.d.ts +0 -1
- package/dist/server/oauth/oauth-server.d.ts.map +1 -1
- package/dist/server/oauth/oauth-server.js +11 -21
- package/dist/server/oauth/oauth-server.js.map +1 -1
- package/dist/server/oauth/storage.d.ts +0 -2
- package/dist/server/oauth/storage.d.ts.map +1 -1
- package/dist/server/oauth/storage.js +0 -6
- package/dist/server/oauth/storage.js.map +1 -1
- package/dist/server/oauth/validators.d.ts +6 -0
- package/dist/server/oauth/validators.d.ts.map +1 -1
- package/dist/server/oauth/validators.js +28 -0
- package/dist/server/oauth/validators.js.map +1 -1
- package/dist/services/session-context.d.ts +8 -7
- package/dist/services/session-context.d.ts.map +1 -1
- package/dist/services/session-context.js +7 -27
- package/dist/services/session-context.js.map +1 -1
- package/package.json +18 -9
- package/.dockerignore +0 -12
- package/.editorconfig +0 -14
- package/.eslintrc.cjs +0 -18
- package/.gitattributes +0 -8
- package/.github/workflows/docker-publish.yml +0 -50
- package/.prettierignore +0 -3
- package/.prettierrc +0 -9
- package/.vscode/launch.json +0 -23
- package/.vscode/mcp.json +0 -13
- package/.vscode/settings.json +0 -16
- package/Agent.md +0 -190
- package/Debug.md +0 -32
- package/Dockerfile +0 -23
- package/docs/coding-style.md +0 -30
- package/eslint.config.cjs +0 -95
- package/src/cli.ts +0 -162
- package/src/config-builder.ts +0 -76
- package/src/consts.ts +0 -3
- package/src/creatio/auth/auth-manager.ts +0 -27
- package/src/creatio/auth/auth.ts +0 -31
- package/src/creatio/auth/index.ts +0 -3
- package/src/creatio/auth/providers/base-oauth2-provider.ts +0 -62
- package/src/creatio/auth/providers/base-provider.ts +0 -42
- package/src/creatio/auth/providers/index.ts +0 -4
- package/src/creatio/auth/providers/legacy-provider.ts +0 -70
- package/src/creatio/auth/providers/oauth2-code-provider.ts +0 -252
- package/src/creatio/auth/providers/oauth2-provider.ts +0 -91
- package/src/creatio/auth/providers/type.ts +0 -5
- package/src/creatio/client-config.ts +0 -34
- package/src/creatio/engines/admin-operation/admin-operation-engine.ts +0 -44
- package/src/creatio/engines/configuration/configuration-engine.ts +0 -26
- package/src/creatio/engines/crud/crud-engine.ts +0 -47
- package/src/creatio/engines/engine-manager.ts +0 -157
- package/src/creatio/engines/engine-registry.ts +0 -39
- package/src/creatio/engines/engine.ts +0 -3
- package/src/creatio/engines/feature/feature-engine.ts +0 -20
- package/src/creatio/engines/index.ts +0 -10
- package/src/creatio/engines/process/process-engine.ts +0 -20
- package/src/creatio/engines/sys-settings/sys-settings-engine.ts +0 -41
- package/src/creatio/engines/user/user-engine.ts +0 -20
- package/src/creatio/index.ts +0 -6
- package/src/creatio/provider-context.ts +0 -21
- package/src/creatio/providers/admin-operation-provider.ts +0 -34
- package/src/creatio/providers/configuration-provider.ts +0 -22
- package/src/creatio/providers/crud-provider.ts +0 -45
- package/src/creatio/providers/feature-provider.ts +0 -10
- package/src/creatio/providers/index.ts +0 -7
- package/src/creatio/providers/process-provider.ts +0 -15
- package/src/creatio/providers/sys-settings-provider.ts +0 -63
- package/src/creatio/providers/user-provider.ts +0 -12
- package/src/creatio/services/admin-operation-service-provider.ts +0 -115
- package/src/creatio/services/configuration-service-provider.ts +0 -127
- package/src/creatio/services/creatio-service-context.ts +0 -55
- package/src/creatio/services/feature-service-provider.ts +0 -60
- package/src/creatio/services/http-client.ts +0 -174
- package/src/creatio/services/index.ts +0 -10
- package/src/creatio/services/metadata-store.ts +0 -181
- package/src/creatio/services/odata-crud-provider.ts +0 -210
- package/src/creatio/services/process-service-provider.ts +0 -76
- package/src/creatio/services/sys-settings-service-provider.ts +0 -192
- package/src/creatio/services/user-info-provider.ts +0 -41
- package/src/index.ts +0 -44
- package/src/log.ts +0 -183
- package/src/server/http/creatio-oauth-handlers.ts +0 -146
- package/src/server/http/httpServer.ts +0 -150
- package/src/server/http/index.ts +0 -5
- package/src/server/http/mcp-handlers.ts +0 -92
- package/src/server/http/mcp-oauth-handlers.ts +0 -108
- package/src/server/http/middleware.ts +0 -91
- package/src/server/index.ts +0 -2
- package/src/server/mcp/filters.ts +0 -97
- package/src/server/mcp/index.ts +0 -1
- package/src/server/mcp/prompts-data.ts +0 -1292
- package/src/server/mcp/server.ts +0 -442
- package/src/server/mcp/tools-data.ts +0 -748
- package/src/server/oauth/client-manager.ts +0 -47
- package/src/server/oauth/index.ts +0 -6
- package/src/server/oauth/oauth-server.ts +0 -185
- package/src/server/oauth/storage.ts +0 -106
- package/src/server/oauth/token-manager.ts +0 -80
- package/src/server/oauth/types.ts +0 -55
- package/src/server/oauth/validators.ts +0 -56
- package/src/services/index.ts +0 -2
- package/src/services/session-context.ts +0 -232
- package/src/services/token-refresh-scheduler.ts +0 -68
- package/src/types/index.ts +0 -1
- package/src/types/network.ts +0 -7
- package/src/utils/context.ts +0 -49
- package/src/utils/env.ts +0 -12
- package/src/utils/index.ts +0 -5
- package/src/utils/mcp.ts +0 -8
- package/src/utils/network.ts +0 -65
- package/src/utils/pkce.ts +0 -39
- package/src/version.ts +0 -15
- package/tsconfig.json +0 -28
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CallConfigurationServiceRequest,
|
|
3
|
-
CallConfigurationServiceResult,
|
|
4
|
-
ConfigurationProvider,
|
|
5
|
-
ConfigurationServiceHttpMethod,
|
|
6
|
-
ConfigurationServiceQueryValue,
|
|
7
|
-
} from '../providers';
|
|
8
|
-
|
|
9
|
-
import { CreatioHttpClient } from './http-client';
|
|
10
|
-
|
|
11
|
-
const VALID_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9_-]*$/;
|
|
12
|
-
const METHODS_WITHOUT_BODY: ReadonlySet<ConfigurationServiceHttpMethod> = new Set([
|
|
13
|
-
'GET',
|
|
14
|
-
'DELETE',
|
|
15
|
-
]);
|
|
16
|
-
|
|
17
|
-
export class ConfigurationServiceProvider implements ConfigurationProvider {
|
|
18
|
-
private readonly _client: CreatioHttpClient;
|
|
19
|
-
|
|
20
|
-
public readonly kind = 'creatio-configuration-service';
|
|
21
|
-
|
|
22
|
-
constructor(client: CreatioHttpClient) {
|
|
23
|
-
this._client = client;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
private _validateName(kind: 'service' | 'method', value: string): void {
|
|
27
|
-
if (!VALID_NAME_PATTERN.test(value)) {
|
|
28
|
-
throw new Error(`creatio_configuration_invalid_${kind}_name:${value}`);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
private _buildQueryString(
|
|
33
|
-
query: Record<string, ConfigurationServiceQueryValue> | undefined,
|
|
34
|
-
): string {
|
|
35
|
-
if (!query) {
|
|
36
|
-
return '';
|
|
37
|
-
}
|
|
38
|
-
const params = new URLSearchParams();
|
|
39
|
-
for (const [key, value] of Object.entries(query)) {
|
|
40
|
-
params.append(key, String(value));
|
|
41
|
-
}
|
|
42
|
-
const serialized = params.toString();
|
|
43
|
-
return serialized ? `?${serialized}` : '';
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
private _buildUrl(request: CallConfigurationServiceRequest): string {
|
|
47
|
-
this._validateName('service', request.service);
|
|
48
|
-
this._validateName('method', request.method);
|
|
49
|
-
const base = `${this._client.normalizedBaseUrl}/0/rest/${request.service}/${request.method}`;
|
|
50
|
-
return `${base}${this._buildQueryString(request.query)}`;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
private async _buildRequestInit(
|
|
54
|
-
httpMethod: ConfigurationServiceHttpMethod,
|
|
55
|
-
body: unknown,
|
|
56
|
-
): Promise<RequestInit> {
|
|
57
|
-
const includeBody = !METHODS_WITHOUT_BODY.has(httpMethod) && body !== undefined;
|
|
58
|
-
const headers = includeBody
|
|
59
|
-
? await this._client.getPostHeaders()
|
|
60
|
-
: await this._client.getJsonHeaders();
|
|
61
|
-
const init: RequestInit = { method: httpMethod, headers };
|
|
62
|
-
if (includeBody) {
|
|
63
|
-
init.body = JSON.stringify(body);
|
|
64
|
-
}
|
|
65
|
-
return init;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
private async _parseResponseBody(response: Response): Promise<{
|
|
69
|
-
body: unknown;
|
|
70
|
-
contentType?: string;
|
|
71
|
-
}> {
|
|
72
|
-
const contentType = response.headers.get('content-type') ?? undefined;
|
|
73
|
-
const text = await response.text();
|
|
74
|
-
if (!text) {
|
|
75
|
-
return contentType !== undefined ? { body: null, contentType } : { body: null };
|
|
76
|
-
}
|
|
77
|
-
if (contentType && contentType.toLowerCase().includes('application/json')) {
|
|
78
|
-
try {
|
|
79
|
-
return { body: JSON.parse(text), contentType };
|
|
80
|
-
} catch {
|
|
81
|
-
return { body: text, contentType };
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return contentType !== undefined ? { body: text, contentType } : { body: text };
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
public async call(
|
|
88
|
-
request: CallConfigurationServiceRequest,
|
|
89
|
-
): Promise<CallConfigurationServiceResult> {
|
|
90
|
-
const httpMethod: ConfigurationServiceHttpMethod = request.httpMethod ?? 'POST';
|
|
91
|
-
const url = this._buildUrl(request);
|
|
92
|
-
const operation = `call-configuration-service:${request.service}.${request.method}`;
|
|
93
|
-
return this._client.executeWithTiming(
|
|
94
|
-
operation,
|
|
95
|
-
url,
|
|
96
|
-
async () => {
|
|
97
|
-
const init = await this._buildRequestInit(httpMethod, request.body);
|
|
98
|
-
return this._client.fetchWithAuth(url, async () => init);
|
|
99
|
-
},
|
|
100
|
-
async (response, duration) => {
|
|
101
|
-
const { body, contentType } = await this._parseResponseBody(response);
|
|
102
|
-
this._client.logSuccess(operation, response.status, duration, {
|
|
103
|
-
httpMethod,
|
|
104
|
-
service: request.service,
|
|
105
|
-
method: request.method,
|
|
106
|
-
});
|
|
107
|
-
const result: CallConfigurationServiceResult = {
|
|
108
|
-
status: response.status,
|
|
109
|
-
body,
|
|
110
|
-
};
|
|
111
|
-
if (contentType !== undefined) {
|
|
112
|
-
result.contentType = contentType;
|
|
113
|
-
}
|
|
114
|
-
return result;
|
|
115
|
-
},
|
|
116
|
-
async (response, duration) =>
|
|
117
|
-
this._client.handleErrorResponse(
|
|
118
|
-
operation,
|
|
119
|
-
response,
|
|
120
|
-
duration,
|
|
121
|
-
'creatio_configuration_service_failed',
|
|
122
|
-
{ url, httpMethod },
|
|
123
|
-
),
|
|
124
|
-
{ httpMethod, service: request.service, method: request.method },
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { CreatioAuthManager, ICreatioAuthProvider } from '../auth';
|
|
2
|
-
import { CreatioClientConfig } from '../client-config';
|
|
3
|
-
import { CreatioProviderContext } from '../provider-context';
|
|
4
|
-
import {
|
|
5
|
-
AdminOperationProvider,
|
|
6
|
-
ConfigurationProvider,
|
|
7
|
-
CrudProvider,
|
|
8
|
-
FeatureProvider,
|
|
9
|
-
ProcessProvider,
|
|
10
|
-
SysSettingsProvider,
|
|
11
|
-
UserProvider,
|
|
12
|
-
} from '../providers';
|
|
13
|
-
|
|
14
|
-
import { AdminOperationServiceProvider } from './admin-operation-service-provider';
|
|
15
|
-
import { ConfigurationServiceProvider } from './configuration-service-provider';
|
|
16
|
-
import { FeatureServiceProvider } from './feature-service-provider';
|
|
17
|
-
import { CreatioHttpClient } from './http-client';
|
|
18
|
-
import { ODataMetadataStore } from './metadata-store';
|
|
19
|
-
import { ODataCrudProvider } from './odata-crud-provider';
|
|
20
|
-
import { ProcessServiceProvider } from './process-service-provider';
|
|
21
|
-
import { SysSettingsServiceProvider } from './sys-settings-service-provider';
|
|
22
|
-
import { UserInfoProvider } from './user-info-provider';
|
|
23
|
-
|
|
24
|
-
export class CreatioServiceContext implements CreatioProviderContext {
|
|
25
|
-
private readonly _config: CreatioClientConfig;
|
|
26
|
-
private readonly _authManager: CreatioAuthManager;
|
|
27
|
-
private readonly _httpClient: CreatioHttpClient;
|
|
28
|
-
|
|
29
|
-
public readonly kind = 'creatio-services';
|
|
30
|
-
public readonly adminOperation: AdminOperationProvider;
|
|
31
|
-
public readonly configuration: ConfigurationProvider;
|
|
32
|
-
public readonly crud: CrudProvider;
|
|
33
|
-
public readonly feature: FeatureProvider;
|
|
34
|
-
public readonly process: ProcessProvider;
|
|
35
|
-
public readonly sysSettings: SysSettingsProvider;
|
|
36
|
-
public readonly user: UserProvider;
|
|
37
|
-
|
|
38
|
-
public get authProvider(): ICreatioAuthProvider {
|
|
39
|
-
return this._authManager.getProvider();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
constructor(config: CreatioClientConfig) {
|
|
43
|
-
this._config = config;
|
|
44
|
-
this._authManager = new CreatioAuthManager(this._config);
|
|
45
|
-
this._httpClient = new CreatioHttpClient(this._config, this._authManager);
|
|
46
|
-
const metadataStore = new ODataMetadataStore(this._httpClient);
|
|
47
|
-
this.adminOperation = new AdminOperationServiceProvider(this._httpClient);
|
|
48
|
-
this.configuration = new ConfigurationServiceProvider(this._httpClient);
|
|
49
|
-
this.crud = new ODataCrudProvider(this._httpClient, metadataStore);
|
|
50
|
-
this.feature = new FeatureServiceProvider(this._httpClient);
|
|
51
|
-
this.process = new ProcessServiceProvider(this._httpClient);
|
|
52
|
-
this.sysSettings = new SysSettingsServiceProvider(this._httpClient);
|
|
53
|
-
this.user = new UserInfoProvider(this._httpClient);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { ClearFeatureCacheResult, FeatureProvider } from '../providers';
|
|
2
|
-
|
|
3
|
-
import { CreatioHttpClient } from './http-client';
|
|
4
|
-
|
|
5
|
-
export class FeatureServiceProvider implements FeatureProvider {
|
|
6
|
-
private readonly _client: CreatioHttpClient;
|
|
7
|
-
|
|
8
|
-
public readonly kind = 'creatio-feature-service';
|
|
9
|
-
|
|
10
|
-
constructor(client: CreatioHttpClient) {
|
|
11
|
-
this._client = client;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
private _getClearCacheUrl(featureCode?: string): string {
|
|
15
|
-
const base = `${this._client.normalizedBaseUrl}/0/rest/FeatureService/ClearFeaturesCacheForAllUsers`;
|
|
16
|
-
if (!featureCode) {
|
|
17
|
-
return `${base}/`;
|
|
18
|
-
}
|
|
19
|
-
const encoded = Buffer.from(featureCode, 'utf8').toString('base64');
|
|
20
|
-
return `${base}/${encoded}`;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
public async clearFeaturesCache(featureCode?: string): Promise<ClearFeatureCacheResult> {
|
|
24
|
-
const url = this._getClearCacheUrl(featureCode);
|
|
25
|
-
return this._client.executeWithTiming(
|
|
26
|
-
'clear-features-cache',
|
|
27
|
-
url,
|
|
28
|
-
async () => {
|
|
29
|
-
const headers = await this._client.getJsonHeaders();
|
|
30
|
-
return this._client.fetchWithAuth(url, async () => ({
|
|
31
|
-
method: 'GET',
|
|
32
|
-
headers,
|
|
33
|
-
}));
|
|
34
|
-
},
|
|
35
|
-
async (response, duration) => {
|
|
36
|
-
const message = await response.text();
|
|
37
|
-
this._client.logSuccess('clear-features-cache', response.status, duration, {
|
|
38
|
-
featureCode: featureCode ?? '(all)',
|
|
39
|
-
});
|
|
40
|
-
const result: ClearFeatureCacheResult = { success: true, message };
|
|
41
|
-
if (featureCode !== undefined) {
|
|
42
|
-
result.featureCode = featureCode;
|
|
43
|
-
}
|
|
44
|
-
return result;
|
|
45
|
-
},
|
|
46
|
-
async (response, duration) =>
|
|
47
|
-
this._client.handleErrorResponse(
|
|
48
|
-
'clear-features-cache',
|
|
49
|
-
response,
|
|
50
|
-
duration,
|
|
51
|
-
'creatio_clear_features_cache_failed',
|
|
52
|
-
{
|
|
53
|
-
featureCode: featureCode ?? '(all)',
|
|
54
|
-
url,
|
|
55
|
-
},
|
|
56
|
-
),
|
|
57
|
-
{ featureCode: featureCode ?? '(all)' },
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import log from '../../log';
|
|
2
|
-
import { JSON_ACCEPT, XML_ACCEPT } from '../../types';
|
|
3
|
-
import { CreatioAuthManager, ICreatioAuthProvider } from '../auth';
|
|
4
|
-
import { CreatioClientConfig } from '../client-config';
|
|
5
|
-
|
|
6
|
-
type RequestFactory = () => Promise<RequestInit>;
|
|
7
|
-
type SuccessHandler<T> = (response: Response, duration: number) => Promise<T>;
|
|
8
|
-
type ErrorHandler<T> = (response: Response, duration: number) => Promise<T>;
|
|
9
|
-
|
|
10
|
-
type LogContext = Record<string, any>;
|
|
11
|
-
|
|
12
|
-
export class CreatioHttpClient {
|
|
13
|
-
private readonly _config: CreatioClientConfig;
|
|
14
|
-
private readonly _authManager: CreatioAuthManager;
|
|
15
|
-
private readonly _normalizedBaseUrl: string;
|
|
16
|
-
|
|
17
|
-
public get authProvider(): ICreatioAuthProvider {
|
|
18
|
-
return this._authManager.getProvider();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
public get normalizedBaseUrl(): string {
|
|
22
|
-
return this._normalizedBaseUrl;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
public get odataRoot(): string {
|
|
26
|
-
return `${this._normalizedBaseUrl}/0/odata`;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
constructor(config: CreatioClientConfig, authManager: CreatioAuthManager) {
|
|
30
|
-
this._config = config;
|
|
31
|
-
this._authManager = authManager;
|
|
32
|
-
this._normalizedBaseUrl = this._config.baseUrl.replace(/\/$/, '');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
private _logRequest(url: string, requestInit: RequestInit): void {
|
|
36
|
-
log.info('creatio.http.request', {
|
|
37
|
-
url,
|
|
38
|
-
method: requestInit.method || 'GET',
|
|
39
|
-
hasAuth: Boolean(requestInit.headers && (requestInit.headers as any)['Authorization']),
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
private _logUnauthorizedResponse(
|
|
44
|
-
url: string,
|
|
45
|
-
response: Response,
|
|
46
|
-
hasTriedRefresh: boolean,
|
|
47
|
-
): void {
|
|
48
|
-
log.warn('creatio.http.401_response', {
|
|
49
|
-
url,
|
|
50
|
-
status: response.status,
|
|
51
|
-
triedRefresh: hasTriedRefresh,
|
|
52
|
-
responseHeaders: Object.fromEntries(response.headers.entries()),
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
public async getJsonHeaders(): Promise<Record<string, string>> {
|
|
57
|
-
return this.authProvider.getHeaders(JSON_ACCEPT, true);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
public async getXmlHeaders(): Promise<Record<string, string>> {
|
|
61
|
-
return this.authProvider.getHeaders(XML_ACCEPT, false);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
public async getPostHeaders(): Promise<Record<string, string>> {
|
|
65
|
-
const headers = await this.getJsonHeaders();
|
|
66
|
-
return {
|
|
67
|
-
...headers,
|
|
68
|
-
'Content-Type': 'application/json',
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
public async createPostRequest(body?: any): Promise<RequestInit> {
|
|
73
|
-
const headers = await this.getPostHeaders();
|
|
74
|
-
return {
|
|
75
|
-
method: 'POST',
|
|
76
|
-
headers,
|
|
77
|
-
body: body ? JSON.stringify(body) : JSON.stringify({}),
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
public async fetchJson(url: string, initFactory: RequestFactory) {
|
|
82
|
-
const response = await this.fetchWithAuth(url, initFactory);
|
|
83
|
-
if (!response.ok) {
|
|
84
|
-
const errorText = await response.text().catch(() => '');
|
|
85
|
-
throw new Error(`creatio_http_error:${response.status} ${errorText}`);
|
|
86
|
-
}
|
|
87
|
-
return response.json();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
public async fetchText(url: string, initFactory: RequestFactory) {
|
|
91
|
-
const response = await this.fetchWithAuth(url, initFactory);
|
|
92
|
-
if (!response.ok) {
|
|
93
|
-
const errorText = await response.text().catch(() => '');
|
|
94
|
-
throw new Error(`creatio_http_error:${response.status} ${errorText}`);
|
|
95
|
-
}
|
|
96
|
-
return response.text();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
public async fetchWithAuth(url: string, initFactory: RequestFactory): Promise<Response> {
|
|
100
|
-
let hasTriedRefresh = false;
|
|
101
|
-
while (true) {
|
|
102
|
-
const requestInit = await initFactory();
|
|
103
|
-
this._logRequest(url, requestInit);
|
|
104
|
-
const response = await fetch(url, requestInit);
|
|
105
|
-
if (response.status !== 401) {
|
|
106
|
-
return response;
|
|
107
|
-
}
|
|
108
|
-
this._logUnauthorizedResponse(url, response, hasTriedRefresh);
|
|
109
|
-
if (hasTriedRefresh) {
|
|
110
|
-
return response;
|
|
111
|
-
}
|
|
112
|
-
hasTriedRefresh = true;
|
|
113
|
-
await this.authProvider.refresh();
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
public async executeWithTiming<T>(
|
|
118
|
-
operation: string,
|
|
119
|
-
url: string,
|
|
120
|
-
request: () => Promise<Response>,
|
|
121
|
-
successHandler: SuccessHandler<T>,
|
|
122
|
-
errorHandler: ErrorHandler<T>,
|
|
123
|
-
logContext: LogContext = {},
|
|
124
|
-
): Promise<T> {
|
|
125
|
-
const startTime = Date.now();
|
|
126
|
-
try {
|
|
127
|
-
const response = await request();
|
|
128
|
-
const duration = Date.now() - startTime;
|
|
129
|
-
if (!response.ok) {
|
|
130
|
-
return await errorHandler(response, duration);
|
|
131
|
-
}
|
|
132
|
-
return await successHandler(response, duration);
|
|
133
|
-
} catch (error: any) {
|
|
134
|
-
const duration = Date.now() - startTime;
|
|
135
|
-
log.error(`creatio.http.${operation}.error`, {
|
|
136
|
-
...logContext,
|
|
137
|
-
url,
|
|
138
|
-
error: String(error?.message ?? error),
|
|
139
|
-
duration,
|
|
140
|
-
});
|
|
141
|
-
throw error;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
public async handleErrorResponse(
|
|
146
|
-
operation: string,
|
|
147
|
-
response: Response,
|
|
148
|
-
duration: number,
|
|
149
|
-
errorPrefix: string,
|
|
150
|
-
logContext: LogContext = {},
|
|
151
|
-
): Promise<never> {
|
|
152
|
-
const errorText = await response.text().catch(() => '');
|
|
153
|
-
log.error(`creatio.http.${operation}.error`, {
|
|
154
|
-
...logContext,
|
|
155
|
-
status: response.status,
|
|
156
|
-
error: errorText,
|
|
157
|
-
duration,
|
|
158
|
-
});
|
|
159
|
-
throw new Error(`${errorPrefix}:${response.status} ${errorText}`);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
public logSuccess(
|
|
163
|
-
operation: string,
|
|
164
|
-
status: number,
|
|
165
|
-
duration: number,
|
|
166
|
-
logContext: LogContext = {},
|
|
167
|
-
) {
|
|
168
|
-
log.info(`creatio.http.${operation}.success`, {
|
|
169
|
-
...logContext,
|
|
170
|
-
status,
|
|
171
|
-
duration,
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export * from './admin-operation-service-provider';
|
|
2
|
-
export * from './configuration-service-provider';
|
|
3
|
-
export * from './creatio-service-context';
|
|
4
|
-
export * from './feature-service-provider';
|
|
5
|
-
export * from './http-client';
|
|
6
|
-
export * from './metadata-store';
|
|
7
|
-
export * from './odata-crud-provider';
|
|
8
|
-
export * from './process-service-provider';
|
|
9
|
-
export * from './sys-settings-service-provider';
|
|
10
|
-
export * from './user-info-provider';
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
import { XMLParser } from 'fast-xml-parser';
|
|
2
|
-
|
|
3
|
-
import log from '../../log';
|
|
4
|
-
import { EntitySchemaDescription } from '../providers';
|
|
5
|
-
|
|
6
|
-
import { CreatioHttpClient } from './http-client';
|
|
7
|
-
|
|
8
|
-
export class ODataMetadataStore {
|
|
9
|
-
private readonly _client: CreatioHttpClient;
|
|
10
|
-
private _metadataXml?: string;
|
|
11
|
-
private _metadataParsed?: any;
|
|
12
|
-
|
|
13
|
-
constructor(client: CreatioHttpClient) {
|
|
14
|
-
this._client = client;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
private _arrayify<T>(value: T | T[] | undefined | null): T[] {
|
|
18
|
-
if (value == null) {
|
|
19
|
-
return [];
|
|
20
|
-
}
|
|
21
|
-
return Array.isArray(value) ? value : [value];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
private async _getMetadataXml(): Promise<string> {
|
|
25
|
-
if (this._metadataXml) {
|
|
26
|
-
return this._metadataXml;
|
|
27
|
-
}
|
|
28
|
-
const headers = await this._client.getXmlHeaders();
|
|
29
|
-
const metadataUrl = `${this._client.odataRoot}/$metadata`;
|
|
30
|
-
const xmlContent = await this._client.fetchText(metadataUrl, async () => ({ headers }));
|
|
31
|
-
this._metadataXml = xmlContent;
|
|
32
|
-
return this._metadataXml;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
private async _getParsedMetadata(): Promise<any> {
|
|
36
|
-
if (this._metadataParsed) {
|
|
37
|
-
return this._metadataParsed;
|
|
38
|
-
}
|
|
39
|
-
const xmlContent = await this._getMetadataXml();
|
|
40
|
-
const parser = new XMLParser({
|
|
41
|
-
ignoreAttributes: false,
|
|
42
|
-
attributeNamePrefix: '@_',
|
|
43
|
-
});
|
|
44
|
-
this._metadataParsed = parser.parse(xmlContent);
|
|
45
|
-
return this._metadataParsed;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
private _extractSchemas(metadata: any): any[] {
|
|
49
|
-
const dataServices = metadata['edmx:Edmx']?.['edmx:DataServices'];
|
|
50
|
-
return this._arrayify<any>(dataServices?.Schema);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
private async _tryGetEntitySetsFromService(): Promise<string[] | null> {
|
|
54
|
-
try {
|
|
55
|
-
const serviceUrl = `${this._client.odataRoot}/`;
|
|
56
|
-
const headers = await this._client.getJsonHeaders();
|
|
57
|
-
const response = await this._client.fetchWithAuth(serviceUrl, async () => ({
|
|
58
|
-
headers,
|
|
59
|
-
}));
|
|
60
|
-
if (response.ok) {
|
|
61
|
-
const body: any = await response.json().catch(() => null);
|
|
62
|
-
if (body && Array.isArray(body.value)) {
|
|
63
|
-
return body.value.map((item: any) => String(item.name));
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
if (!response.ok) {
|
|
67
|
-
log.error('creatio.metadata.list_entity_sets.error', {
|
|
68
|
-
url: serviceUrl,
|
|
69
|
-
status: response.status,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
} catch (error: any) {
|
|
73
|
-
log.error('creatio.metadata.list_entity_sets.error', {
|
|
74
|
-
url: `${this._client.odataRoot}/`,
|
|
75
|
-
error: String(error?.message ?? error),
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
private async _getEntitySetsFromMetadata(): Promise<string[]> {
|
|
82
|
-
const metadata = await this._getParsedMetadata();
|
|
83
|
-
const schemas = this._extractSchemas(metadata);
|
|
84
|
-
const entitySets: string[] = [];
|
|
85
|
-
for (const schema of schemas) {
|
|
86
|
-
const containers = this._arrayify<any>(schema.EntityContainer);
|
|
87
|
-
for (const container of containers) {
|
|
88
|
-
const sets = this._arrayify<any>(container.EntitySet);
|
|
89
|
-
for (const set of sets) {
|
|
90
|
-
const name = set?.['@_Name'];
|
|
91
|
-
if (name) {
|
|
92
|
-
entitySets.push(String(name));
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return Array.from(new Set(entitySets));
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
private _findEntityType(schemas: any[], entitySet: string): string {
|
|
101
|
-
for (const schema of schemas) {
|
|
102
|
-
const containers = this._arrayify<any>(schema.EntityContainer);
|
|
103
|
-
for (const container of containers) {
|
|
104
|
-
const sets = this._arrayify<any>(container.EntitySet);
|
|
105
|
-
for (const set of sets) {
|
|
106
|
-
if (set?.['@_Name'] === entitySet) {
|
|
107
|
-
return String(set?.['@_EntityType'] ?? '');
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return '';
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
private _findEntityTypeNode(schemas: any[], typeName: string): any {
|
|
116
|
-
for (const schema of schemas) {
|
|
117
|
-
const types = this._arrayify<any>(schema.EntityType);
|
|
118
|
-
for (const type of types) {
|
|
119
|
-
if (type?.['@_Name'] === typeName) {
|
|
120
|
-
return type;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
return undefined;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
private _parseEntityProperties(entityTypeNode: any): {
|
|
128
|
-
key: string[];
|
|
129
|
-
properties: Array<{
|
|
130
|
-
name: string;
|
|
131
|
-
type: string;
|
|
132
|
-
nullable?: boolean;
|
|
133
|
-
}>;
|
|
134
|
-
} {
|
|
135
|
-
const keyRefs = this._arrayify<any>(entityTypeNode.Key?.PropertyRef);
|
|
136
|
-
const key = keyRefs.map((ref) => String(ref?.['@_Name'] ?? '')).filter(Boolean) as string[];
|
|
137
|
-
const propertyNodes = this._arrayify<any>(entityTypeNode.Property);
|
|
138
|
-
const properties = propertyNodes.map((prop) => {
|
|
139
|
-
const name = String(prop?.['@_Name'] ?? '');
|
|
140
|
-
const type = String(prop?.['@_Type'] ?? '');
|
|
141
|
-
const result: {
|
|
142
|
-
name: string;
|
|
143
|
-
type: string;
|
|
144
|
-
nullable?: boolean;
|
|
145
|
-
} = { name, type };
|
|
146
|
-
if (Object.prototype.hasOwnProperty.call(prop, '@_Nullable')) {
|
|
147
|
-
result.nullable = String(prop['@_Nullable']) === 'true';
|
|
148
|
-
}
|
|
149
|
-
return result;
|
|
150
|
-
});
|
|
151
|
-
return { key, properties };
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
public async listEntitySets(): Promise<string[]> {
|
|
155
|
-
const serviceSets = await this._tryGetEntitySetsFromService();
|
|
156
|
-
if (serviceSets) {
|
|
157
|
-
return serviceSets;
|
|
158
|
-
}
|
|
159
|
-
return this._getEntitySetsFromMetadata();
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
public async describeEntity(entitySet: string): Promise<EntitySchemaDescription> {
|
|
163
|
-
const metadata = await this._getParsedMetadata();
|
|
164
|
-
const schemas = this._extractSchemas(metadata);
|
|
165
|
-
const fullType = this._findEntityType(schemas, entitySet);
|
|
166
|
-
if (!fullType) {
|
|
167
|
-
const error = `entity_not_found:${entitySet}`;
|
|
168
|
-
log.error('creatio.metadata.describe_entity.error', { entitySet, error });
|
|
169
|
-
throw new Error(error);
|
|
170
|
-
}
|
|
171
|
-
const typeName = fullType.split('.').pop()!;
|
|
172
|
-
const entityTypeNode = this._findEntityTypeNode(schemas, typeName);
|
|
173
|
-
if (!entityTypeNode) {
|
|
174
|
-
const error = `entity_type_not_found:${typeName}`;
|
|
175
|
-
log.error('creatio.metadata.describe_entity.error', { entitySet, error });
|
|
176
|
-
throw new Error(error);
|
|
177
|
-
}
|
|
178
|
-
const { key, properties } = this._parseEntityProperties(entityTypeNode);
|
|
179
|
-
return { entitySet, entityType: typeName, key, properties };
|
|
180
|
-
}
|
|
181
|
-
}
|