@redocly/openapi-core 1.0.0-beta.92 → 1.0.0-beta.95

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 (122) hide show
  1. package/__tests__/bundle.test.ts +6 -6
  2. package/__tests__/fixtures/extension.js +1 -1
  3. package/__tests__/login.test.ts +2 -2
  4. package/__tests__/normalizeVisitors.test.ts +1 -1
  5. package/__tests__/ref-utils.test.ts +1 -1
  6. package/__tests__/utils.ts +30 -18
  7. package/__tests__/walk.test.ts +6 -6
  8. package/lib/benchmark/benches/recommended-oas3.bench.js +2 -3
  9. package/lib/benchmark/utils.d.ts +2 -1
  10. package/lib/benchmark/utils.js +10 -7
  11. package/lib/bundle.d.ts +2 -2
  12. package/lib/config/all.d.ts +2 -2
  13. package/lib/config/builtIn.d.ts +1 -1
  14. package/lib/config/config-resolvers.d.ts +16 -0
  15. package/lib/config/config-resolvers.js +213 -0
  16. package/lib/config/config.d.ts +14 -129
  17. package/lib/config/config.js +17 -234
  18. package/lib/config/index.d.ts +7 -0
  19. package/lib/config/index.js +19 -0
  20. package/lib/config/load.d.ts +2 -1
  21. package/lib/config/load.js +20 -13
  22. package/lib/config/minimal.d.ts +2 -2
  23. package/lib/config/recommended.d.ts +2 -2
  24. package/lib/config/types.d.ts +113 -0
  25. package/lib/config/types.js +2 -0
  26. package/lib/config/utils.d.ts +13 -0
  27. package/lib/config/utils.js +160 -0
  28. package/lib/format/format.d.ts +1 -1
  29. package/lib/format/format.js +28 -0
  30. package/lib/index.d.ts +1 -2
  31. package/lib/index.js +5 -6
  32. package/lib/lint.d.ts +1 -1
  33. package/lib/lint.js +5 -7
  34. package/lib/redocly/index.d.ts +1 -1
  35. package/lib/redocly/redocly-client-types.d.ts +1 -1
  36. package/lib/redocly/registry-api.d.ts +1 -1
  37. package/lib/resolve.d.ts +1 -1
  38. package/lib/resolve.js +1 -2
  39. package/lib/rules/common/assertions/utils.d.ts +1 -1
  40. package/lib/rules/common/assertions/utils.js +6 -2
  41. package/lib/types/index.js +2 -2
  42. package/lib/types/oas3_1.js +31 -5
  43. package/lib/utils.d.ts +4 -1
  44. package/lib/utils.js +18 -1
  45. package/package.json +5 -2
  46. package/src/__tests__/lint.test.ts +1 -1
  47. package/src/benchmark/benches/recommended-oas3.bench.ts +2 -3
  48. package/src/benchmark/utils.ts +13 -8
  49. package/src/bundle.ts +2 -1
  50. package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +140 -0
  51. package/src/config/__tests__/config-resolvers.test.ts +398 -0
  52. package/src/config/__tests__/config.test.ts +244 -0
  53. package/src/config/__tests__/fixtures/plugin.js +1 -1
  54. package/src/config/__tests__/fixtures/resolve-config/api/nested-config.yaml +7 -0
  55. package/src/config/__tests__/fixtures/resolve-config/api/plugin.js +67 -0
  56. package/src/config/__tests__/fixtures/resolve-config/local-config-with-circular.yaml +8 -0
  57. package/src/config/__tests__/fixtures/resolve-config/local-config-with-file.yaml +12 -0
  58. package/src/config/__tests__/fixtures/resolve-config/local-config.yaml +10 -0
  59. package/src/config/__tests__/fixtures/resolve-config/plugin.js +66 -0
  60. package/src/config/__tests__/fixtures/resolve-remote-configs/nested-remote-config.yaml +4 -0
  61. package/src/config/__tests__/fixtures/resolve-remote-configs/remote-config.yaml +5 -0
  62. package/src/config/__tests__/load.test.ts +8 -1
  63. package/src/config/all.ts +3 -2
  64. package/src/config/builtIn.ts +2 -1
  65. package/src/config/config-resolvers.ts +304 -0
  66. package/src/config/config.ts +40 -454
  67. package/src/config/index.ts +7 -0
  68. package/src/config/load.ts +37 -31
  69. package/src/config/minimal.ts +2 -2
  70. package/src/config/recommended.ts +2 -2
  71. package/src/config/types.ts +168 -0
  72. package/src/config/utils.ts +208 -0
  73. package/src/decorators/__tests__/remove-x-internal.test.ts +5 -5
  74. package/src/format/format.ts +36 -6
  75. package/src/index.ts +6 -2
  76. package/src/lint.ts +4 -5
  77. package/src/redocly/__tests__/redocly-client.test.ts +7 -0
  78. package/src/redocly/index.ts +3 -1
  79. package/src/redocly/redocly-client-types.ts +1 -1
  80. package/src/redocly/registry-api.ts +3 -1
  81. package/src/resolve.ts +2 -4
  82. package/src/rules/__tests__/no-unresolved-refs.test.ts +4 -4
  83. package/src/rules/common/__tests__/info-description.test.ts +3 -3
  84. package/src/rules/common/__tests__/info-license.test.ts +2 -2
  85. package/src/rules/common/__tests__/license-url.test.ts +2 -2
  86. package/src/rules/common/__tests__/no-ambiguous-paths.test.ts +1 -1
  87. package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +5 -5
  88. package/src/rules/common/__tests__/no-identical-paths.test.ts +1 -1
  89. package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +3 -3
  90. package/src/rules/common/__tests__/operation-2xx-response.test.ts +3 -3
  91. package/src/rules/common/__tests__/operation-4xx-response.test.ts +3 -3
  92. package/src/rules/common/__tests__/operation-operationId-unique.test.ts +2 -2
  93. package/src/rules/common/__tests__/operation-operationId-url-safe.test.ts +1 -1
  94. package/src/rules/common/__tests__/operation-parameters-unique.test.ts +4 -4
  95. package/src/rules/common/__tests__/operation-security-defined.test.ts +2 -2
  96. package/src/rules/common/__tests__/operation-singular-tag.test.ts +2 -2
  97. package/src/rules/common/__tests__/path-http-verbs-order.test.ts +2 -2
  98. package/src/rules/common/__tests__/path-not-include-query.test.ts +2 -2
  99. package/src/rules/common/__tests__/path-params-defined.test.ts +3 -3
  100. package/src/rules/common/__tests__/paths-kebab-case.test.ts +3 -3
  101. package/src/rules/common/__tests__/spec.test.ts +1 -1
  102. package/src/rules/common/__tests__/tag-description.test.ts +2 -2
  103. package/src/rules/common/__tests__/tags-alphabetical.test.ts +2 -2
  104. package/src/rules/common/assertions/utils.ts +5 -2
  105. package/src/rules/oas2/__tests__/boolean-parameter-prefixes.test.ts +3 -3
  106. package/src/rules/oas2/__tests__/spec/referenceableScalars.test.ts +1 -1
  107. package/src/rules/oas2/__tests__/spec/utils.ts +10 -7
  108. package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +3 -3
  109. package/src/rules/oas3/__tests__/no-empty-enum-servers.com.test.ts +6 -6
  110. package/src/rules/oas3/__tests__/no-example-value-and-externalValue.test.ts +2 -2
  111. package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +8 -8
  112. package/src/rules/oas3/__tests__/no-server-example.com.test.ts +2 -2
  113. package/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts +3 -3
  114. package/src/rules/oas3/__tests__/no-unused-components.test.ts +1 -1
  115. package/src/rules/oas3/__tests__/spec/referenceableScalars.test.ts +23 -14
  116. package/src/rules/oas3/__tests__/spec/servers.test.ts +1 -1
  117. package/src/rules/oas3/__tests__/spec/spec.test.ts +4 -4
  118. package/src/rules/oas3/__tests__/spec/utils.ts +10 -7
  119. package/src/types/index.ts +2 -2
  120. package/src/types/oas3_1.ts +32 -7
  121. package/src/utils.ts +18 -2
  122. package/tsconfig.tsbuildinfo +1 -1
