@checkdigit/eslint-plugin 7.3.0-PR.75-f04b → 7.3.0-PR.89-2e8d

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 (81) hide show
  1. package/README.md +2 -1
  2. package/dist-mjs/agent/no-full-response.mjs +35 -0
  3. package/dist-mjs/{no-serve-runtime.mjs → agent/no-serve-runtime.mjs} +3 -3
  4. package/dist-mjs/index.mjs +51 -172
  5. package/dist-mjs/library/tree.mjs +2 -2
  6. package/dist-mjs/no-random-v4-uuid.mjs +67 -0
  7. package/dist-mjs/require-resolve-full-response.mjs +15 -30
  8. package/dist-types/agent/no-full-response.d.ts +4 -0
  9. package/dist-types/index.d.ts +2 -4
  10. package/dist-types/no-random-v4-uuid.d.ts +5 -0
  11. package/package.json +1 -1
  12. package/src/agent/no-full-response.ts +41 -0
  13. package/src/{no-serve-runtime.ts → agent/no-serve-runtime.ts} +2 -2
  14. package/src/index.ts +50 -173
  15. package/src/library/tree.ts +0 -1
  16. package/src/no-random-v4-uuid.ts +92 -0
  17. package/src/require-resolve-full-response.ts +21 -38
  18. package/dist-mjs/agent/add-assert-import.mjs +0 -58
  19. package/dist-mjs/agent/add-base-path-const.mjs +0 -65
  20. package/dist-mjs/agent/add-base-path-import.mjs +0 -60
  21. package/dist-mjs/agent/add-url-domain.mjs +0 -61
  22. package/dist-mjs/agent/agent-test-wiring.mjs +0 -221
  23. package/dist-mjs/agent/fetch-response-body-json.mjs +0 -146
  24. package/dist-mjs/agent/fetch-response-header-getter.mjs +0 -117
  25. package/dist-mjs/agent/fetch-then.mjs +0 -269
  26. package/dist-mjs/agent/fetch.mjs +0 -38
  27. package/dist-mjs/agent/file.mjs +0 -43
  28. package/dist-mjs/agent/fix-function-call-arguments.mjs +0 -153
  29. package/dist-mjs/agent/no-fixture.mjs +0 -356
  30. package/dist-mjs/agent/no-mapped-response.mjs +0 -75
  31. package/dist-mjs/agent/no-service-wrapper.mjs +0 -185
  32. package/dist-mjs/agent/no-status-code.mjs +0 -59
  33. package/dist-mjs/agent/no-unused-function-argument.mjs +0 -79
  34. package/dist-mjs/agent/no-unused-imports.mjs +0 -81
  35. package/dist-mjs/agent/no-unused-service-variable.mjs +0 -74
  36. package/dist-mjs/agent/response-reference.mjs +0 -70
  37. package/dist-mjs/agent/url.mjs +0 -32
  38. package/dist-mjs/no-legacy-service-typing.mjs +0 -39
  39. package/dist-types/agent/add-assert-import.d.ts +0 -4
  40. package/dist-types/agent/add-base-path-const.d.ts +0 -4
  41. package/dist-types/agent/add-base-path-import.d.ts +0 -4
  42. package/dist-types/agent/add-url-domain.d.ts +0 -4
  43. package/dist-types/agent/agent-test-wiring.d.ts +0 -4
  44. package/dist-types/agent/fetch-response-body-json.d.ts +0 -4
  45. package/dist-types/agent/fetch-response-header-getter.d.ts +0 -4
  46. package/dist-types/agent/fetch-then.d.ts +0 -4
  47. package/dist-types/agent/fetch.d.ts +0 -5
  48. package/dist-types/agent/file.d.ts +0 -7
  49. package/dist-types/agent/fix-function-call-arguments.d.ts +0 -9
  50. package/dist-types/agent/no-fixture.d.ts +0 -4
  51. package/dist-types/agent/no-mapped-response.d.ts +0 -4
  52. package/dist-types/agent/no-service-wrapper.d.ts +0 -4
  53. package/dist-types/agent/no-status-code.d.ts +0 -4
  54. package/dist-types/agent/no-unused-function-argument.d.ts +0 -4
  55. package/dist-types/agent/no-unused-imports.d.ts +0 -4
  56. package/dist-types/agent/no-unused-service-variable.d.ts +0 -4
  57. package/dist-types/agent/response-reference.d.ts +0 -16
  58. package/dist-types/agent/url.d.ts +0 -4
  59. package/dist-types/no-legacy-service-typing.d.ts +0 -5
  60. package/src/agent/add-assert-import.ts +0 -74
  61. package/src/agent/add-base-path-const.ts +0 -81
  62. package/src/agent/add-base-path-import.ts +0 -69
  63. package/src/agent/add-url-domain.ts +0 -76
  64. package/src/agent/agent-test-wiring.ts +0 -273
  65. package/src/agent/fetch-response-body-json.ts +0 -197
  66. package/src/agent/fetch-response-header-getter.ts +0 -148
  67. package/src/agent/fetch-then.ts +0 -357
  68. package/src/agent/fetch.ts +0 -57
  69. package/src/agent/file.ts +0 -42
  70. package/src/agent/fix-function-call-arguments.ts +0 -200
  71. package/src/agent/no-fixture.ts +0 -512
  72. package/src/agent/no-mapped-response.ts +0 -84
  73. package/src/agent/no-service-wrapper.ts +0 -241
  74. package/src/agent/no-status-code.ts +0 -72
  75. package/src/agent/no-unused-function-argument.ts +0 -98
  76. package/src/agent/no-unused-imports.ts +0 -103
  77. package/src/agent/no-unused-service-variable.ts +0 -93
  78. package/src/agent/response-reference.ts +0 -129
  79. package/src/agent/url.ts +0 -32
  80. package/src/no-legacy-service-typing.ts +0 -49
  81. /package/dist-types/{no-serve-runtime.d.ts → agent/no-serve-runtime.d.ts} +0 -0
@@ -1,4 +1,4 @@
1
- // no-serve-runtime.ts
1
+ // agent/no-serve-runtime.ts
2
2
 
