@emilgroup/translation-sdk 1.0.0 → 1.0.1-beta.4

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.
Files changed (38) hide show
  1. package/.openapi-generator/FILES +4 -0
  2. package/README.md +9 -26
  3. package/api/default-api.ts +124 -0
  4. package/api/translation-api.ts +170 -209
  5. package/api.ts +2 -4
  6. package/base.ts +140 -97
  7. package/common.ts +2 -3
  8. package/configuration.ts +9 -8
  9. package/dist/api/default-api.d.ts +70 -0
  10. package/dist/api/default-api.js +200 -0
  11. package/dist/api/translation-api.d.ts +139 -165
  12. package/dist/api/translation-api.js +125 -147
  13. package/dist/api.d.ts +1 -0
  14. package/dist/api.js +1 -0
  15. package/dist/base.d.ts +22 -13
  16. package/dist/base.js +125 -153
  17. package/dist/common.d.ts +0 -1
  18. package/dist/common.js +3 -4
  19. package/dist/configuration.d.ts +6 -7
  20. package/dist/configuration.js +8 -0
  21. package/dist/models/create-product-language-request-dto.d.ts +1 -1
  22. package/dist/models/get-product-language-response-class.d.ts +25 -0
  23. package/dist/models/get-product-language-response-class.js +15 -0
  24. package/dist/models/index.d.ts +3 -0
  25. package/dist/models/index.js +3 -0
  26. package/dist/models/inline-response200.d.ts +54 -0
  27. package/dist/models/inline-response200.js +15 -0
  28. package/dist/models/inline-response503.d.ts +54 -0
  29. package/dist/models/inline-response503.js +15 -0
  30. package/dist/models/product-language-class.d.ts +4 -4
  31. package/models/create-product-language-request-dto.ts +1 -1
  32. package/models/get-product-language-response-class.ts +31 -0
  33. package/models/index.ts +3 -0
  34. package/models/inline-response200.ts +48 -0
  35. package/models/inline-response503.ts +48 -0
  36. package/models/product-language-class.ts +4 -4
  37. package/package.json +2 -5
  38. package/tsconfig.json +1 -0
package/api.ts CHANGED
@@ -15,17 +15,15 @@
15
15
 
16
16
  import { Configuration } from './configuration';