@@ -33,7 +33,7 @@ describe('no-invalid-media-type-examples', () => {
33
33
  const results = await lintDocument({
34
34
  externalRefResolver: new BaseResolver(),
35
35
  document,
36
- config: makeConfig({ 'no-invalid-media-type-examples': 'error' }),
36
+ config: await makeConfig({ 'no-invalid-media-type-examples': 'error' }),
37
37
  });
38
38
 
39
39
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
@@ -106,7 +106,7 @@ describe('no-invalid-media-type-examples', () => {
106
106
  const results = await lintDocument({
107
107
  externalRefResolver: new BaseResolver(),
108
108
  document,
109
- config: makeConfig({
109
+ config: await makeConfig({
110
110
  'no-invalid-media-type-examples': {
111
111
  severity: 'error',
112
112
  disallowAdditionalProperties: true,
@@ -166,7 +166,7 @@ describe('no-invalid-media-type-examples', () => {
166
166
  const results = await lintDocument({
167
167
  externalRefResolver: new BaseResolver(),
168
168
  document,
169
- config: makeConfig({
169
+ config: await makeConfig({
170
170
  'no-invalid-media-type-examples': {
171
171
  severity: 'error',
172
172
  disallowAdditionalProperties: true,
@@ -216,7 +216,7 @@ describe('no-invalid-media-type-examples', () => {
216
216
  const results = await lintDocument({
217
217
  externalRefResolver: new BaseResolver(),
218
218
  document,
219
- config: makeConfig({
219
+ config: await makeConfig({
220
220
  'no-invalid-media-type-examples': {
221
221
  severity: 'error',
222
222
  disallowAdditionalProperties: true,
@@ -269,7 +269,7 @@ describe('no-invalid-media-type-examples', () => {
269
269
  const results = await lintDocument({
270
270
  externalRefResolver: new BaseResolver(),
271
271
  document,
272
- config: makeConfig({ 'no-invalid-media-type-examples': 'error' }),
272
+ config: await makeConfig({ 'no-invalid-media-type-examples': 'error' }),
273
273
  });
274
274
 
275
275
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
@@ -301,7 +301,7 @@ describe('no-invalid-media-type-examples', () => {
301
301
  const results = await lintDocument({
302
302
  externalRefResolver: new BaseResolver(),
303
303
  document,
304
- config: makeConfig({ 'no-invalid-media-type-examples': 'error' }),
304
+ config: await makeConfig({ 'no-invalid-media-type-examples': 'error' }),
305
305
  });
306
306
 
307
307
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
@@ -336,7 +336,7 @@ describe('no-invalid-media-type-examples', () => {
336
336
  const results = await lintDocument({
337
337
  externalRefResolver: new BaseResolver(),
338
338
  document,
339
- config: makeConfig({ 'no-invalid-media-type-examples': 'error' }),
339
+ config: await makeConfig({ 'no-invalid-media-type-examples': 'error' }),
340
340
  });
341
341
 
342
342
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
@@ -364,7 +364,7 @@ describe('no-invalid-media-type-examples', () => {
364
364
  const results = await lintDocument({
365
365
  externalRefResolver: new BaseResolver(),
366
366
  document,
367
- config: makeConfig({ 'no-invalid-media-type-examples': 'error' }),
367
+ config: await makeConfig({ 'no-invalid-media-type-examples': 'error' }),
368
368
  });
369
369
 
370
370
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
@@ -17,7 +17,7 @@ describe('Oas3 oas3-no-server-example.com', () => {
17
17
  const results = await lintDocument({
18
18
  externalRefResolver: new BaseResolver(),
19
19
  document,
20
- config: makeConfig({ 'no-server-example.com': 'error' }),
20
+ config: await makeConfig({ 'no-server-example.com': 'error' }),
21
21
  });
22
22
 
23
23
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
@@ -52,7 +52,7 @@ describe('Oas3 oas3-no-server-example.com', () => {
52
52
  const results = await lintDocument({
53
53
  externalRefResolver: new BaseResolver(),
54
54
  document,
55
- config: makeConfig({ 'no-server-example.com': 'error' }),
55
+ config: await makeConfig({ 'no-server-example.com': 'error' }),
56
56
  });
57
57
 
58
58
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
@@ -17,7 +17,7 @@ describe('Oas3 oas3-no-server-trailing-slash', () => {
17
17
  const results = await lintDocument({
18
18
  externalRefResolver: new BaseResolver(),
19
19
  document,
20
- config: makeConfig({ 'no-server-trailing-slash': 'error' }),
20
+ config: await makeConfig({ 'no-server-trailing-slash': 'error' }),
21
21
  });
22
22
 
23
23
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
@@ -52,7 +52,7 @@ describe('Oas3 oas3-no-server-trailing-slash', () => {
52
52
  const results = await lintDocument({
53
53
  externalRefResolver: new BaseResolver(),
54
54
  document,
55
- config: makeConfig({ 'no-server-trailing-slash': 'error' }),
55
+ config: await makeConfig({ 'no-server-trailing-slash': 'error' }),
56
56
  });
57
57
 
58
58
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
@@ -71,7 +71,7 @@ describe('Oas3 oas3-no-server-trailing-slash', () => {
71
71
  const results = await lintDocument({
72
72
  externalRefResolver: new BaseResolver(),
73
73
  document,
74
- config: makeConfig({ 'no-server-trailing-slash': 'error' }),
74
+ config: await makeConfig({ 'no-server-trailing-slash': 'error' }),
75
75
  });
76
76
 
77
77
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
@@ -42,7 +42,7 @@ describe('Oas3 no-unused-components', () => {
42
42
  const results = await lintDocument({
43
43
  externalRefResolver: new BaseResolver(),
44
44
  document,
45
- config: makeConfig({ 'no-unused-components': 'error' }),
45
+ config: await makeConfig({ 'no-unused-components': 'error' }),
46
46
  });
47
47
 
48
48
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
@@ -3,6 +3,7 @@ import { parseYamlToDocument, replaceSourceWithRef } from '../../../../../__test
3
3
  import { lintDocument } from '../../../../lint';
4
4
  import { LintConfig } from '../../../..';
5
5
  import { BaseResolver } from '../../../../resolve';
6
+ import { resolveLint } from '../../../../config';
6
7
 
7
8
  describe('Referenceable scalars', () => {
8
9
  it('should not report $ref description', async () => {
@@ -22,13 +23,17 @@ describe('Referenceable scalars', () => {
22
23
  const results = await lintDocument({
23
24
  externalRefResolver: new BaseResolver(),
24
25
  document,
25
- config: new LintConfig({
26
- extends: [],
27
- rules: {
28
- spec: 'error',
29
- 'no-unresolved-refs': 'error',
30
- },
31
- }),
26
+ config: new LintConfig(
27
+ await resolveLint({
28
+ lintConfig: {
29
+ extends: [],
30
+ rules: {
31
+ spec: 'error',
32
+ 'no-unresolved-refs': 'error',
33
+ },
34
+ },
35
+ }),
36
+ ),
32
37
  });
33
38
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
34
39
  });
@@ -55,13 +60,17 @@ describe('Referenceable scalars', () => {
55
60
  const results = await lintDocument({
56
61
  externalRefResolver: new BaseResolver(),
57
62
  document,
58
- config: new LintConfig({
59
- extends: [],
60
- rules: {
61
- 'no-unresolved-refs': 'error',
62
- },
63
- doNotResolveExamples: true,
64
- }),
63
+ config: new LintConfig(
64
+ await resolveLint({
65
+ lintConfig: {
66
+ extends: [],
67
+ rules: {
68
+ 'no-unresolved-refs': 'error',
69
+ },
70
+ doNotResolveExamples: true,
71
+ },
72
+ }),
73
+ ),
65
74
  });
66
75
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
67
76
  });
@@ -176,7 +176,7 @@ describe('OpenAPI Schema', () => {
176
176
  Array [
177
177
  Object {
178
178
  "location": "#/servers",
179
- "message": "Expected type \`Server_List\` (array) but got \`object\`",
179
+ "message": "Expected type \`ServerList\` (array) but got \`object\`",
180
180
  },
181
181
  ]
182
182
  `);
@@ -1,13 +1,13 @@
1
1
  import { outdent } from 'outdent';
2
2
  import { lintDocument } from '../../../../lint';
3
3
  import { parseYamlToDocument, replaceSourceWithRef } from '../../../../../__tests__/utils';
4
- import { LintConfig } from '../../../../config/config';
5
- import { defaultPlugin } from '../../../../config/builtIn';
4
+ import { LintConfig, defaultPlugin, resolvePlugins, resolvePreset } from '../../../../config';
6
5
 
7
6
  import { BaseResolver } from '../../../../resolve';
8
7
 
9
- const allConfig = new LintConfig({ plugins: [defaultPlugin], extends: ['all'] });
10
-
8
+ const plugins = resolvePlugins([defaultPlugin]);
9
+ const pressets = resolvePreset('all', plugins);
10
+ const allConfig = new LintConfig({ ...pressets, plugins });
11
11
  describe('Oas3 Structural visitor basic', () => {
12
12
  it('should report wrong types', async () => {
13
13
  const document = parseYamlToDocument(
@@ -1,8 +1,7 @@
1
- import { LintConfig, RuleConfig } from '../../../../config/config';
1
+ import { LintConfig, RuleConfig, resolveLint } from '../../../../config';
2
2
  import { parseYamlToDocument } from '../../../../../__tests__/utils';
3
3
  import { lintDocument } from '../../../../lint';
4
4
  import { BaseResolver } from '../../../../resolve';
5
- import { defaultPlugin } from '../../../../config/builtIn';
6
5
 
7
6
  export async function validateDoc(
8
7
  source: string,
@@ -13,11 +12,15 @@ export async function validateDoc(
13
12
  const results = await lintDocument({
14
13
  externalRefResolver: new BaseResolver(),
15
14
  document,
16
- config: new LintConfig({
17
- plugins: [defaultPlugin],
18
- extends: [],
19
- rules,
20
- }),
15
+ config: new LintConfig(
16
+ await resolveLint({
17
+ lintConfig: {
18
+ plugins: [],
19
+ extends: [],
20
+ rules,
21
+ },
22
+ }),
23
+ ),
21
24
  });
22
25
 
23
26
  return results.map((res) => {
@@ -49,7 +49,7 @@ type NormalizedResolveTypeFn = (
49
49
 
50
50
  export function listOf(typeName: string) {
51
51
  return {
52
- name: typeName + '_List',
52
+ name: `${typeName}List`,
53
53
  properties: {},
54
54
  items: typeName,
55
55
  };
@@ -57,7 +57,7 @@ export function listOf(typeName: string) {
57
57
 
58
58
  export function mapOf(typeName: string) {
59
59
  return {
60
- name: typeName + '_Map',
60
+ name: `${typeName}Map`,
61
61
  properties: {},
62
62
  additionalProperties: () => typeName,
63
63
  };
@@ -1,5 +1,5 @@
1
1
  import { NodeType, listOf, mapOf } from '.';
2
- import { Oas3Types } from './oas3'
2
+ import { Oas3Types } from './oas3';
3
3
 
4
4
  const DefinitionRoot: NodeType = {
5
5
  properties: {
@@ -15,7 +15,7 @@ const DefinitionRoot: NodeType = {
15
15
  jsonSchemaDialect: { type: 'string' },
16
16
  },
17
17
  required: ['openapi', 'info'],
18
- requiredOneOf: ['paths', 'components', 'webhooks']
18
+ requiredOneOf: ['paths', 'components', 'webhooks'],
19
19
  };
20
20
 
21
21
  const License: NodeType = {
@@ -106,11 +106,14 @@ const Schema: NodeType = {
106
106
  enum: { type: 'array' },
107
107
  type: (value: any) => {
108
108
  if (Array.isArray(value)) {
109
- return { type: 'array', items: { enum: ['object', 'array', 'string', 'number', 'integer', 'boolean', 'null'] } }
109
+ return {
110
+ type: 'array',
111
+ items: { enum: ['object', 'array', 'string', 'number', 'integer', 'boolean', 'null'] },
112
+ };
110
113
  } else {
111
114
  return {
112
115
  enum: ['object', 'array', 'string', 'number', 'integer', 'boolean', 'null'],
113
- }
116
+ };
114
117
  }
115
118
  },
116
119
  allOf: listOf('Schema'),
@@ -126,7 +129,13 @@ const Schema: NodeType = {
126
129
  patternProperties: { type: 'object' },
127
130
  propertyNames: 'Schema',
128
131
  unevaluatedItems: 'Schema',
129
- unevaluatedProperties: 'Schema',
132
+ unevaluatedProperties: (value: unknown) => {
133
+ if (typeof value === 'boolean') {
134
+ return { type: 'boolean' };
135
+ } else {
136
+ return 'Schema';
137
+ }
138
+ },
130
139
  summary: { type: 'string' },
131
140
  properties: 'SchemaProperties',
132
141
  items: (value: any) => {
@@ -196,9 +205,25 @@ const SecurityScheme: NodeType = {
196
205
  case 'clientCredentials':
197
206
  return ['type', 'flows', 'tokenUrl', 'refreshUrl', 'description', 'scopes'];
198
207
  case 'authorizationCode':
199
- return ['type', 'flows', 'authorizationUrl', 'refreshUrl', 'tokenUrl', 'description', 'scopes'];
208
+ return [
209
+ 'type',
210
+ 'flows',
211
+ 'authorizationUrl',
212
+ 'refreshUrl',
213
+ 'tokenUrl',
214
+ 'description',
215
+ 'scopes',
216
+ ];
200
217
  default:
201
- return ['type', 'flows', 'authorizationUrl', 'refreshUrl', 'tokenUrl', 'description', 'scopes'];
218
+ return [
219
+ 'type',
220
+ 'flows',
221
+ 'authorizationUrl',
222
+ 'refreshUrl',
223
+ 'tokenUrl',
224
+ 'description',
225
+ 'scopes',
226
+ ];
202
227
  }
203
228
  case 'openIdConnect':
204
229
  return ['type', 'openIdConnectUrl', 'description'];
package/src/utils.ts CHANGED
@@ -2,10 +2,9 @@ import * as fs from 'fs';
2
2
  import * as minimatch from 'minimatch';
3
3
  import fetch from 'node-fetch';
4
4
  import * as pluralize from 'pluralize';
5
-
6
5
  import { parseYaml } from './js-yaml';
7
- import { HttpResolveConfig } from './config/config';
8
6
  import { UserContext } from './walk';
7
+ import type { HttpResolveConfig } from './config';
9
8
 
10
9
  export { parseYaml, stringifyYaml } from './js-yaml';
11
10
 
@@ -171,3 +170,20 @@ export function isPathParameter(pathSegment: string) {
171
170
  export function isNotEmptyObject(obj: any) {
172
171
  return !!obj && Object.keys(obj).length > 0;
173
172
  }
173
+
174
+ // TODO: use it everywhere
175
+ export function isString(value: unknown): value is string {
176
+ return typeof value === 'string';
177
+ }
178
+
179
+ export function isNotString<T>(value: string | T): value is T {
180
+ return !isString(value);
181
+ }
182
+
183
+ export function assignExisting<T>(target: Record<string, T>, obj: Record<string, T>) {
184
+ for (let k of Object.keys(obj)) {
185
+ if (target.hasOwnProperty(k)) {
186
+ target[k] = obj[k];
187
+ }
188
+ }
189
+ }