@cloudbase/app 1.5.2-alpha.0 → 1.8.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.
@@ -1,18 +1,21 @@
1
+ /* eslint-disable no-plusplus */
2
+ /* eslint-disable no-prototype-builtins */
3
+ /* eslint-disable no-restricted-syntax */
4
+ /* eslint-disable @typescript-eslint/no-misused-promises */
1
5
  import {
2
6
  DATA_VERSION,
3
7
  LOGINTYPE,
4
8
  getSdkVersion,
5
9
  getEndPoint,
6
- OAUTH2_LOGINTYPE_PREFIX
7
10
  } from '../constants/common';
8
11
  import {
9
12
  IRequestOptions,
10
13
  SDKRequestInterface,
11
14
  ResponseObject,
12
15
  IUploadRequestOptions,
13
- IRequestConfig
16
+ IRequestConfig,
14
17
  } from '@cloudbase/adapter-interface';
15
- import { utils, jwt, adapters, constants } from '@cloudbase/utilities';
18
+ import { utils, adapters, constants } from '@cloudbase/utilities';
16
19
  import { KV } from '@cloudbase/types';
17
20
  import { IGetAccessTokenResult, ICloudbaseRequestConfig, IAppendedRequestInfo, IRequestBeforeHook } from '@cloudbase/types/request';
18
21
  import { ICloudbaseCache } from '@cloudbase/types/cache';
@@ -20,15 +23,11 @@ import { cloudbase } from '..';
20
23
  import { getCacheByEnvId, getLocalCache } from './cache';
21
24
  import { EVENTS } from '../constants/events';
22
25
  import { Platform } from './adapter';
23
- const { getSdkName, ERRORS } = constants;
26
+
27
+ const { ERRORS } = constants;
24
28
  const { genSeqId, isFormData, formatUrl, createSign } = utils;
25
29
  const { RUNTIME } = adapters;
26
30
 
27
- import { v4 as uuidv4 } from 'uuid'
28
-
29
- // import FingerprintJS from '@fingerprintjs/fingerprintjs'
30
- // const fpPromise = FingerprintJS.load()
31
-
32
31
  // 下面几种 action 不需要 access token
