d5-api-initializer 0.0.2-alpha.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.
@@ -0,0 +1,337 @@
1
+ import ApiResponse from './ApiResponse';
2
+ import {IMappedCollection, IFiltersCollection, LanguageCode} from '../api-interfaces';
3
+ import UserMessages from './UserMessages';
4
+ import ApiInvoker from "./ApiInvoker";
5
+
6
+ export default class ApiRequest {
7
+ private _jsWapiRequest: any;
8
+ private readonly _objectName: string;
9
+
10
+ constructor(jsWapiRequest: any, objectName: string) {
11
+ this._jsWapiRequest = jsWapiRequest;
12
+ this._objectName = objectName;
13
+ }
14
+
15
+ /* ----------------------------Accessors---------------------------- */
16
+ get objectName(): string {
17
+ return this._objectName;
18
+ }
19
+
20
+ get columns(): string[] {
21
+ return this._jsWapiRequest.getColumns();
22
+ }
23
+
24
+ get aggregatedColumns(): IMappedCollection {
25
+ return this._jsWapiRequest.getAggregatedColumns();
26
+ }
27
+
28
+ get nestedColumns(): IMappedCollection {
29
+ return this._jsWapiRequest.getNestedColumns();
30
+ }
31
+
32
+ get filters(): IFiltersCollection {
33
+ return this._jsWapiRequest.getFilters();
34
+ }
35
+
36
+ get params(): IMappedCollection {
37
+ return this._jsWapiRequest.getParams();
38
+ }
39
+
40
+ get request(): IMappedCollection | Array<IMappedCollection> {
41
+ return this._jsWapiRequest.getRequest(this._objectName);
42
+ }
43
+
44
+ get userId(): number {
45
+ return this._jsWapiRequest.getUserId();
46
+ }
47
+
48
+ get page(): number {
49
+ return this._jsWapiRequest.getPage();
50
+ }
51
+
52
+ get rowsPerPage(): number {
53
+ return this._jsWapiRequest.getRowsPerPage();
54
+ }
55
+
56
+ get sorts(): string[] {
57
+ return this._jsWapiRequest.getSorts();
58
+ }
59
+
60
+ get lang(): LanguageCode {
61
+ return this._jsWapiRequest.getLanguage();
62
+ }
63
+
64
+ set columns(columns: string[]) {
65
+ this._jsWapiRequest = this._jsWapiRequest.setColumns(columns);
66
+ }
67
+
68
+ set aggregatedColumns(columns: IMappedCollection) {
69
+ this._jsWapiRequest = this._jsWapiRequest.setAggregatedColumns(columns);
70
+ }
71
+
72
+ set nestedColumns(columns: IMappedCollection) {
73
+ this._jsWapiRequest = this._jsWapiRequest.setNestedColumns(columns);
74
+ }
75
+
76
+ set filters(filters: IFiltersCollection) {
77
+ this._jsWapiRequest = this._jsWapiRequest.setFilters(filters);
78
+ }
79
+
80
+ set params(params: IMappedCollection) {
81
+ this._jsWapiRequest = this._jsWapiRequest.setParams(params);
82
+ }
83
+
84
+ set sorts(sorts: string[]) {
85
+ this._jsWapiRequest = this._jsWapiRequest.setSorts(sorts);
86
+ }
87
+
88
+ set page(number: number) {
89
+ this._jsWapiRequest = this._jsWapiRequest.setPage(number);
90
+ }
91
+
92
+ set rowsPerPage(amount: number) {
93
+ this._jsWapiRequest = this._jsWapiRequest.setRowsPerPage(amount);
94
+ }
95
+
96
+ /* -----------------------------Getters----------------------------- */
97
+ getFilter(filterName: string): any {
98
+ return this._jsWapiRequest.getFilter(filterName);
99
+ }
100
+
101
+ /**
102
+ * Вернуть значение фильтра типа "равно".
103
+ * Возможные варианты:
104
+ * "поле": "значение"
105
+ * "поле": {"=": "значение"}
106
+ * "поле": ["значение"]
107
+ * "поле": {"=": [123]}
108
+ * Это чтобы не парсить каждый раз все эти варианты.
109
+ *
110
+ * Работает только для условия "равно", для други возвращает null!!!!
111
+ */
112
+ getFilterValue(fieldName: string): any {
113
+ return this._jsWapiRequest.getFilterEqualOneValue(fieldName)
114
+ }
115
+
116
+ getParam(paramName: string): any {
117
+ return this._jsWapiRequest.getParam(paramName);
118
+ }
119
+
120
+ getExcelFileAsJson(fileRequestId: string): any {
121
+ return this._jsWapiRequest.getExcelFileAsJson(fileRequestId);
122
+ }
123
+
124
+ getFileAsString(fileRequestId: string): string {
125
+ return this._jsWapiRequest.getFileAsString(fileRequestId);
126
+ }
127
+
128
+ getFilesListAsString(filesRequestIds: string[] | number[]): IMappedCollection {
129
+ return this._jsWapiRequest.getMultiFileAsString(...this._getWithStringifiedElements(filesRequestIds));
130
+ }
131
+
132
+ getExcelFilesListAsJson(filesRequestIds: string[] | number[]): IMappedCollection {
133
+ return this._jsWapiRequest.getMultiExcelFileAsJson(...this._getWithStringifiedElements(filesRequestIds));
134
+ }
135
+
136
+ getRequest(requestName: string): IMappedCollection[] {
137
+ return this._jsWapiRequest.getRequest(requestName);
138
+ }
139
+
140
+ /* -----------------------------Setters----------------------------- */
141
+ setHierarchy(parentColumn: string, requestKind?: number) {
142
+ this._jsWapiRequest = this._jsWapiRequest.setHierarchy(parentColumn, requestKind);
143
+ return this;
144
+ }
145
+
146
+ setColumns(columns: string[]) {
147
+ this.columns = columns;
148
+
149
+ return this;
150
+ }
151
+
152
+ setNestedColumns(nestedColumns: IMappedCollection) {
153
+ this.nestedColumns = nestedColumns;
154
+
155
+ return this;
156
+ }
157
+
158
+ setAggregatedColumns(aggregatedColumns: IMappedCollection) {
159
+ this.aggregatedColumns = aggregatedColumns;
160
+
161
+ return this;
162
+ }
163
+
164
+ setFilters(filters: IFiltersCollection): ApiRequest {
165
+ this.filters = filters;
166
+
167
+ return this;
168
+ }
169
+
170
+ setSorts(sorts: string[]) {
171
+ this.sorts = sorts;
172
+
173
+ return this;
174
+ }
175
+
176
+ setParams(params: IMappedCollection): ApiRequest {
177
+ this.params = params;
178
+
179
+ return this;
180
+ }
181
+
182
+ setPage(number: number): ApiRequest {
183
+ this.page = number;
184
+
185
+ return this;
186
+ }
187
+
188
+ setRowsPerPage(amount: number): ApiRequest {
189
+ this.rowsPerPage = amount;
190
+
191
+ return this;
192
+ }
193
+
194
+ setRequest(request: IMappedCollection | any[]): ApiRequest {
195
+ if (Array.isArray(request)) {
196
+ this._jsWapiRequest = this._jsWapiRequest.putRequest(this._objectName, request);
197
+ } else {
198
+ this._jsWapiRequest = this._jsWapiRequest.setRequest(request);
199
+ }
200
+ return this;
201
+ }
202
+
203
+ setFirstRows(firstRows: number) {
204
+ this._jsWapiRequest.setFirstRows(firstRows);
205
+
206
+ return this;
207
+ }
208
+
209
+ getFirstRows(): number {
210
+ return this._jsWapiRequest.getFirstRows();
211
+ }
212
+
213
+
214
+ addSorts(sorts: string[]): ApiRequest {
215
+ this._jsWapiRequest = this._jsWapiRequest.addSorts(sorts);
216
+
217
+ return this;
218
+ }
219
+
220
+ addColumns(columns: string[]): ApiRequest {
221
+ this._jsWapiRequest = this._jsWapiRequest.addColumns(columns);
222
+
223
+ return this;
224
+ }
225
+
226
+ addAggregatedColumns(columns: IMappedCollection): ApiRequest {
227
+ this._jsWapiRequest = this._jsWapiRequest.putAggregatedColumns(columns);
228
+
229
+ return this;
230
+ }
231
+
232
+ /**
233
+ * @link http://d5.develop.erp-director.com/userscript-docs/docs/server_scripts/api-request/api-request#addnestedcolumnscolumns
234
+ * @example
235
+ * apiRequest.addNestedColumns({
236
+ * 'AuthorsNested': {
237
+ * 'Columns': ['ID', 'Name']
238
+ * }
239
+ * });
240
+ */
241
+ addNestedColumns(columns: IMappedCollection): ApiRequest {
242
+ this._jsWapiRequest = this._jsWapiRequest.putNestedColumns(columns);
243
+
244
+ return this;
245
+ }
246
+
247
+ addFilters(filters: IFiltersCollection): ApiRequest {
248
+ this._jsWapiRequest = this._jsWapiRequest.putFilters(filters);
249
+
250
+ return this;
251
+ }
252
+
253
+ addParams(params: IMappedCollection): ApiRequest {
254
+ for (const name in params) {
255
+ this._jsWapiRequest = this._jsWapiRequest.putParam(name, params[name]);
256
+ }
257
+
258
+ return this;
259
+ }
260
+
261
+ /* ----------------------------Removers----------------------------- */
262
+ removeSorts(sortsNames: string[]): ApiRequest {
263
+ this._jsWapiRequest = this._jsWapiRequest.removeSorts(sortsNames);
264
+
265
+ return this;
266
+ }
267
+
268
+ removeColumns(columnsNames: string[]): ApiRequest {
269
+ this._jsWapiRequest = this._jsWapiRequest.removeColumns(columnsNames);
270
+
271
+ return this;
272
+ }
273
+
274
+ removeAggregatedColumns(aggregatedColumnsNames: string[]): ApiRequest {
275
+ this._jsWapiRequest = this._jsWapiRequest.removeAggregatedColumns(aggregatedColumnsNames);
276
+
277
+ return this;
278
+ }
279
+
280
+ removeNestedColumns(nestedColumnsNames: string[]): ApiRequest {
281
+ this._jsWapiRequest = this._jsWapiRequest.removeNestedColumns(nestedColumnsNames);
282
+
283
+ return this;
284
+ }
285
+
286
+ removeParams(paramsNames: string[]): ApiRequest {
287
+ this._jsWapiRequest = this._jsWapiRequest.removeParams(paramsNames);
288
+
289
+ return this;
290
+ }
291
+
292
+ removeFilters(filtersNames: string[]): ApiRequest {
293
+ this._jsWapiRequest = this._jsWapiRequest.removeFilters(filtersNames);
294
+
295
+ return this;
296
+ }
297
+
298
+ /* ------------------------------Other------------------------------ */
299
+ hasFilter(filterName: string): boolean {
300
+ return this._jsWapiRequest.isFilterExists(filterName);
301
+ }
302
+
303
+ invoke(): ApiResponse {
304
+ return new ApiResponse(this._jsWapiRequest.invoke(), this._objectName);
305
+ }
306
+
307
+ newJSWapiInvoker(objectName: string, operName: string) {
308
+ return this._jsWapiRequest.newJSWapiInvoker(objectName, operName);
309
+ }
310
+
311
+ newApiInvoker(objectName: string, operName: string): ApiInvoker {
312
+ return new ApiInvoker(this.newJSWapiInvoker(objectName, operName), objectName);
313
+ }
314
+
315
+ /**
316
+ * Переводит и форматирует строку из словаря переводов согласно текущего языка приложения.
317
+ * @param msgKey
318
+ * @param params
319
+ *
320
+ * @example
321
+ * {
322
+ * ...
323
+ * "myKey": 'some text with {0}'
324
+ * ...
325
+ * }
326
+ * t('myKey', ['placeholder text']) // 'some text with placeholder text'
327
+ */
328
+ t(msgKey: string, params?: string[]): string {
329
+ UserMessages.lang = this.lang || LanguageCode.ua;
330
+ return UserMessages.format(msgKey, params);
331
+ }
332
+
333
+ /* -------------------------Support methods------------------------- */
334
+ _getWithStringifiedElements(array: any[]): string[] {
335
+ return array.map((element) => element.toString());
336
+ }
337
+ }
@@ -0,0 +1,72 @@
1
+ import {IMappedCollection} from '../api-interfaces';
2
+
3
+ export default class ApiResponse {
4
+ private _jsWapiResponse: any;
5
+ private readonly _objectName: string;
6
+
7
+ constructor(jsWapiResponse: any, objectName: string) {
8
+ this._jsWapiResponse = jsWapiResponse;
9
+ this._objectName = objectName;
10
+ }
11
+
12
+ get objectName(): string {
13
+ return this._objectName;
14
+ }
15
+
16
+ set response(response: IMappedCollection | any[]) {
17
+ this.setResponse(response);
18
+ }
19
+
20
+ getResponse(responseName?: string): IMappedCollection[] | any {
21
+ return this._jsWapiResponse.getResponse(responseName || this._objectName);
22
+ }
23
+
24
+ setResponse(response: IMappedCollection | any[], fieldsMap?: Record<string, any>) {
25
+ if (Array.isArray(response)) {
26
+ const data = !fieldsMap ? response : response.map(row => {
27
+ const res: any = {};
28
+ for (const externalKey in fieldsMap) {
29
+ res[fieldsMap[externalKey]] = row[externalKey];
30
+ }
31
+ return res;
32
+ });
33
+ this._jsWapiResponse.putResponse(this._objectName, data);
34
+ } else {
35
+ this._jsWapiResponse.setResponse(response);
36
+ }
37
+
38
+ return this;
39
+ }
40
+
41
+ sendHttpResponse(headers: IMappedCollection, body: string | jsWapi.BinaryDataStream) {
42
+ this._jsWapiResponse.sendHttpResponse(headers, body);
43
+
44
+ return this;
45
+ }
46
+
47
+ sendHttpBody(body: string) {
48
+ this._jsWapiResponse.sendHttpResponse({}, body);
49
+
50
+ return this;
51
+ }
52
+
53
+ getPage(): number {
54
+ return this._jsWapiResponse.getPage();
55
+ }
56
+
57
+ setPage(page: number) {
58
+ this._jsWapiResponse.setPage(page);
59
+
60
+ return this;
61
+ }
62
+
63
+ getPagesPredict(): number {
64
+ return this._jsWapiResponse.getPagesPredict();
65
+ }
66
+
67
+ setPagesPredict(pagesPredict: number) {
68
+ this._jsWapiResponse.setPagesPredict(pagesPredict);
69
+
70
+ return this;
71
+ }
72
+ }
@@ -0,0 +1,88 @@
1
+ import {ApiObjectInitializerConstructor} from './ApiObjectInitializer';
2
+ import ApiRequest from './ApiRequest';
3
+ import ApiCore from './ApiCore';
4
+ import ApiResponse from './ApiResponse';
5
+ import {IApiOperations, LanguageCode} from '../api-interfaces';
6
+ import UserMessages from './UserMessages';
7
+
8
+ export default class EngineInitializer<MetaParams = Record<string, any>> {
9
+ private engine: jsWapi.JSWapiEngine;
10
+ protected _operations: IApiOperations<MetaParams>;
11
+
12
+
13
+ constructor(options: Omit<ApiObjectInitializerConstructor, 'objectName'>);
14
+ constructor(operations: IApiOperations<MetaParams>);
15
+ constructor(operations: IApiOperations<MetaParams>, options: Pick<ApiObjectInitializerConstructor, 'translations'>);
16
+ constructor(arg1: Omit<ApiObjectInitializerConstructor, 'objectName'> | IApiOperations<MetaParams>, arg2?: Pick<ApiObjectInitializerConstructor, 'translations'>) {
17
+ let operations = arg1.operations || arg1;
18
+ let translations = arg1.translations || arg2?.translations;
19
+
20
+ const throwError = (msg: string) => {
21
+ throw new Error(msg);
22
+ };
23
+
24
+ if (!operations) throwError('Property "operations" in the settings is required');
25
+ //@ts-ignore
26
+ this._operations = operations;
27
+ this.internalCreate();
28
+ //@ts-ignore
29
+ translations && this.initTranslation(translations);
30
+ }
31
+
32
+ private internalCreate() {
33
+ jsWapi.setJSWapiEngine((engine) => {
34
+ this.engine = engine;
35
+ for (const operationName in this._operations) {
36
+ this.putOperation(operationName);
37
+ }
38
+ });
39
+ }
40
+
41
+ private putOperation(operationName: string) {
42
+ this.engine.putJSWapiOper(operationName, (jsWapiRequest,jsWapiResponse) => {
43
+ const request = new ApiRequest(jsWapiRequest, this.engine.getName());
44
+ const apiCore = new ApiCore({http: this.engine, request});
45
+ return this._operations[operationName](
46
+ apiCore,
47
+ request,
48
+ new ApiResponse(jsWapiResponse, this.engine.getName()),
49
+ {
50
+ parameters: this.engine.getExternalSystemParameters() as MetaParams,
51
+ objectName: this.engine.getName(),
52
+ externalObject: this.engine.getExternalName(),
53
+ externalFieldsMap: this.engine.getExternalObjectFields(),
54
+ }
55
+ );
56
+ });
57
+ }
58
+
59
+ /**
60
+ * Инициализация словаря переводов.
61
+ * @param translations
62
+ * @example Пример строки перевода
63
+ * { ...
64
+ * "ru": {"key": 'some text {0} {1}'}
65
+ * ...
66
+ * }
67
+ *
68
+ * core.t('key', ['test1', 'test2']); // 'some text test1 test2'
69
+ */
70
+ initTranslation(translations: Record<LanguageCode, Record<string, string>>) {
71
+ UserMessages.appendDictionary(translations);
72
+ }
73
+
74
+ public call({apiCore, apiRequest, apiResponse, operation, meta}: {
75
+ apiCore: ApiCore,
76
+ apiRequest: ApiRequest,
77
+ apiResponse: ApiResponse
78
+ operation: string,
79
+ meta: jsWapi.JSWapiMeta<MetaParams>
80
+ }) {
81
+ return this._operations[operation](
82
+ apiCore,
83
+ apiRequest,
84
+ apiResponse,
85
+ meta
86
+ );
87
+ }
88
+ }
@@ -0,0 +1,38 @@
1
+ import {LanguageCode} from '../api-interfaces';
2
+
3
+ function formatMessage(text: string, args: string[] = []) {
4
+ let str = text;
5
+
6
+ for (let v in args) {
7
+ str = str.replace(`{${v}}`, args[v] == null ? '' : args[v]);
8
+ }
9
+ return str;
10
+ }
11
+
12
+
13
+ class UserMessages {
14
+ private _messages: Record<string, Record<string, string>> = {};
15
+ private _lang: LanguageCode = LanguageCode.ua;
16
+
17
+ appendDictionary(newDictionary: Record<LanguageCode, Record<string, string>>) {
18
+ if (Array.isArray(newDictionary) || !newDictionary || typeof newDictionary !== 'object') return;
19
+
20
+ for (const key in newDictionary) {
21
+ if (!this._messages.hasOwnProperty(key)) {
22
+ this._messages[key] = {};
23
+ }
24
+ this._messages[key] = Object.assign(this._messages[key], newDictionary[key as LanguageCode]);
25
+ }
26
+ }
27
+
28
+ format(msgKey: string, params?: string[]) {
29
+ const msg = this._messages[this._lang]?.[msgKey] ?? msgKey;
30
+ return formatMessage(msg, params);
31
+ }
32
+
33
+ set lang(value: LanguageCode) {
34
+ this._lang = value;
35
+ }
36
+ }
37
+
38
+ export default new UserMessages();
@@ -0,0 +1,4 @@
1
+ import EngineInitializer from './classes/EngineInitializer';
2
+
3
+ export default EngineInitializer;
4
+
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ import ApiObjectInitializer from './classes/ApiObjectInitializer';
2
+
3
+ export default ApiObjectInitializer;
@@ -0,0 +1,3 @@
1
+ export {default as ApiObjectInitializer} from './classes/ApiObjectInitializer';
2
+ export {default as EngineInitializer} from './classes/EngineInitializer';
3
+
package/tsconfig.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": true,
4
+ "target": "ESNext",
5
+ "module": "ESNext",
6
+ "moduleResolution": "Node",
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "lib": [
10
+ "dom",
11
+ "es2017"
12
+ ],
13
+ "jsx": "react",
14
+ "declaration": true,
15
+ "declarationDir": "./types",
16
+ "sourceMap": true,
17
+ "strictNullChecks": false,
18
+ "removeComments": false,
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "baseUrl": "./",
22
+ "outDir": "./dist/",
23
+ "noImplicitAny": true,
24
+ "experimentalDecorators": true,
25
+ "typeRoots": [
26
+ "./types/"
27
+ ],
28
+ "allowJs": true,
29
+ "allowSyntheticDefaultImports": true
30
+ },
31
+ "exclude": [
32
+ "node_modules",
33
+ "dist"
34
+ ]
35
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,46 @@
1
+ import {defineConfig, Options} from 'tsup';
2
+ import fs from 'fs';
3
+
4
+
5
+ const LIB_NAME = 'd5-api-initializer';
6
+
7
+ const outputDir = 'publish';
8
+
9
+
10
+ //@ts-ignore
11
+ export default defineConfig(options => {
12
+ const commonOptions: Partial<Options> = {
13
+ entry: {
14
+ [LIB_NAME]: 'src/lib-index.ts',
15
+ },
16
+ esbuildPlugins: [],
17
+ outDir: outputDir,
18
+ target: 'es2020',
19
+
20
+ skipNodeModulesBundle: true,
21
+ sourcemap: false,
22
+ ...options
23
+ };
24
+
25
+ return [
26
+ // Standard ESM, embedded `process.env.NODE_ENV` checks
27
+ {
28
+ ...commonOptions,
29
+ format: ['esm'],
30
+ splitting: false,
31
+ outExtension: () => ({js: '.mjs'}),
32
+ dts: true,
33
+ clean: true,
34
+ onSuccess() {
35
+ // Support Webpack 4 by pointing `"module"` to a file with a `.js` extension
36
+ fs.copyFileSync(`${outputDir}/${LIB_NAME}.mjs`, `${outputDir}/${LIB_NAME}.legacy-esm.js`);
37
+ }
38
+ },
39
+ {
40
+ ...commonOptions,
41
+ format: 'cjs',
42
+ outDir: `./${outputDir}/cjs/`,
43
+ outExtension: () => ({js: '.cjs'})
44
+ }
45
+ ];
46
+ });