3
3
  /*
4
4
  * Copyright (c) 2021-2024 Check Digit, LLC
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import { ESLintUtils, TSESTree } from '@typescript-eslint/utils';
10
- import getDocumentationUrl from './get-documentation-url';
10
+ import getDocumentationUrl from '../get-documentation-url';
11
11
 
12
12
  export const ruleId = 'no-serve-runtime';
13
13
 
package/src/index.ts CHANGED
@@ -8,29 +8,10 @@
8
8
 
9
9
  import type { TSESLint } from '@typescript-eslint/utils';
10
10
 
11
- import addUrlDomain, { ruleId as addUrlDomainRuleId } from './agent/add-url-domain';
12
- import agentTestWiring, { ruleId as agentTestWiringRuleId } from './agent/agent-test-wiring';
13
- import fetchResponseBodyJson, { ruleId as fetchResponseBodyJsonRuleId } from './agent/fetch-response-body-json';
14
- import fetchResponseHeaderGetter, {
15
- ruleId as fetchResponseHeaderGetterRuleId,
16
- } from './agent/fetch-response-header-getter';
17
- import fetchThen, { ruleId as fetchThenRuleId } from './agent/fetch-then';
18
- import fixFunctionCallArguments, {
19
- ruleId as fixFunctionCallArgumentsRuleId,
20
- } from './agent/fix-function-call-arguments';
21
11
  import invalidJsonStringify, { ruleId as invalidJsonStringifyRuleId } from './invalid-json-stringify';
22
12
  import noDuplicatedImports, { ruleId as noDuplicatedImportsRuleId } from './no-duplicated-imports';
23
- import noFixture, { ruleId as noFixtureRuleId } from './agent/no-fixture';
24
- import noLegacyServiceTyping, { ruleId as noLegacyServiceTypingRuleId } from './no-legacy-service-typing';
25
- import noMappedResponse, { ruleId as noMappedResponseRuleId } from './agent/no-mapped-response';
13
+ import noFullResponse, { ruleId as noFullResponseRuleId } from './agent/no-full-response';
26
14
  import noPromiseInstanceMethod, { ruleId as noPromiseInstanceMethodRuleId } from './no-promise-instance-method';
27
- import noServiceWrapper, { ruleId as noServiceWrapperRuleId } from './agent/no-service-wrapper';
28
- import noStatusCode, { ruleId as noStatusCodeRuleId } from './agent/no-status-code';
29
- import noUnusedFunctionArguments, {
30
- ruleId as noUnusedFunctionArgumentsRuleId,
31
- } from './agent/no-unused-function-argument';
32
- import noUnusedImports, { ruleId as noUnusedImportsRuleId } from './agent/no-unused-imports';
33
- import noUnusedServiceVariables, { ruleId as noUnusedServiceVariablesRuleId } from './agent/no-unused-service-variable';
34
15
  import requireFixedServicesImport, {
35
16
  ruleId as requireFixedServicesImportRuleId,
36
17
  } from './require-fixed-services-import';
@@ -40,12 +21,10 @@ import requireResolveFullResponse, {
40
21
  import requireTypeOutOfTypeOnlyImports, {
41
22
  ruleId as requireTypeOutOfTypeOnlyImportsRuleId,
42
23
  } from './require-type-out-of-type-only-imports';
43
- import noServeRuntime, { ruleId as noServeRuntimeRuleId } from './no-serve-runtime';
44
- import addBasePathConst, { ruleId as addBasePathConstRuleId } from './agent/add-base-path-const';
45
- import addBasePathImport, { ruleId as addBasePathImportRuleId } from './agent/add-base-path-import';
46
- import addAssertImport, { ruleId as addAssertImportRuleId } from './agent/add-assert-import';
24
+ import noServeRuntime, { ruleId as noServeRuntimeRuleId } from './agent/no-serve-runtime';
47
25
  import filePathComment from './file-path-comment';
48
26
  import noCardNumbers from './no-card-numbers';
27
+ import noRandomV4UUID from './no-random-v4-uuid';
49
28
  import noTestImport from './no-test-import';
50
29
  import noUuid from './no-uuid';
51
30
  import noWallabyComment from './no-wallaby-comment';
@@ -57,6 +36,7 @@ import requireStrictAssert from './require-strict-assert';
57
36
  const rules: Record<string, TSESLint.LooseRuleDefinition> = {
58
37
  'file-path-comment': filePathComment,
59
38
  'no-card-numbers': noCardNumbers,
39
+ 'no-random-v4-uuid': noRandomV4UUID,
60
40
  'no-uuid': noUuid,
61
41
  'require-strict-assert': requireStrictAssert,
62
42
  'no-test-import': noTestImport,
@@ -66,170 +46,67 @@ const rules: Record<string, TSESLint.LooseRuleDefinition> = {
66
46
  'object-literal-response': objectLiteralResponse,
67
47
  [invalidJsonStringifyRuleId]: invalidJsonStringify,
68
48
  [noPromiseInstanceMethodRuleId]: noPromiseInstanceMethod,
69
- [noFixtureRuleId]: noFixture,
70
- [fetchThenRuleId]: fetchThen,
71
- [noServiceWrapperRuleId]: noServiceWrapper,
72
- [noStatusCodeRuleId]: noStatusCode,
73
- [fetchResponseBodyJsonRuleId]: fetchResponseBodyJson,
74
- [fetchResponseHeaderGetterRuleId]: fetchResponseHeaderGetter,
75
- [addUrlDomainRuleId]: addUrlDomain,
76
- [noLegacyServiceTypingRuleId]: noLegacyServiceTyping,
77
- [noMappedResponseRuleId]: noMappedResponse,
49
+ [noFullResponseRuleId]: noFullResponse,
78
50
  [requireResolveFullResponseRuleId]: requireResolveFullResponse,
51
+ [requireTypeOutOfTypeOnlyImportsRuleId]: requireTypeOutOfTypeOnlyImports,
79
52
  [noDuplicatedImportsRuleId]: noDuplicatedImports,
80
- [noServeRuntimeRuleId]: noServeRuntime,
81
- [addBasePathConstRuleId]: addBasePathConst,
82
- [addBasePathImportRuleId]: addBasePathImport,
83
- [addAssertImportRuleId]: addAssertImport,
84
53
  [requireFixedServicesImportRuleId]: requireFixedServicesImport,
85
- [requireTypeOutOfTypeOnlyImportsRuleId]: requireTypeOutOfTypeOnlyImports,
86
- [noUnusedFunctionArgumentsRuleId]: noUnusedFunctionArguments,
87
- [noUnusedServiceVariablesRuleId]: noUnusedServiceVariables,
88
- [noUnusedImportsRuleId]: noUnusedImports,
89
- [fixFunctionCallArgumentsRuleId]: fixFunctionCallArguments,
90
- [agentTestWiringRuleId]: agentTestWiring,
54
+ [noServeRuntimeRuleId]: noServeRuntime,
91
55
  };
92
56
 
93
57
  const plugin: TSESLint.FlatConfig.Plugin = {
94
58
  rules,
95
59
  };
96
60
 
97
- const configs: Record<string, TSESLint.FlatConfig.Config | TSESLint.FlatConfig.Config[]> = {
98
- all: [
99
- {
100
- files: ['**/*.ts'],
101
- plugins: {
102
- '@checkdigit': plugin,
103
- },
104
- rules: {
105
- '@checkdigit/no-card-numbers': 'error',
106
- '@checkdigit/file-path-comment': 'error',
107
- '@checkdigit/no-uuid': 'error',
108
- '@checkdigit/require-strict-assert': 'error',
109
- '@checkdigit/no-wallaby-comment': 'error',
110
- '@checkdigit/regular-expression-comment': 'error',
111
- '@checkdigit/require-assert-predicate-rejects-throws': 'error',
112
- '@checkdigit/object-literal-response': 'error',
113
- '@checkdigit/no-test-import': 'error',
114
- [`@checkdigit/${invalidJsonStringifyRuleId}`]: 'error',
115
- [`@checkdigit/${noPromiseInstanceMethodRuleId}`]: 'error',
116
- [`@checkdigit/${noLegacyServiceTypingRuleId}`]: 'error',
117
- [`@checkdigit/${requireResolveFullResponseRuleId}`]: 'error',
118
- [`@checkdigit/${noDuplicatedImportsRuleId}`]: 'error',
119
- [`@checkdigit/${requireFixedServicesImportRuleId}`]: 'error',
120
- [`@checkdigit/${requireTypeOutOfTypeOnlyImportsRuleId}`]: 'error',
121
- [`@checkdigit/${noServeRuntimeRuleId}`]: 'error',
122
- // --- agent rules BEGIN ---
123
- [`@checkdigit/${noMappedResponseRuleId}`]: 'off',
124
- [`@checkdigit/${addUrlDomainRuleId}`]: 'off',
125
- [`@checkdigit/${noFixtureRuleId}`]: 'off',
126
- [`@checkdigit/${noServiceWrapperRuleId}`]: 'off',
127
- [`@checkdigit/${noStatusCodeRuleId}`]: 'off',
128
- [`@checkdigit/${fetchResponseBodyJsonRuleId}`]: 'off',
129
- [`@checkdigit/${fetchResponseHeaderGetterRuleId}`]: 'off',
130
- [`@checkdigit/${fetchThenRuleId}`]: 'off',
131
- [`@checkdigit/${noUnusedFunctionArgumentsRuleId}`]: 'off',
132
- [`@checkdigit/${noUnusedServiceVariablesRuleId}`]: 'off',
133
- [`@checkdigit/${noUnusedImportsRuleId}`]: 'off',
134
- [`@checkdigit/${fixFunctionCallArgumentsRuleId}`]: 'off',
135
- [`@checkdigit/${agentTestWiringRuleId}`]: 'off',
136
- [`@checkdigit/${addBasePathConstRuleId}`]: 'off',
137
- [`@checkdigit/${addBasePathImportRuleId}`]: 'off',
138
- [`@checkdigit/${addAssertImportRuleId}`]: 'off',
139
- // --- agent rules END ---
140
- },
141
- },
142
- ],
143
- recommended: [
144
- {
145
- files: ['**/*.ts'],
146
- plugins: {
147
- '@checkdigit': plugin,
148
- },
149
- rules: {
150
- '@checkdigit/no-card-numbers': 'error',
151
- '@checkdigit/file-path-comment': 'off',
152
- '@checkdigit/no-uuid': 'error',
153
- '@checkdigit/require-strict-assert': 'error',
154
- '@checkdigit/no-wallaby-comment': 'off',
155
- '@checkdigit/regular-expression-comment': 'error',
156
- '@checkdigit/require-assert-predicate-rejects-throws': 'error',
157
- '@checkdigit/object-literal-response': 'error',
158
- '@checkdigit/no-test-import': 'error',
159
- [`@checkdigit/${invalidJsonStringifyRuleId}`]: 'error',
160
- [`@checkdigit/${noPromiseInstanceMethodRuleId}`]: 'error',
161
- },
61
+ const configs: Record<string, TSESLint.FlatConfig.Config> = {
62
+ all: {
63
+ plugins: {
64
+ '@checkdigit': plugin,
162
65
  },
163
- ],
164
- 'agent-phase-1-test': [
165
- {
166
- files: ['**/*.spec.ts', '**/*.test.ts', 'src/api/v*/index.ts'],
167
- // eslint-disable-next-line sonarjs/no-duplicate-string
168
- ignores: ['src/plugin/**'],
169
- plugins: {
170
- '@checkdigit': plugin,
171
- },
172
- rules: {
173
- [`@checkdigit/${noMappedResponseRuleId}`]: 'error',
174
- [`@checkdigit/${addUrlDomainRuleId}`]: 'error',
175
- [`@checkdigit/${noFixtureRuleId}`]: 'error',
176
- [`@checkdigit/${noServiceWrapperRuleId}`]: 'error',
177
- [`@checkdigit/${noStatusCodeRuleId}`]: 'error',
178
- [`@checkdigit/${fetchResponseBodyJsonRuleId}`]: 'error',
179
- [`@checkdigit/${fetchResponseHeaderGetterRuleId}`]: 'error',
180
- [`@checkdigit/${fetchThenRuleId}`]: 'error',
181
- [`@checkdigit/${noUnusedFunctionArgumentsRuleId}`]: 'error',
182
- [`@checkdigit/${noUnusedServiceVariablesRuleId}`]: 'error',
183
- [`@checkdigit/${noUnusedImportsRuleId}`]: 'error',
184
- [`@checkdigit/${fixFunctionCallArgumentsRuleId}`]: 'error',
185
- [`@checkdigit/${addBasePathConstRuleId}`]: 'error',
186
- [`@checkdigit/${addBasePathImportRuleId}`]: 'error',
187
- [`@checkdigit/${addAssertImportRuleId}`]: 'error',
188
- },
66
+ rules: {
67
+ '@checkdigit/no-card-numbers': 'error',
68
+ '@checkdigit/file-path-comment': 'error',
69
+ '@checkdigit/no-random-v4-uuid': 'error',
70
+ '@checkdigit/no-uuid': 'error',
71
+ '@checkdigit/require-strict-assert': 'error',
72
+ '@checkdigit/no-wallaby-comment': 'error',
73
+ '@checkdigit/regular-expression-comment': 'error',
74
+ '@checkdigit/require-assert-predicate-rejects-throws': 'error',
75
+ '@checkdigit/object-literal-response': 'error',
76
+ '@checkdigit/no-test-import': 'error',
77
+ [`@checkdigit/${invalidJsonStringifyRuleId}`]: 'error',
78
+ [`@checkdigit/${noPromiseInstanceMethodRuleId}`]: 'error',
79
+ [`@checkdigit/${noFullResponseRuleId}`]: 'error',
80
+ [`@checkdigit/${requireResolveFullResponseRuleId}`]: 'error',
81
+ [`@checkdigit/${requireTypeOutOfTypeOnlyImportsRuleId}`]: 'error',
82
+ [`@checkdigit/${noDuplicatedImportsRuleId}`]: 'error',
83
+ [`@checkdigit/${requireFixedServicesImportRuleId}`]: 'error',
84
+ [`@checkdigit/${noServeRuntimeRuleId}`]: 'error',
189
85
  },
190
- {
191
- files: ['**/*.spec.ts'],
192
- ignores: ['src/plugin/**'],
193
- plugins: {
194
- '@checkdigit': plugin,
195
- },
196
- rules: {
197
- [`@checkdigit/${agentTestWiringRuleId}`]: 'error',
198
- },
86
+ },
87
+ recommended: {
88
+ plugins: {
89
+ '@checkdigit': plugin,
199
90
  },
200
- ],
201
- 'agent-phase-2-production': [
202
- {
203
- files: ['**/*.ts'],
204
- ignores: ['src/plugin/**'],
205
- plugins: {
206
- '@checkdigit': plugin,
207
- },
208
- rules: {
209
- [`@checkdigit/${noMappedResponseRuleId}`]: 'error',
210
- [`@checkdigit/${addUrlDomainRuleId}`]: 'error',
211
- [`@checkdigit/${noFixtureRuleId}`]: 'off',
212
- [`@checkdigit/${noServiceWrapperRuleId}`]: 'error',
213
- [`@checkdigit/${noStatusCodeRuleId}`]: 'error',
214
- [`@checkdigit/${fetchResponseBodyJsonRuleId}`]: 'error',
215
- [`@checkdigit/${fetchResponseHeaderGetterRuleId}`]: 'error',
216
- [`@checkdigit/${fetchThenRuleId}`]: 'error',
217
- [`@checkdigit/${noUnusedFunctionArgumentsRuleId}`]: 'error',
218
- [`@checkdigit/${noUnusedServiceVariablesRuleId}`]: 'error',
219
- [`@checkdigit/${noUnusedImportsRuleId}`]: 'error',
220
- [`@checkdigit/${fixFunctionCallArgumentsRuleId}`]: 'error',
221
- [`@checkdigit/${addBasePathConstRuleId}`]: 'error',
222
- [`@checkdigit/${addBasePathImportRuleId}`]: 'error',
223
- [`@checkdigit/${addAssertImportRuleId}`]: 'error',
224
- },
91
+ rules: {
92
+ '@checkdigit/no-card-numbers': 'error',
93
+ '@checkdigit/file-path-comment': 'off',
94
+ '@checkdigit/no-random-v4-uuid': 'error',
95
+ '@checkdigit/no-uuid': 'error',
96
+ '@checkdigit/require-strict-assert': 'error',
97
+ '@checkdigit/no-wallaby-comment': 'off',
98
+ '@checkdigit/regular-expression-comment': 'error',
99
+ '@checkdigit/require-assert-predicate-rejects-throws': 'error',
100
+ '@checkdigit/object-literal-response': 'error',
101
+ '@checkdigit/no-test-import': 'error',
102
+ [`@checkdigit/${invalidJsonStringifyRuleId}`]: 'error',
103
+ [`@checkdigit/${noPromiseInstanceMethodRuleId}`]: 'error',
225
104
  },
226
- ],
105
+ },
227
106
  };
228
107
 
229
- const defaultToExport: Exclude<TSESLint.FlatConfig.Plugin, 'config'> & {
230
- configs: Record<string, TSESLint.FlatConfig.Config | TSESLint.FlatConfig.Config[]>;
231
- } = {
108
+ const pluginToExport: TSESLint.FlatConfig.Plugin = {
232
109
  ...plugin,
233
110
  configs,
234
111
  };
235
- export default defaultToExport;
112
+ export default pluginToExport;
@@ -64,7 +64,6 @@ export function isUsedInArrayOrAsArgument(node: Node): boolean {
64
64
 
65
65
  if (
66
66
  parent.type === 'ArrayExpression' ||
67
- parent.type === 'ArrowFunctionExpression' ||
68
67
  (parent.type === 'CallExpression' && parent.arguments.includes(node as Expression))
69
68
  ) {
70
69
  return true;
@@ -0,0 +1,92 @@
1
+ // no-random-v4-uuid.ts
2
+
3
+ /*
4
+ * Copyright (c) 2022-2024 Check Digit, LLC
5
+ *
6
+ * This code is licensed under the MIT license (see LICENSE.txt for details).
7
+ */
8
+
9
+ import { AST_NODE_TYPES, ESLintUtils, TSESLint, TSESTree } from '@typescript-eslint/utils';
10
+ import getDocumentationUrl from './get-documentation-url';
11
+
12
+ export const ruleId = 'no-random-v4-uuid';
13
+ const NO_RANDOM_V4_UUID = 'NO_RANDOM_V4_UUID';
14
+
15
+ const createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
16
+
17
+ // process the import declaration to get the alias for uuid.v4 and uuid.
18
+ const processImportDeclaration = (
19
+ node: TSESTree.ImportDeclaration,
20
+ uuid4Alias: string | undefined,
21
+ uuidDefaultAlias: string | undefined,
22
+ ) => {
23
+ let updatedUuid4Alias = uuid4Alias;
24
+ let updatedUuidDefaultAlias = uuidDefaultAlias;
25
+ node.specifiers.forEach((specifier) => {
26
+ switch (specifier.type) {
27
+ case AST_NODE_TYPES.ImportSpecifier:
28
+ if (specifier.imported.type === AST_NODE_TYPES.Identifier && specifier.imported.name === 'v4') {
29
+ updatedUuid4Alias = specifier.local.name;
30
+ }
31
+ break;
32
+ case AST_NODE_TYPES.ImportDefaultSpecifier:
33
+ updatedUuidDefaultAlias = specifier.local.name;
34
+ break;
35
+ }
36
+ });
37
+ return { uuid4Alias: updatedUuid4Alias, uuidDefaultAlias: updatedUuidDefaultAlias };
38
+ };
39
+
40
+ // checks if the function call is either directly using the alias for uuid.v4 or using uuid.v4 as a member expression.
41
+ const isUuid4Call = (
42
+ node: TSESTree.CallExpression,
43
+ uuid4Alias: string | undefined,
44
+ uuidDefaultAlias: string | undefined,
45
+ ): boolean =>
46
+ (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === uuid4Alias) ||
47
+ (node.callee.type === AST_NODE_TYPES.MemberExpression &&
48
+ node.callee.object.type === AST_NODE_TYPES.Identifier &&
49
+ node.callee.object.name === uuidDefaultAlias &&
50
+ node.callee.property.type === AST_NODE_TYPES.Identifier &&
51
+ node.callee.property.name === 'v4');
52
+
53
+ const rule: TSESLint.RuleModule<typeof NO_RANDOM_V4_UUID> = createRule({
54
+ name: ruleId,
55
+ meta: {
56
+ type: 'problem',
57
+ docs: {
58
+ description: 'Disallow the use of `uuid.v4` for generating random v4 UUIDs',
59
+ },
60
+ schema: [],
61
+ messages: {
62
+ [NO_RANDOM_V4_UUID]: 'Avoid using `uuid.v4` for generating random v4 UUIDs.',
63
+ },
64
+ },
65
+ defaultOptions: [],
66
+ create(context) {
67
+ let uuid4Alias: string | undefined;
68
+ let uuidDefaultAlias: string | undefined;
69
+ let hasUuidImport = false;
70
+
71
+ return {
72
+ ImportDeclaration(node: TSESTree.ImportDeclaration) {
73
+ if (node.source.value === 'uuid') {
74
+ hasUuidImport = true;
75
+ const result = processImportDeclaration(node, uuid4Alias, uuidDefaultAlias);
76
+ uuid4Alias = result.uuid4Alias;
77
+ uuidDefaultAlias = result.uuidDefaultAlias;
78
+ }
79
+ },
80
+ CallExpression(node: TSESTree.CallExpression) {
81
+ if (hasUuidImport && isUuid4Call(node, uuid4Alias, uuidDefaultAlias)) {
82
+ context.report({
83
+ node,
84
+ messageId: NO_RANDOM_V4_UUID,
85
+ });
86
+ }
87
+ },
88
+ };
89
+ },
90
+ });
91
+
92
+ export default rule;
@@ -54,12 +54,10 @@ const rule: ESLintUtils.RuleModule<'invalidOptions' | 'unknownError'> = createRu
54
54
  const foundVariable = scope.variables.find((variable) => variable.name === urlArgument.name);
55
55
  if (foundVariable) {
56
56
  const variableDefinition = foundVariable.defs.find((def) => def.type === DefinitionType.Variable);
57
- if (variableDefinition) {
58
- const variableDefinitionNode = variableDefinition.node;
59
- assert.ok(variableDefinitionNode.init, 'Variable definition node has no init property');
60
- return isUrlArgumentValid(variableDefinitionNode.init, scope);
61
- }
62
- return true;
57
+ assert.ok(variableDefinition, `Variable "${urlArgument.name}" not defined in scope`);
58
+ const variableDefinitionNode = variableDefinition.node;
59
+ assert.ok(variableDefinitionNode.init, 'Variable definition node has no init property');
60
+ return isUrlArgumentValid(variableDefinitionNode.init, scope);
63
61
  }
64
62
  }
65
63
 
@@ -158,7 +156,7 @@ const rule: ESLintUtils.RuleModule<'invalidOptions' | 'unknownError'> = createRu
158
156
  const optionsArgument = ['get', 'head', 'del'].includes(method)
159
157
  ? serviceCall.arguments[1]
160
158
  : serviceCall.arguments[2];
161
- if (optionsArgument === undefined) {
159
+ if (optionsArgument === undefined || optionsArgument.type !== AST_NODE_TYPES.ObjectExpression) {
162
160
  context.report({
163
161
  node: serviceCall,
164
162
  messageId: 'invalidOptions',
@@ -166,38 +164,23 @@ const rule: ESLintUtils.RuleModule<'invalidOptions' | 'unknownError'> = createRu
166
164
  return;
167
165
  }
168
166
 
169
- if (optionsArgument.type === AST_NODE_TYPES.Identifier) {
170
- const optionsTypeString = getType(optionsArgument);
171
- if (optionsTypeString === 'FullResponseOptions') {
172
- return;
173
- }
174
-
175
- const variable = parserService.esTreeNodeToTSNodeMap.get(optionsArgument);
176
- const optionType = typeChecker.getTypeAtLocation(variable);
177
- const resolveWithFullResponseProperty = optionType.getProperty('resolveWithFullResponse');
178
- if (resolveWithFullResponseProperty?.declarations?.[0]?.getText() === 'resolveWithFullResponse: true') {
179
- return;
180
- }
181
- } else if (optionsArgument.type === AST_NODE_TYPES.ObjectExpression) {
182
- const resolveWithFullResponseProperty = optionsArgument.properties.find(
183
- (property) =>
184
- property.type === AST_NODE_TYPES.Property &&
185
- property.key.type === AST_NODE_TYPES.Identifier &&
186
- property.key.name === 'resolveWithFullResponse',
187
- );
188
- if (
189
- resolveWithFullResponseProperty?.type === AST_NODE_TYPES.Property &&
190
- resolveWithFullResponseProperty.value.type === AST_NODE_TYPES.Literal &&
191
- resolveWithFullResponseProperty.value.value === true
192
- ) {
193
- return;
194
- }
167
+ const resolveWithFullResponseProperty = optionsArgument.properties.find(
168
+ (property) =>
169
+ property.type === AST_NODE_TYPES.Property &&
170
+ property.key.type === AST_NODE_TYPES.Identifier &&
171
+ property.key.name === 'resolveWithFullResponse',
172
+ );
173
+ if (
174
+ resolveWithFullResponseProperty?.type !== AST_NODE_TYPES.Property ||
175
+ resolveWithFullResponseProperty.value.type !== AST_NODE_TYPES.Literal ||
176
+ resolveWithFullResponseProperty.value.value !== true
177
+ ) {
178
+ context.report({
179
+ node: optionsArgument,
180
+ messageId: 'invalidOptions',
181
+ });
182
+ return;
195
183
  }
196
-
197
- context.report({
198
- node: optionsArgument,
199
- messageId: 'invalidOptions',
200
- });
201
184
  } catch (error) {
202
185
  // eslint-disable-next-line no-console
203
186
  console.error(`Failed to apply ${ruleId} rule for file "${context.filename}":`, error);
@@ -1,58 +0,0 @@
1
- // src/agent/add-assert-import.ts
2
- import { strict as assert } from "node:assert";
3
- import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
4
- import getDocumentationUrl from "../get-documentation-url.mjs";
5
- var ruleId = "add-assert-import";
6
- var ASSERT_IMPORT_STATEMENT = "import { strict as assert } from 'node:assert';";
7
- var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
8
- var rule = createRule({
9
- name: ruleId,
10
- meta: {
11
- type: "suggestion",
12
- docs: {
13
- description: "Add import of assert module of node."
14
- },
15
- messages: {
16
- addAssertImport: "Add import of assert module of node."
17
- },
18
- fixable: "code",
19
- schema: []
20
- },
21
- defaultOptions: [],
22
- create(context) {
23
- let isAssertImported = false;
24
- let isAssertUsed = false;
25
- return {
26
- ImportDeclaration: (node) => {
27
- if (node.source.value === "assert" || node.source.value === "node:assert") {
28
- isAssertImported = true;
29
- }
30
- },
31
- CallExpression: (callExpression) => {
32
- if (callExpression.callee.type === AST_NODE_TYPES.Identifier && callExpression.callee.name === "assert" || callExpression.callee.type === AST_NODE_TYPES.MemberExpression && callExpression.callee.object.type === AST_NODE_TYPES.Identifier && callExpression.callee.object.name === "assert") {
33
- isAssertUsed = true;
34
- }
35
- },
36
- "Program:exit": (program) => {
37
- if (isAssertUsed && !isAssertImported) {
38
- const firstStatement = program.body[0];
39
- assert(firstStatement);
40
- context.report({
41
- node: program,
42
- messageId: "addAssertImport",
43
- fix(fixer) {
44
- return fixer.insertTextBefore(firstStatement, `${ASSERT_IMPORT_STATEMENT}
45
- `);
46
- }
47
- });
48
- }
49
- }
50
- };
51
- }
52
- });
53
- var add_assert_import_default = rule;
54
- export {
55
- add_assert_import_default as default,
56
- ruleId
57
- };
58
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FnZW50L2FkZC1hc3NlcnQtaW1wb3J0LnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQVFBLFNBQVMsVUFBVSxjQUFjO0FBRWpDLFNBQVMsZ0JBQWdCLG1CQUFtQjtBQUU1QyxPQUFPLHlCQUF5QjtBQUV6QixJQUFNLFNBQVM7QUFFdEIsSUFBTSwwQkFBMEI7QUFFaEMsSUFBTSxhQUFhLFlBQVksWUFBWSxDQUFDLFNBQVMsb0JBQW9CLElBQUksQ0FBQztBQUU5RSxJQUFNLE9BQWtELFdBQVc7QUFBQSxFQUNqRSxNQUFNO0FBQUEsRUFDTixNQUFNO0FBQUEsSUFDSixNQUFNO0FBQUEsSUFDTixNQUFNO0FBQUEsTUFDSixhQUFhO0FBQUEsSUFDZjtBQUFBLElBQ0EsVUFBVTtBQUFBLE1BQ1IsaUJBQWlCO0FBQUEsSUFDbkI7QUFBQSxJQUNBLFNBQVM7QUFBQSxJQUNULFFBQVEsQ0FBQztBQUFBLEVBQ1g7QUFBQSxFQUNBLGdCQUFnQixDQUFDO0FBQUEsRUFDakIsT0FBTyxTQUFTO0FBQ2QsUUFBSSxtQkFBbUI7QUFDdkIsUUFBSSxlQUFlO0FBRW5CLFdBQU87QUFBQSxNQUNMLG1CQUFtQixDQUFDLFNBQVM7QUFDM0IsWUFBSSxLQUFLLE9BQU8sVUFBVSxZQUFZLEtBQUssT0FBTyxVQUFVLGVBQWU7QUFDekUsNkJBQW1CO0FBQUEsUUFDckI7QUFBQSxNQUNGO0FBQUEsTUFDQSxnQkFBZ0IsQ0FBQyxtQkFBbUI7QUFFbEMsWUFDRyxlQUFlLE9BQU8sU0FBUyxlQUFlLGNBQWMsZUFBZSxPQUFPLFNBQVMsWUFDM0YsZUFBZSxPQUFPLFNBQVMsZUFBZSxvQkFDN0MsZUFBZSxPQUFPLE9BQU8sU0FBUyxlQUFlLGNBQ3JELGVBQWUsT0FBTyxPQUFPLFNBQVMsVUFDeEM7QUFDQSx5QkFBZTtBQUFBLFFBQ2pCO0FBQUEsTUFDRjtBQUFBLE1BQ0EsZ0JBQWdCLENBQUMsWUFBWTtBQUUzQixZQUFJLGdCQUFnQixDQUFDLGtCQUFrQjtBQUNyQyxnQkFBTSxpQkFBaUIsUUFBUSxLQUFLLENBQUM7QUFDckMsaUJBQU8sY0FBYztBQUNyQixrQkFBUSxPQUFPO0FBQUEsWUFDYixNQUFNO0FBQUEsWUFDTixXQUFXO0FBQUEsWUFDWCxJQUFJLE9BQU87QUFDVCxxQkFBTyxNQUFNLGlCQUFpQixnQkFBZ0IsR0FBRyx1QkFBdUI7QUFBQSxDQUFJO0FBQUEsWUFDOUU7QUFBQSxVQUNGLENBQUM7QUFBQSxRQUNIO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQ0YsQ0FBQztBQUVELElBQU8sNEJBQVE7IiwKICAibmFtZXMiOiBbXQp9Cg==
@@ -1,65 +0,0 @@
1
- // src/agent/add-base-path-const.ts
2
- import { strict as assert } from "node:assert";
3
- import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
4
- import getDocumentationUrl from "../get-documentation-url.mjs";
5
- import { getProjectRootFolder, getSwaggerPathByIndexFile, isApiIndexFile, loadPackageJson, loadSwagger } from "./file.mjs";
6
- var ruleId = "add-base-path-const";
7
- var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
8
- var rule = createRule({
9
- name: ruleId,
10
- meta: {
11
- type: "suggestion",
12
- docs: {
13
- description: "Add BASE_PATH const variable."
14
- },
15
- messages: {
16
- addBasePathConst: "Add BASE_PATH const variable."
17
- },
18
- fixable: "code",
19
- schema: []
20
- },
21
- defaultOptions: [],
22
- create(context) {
23
- const sourceCode = context.sourceCode;
24
- return {
25
- Program: (program) => {
26
- if (!isApiIndexFile(context.filename)) {
27
- return;
28
- }
29
- const scope = sourceCode.getScope(program).childScopes[0];
30
- assert(scope);
31
- const foundBasePathConst = scope.variables.find((variable) => variable.name === "BASE_PATH");
32
- if (foundBasePathConst) {
33
- return;
34
- }
35
- const swaggerPath = getSwaggerPathByIndexFile(context.filename);
36
- const swaggerFileContents = loadSwagger(swaggerPath);
37
- const baseUrlLine = swaggerFileContents.split("\n").find((line) => /^\s*-\s*url:\s*\/.*$/u.test(line) || /^basePath:.*/u.test(line));
38
- const baseUrl = baseUrlLine?.split(":")[1]?.trim();
39
- assert(baseUrl !== void 0);
40
- const packageRoot = getProjectRootFolder(context.filename);
41
- const packageJson = JSON.parse(loadPackageJson(packageRoot));
42
- const serviceName = packageJson.name.split("/")[1];
43
- assert(serviceName !== void 0);
44
- const domain = `https://${serviceName}.checkdigit${baseUrl}`;
45
- const lastImportStatement = program.body.findLast((node) => node.type === AST_NODE_TYPES.ImportDeclaration);
46
- assert(lastImportStatement);
47
- context.report({
48
- messageId: "addBasePathConst",
49
- node: program,
50
- fix(fixer) {
51
- return fixer.insertTextAfter(lastImportStatement, `
52
- export const BASE_PATH = '${domain}';
53
- `);
54
- }
55
- });
56
- }
57
- };
58
- }
59
- });
60
- var add_base_path_const_default = rule;
61
- export {
62
- add_base_path_const_default as default,
63
- ruleId
64
- };
65
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FnZW50L2FkZC1iYXNlLXBhdGgtY29uc3QudHMiXSwKICAibWFwcGluZ3MiOiAiO0FBUUEsU0FBUyxVQUFVLGNBQWM7QUFFakMsU0FBUyxnQkFBZ0IsbUJBQTZCO0FBRXRELE9BQU8seUJBQXlCO0FBQ2hDLFNBQVMsc0JBQXNCLDJCQUEyQixnQkFBZ0IsaUJBQWlCLG1CQUFtQjtBQUV2RyxJQUFNLFNBQVM7QUFFdEIsSUFBTSxhQUFhLFlBQVksWUFBWSxDQUFDLFNBQVMsb0JBQW9CLElBQUksQ0FBQztBQUU5RSxJQUFNLE9BQW1ELFdBQVc7QUFBQSxFQUNsRSxNQUFNO0FBQUEsRUFDTixNQUFNO0FBQUEsSUFDSixNQUFNO0FBQUEsSUFDTixNQUFNO0FBQUEsTUFDSixhQUFhO0FBQUEsSUFDZjtBQUFBLElBQ0EsVUFBVTtBQUFBLE1BQ1Isa0JBQWtCO0FBQUEsSUFDcEI7QUFBQSxJQUNBLFNBQVM7QUFBQSxJQUNULFFBQVEsQ0FBQztBQUFBLEVBQ1g7QUFBQSxFQUNBLGdCQUFnQixDQUFDO0FBQUEsRUFDakIsT0FBTyxTQUFTO0FBQ2QsVUFBTSxhQUFhLFFBQVE7QUFFM0IsV0FBTztBQUFBLE1BQ0wsU0FBUyxDQUFDLFlBQThCO0FBQ3RDLFlBQUksQ0FBQyxlQUFlLFFBQVEsUUFBUSxHQUFHO0FBQ3JDO0FBQUEsUUFDRjtBQUVBLGNBQU0sUUFBUSxXQUFXLFNBQVMsT0FBTyxFQUFFLFlBQVksQ0FBQztBQUN4RCxlQUFPLEtBQUs7QUFFWixjQUFNLHFCQUFxQixNQUFNLFVBQVUsS0FBSyxDQUFDLGFBQWEsU0FBUyxTQUFTLFdBQVc7QUFDM0YsWUFBSSxvQkFBb0I7QUFDdEI7QUFBQSxRQUNGO0FBRUEsY0FBTSxjQUFjLDBCQUEwQixRQUFRLFFBQVE7QUFDOUQsY0FBTSxzQkFBc0IsWUFBWSxXQUFXO0FBQ25ELGNBQU0sY0FBYyxvQkFDakIsTUFBTSxJQUFJLEVBQ1YsS0FBSyxDQUFDLFNBQVMsd0JBQXdCLEtBQUssSUFBSSxLQUFLLGdCQUFnQixLQUFLLElBQUksQ0FBQztBQUNsRixjQUFNLFVBQVUsYUFBYSxNQUFNLEdBQUcsRUFBRSxDQUFDLEdBQUcsS0FBSztBQUNqRCxlQUFPLFlBQVksTUFBUztBQUU1QixjQUFNLGNBQWMscUJBQXFCLFFBQVEsUUFBUTtBQUN6RCxjQUFNLGNBQWMsS0FBSyxNQUFNLGdCQUFnQixXQUFXLENBQUM7QUFDM0QsY0FBTSxjQUFjLFlBQVksS0FBSyxNQUFNLEdBQUcsRUFBRSxDQUFDO0FBQ2pELGVBQU8sZ0JBQWdCLE1BQVM7QUFFaEMsY0FBTSxTQUFTLFdBQVcsV0FBVyxjQUFjLE9BQU87QUFFMUQsY0FBTSxzQkFBc0IsUUFBUSxLQUFLLFNBQVMsQ0FBQyxTQUFTLEtBQUssU0FBUyxlQUFlLGlCQUFpQjtBQUMxRyxlQUFPLG1CQUFtQjtBQUUxQixnQkFBUSxPQUFPO0FBQUEsVUFDYixXQUFXO0FBQUEsVUFDWCxNQUFNO0FBQUEsVUFDTixJQUFJLE9BQU87QUFDVCxtQkFBTyxNQUFNLGdCQUFnQixxQkFBcUI7QUFBQSw0QkFBK0IsTUFBTTtBQUFBLENBQU07QUFBQSxVQUMvRjtBQUFBLFFBQ0YsQ0FBQztBQUFBLE1BQ0g7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUNGLENBQUM7QUFFRCxJQUFPLDhCQUFROyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -1,60 +0,0 @@
1
- // src/agent/add-base-path-import.ts
2
- import { strict as assert } from "node:assert";
3
- import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
4
- import getDocumentationUrl from "../get-documentation-url.mjs";
5
- import { getApiIndexPathByFilename } from "./file.mjs";
6
- var ruleId = "add-base-path-import";
7
- var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
8
- var rule = createRule({
9
- name: ruleId,
10
- meta: {
11
- type: "suggestion",
12
- docs: {
13
- description: "Add import of BASE_PATH if it is used but not imported."
14
- },
15
- messages: {
16
- addBasePathImport: "Add import of BASE_PATH."
17
- },
18
- fixable: "code",
19
- schema: []
20
- },
21
- defaultOptions: [],
22
- create(context) {
23
- const sourceCode = context.sourceCode;
24
- return {
25
- Program: (program) => {
26
- const isBasePathUsed = sourceCode.text.includes(`\${BASE_PATH}`);
27
- if (isBasePathUsed) {
28
- const topScope = sourceCode.getScope(program).childScopes[0];
29
- assert(topScope);
30
- if (topScope.variables.some((variable) => variable.name === "BASE_PATH")) {
31
- return;
32
- }
33
- const apiIndexPath = getApiIndexPathByFilename(context.filename);
34
- if (apiIndexPath !== void 0) {
35
- const lastImportStatement = program.body.findLast(
36
- (statement) => statement.type === AST_NODE_TYPES.ImportDeclaration
37
- );
38
- assert(lastImportStatement);
39
- const basePathImportStatement = `
40
- import { BASE_PATH } from '${apiIndexPath}';
41
- `;
42
- context.report({
43
- node: program,
44
- messageId: "addBasePathImport",
45
- fix(fixer) {
46
- return fixer.insertTextAfter(lastImportStatement, basePathImportStatement);
47
- }
48
- });
49
- }
50
- }
51
- }
52
- };
53
- }
54
- });
55
- var add_base_path_import_default = rule;
56
- export {
57
- add_base_path_import_default as default,
58
- ruleId
59
- };
60
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FnZW50L2FkZC1iYXNlLXBhdGgtaW1wb3J0LnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQVFBLFNBQVMsVUFBVSxjQUFjO0FBRWpDLFNBQVMsZ0JBQWdCLG1CQUFtQjtBQUU1QyxPQUFPLHlCQUF5QjtBQUNoQyxTQUFTLGlDQUFpQztBQUVuQyxJQUFNLFNBQVM7QUFFdEIsSUFBTSxhQUFhLFlBQVksWUFBWSxDQUFDLFNBQVMsb0JBQW9CLElBQUksQ0FBQztBQUU5RSxJQUFNLE9BQW9ELFdBQVc7QUFBQSxFQUNuRSxNQUFNO0FBQUEsRUFDTixNQUFNO0FBQUEsSUFDSixNQUFNO0FBQUEsSUFDTixNQUFNO0FBQUEsTUFDSixhQUFhO0FBQUEsSUFDZjtBQUFBLElBQ0EsVUFBVTtBQUFBLE1BQ1IsbUJBQW1CO0FBQUEsSUFDckI7QUFBQSxJQUNBLFNBQVM7QUFBQSxJQUNULFFBQVEsQ0FBQztBQUFBLEVBQ1g7QUFBQSxFQUNBLGdCQUFnQixDQUFDO0FBQUEsRUFDakIsT0FBTyxTQUFTO0FBQ2QsVUFBTSxhQUFhLFFBQVE7QUFFM0IsV0FBTztBQUFBLE1BQ0wsU0FBUyxDQUFDLFlBQVk7QUFDcEIsY0FBTSxpQkFBaUIsV0FBVyxLQUFLLFNBQVMsZUFBZTtBQUMvRCxZQUFJLGdCQUFnQjtBQUNsQixnQkFBTSxXQUFXLFdBQVcsU0FBUyxPQUFPLEVBQUUsWUFBWSxDQUFDO0FBQzNELGlCQUFPLFFBQVE7QUFDZixjQUFJLFNBQVMsVUFBVSxLQUFLLENBQUMsYUFBYSxTQUFTLFNBQVMsV0FBVyxHQUFHO0FBQ3hFO0FBQUEsVUFDRjtBQUVBLGdCQUFNLGVBQWUsMEJBQTBCLFFBQVEsUUFBUTtBQUMvRCxjQUFJLGlCQUFpQixRQUFXO0FBQzlCLGtCQUFNLHNCQUFzQixRQUFRLEtBQUs7QUFBQSxjQUN2QyxDQUFDLGNBQWMsVUFBVSxTQUFTLGVBQWU7QUFBQSxZQUNuRDtBQUNBLG1CQUFPLG1CQUFtQjtBQUUxQixrQkFBTSwwQkFBMEI7QUFBQSw2QkFBZ0MsWUFBWTtBQUFBO0FBQzVFLG9CQUFRLE9BQU87QUFBQSxjQUNiLE1BQU07QUFBQSxjQUNOLFdBQVc7QUFBQSxjQUNYLElBQUksT0FBTztBQUNULHVCQUFPLE1BQU0sZ0JBQWdCLHFCQUFxQix1QkFBdUI7QUFBQSxjQUMzRTtBQUFBLFlBQ0YsQ0FBQztBQUFBLFVBQ0g7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQ0YsQ0FBQztBQUVELElBQU8sK0JBQVE7IiwKICAibmFtZXMiOiBbXQp9Cg==