33
32
  const ACTIONS_WITHOUT_ACCESSTOKEN = [
34
33
  'auth.getJwt',
@@ -41,7 +40,7 @@ const ACTIONS_WITHOUT_ACCESSTOKEN = [
41
40
  'auth.activateEndUserMail',
42
41
  'auth.sendPasswordResetEmail',
43
42
  'auth.resetPasswordWithToken',
44
- 'auth.isUsernameRegistered'
43
+ 'auth.isUsernameRegistered',
45
44
  ];
46
45
 
47
46
  function bindHooks(instance: SDKRequestInterface, name: string, hooks: IRequestBeforeHook[]) {
@@ -49,7 +48,7 @@ function bindHooks(instance: SDKRequestInterface, name: string, hooks: IRequestB
49
48
  instance[name] = function (options: IRequestOptions) {
50
49
  const data = {};
51
50
  const headers = {};
52
- hooks.forEach(hook => {
51
+ hooks.forEach((hook) => {
53
52
  const { data: appendedData, headers: appendedHeaders } = hook.call(instance, options);
54
53
  Object.assign(data, appendedData);
55
54
  Object.assign(headers, appendedHeaders);
@@ -64,12 +63,12 @@ function bindHooks(instance: SDKRequestInterface, name: string, hooks: IRequestB
64
63
  }
65
64
  options.data = {
66
65
  ...originData,
67
- ...data
66
+ ...data,
68
67
  };
69
68
  })();
70
69
  options.headers = {
71
70
  ...(options.headers || {}),
72
- ...headers
71
+ ...headers,
73
72
  };
74
73
  return (originMethod as Function).call(instance, options);
75
74
  };
@@ -78,16 +77,15 @@ function beforeEach(): IAppendedRequestInfo {
78
77
  const seqId = genSeqId();
79
78
  return {
80
79
  data: {
81
- seqId
80
+ seqId,
82
81
  },
83
82
  headers: {
84
83
  'X-SDK-Version': `@cloudbase/js-sdk/${getSdkVersion()}`,
85
- 'x-seqid': seqId
86
- }
84
+ 'x-seqid': seqId,
85
+ },
87
86
  };
88
87
  }
89
88
  export interface ICloudbaseRequest {
90
- fetch: (urlOrPath: string, init?: RequestInit) => Promise<Response>;
91
89
  post: (options: IRequestOptions) => Promise<ResponseObject>;
92
90
  upload: (options: IUploadRequestOptions) => Promise<ResponseObject>;
93
91
  download: (options: IRequestOptions) => Promise<ResponseObject>;
@@ -102,8 +100,8 @@ export interface ICloudbaseRequest {
102
100
  */
103
101
  export class CloudbaseRequest implements ICloudbaseRequest {
104
102
  config: ICloudbaseRequestConfig;
105
- _shouldRefreshAccessTokenHook: Function
106
- _refreshAccessTokenPromise: Promise<IGetAccessTokenResult> | null
103
+ _shouldRefreshAccessTokenHook: Function;
104
+ _refreshAccessTokenPromise: Promise<IGetAccessTokenResult> | null;
107
105
  _reqClass: SDKRequestInterface;
108
106
  // 请求失败是否抛出Error
109
107
  private _throwWhenRequestFail = false;
@@ -120,7 +118,7 @@ export class CloudbaseRequest implements ICloudbaseRequest {
120
118
  this._reqClass = new Platform.adapter.reqClass(<IRequestConfig>{
121
119
  timeout: this.config.timeout,
122
120
  timeoutMsg: `[@cloudbase/js-sdk] 请求在${this.config.timeout / 1000}s内未完成,已中断`,
123
- restrictedMethods: ['post']
121
+ restrictedMethods: ['post'],
124
122
  });
125
123
  this._throwWhenRequestFail = config.throw || false;
126
124
  this._cache = getCacheByEnvId(this.config.env);
@@ -129,49 +127,6 @@ export class CloudbaseRequest implements ICloudbaseRequest {
129
127
  bindHooks(this._reqClass, 'upload', [beforeEach]);
130
128
  bindHooks(this._reqClass, 'download', [beforeEach]);
131
129
  }
132
-
133
- /**
134
- * 套一层 fetch,方便处理请求地址
135
- * @param {string} urlOrPath
136
- * @param {RequestInit} init
137
- * @returns
138
- */
139
- public async fetch(urlOrPath: string, init?: RequestInit): Promise<Response> {
140
- const deviceId = await this.getDeviceId();
141
-
142
- const headers = {
143
- 'X-Project-Id': this.config.env,
144
- 'X-SDK-Version': `@cloudbase/js-sdk/${getSdkVersion()}`,
145
- 'X-Request-Id': genSeqId(),
146
- 'X-Request-Timestamp': Date.now(),
147
- 'X-Device-Id': deviceId
148
- }
149
- // 非web平台使用凭证检验有效性
150
- if (Platform.runtime !== RUNTIME.WEB) {
151
- const { appSign, appSecret } = this.config
152
- const timestamp = Date.now()
153
- const { appAccessKey, appAccessKeyId } = appSecret
154
- const sign = createSign({
155
- // data: init.body,
156
- data: {},
157
- timestamp,
158
- appAccessKeyId,
159
- appSign
160
- }, appAccessKey)
161
-
162
- headers['X-TCB-App-Source'] = `timestamp=${timestamp};appAccessKeyId=${appAccessKeyId};appSign=${appSign};sign=${sign}`
163
- }
164
-
165
- init.headers = Object.assign({}, init.headers, headers)
166
-
167
- const { PROTOCOL, BASE_URL } = getEndPoint()
168
- const webEndpoint = `${PROTOCOL}${BASE_URL}`
169
- const url = urlOrPath.startsWith('http')
170
- ? urlOrPath
171
- : `${new URL(webEndpoint).origin}${urlOrPath}`
172
- return await fetch(url, init)
173
- }
174
-
175
130
  public async post(options: IRequestOptions): Promise<ResponseObject> {
176
131
  const res = await this._reqClass.post(options);
177
132
  return res;
@@ -207,51 +162,15 @@ export class CloudbaseRequest implements ICloudbaseRequest {
207
162
  return result;
208
163
  }
209
164
 
210
- public async refreshAccessTokenFromOauthServer(clientId: string): Promise<IGetAccessTokenResult> {
211
- // 可能会同时调用多次刷新 access token,这里把它们合并成一个
212
- if (!this._refreshAccessTokenPromise) {
213
- // 没有正在刷新,那么正常执行刷新逻辑
214
- this._refreshAccessTokenPromise = this._refreshAccessTokenFromOauthServer(clientId);
215
- }
216
-
217
- let result;
218
- let err;
219
- try {
220
- result = await this._refreshAccessTokenPromise;
221
- } catch (e) {
222
- err = e;
223
- }
224
- this._refreshAccessTokenPromise = null;
225
- this._shouldRefreshAccessTokenHook = null;
226
- if (err) {
227
- throw err;
228
- }
229
- return result;
230
- }
231
-
232
- // 获取 OAuth accesstoken
233
- public async getOauthAccessToken(): Promise<IGetAccessTokenResult> {
234
- const { oauthClient } = this.config
235
- if (oauthClient) {
236
- const validAccessToken = await oauthClient.getAccessToken()
237
- const credentials = await oauthClient._getCredentials()
238
- return {
239
- accessToken: validAccessToken,
240
- accessTokenExpire: new Date(credentials.expires_at).getTime()
241
- }
242
- }
243
- }
244
-
245
- // 获取 access token
165
+ // 获取access token
246
166
  public async getAccessToken(): Promise<IGetAccessTokenResult> {
247
- const { loginTypeKey, accessTokenKey, accessTokenExpireKey, refreshTokenKey } = this._cache.keys;
248
- const loginType = await this._cache.getStoreAsync(loginTypeKey);
167
+ const { accessTokenKey, accessTokenExpireKey, refreshTokenKey } = this._cache.keys;
249
168
  const refreshToken = await this._cache.getStoreAsync(refreshTokenKey);
250
169
  if (!refreshToken) {
251
170
  // 不该出现的状态:有 access token 却没有 refresh token
252
171
  throw new Error(JSON.stringify({
253
172
  code: ERRORS.OPERATION_FAIL,
254
- msg: 'refresh token is not exist, your local data might be messed up, please retry after clear localStorage or sessionStorage'
173
+ msg: 'refresh token is not exist, your local data might be messed up, please retry after clear localStorage or sessionStorage',
255
174
  }));
256
175
  }
257
176
  // 如果没有access token或者过期,那么刷新
@@ -265,43 +184,18 @@ export class CloudbaseRequest implements ICloudbaseRequest {
265
184
  }
266
185
 
267
186
  if ((!accessToken || !accessTokenExpire || accessTokenExpire < Date.now()) && shouldRefreshAccessToken) {
268
- if (loginType.startsWith(OAUTH2_LOGINTYPE_PREFIX)) {
269
- // NOTE: 这里需要从 accessToken 解出来部分信息,用于刷新 accessToken
270
- // 所以过期的 accessToken 不能删除,而是用新 accessToken 覆盖
271
- if (accessToken) {
272
- let header = null
273
- let payload = null
274
- try {
275
- header = jwt.decode(accessToken, { header: true })
276
- payload = jwt.decode(accessToken)
277
- }
278
- catch (e) {
279
- throw new Error(`[DECODE_ACCESS_TOKEN_ERROR] ${e.message}, accesstoken: ${accessToken}`)
280
- }
281
- if (header?.kid && payload?.project_id) {
282
- return await this.refreshAccessTokenFromOauthServer(payload?.project_id)
283
- }
284
- }
285
- else {
286
- // 这里用 env 试一下
287
- return await this.refreshAccessTokenFromOauthServer(this.config.env)
288
- }
289
- }
290
- else {
291
- return await this.refreshAccessToken();
292
- }
293
- } else {
294
- // 返回本地的access token
295
- return {
296
- accessToken,
297
- accessTokenExpire
298
- };
187
+ // 返回新的access tolen
188
+ return await this.refreshAccessToken();
299
189
  }
190
+ // 返回本地的access token
191
+ return {
192
+ accessToken,
193
+ accessTokenExpire,
194
+ };
300
195
  }
301
196
 
302
197
  /* eslint-disable complexity */
303
198
  public async request(action: string, params: KV<any>, options?: KV<any>): Promise<ResponseObject> {
304
- const { oauthClient } = this.config
305
199
  const tcbTraceKey = `x-tcb-trace_${this.config.env}`;
306
200
  let contentType = 'application/x-www-form-urlencoded';
307
201
  // const webDeviceId = await getTcbFingerprintId();
@@ -310,13 +204,9 @@ export class CloudbaseRequest implements ICloudbaseRequest {
310
204
  // webDeviceId,
311
205
  dataVersion: DATA_VERSION,
312
206
  env: this.config.env,
313
- ...params
207
+ ...params,
314
208
  };
315
209
 
316
- // 若识别到注册了 Oauth 模块,则使用oauth getAccessToken
317
- if (oauthClient) {
318
- tmpObj.access_token = (await this.getOauthAccessToken()).accessToken
319
- }
320
210
 
321
211
  if (ACTIONS_WITHOUT_ACCESSTOKEN.indexOf(action) === -1) {
322
212
  const { refreshTokenKey } = this._cache.keys;
@@ -332,7 +222,7 @@ export class CloudbaseRequest implements ICloudbaseRequest {
332
222
  let payload;
333
223
  if (action === 'storage.uploadFile') {
334
224
  payload = new FormData();
335
- for (let key in payload) {
225
+ for (const key in payload) {
336
226
  if (payload.hasOwnProperty(key) && payload[key] !== undefined) {
337
227
  payload.append(key, tmpObj[key]);
338
228
  }
@@ -341,19 +231,19 @@ export class CloudbaseRequest implements ICloudbaseRequest {
341
231
  } else {
342
232
  contentType = 'application/json;charset=UTF-8';
343
233
  payload = {};
344
- for (let key in tmpObj) {
234
+ for (const key in tmpObj) {
345
235
  if (tmpObj[key] !== undefined) {
346
236
  payload[key] = tmpObj[key];
347
237
  }
348
238
  }
349
239
  }
350
- let opts: any = {
240
+ const opts: any = {
351
241
  headers: {
352
- 'content-type': contentType
353
- }
242
+ 'content-type': contentType,
243
+ },
354
244
  };
355
- if (options?.['onUploadProgress']) {
356
- opts.onUploadProgress = options['onUploadProgress'];
245
+ if (options?.onUploadProgress) {
246
+ opts.onUploadProgress = options.onUploadProgress;
357
247
  }
358
248
 
359
249
  if (this.config.region) {
@@ -373,7 +263,7 @@ export class CloudbaseRequest implements ICloudbaseRequest {
373
263
  data: {}, // 校验签名流程实际未用到,可设空
374
264
  timestamp,
375
265
  appAccessKeyId,
376
- appSign
266
+ appSign,
377
267
  }, appAccessKey);
378
268
 
379
269
  opts.headers['X-TCB-App-Source'] = `timestamp=${timestamp};appAccessKeyId=${appAccessKeyId};appSign=${appSign};sign=${sign}`;
@@ -384,13 +274,13 @@ export class CloudbaseRequest implements ICloudbaseRequest {
384
274
  // 请求链接支持添加动态 query 参数,方便用户调试定位请求
385
275
  const { parse, inQuery, search } = params;
386
276
  let formatQuery: Record<string, any> = {
387
- env: this.config.env
277
+ env: this.config.env,
388
278
  };
389
279
  // 尝试解析响应数据为 JSON
390
280
  parse && (formatQuery.parse = true);
391
281
  inQuery && (formatQuery = {
392
282
  ...inQuery,
393
- ...formatQuery
283
+ ...formatQuery,
394
284
  });
395
285
  const { BASE_URL, PROTOCOL } = getEndPoint();
396
286
  // 生成请求 url
@@ -403,7 +293,7 @@ export class CloudbaseRequest implements ICloudbaseRequest {
403
293
  const res: ResponseObject = await this.post({
404
294
  url: newUrl,
405
295
  data: payload,
406
- ...opts
296
+ ...opts,
407
297
  });
408
298
 
409
299
  // 保存 trace header
@@ -430,7 +320,7 @@ export class CloudbaseRequest implements ICloudbaseRequest {
430
320
  if (response.data.code && this._throwWhenRequestFail) {
431
321
  throw new Error(JSON.stringify({
432
322
  code: ERRORS.OPERATION_FAIL,
433
- msg: `[${response.data.code}] ${response.data.message}`
323
+ msg: `[${response.data.code}] ${response.data.message}`,
434
324
  }));
435
325
  }
436
326
 
@@ -443,15 +333,15 @@ export class CloudbaseRequest implements ICloudbaseRequest {
443
333
  await this._cache.removeStoreAsync(accessTokenKey);
444
334
  await this._cache.removeStoreAsync(accessTokenExpireKey);
445
335
 
446
- let refreshToken = await this._cache.getStoreAsync(refreshTokenKey);
336
+ const refreshToken = await this._cache.getStoreAsync(refreshTokenKey);
447
337
  if (!refreshToken) {
448
338
  throw new Error(JSON.stringify({
449
339
  code: ERRORS.INVALID_OPERATION,
450
- msg: 'not login'
340
+ msg: 'not login',
451
341
  }));
452
342
  }
453
343
  const params: KV<string> = {
454
- refresh_token: refreshToken
344
+ refresh_token: refreshToken,
455
345
  };
456
346
  const response = await this.request('auth.fetchAccessTokenWithRefreshToken', params);
457
347
  if (response.data.code) {
@@ -469,26 +359,23 @@ export class CloudbaseRequest implements ICloudbaseRequest {
469
359
  const refresh_token = await this._cache.getStoreAsync(refreshTokenKey);
470
360
  const res = await this.send('auth.signInAnonymously', {
471
361
  anonymous_uuid,
472
- refresh_token
362
+ refresh_token,
473
363
  });
474
364
  this._setRefreshToken(res.refresh_token);
475
365
  if (retryNum >= 1) {
476
366
  return this._refreshAccessToken(--retryNum);
477
- } else {
478
- throw new Error(
479
- JSON.stringify({
480
- code: ERRORS.OPERATION_FAIL,
481
- message: '重试获取 refresh token 失败'
482
- })
483
- )
484
367
  }
368
+ throw new Error(JSON.stringify({
369
+ code: ERRORS.OPERATION_FAIL,
370
+ message: '重试获取 refresh token 失败',
371
+ }));
485
372
  }
486
373
  cloudbase.fire(EVENTS.LOGIN_STATE_EXPIRED);
487
374
  await this._cache.removeStoreAsync(refreshTokenKey);
488
375
  }
489
376
  throw new Error(JSON.stringify({
490
377
  code: ERRORS.NETWORK_ERROR,
491
- msg: `refresh access_token failed:${response.data.code}`
378
+ msg: `refresh access_token failed:${response.data.code}`,
492
379
  }));
493
380
  }
494
381
  if (response.data.access_token) {
@@ -498,7 +385,7 @@ export class CloudbaseRequest implements ICloudbaseRequest {
498
385
  await this._cache.setStoreAsync(accessTokenExpireKey, response.data.access_token_expire + Date.now());
499
386
  return {
500
387
  accessToken: response.data.access_token,
501
- accessTokenExpire: response.data.access_token_expire
388
+ accessTokenExpire: response.data.access_token_expire,
502
389
  };
503
390
  }
504
391
  // 匿名登录refresh_token过期情况下返回refresh_token
@@ -509,103 +396,13 @@ export class CloudbaseRequest implements ICloudbaseRequest {
509
396
  await this._refreshAccessToken();
510
397
  }
511
398
  }
512
-
513
- private async _fetchAccessTokenFromOauthServer(refreshToken: string, clientId: string) {
514
- const resp = await this.fetch('/auth/v1/token', {
515
- method: 'POST',
516
- headers: {
517
- 'Accept': 'application/json',
518
- 'Content-Type': 'application/json'
519
- },
520
- body: JSON.stringify({
521
- grant_type: 'refresh_token',
522
- client_id: clientId,
523
- refresh_token: refreshToken
524
- })
525
- })
526
- // Resp:
527
- // {
528
- // "token_type": "Bearer",
529
- // "access_token": "",
530
- // "refresh_token":"",
531
- // "expires_in": 259200,
532
- // "sub": ""
533
- // }
534
- // 以下代码重复
535
- const seqIdFromHeader = resp.headers.get('SeqId') || resp.headers.get('RequestId')
536
- if (resp.status >= 400 && resp.status < 500) {
537
- const body: any = await resp.json()
538
- const seqId = body.request_id || seqIdFromHeader
539
- throw new Error(`[${getSdkName()}/${getSdkVersion()}][OAuth2AuthProvider][status:${resp.status}][${body.error}(${body.error_code})] ${body.error_description} (${seqId})`)
540
- }
541
- else if (resp.status >= 500) {
542
- const body: any = await resp.json()
543
- const seqId = body.request_id || seqIdFromHeader
544
- throw new Error(`[${getSdkName()}/${getSdkVersion()}][OAuth2AuthProvider][status:${resp.status}][${body.error}(${body.error_code})] ${body.error_description} (${seqId})`)
545
- }
546
- return resp.json()
547
- }
548
-
549
- // 调用接口刷新access token,并且返回
550
- private async _refreshAccessTokenFromOauthServer(clientId: string): Promise<IGetAccessTokenResult> {
551
- const { accessTokenKey, accessTokenExpireKey, refreshTokenKey } = this._cache.keys;
552
- const refreshToken = await this._cache.getStoreAsync(refreshTokenKey);
553
- if (!refreshToken) {
554
- throw new Error(JSON.stringify({
555
- code: ERRORS.INVALID_OPERATION,
556
- msg: 'not login'
557
- }));
558
- }
559
-
560
- const token = await this._fetchAccessTokenFromOauthServer(refreshToken, clientId);
561
- const { refresh_token: newRefreshToken, access_token: accessToken, expires_in: accessTokenExpire } = token
562
-
563
- // 错误处理
564
- if (!accessToken || !accessTokenExpire) {
565
- throw new Error(JSON.stringify({
566
- code: ERRORS.NETWORK_ERROR,
567
- msg: 'refresh access_token failed'
568
- }));
569
- }
570
- if (accessToken && accessTokenExpire) {
571
- if (newRefreshToken === refreshToken) {
572
- await this._cache.setStoreAsync(refreshTokenKey, newRefreshToken);
573
- }
574
- await this._cache.setStoreAsync(accessTokenKey, accessToken);
575
- await this._cache.setStoreAsync(accessTokenExpireKey, accessTokenExpire * 1000 + Date.now());
576
- cloudbase.fire(EVENTS.ACCESS_TOKEN_REFRESHD);
577
- return {
578
- accessToken: accessToken,
579
- accessTokenExpire: accessTokenExpire
580
- };
581
- }
582
- }
583
-
584
399
  private async _setRefreshToken(refreshToken: string) {
585
400
  const { accessTokenKey, accessTokenExpireKey, refreshTokenKey } = this._cache.keys;
586
401
  // refresh token设置前,先清掉 access token
587
- // 设置是直接拉取新 access token 覆盖,而不是 remove
588
402
  await this._cache.removeStoreAsync(accessTokenKey);
589
403
  await this._cache.removeStoreAsync(accessTokenExpireKey);
590
404
  await this._cache.setStoreAsync(refreshTokenKey, refreshToken);
591
405
  }
592
-
593
- private async getDeviceId(): Promise<string> {
594
- const { deviceIdKey } = this._cache.keys
595
- const deviceId = await this._cache.getStoreAsync(deviceIdKey)
596
-
597
- if (!deviceId) {
598
- // const fp = await fpPromise
599
- // const result = await fp.get()
600
- // const deviceId = result.visitorId
601
- const newDeviceId = uuidv4()
602
- this._cache.setStoreAsync(deviceIdKey, newDeviceId)
603
- return newDeviceId
604
- }
605
- else {
606
- return deviceId
607
- }
608
- }
609
406
  }
610
407
 
611
408
  const requestMap: KV<CloudbaseRequest> = {};
@@ -613,10 +410,10 @@ const requestMap: KV<CloudbaseRequest> = {};
613
410
  export function initRequest(config: ICloudbaseRequestConfig) {
614
411
  requestMap[config.env] = new CloudbaseRequest({
615
412
  ...config,
616
- throw: true
413
+ throw: true,
617
414
  });
618
415
  }
619
416
 
620
417
  export function getRequestByEnvId(env: string): CloudbaseRequest {
621
418
  return requestMap[env];
622
- }
419
+ }
package/.eslintrc DELETED
@@ -1,29 +0,0 @@
1
- {
2
- "extends": [
3
- "eslint-config-alloy/typescript"
4
- ],
5
- "rules": {
6
- "indent": [
7
- "error",
8
- 2,
9
- {
10
- "SwitchCase": 1,
11
- "flatTernaryExpressions": true
12
- }
13
- ],
14
- "guard-for-in": 0,
15
- "no-param-reassign": 0,
16
- "no-undefined": 0,
17
- "@typescript-eslint/explicit-member-accessibility": 0,
18
- "@typescript-eslint/consistent-type-assertions": 0,
19
- "@typescript-eslint/no-loss-of-precision": 0,
20
- "@typescript-eslint/no-duplicate-imports": 0
21
- },
22
- "parserOptions": {
23
- "ecmaVersion": 6,
24
- "sourceType": "module",
25
- "ecmaFeatures": {
26
- "modules": true
27
- }
28
- }
29
- }