17
17
  import globalAxios, { AxiosPromise, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
18
- // URLSearchParams not necessarily used
19
- // @ts-ignore
20
- import { URL, URLSearchParams } from 'url';
21
- import FormData from 'form-data'
22
18
  // Some imports not used depending on template conditions
23
19
  // @ts-ignore
24
20
  import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from './common';
25
21
  // @ts-ignore
26
22
  import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from './base';
23
+ import { DefaultApi } from './api';
27
24
  import { TranslationApi } from './api';
28
25
 
29
26
 
27
+ export * from './api/default-api';
30
28
  export * from './api/translation-api';
31
29
 
package/base.ts CHANGED
@@ -14,20 +14,13 @@
14
14
 
15
15
 
16
16
  import { Configuration } from "./configuration";
17
+ import { defaultStorage } from "./common";
17
18
  // Some imports not used depending on template conditions
18
19
  // @ts-ignore
19
20
  import globalAxios, { AxiosPromise, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
20
- import * as fs from 'fs';
21
- import * as path from 'path';
22
- import * as os from 'os';
23
21
 
24
- export const BASE_PATH = "https://apiv2.emil.de".replace(/\/+$/, "");
25
- const CONFIG_DIRECTORY = '.emil';
26
- const CONFIG_FILENAME = 'credentials';
27
- const KEY_USERNAME = 'emil_username';
28
- const KEY_PASSWORD = 'emil_password';
29
22
 
30
- const filePath = os.homedir() + path.sep + CONFIG_DIRECTORY + path.sep + CONFIG_FILENAME;
23
+ export const BASE_PATH = "https://apiv2.emil.de".replace(/\/+$/, "");
31
24
  /**
32
25
  *
33
26
  * @export
@@ -41,13 +34,25 @@ export const COLLECTION_FORMATS = {
41
34
 
42
35
  export interface LoginClass {
43
36
  accessToken: string;
44
- permissions: Array<string>;
37
+ permissions: string;
38
+ }
39
+
40
+ export interface SwitchWorkspaceRequest {
41
+ username: string;
42
+ targetWorkspace: string;
43
+ }
44
+
45
+ export interface SwitchWorkspaceResponseClass {
46
+ accessToken: string;
47
+ permissions: string;
45
48
  }
46
49
 
47
50
  export enum Environment {
48
51
  Production = 'https://apiv2.emil.de',
49
52
  Test = 'https://apiv2-test.emil.de',
53
+ Staging = 'https://apiv2-staging.emil.de',
50
54
  Development = 'https://apiv2-dev.emil.de',
55
+ ProductionZurich = 'https://eu-central-2.apiv2.emil.de',
51
56
  }
52
57
 
53
58
  let _retry_count = 0
@@ -67,7 +72,14 @@ export interface RequestArgs {
67
72
  options: AxiosRequestConfig;
68
73
  }
69
74
 
75
+ interface TokenData {
76
+ accessToken?: string;
77
+ username?: string;
78
+ permissions?: string;
79
+ }
80
+
70
81
  const NETWORK_ERROR_MESSAGE = "Network Error";
82
+ const TOKEN_DATA = 'APP_TOKEN';
71
83
 
72
84
  /**
73
85
  *
@@ -75,80 +87,54 @@ const NETWORK_ERROR_MESSAGE = "Network Error";
75
87
  * @class BaseAPI
76
88
  */
77
89
  export class BaseAPI {
78
- protected configuration: Configuration;
79
- private username?: string;
80
- private password?: string;
90
+ protected configuration: Configuration | undefined;
91
+ private tokenData?: TokenData;
92
+
93
+ constructor(configuration?: Configuration,
94
+ protected basePath: string = BASE_PATH,
95
+ protected axios: AxiosInstance = globalAxios) {
96
+
97
+ this.loadTokenData();
81
98
 
82
- constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) {
83
99
  if (configuration) {
100
+ const { accessToken } = this.tokenData;
84
101
  this.configuration = configuration;
85
102
  this.basePath = configuration.basePath || this.basePath;
103
+
104
+ // Use config token if provided, otherwise use tokenData token
105
+ const configToken = this.configuration.accessToken;
106
+ const storedToken = accessToken ? `Bearer ${accessToken}` : '';
107
+ this.configuration.accessToken = configToken || storedToken;
86
108
  } else {
109
+ const { accessToken, username } = this.tokenData;
110
+
87
111
  this.configuration = new Configuration({
88
112
  basePath: this.basePath,
113
+ accessToken: accessToken ? `Bearer ${accessToken}` : '',
114
+ username,
89
115
  });
90
116
  }
91
117
 
92
118
  this.attachInterceptor(axios);
93
119
  }
94
120
 
95
- async initialize(env: Environment = Environment.Production) {
96
- this.configuration.basePath = env;
97
-
98
- await this.loadCredentials();
99
-
100
- if (this.username) {
101
- await this.authorize(this.username, this.password);
102
- this.password = null; // to avoid keeping password loaded in memory.
103
- }
104
- }
105
-
106
- private async loadCredentials() {
107
- try {
108
- await this.readConfigFile();
109
- } catch (error) {
110
- console.warn(`No credentials file found. Check that ${filePath} exists.`);
111
- }
112
-
113
- this.readEnvVariables();
114
-
115
- if (!this.username) {
116
- console.info(`No credentials found in credentials file or environment variables. Either provide some or use
117
- authorize() function.`);
118
- }
121
+ selectEnvironment(env: Environment) {
122
+ this.selectBasePath(env);
119
123
  }
120
124
 
121
- private async readConfigFile() {
122
- const file = await fs.promises.readFile(filePath, 'utf-8');
123
-
124
- const lines = file.split(os.EOL)
125
- .filter(Boolean);
126
-
127
- lines.forEach((line: string) => {
128
- if (line.startsWith(KEY_USERNAME)) {
129
- this.username = line.length > KEY_USERNAME.length + 1 ? line.substring(KEY_USERNAME.length + 1) : '';
130
- } else if (line.startsWith(KEY_PASSWORD)) {
131
- this.password = line.length > KEY_PASSWORD.length + 1 ? line.substring(KEY_PASSWORD.length + 1) : '';
132
- }
133
- });
125
+ selectBasePath(path: string) {
126
+ this.configuration.basePath = path;
134
127
  }
135
128
 
136
- private readEnvVariables(): boolean {
137
- if (process.env.EMIL_USERNAME) {
138
- this.username = process.env.EMIL_USERNAME;
139
- this.password = process.env.EMIL_PASSWORD || '';
140
-
141
- return true;
129
+ getPermissions(): Array<string> {
130
+ if (!this.tokenData?.permissions) {
131
+ return [];
142
132
  }
143
133
 
144
- return false;
145
- }
146
-
147
- selectEnvironment(env: Environment) {
148
- this.configuration.basePath = env;
134
+ return this.tokenData.permissions.split(',');
149
135
  }
150
136
 
151
- async authorize(username: string, password: string): Promise<void> {
137
+ async authorize(username: string, password: string, targetWorkspace?: string): Promise<void> {
152
138
  const options: AxiosRequestConfig = {
153
139
  method: 'POST',
154
140
  url: `${this.configuration.basePath}/authservice/v1/login`,
@@ -162,50 +148,100 @@ export class BaseAPI {
162
148
 
163
149
  const response = await globalAxios.request<LoginClass>(options);
164
150
 
165
- const { data: { accessToken } } = response;
151
+ const { data: { accessToken, permissions } } = response;
152
+
166
153
  this.configuration.username = username;
167
154
  this.configuration.accessToken = `Bearer ${accessToken}`;
155
+ this.tokenData.username = username;
156
+ this.tokenData.accessToken = accessToken;
157
+ this.tokenData.permissions = permissions;
168
158
 
169
- const refreshToken = this.extractRefreshToken(response)
170
- this.configuration.refreshToken = refreshToken;
159
+ // Switch workspace if provided
160
+ if (targetWorkspace) {
161
+ await this.switchWorkspace(targetWorkspace);
162
+ } else {
163
+ // Only store if no workspace switch (since switchWorkspace will store after switching)
164
+ this.storeTokenData({
165
+ ...this.tokenData
166
+ });
167
+ }
171
168
  }
172
169
 
173
- async refreshTokenInternal(): Promise<string> {
174
- const { username, refreshToken } = this.configuration;
170
+ async switchWorkspace(targetWorkspace: string): Promise<void> {
171
+ const options: AxiosRequestConfig = {
172
+ method: 'POST',
173
+ url: `${this.configuration.basePath}/authservice/v1/workspaces/switch`,
174
+ headers: {
175
+ 'Content-Type': 'application/json',
176
+ 'Authorization': `Bearer ${this.configuration.accessToken}`,
177
+ },
178
+ data: {
179
+ username: this.configuration.username,
180
+ targetWorkspace,
181
+ } as SwitchWorkspaceRequest,
182
+ withCredentials: true,
183
+ };
184
+
185
+ const response = await globalAxios.request<SwitchWorkspaceResponseClass>(options);
186
+
187
+ const { data: { accessToken, permissions } } = response;
175
188
 
189
+ this.configuration.accessToken = `Bearer ${accessToken}`;
190
+ this.tokenData.accessToken = accessToken;
191
+ this.tokenData.permissions = permissions;
176
192
 
177
- if (!username || !refreshToken) {
178
- return '';
193
+ this.storeTokenData({
194
+ ...this.tokenData
195
+ });
196
+ }
197
+
198
+ async refreshTokenInternal(): Promise<LoginClass> {
199
+ const { username } = this.configuration;
200
+
201
+ if (!username) {
202
+ throw new Error('Failed to refresh token.');
179
203
  }
180
204
 
205
+ const refreshTokenAxios = globalAxios.create()
206
+ refreshTokenAxios.interceptors.response.use(response => {
207
+ const { permissions } = response.data;
208
+
209
+ this.tokenData.permissions = permissions;
210
+ this.storeTokenData(this.tokenData);
211
+
212
+ return response;
213
+ })
214
+
181
215
  const options: AxiosRequestConfig = {
182
216
  method: 'POST',
183
217
  url: `${this.configuration.basePath}/authservice/v1/refresh-token`,
184
218
  headers: {
185
219
  'Content-Type': 'application/json',
186
- Cookie: refreshToken,
187
220
  },
188
221
  data: { username: username },
189
222
  withCredentials: true,
190
223
  };
191
224
 
192
- const { data: { accessToken } } = await globalAxios.request<LoginClass>(options);
193
-
194
- return accessToken;
225
+ const response = await refreshTokenAxios.request<LoginClass>(options);
226
+ return response.data;
195
227
  }
196
228
 
197
- private extractRefreshToken(response: AxiosResponse): string {
198
- if (response.headers && response.headers['set-cookie']
199
- && response.headers['set-cookie'].length > 0) {
200
-
201
- return `${response.headers['set-cookie'][0].split(';')[0]};`;
229
+ private storeTokenData(tokenData?: TokenData) {
230
+ if (typeof window !== 'undefined') {
231
+ defaultStorage().set<TokenData>(TOKEN_DATA, tokenData);
202
232
  }
233
+ }
203
234
 
204
- return '';
235
+ public loadTokenData() {
236
+ if (typeof window !== 'undefined') {
237
+ this.tokenData = defaultStorage().get<TokenData>(TOKEN_DATA) || {};
238
+ } else {
239
+ this.tokenData = {};
240
+ }
205
241
  }
206
242
 
207
- getConfiguration(): Configuration {
208
- return this.configuration;
243
+ public cleanTokenData() {
244
+ this.storeTokenData(null);
209
245
  }
210
246
 
211
247
  private attachInterceptor(axios: AxiosInstance) {
@@ -215,19 +251,26 @@ export class BaseAPI {
215
251
  },
216
252
  async (err) => {
217
253
  let originalConfig = err.config;
218
- if (err.response) {
254
+ if (err.response && !(err.response instanceof XMLHttpRequest)) { // sometimes buggy and is of type request
219
255
  // Access Token was expired
220
- if (err.response.status === 401 && !originalConfig._retry) {
256
+ if ((err.response.status === 401 || err.response.status === 403)
257
+ && !originalConfig._retry) {
221
258
  originalConfig._retry = true;
222
259
  try {
223
- const tokenString = await this.refreshTokenInternal();
260
+ const { accessToken: tokenString, permissions } = await this.refreshTokenInternal();
224
261
  const accessToken = `Bearer ${tokenString}`;
262
+ this.tokenData.permissions = permissions;
225
263
 
226
- originalConfig.headers['Authorization'] = `Bearer ${accessToken}`
264
+ delete originalConfig.headers['Authorization']
265
+
266
+ originalConfig.headers['Authorization'] = accessToken;
227
267
 
228
268
  this.configuration.accessToken = accessToken;
269
+ this.tokenData.accessToken = tokenString;
270
+
271
+ this.storeTokenData(this.tokenData);
229
272
 
230
- return axios.request(originalConfig);
273
+ return axios(originalConfig);
231
274
  } catch (_error) {
232
275
  if (_error.response && _error.response.data) {
233
276
  return Promise.reject(_error.response.data);
@@ -235,23 +278,23 @@ export class BaseAPI {
235
278
  return Promise.reject(_error);
236
279
  }
237
280
  }
238
- if (err.response.status === 403 && err.response.data) {
239
- return Promise.reject(err.response.data);
240
- }
241
- } else if(err.message === NETWORK_ERROR_MESSAGE
242
- && err.isAxiosError
281
+ } else if (err.message === NETWORK_ERROR_MESSAGE
243
282
  && originalConfig.headers.hasOwnProperty('Authorization')
244
283
  && _retry_count < 4
245
- ){
284
+ ) {
246
285
  _retry_count++;
247
286
  try {
248
- const tokenString = await this.refreshTokenInternal();
287
+ const { accessToken: tokenString, permissions } = await this.refreshTokenInternal();
249
288
  const accessToken = `Bearer ${tokenString}`;
289
+ this.tokenData.permissions = permissions;
250
290
 
251
291
  _retry = true;
252
- originalConfig.headers['Authorization'] = accessToken;
292
+ originalConfig.headers['Authorization'] = accessToken;
253
293
 
254
294
  this.configuration.accessToken = accessToken;
295
+ this.tokenData.accessToken = tokenString;
296
+
297
+ this.storeTokenData(this.tokenData);
255
298
 
256
299
  return axios.request({
257
300
  ...originalConfig,
@@ -261,7 +304,7 @@ export class BaseAPI {
261
304
  return Promise.reject(_error.response.data);
262
305
  }
263
306
  return Promise.reject(_error);
264
- }
307
+ }
265
308
  }
266
309
  return Promise.reject(err);
267
310
  }
@@ -276,7 +319,7 @@ export class BaseAPI {
276
319
  * @extends {Error}
277
320
  */
278
321
  export class RequiredError extends Error {
279
- name: "RequiredError" = "RequiredError";
322
+ override name: "RequiredError" = "RequiredError";
280
323
  constructor(public field: string, msg?: string) {
281
324
  super(msg);
282
325
  }
package/common.ts CHANGED
@@ -16,7 +16,6 @@
16
16
  import { Configuration } from "./configuration";
17
17
  import { RequiredError, RequestArgs } from "./base";
18
18
  import { AxiosInstance, AxiosResponse } from 'axios';
19
- import { URL, URLSearchParams } from 'url';
20
19
  /**
21
20
  *
22
21
  * @export
@@ -66,7 +65,7 @@ export const setBearerAuthToObject = async function (object: any, configuration?
66
65
  const accessToken = typeof configuration.accessToken === 'function'
67
66
  ? await configuration.accessToken()
68
67
  : await configuration.accessToken;
69
- object["Authorization"] = "Bearer " + accessToken;
68
+ object["Authorization"] = configuration.getBearerToken(accessToken);
70
69
  }
71
70
  }
72
71
 
@@ -79,7 +78,7 @@ export const setOAuthToObject = async function (object: any, name: string, scope
79
78
  const localVarAccessTokenValue = typeof configuration.accessToken === 'function'
80
79
  ? await configuration.accessToken(name, scopes)
81
80
  : await configuration.accessToken;
82
- object["Authorization"] = "Bearer " + localVarAccessTokenValue;
81
+ object["Authorization"] = configuration.getBearerToken(localVarAccessTokenValue);
83
82
  }
84
83
  }
85
84
 
package/configuration.ts CHANGED
@@ -74,14 +74,6 @@ export class Configuration {
74
74
  */
75
75
  formDataCtor?: new () => any;
76
76
 
77
- /**
78
- * parameter for automatically refreshing access token for oauth2 security
79
- *
80
- * @type {string}
81
- * @memberof Configuration
82
- */
83
- refreshToken?: string;
84
-
85
77
  constructor(param: ConfigurationParameters = {}) {
86
78
  this.apiKey = param.apiKey;
87
79
  this.username = param.username;
@@ -106,4 +98,13 @@ export class Configuration {
106
98
  const jsonMime: RegExp = new RegExp('^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$', 'i');
107
99
  return mime !== null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json');
108
100
  }
101
+
102
+ /**
103
+ * Returns "Bearer" token.
104
+ * @param token - access token.
105
+ * @return Bearer token.
106
+ */
107
+ public getBearerToken(token?: string): string {
108
+ return ('' + token).startsWith("Bearer") ? token : "Bearer " + token;
109
+ }
109
110
  }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * EMIL TranslationService
3
+ * The EMIL TranslationService API description
4
+ *
5
+ * The version of the OpenAPI document: 1.0
6
+ * Contact: kontakt@emil.de
7
+ *
8
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
9
+ * https://openapi-generator.tech
10
+ * Do not edit the class manually.
11
+ */
12
+ import { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios';
13
+ import { Configuration } from '../configuration';
14
+ import { RequestArgs, BaseAPI } from '../base';
15
+ import { InlineResponse200 } from '../models';
16
+ /**
17
+ * DefaultApi - axios parameter creator
18
+ * @export
19
+ */
20
+ export declare const DefaultApiAxiosParamCreator: (configuration?: Configuration) => {
21
+ /**
22
+ * Returns the health status of the translation service. This endpoint is used to monitor the operational status of the translation service. It typically returns a simple status indicator, such as \'UP\' or \'OK\', confirming that the service is operational and available.
23
+ * @summary Health Check
24
+ * @param {*} [options] Override http request option.
25
+ * @throws {RequiredError}
26
+ */
27
+ check: (options?: AxiosRequestConfig) => Promise<RequestArgs>;
28
+ };
29
+ /**
30
+ * DefaultApi - functional programming interface
31
+ * @export
32
+ */
33
+ export declare const DefaultApiFp: (configuration?: Configuration) => {
34
+ /**
35
+ * Returns the health status of the translation service. This endpoint is used to monitor the operational status of the translation service. It typically returns a simple status indicator, such as \'UP\' or \'OK\', confirming that the service is operational and available.
36
+ * @summary Health Check
37
+ * @param {*} [options] Override http request option.
38
+ * @throws {RequiredError}
39
+ */
40
+ check(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse200>>;
41
+ };
42
+ /**
43
+ * DefaultApi - factory interface
44
+ * @export
45
+ */
46
+ export declare const DefaultApiFactory: (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) => {
47
+ /**
48
+ * Returns the health status of the translation service. This endpoint is used to monitor the operational status of the translation service. It typically returns a simple status indicator, such as \'UP\' or \'OK\', confirming that the service is operational and available.
49
+ * @summary Health Check
50
+ * @param {*} [options] Override http request option.
51
+ * @throws {RequiredError}
52
+ */
53
+ check(options?: any): AxiosPromise<InlineResponse200>;
54
+ };
55
+ /**
56
+ * DefaultApi - object-oriented interface
57
+ * @export
58
+ * @class DefaultApi
59
+ * @extends {BaseAPI}
60
+ */
61
+ export declare class DefaultApi extends BaseAPI {
62
+ /**
63
+ * Returns the health status of the translation service. This endpoint is used to monitor the operational status of the translation service. It typically returns a simple status indicator, such as \'UP\' or \'OK\', confirming that the service is operational and available.
64
+ * @summary Health Check
65
+ * @param {*} [options] Override http request option.
66
+ * @throws {RequiredError}
67
+ * @memberof DefaultApi
68
+ */
69
+ check(options?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<InlineResponse200, any>>;
70
+ }