@ankhorage/data-sources 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +6 -41
  3. package/dist/ankh.provider.js +1 -1
  4. package/dist/ankh.provider.js.map +1 -1
  5. package/dist/discovery/http.d.ts +10 -0
  6. package/dist/discovery/http.d.ts.map +1 -0
  7. package/dist/discovery/http.js +35 -0
  8. package/dist/discovery/http.js.map +1 -0
  9. package/dist/discovery/index.d.ts +9 -9
  10. package/dist/discovery/index.d.ts.map +1 -1
  11. package/dist/discovery/index.js +27 -55
  12. package/dist/discovery/index.js.map +1 -1
  13. package/dist/graphql/index.d.ts +8 -76
  14. package/dist/graphql/index.d.ts.map +1 -1
  15. package/dist/graphql/index.js +17 -197
  16. package/dist/graphql/index.js.map +1 -1
  17. package/dist/graphql/introspection.d.ts +5 -0
  18. package/dist/graphql/introspection.d.ts.map +1 -0
  19. package/dist/graphql/introspection.js +136 -0
  20. package/dist/graphql/introspection.js.map +1 -0
  21. package/dist/graphql/operation.d.ts +5 -0
  22. package/dist/graphql/operation.d.ts.map +1 -0
  23. package/dist/graphql/operation.js +39 -0
  24. package/dist/graphql/operation.js.map +1 -0
  25. package/dist/graphql/types.d.ts +71 -0
  26. package/dist/graphql/types.d.ts.map +1 -0
  27. package/dist/graphql/types.js +2 -0
  28. package/dist/graphql/types.js.map +1 -0
  29. package/dist/index.d.ts +1 -17
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +1 -34
  32. package/dist/index.js.map +1 -1
  33. package/dist/openapi/endpoints.d.ts +5 -0
  34. package/dist/openapi/endpoints.d.ts.map +1 -0
  35. package/dist/openapi/endpoints.js +77 -0
  36. package/dist/openapi/endpoints.js.map +1 -0
  37. package/dist/openapi/index.d.ts +7 -87
  38. package/dist/openapi/index.d.ts.map +1 -1
  39. package/dist/openapi/index.js +8 -267
  40. package/dist/openapi/index.js.map +1 -1
  41. package/dist/openapi/operation.d.ts +5 -0
  42. package/dist/openapi/operation.d.ts.map +1 -0
  43. package/dist/openapi/operation.js +141 -0
  44. package/dist/openapi/operation.js.map +1 -0
  45. package/dist/openapi/schema.d.ts +5 -0
  46. package/dist/openapi/schema.d.ts.map +1 -0
  47. package/dist/openapi/schema.js +84 -0
  48. package/dist/openapi/schema.js.map +1 -0
  49. package/dist/openapi/types.d.ts +82 -0
  50. package/dist/openapi/types.d.ts.map +1 -0
  51. package/dist/openapi/types.js +2 -0
  52. package/dist/openapi/types.js.map +1 -0
  53. package/dist/packageInfo.d.ts +18 -0
  54. package/dist/packageInfo.d.ts.map +1 -0
  55. package/dist/packageInfo.js +30 -0
  56. package/dist/packageInfo.js.map +1 -0
  57. package/dist/rest/index.d.ts +5 -5
  58. package/dist/rest/index.d.ts.map +1 -1
  59. package/dist/rest/index.js +49 -48
  60. package/dist/rest/index.js.map +1 -1
  61. package/dist/test-runner/index.d.ts +2 -57
  62. package/dist/test-runner/index.d.ts.map +1 -1
  63. package/dist/test-runner/index.js +58 -160
  64. package/dist/test-runner/index.js.map +1 -1
  65. package/dist/test-runner/response.d.ts +3 -0
  66. package/dist/test-runner/response.d.ts.map +1 -0
  67. package/dist/test-runner/response.js +29 -0
  68. package/dist/test-runner/response.js.map +1 -0
  69. package/dist/test-runner/result.d.ts +6 -0
  70. package/dist/test-runner/result.d.ts.map +1 -0
  71. package/dist/test-runner/result.js +17 -0
  72. package/dist/test-runner/result.js.map +1 -0
  73. package/dist/test-runner/serialization.d.ts +12 -0
  74. package/dist/test-runner/serialization.d.ts.map +1 -0
  75. package/dist/test-runner/serialization.js +99 -0
  76. package/dist/test-runner/serialization.js.map +1 -0
  77. package/dist/test-runner/types.d.ts +58 -0
  78. package/dist/test-runner/types.d.ts.map +1 -0
  79. package/dist/test-runner/types.js +2 -0
  80. package/dist/test-runner/types.js.map +1 -0
  81. package/package.json +5 -5
  82. package/src/ankh.provider.ts +1 -1
  83. package/src/api-phase1.contract.test.ts +24 -0
  84. package/src/discovery/http.ts +38 -0
  85. package/src/discovery/index.test.ts +76 -75
  86. package/src/discovery/index.ts +49 -72
  87. package/src/graphql/index.test.ts +10 -11
  88. package/src/graphql/index.ts +35 -315
  89. package/src/graphql/introspection.ts +163 -0
  90. package/src/graphql/operation.ts +60 -0
  91. package/src/graphql/types.ts +79 -0
  92. package/src/index.test.ts +21 -13
  93. package/src/index.ts +1 -54
  94. package/src/openapi/endpoints.ts +124 -0
  95. package/src/openapi/index.test.ts +47 -47
  96. package/src/openapi/index.ts +12 -467
  97. package/src/openapi/operation.ts +231 -0
  98. package/src/openapi/schema.ts +127 -0
  99. package/src/openapi/types.ts +93 -0
  100. package/src/packageInfo.ts +50 -0
  101. package/src/rest/index.test.ts +17 -14
  102. package/src/rest/index.ts +67 -61
  103. package/src/test-runner/index.test.ts +153 -120
  104. package/src/test-runner/index.ts +97 -299
  105. package/src/test-runner/response.ts +32 -0
  106. package/src/test-runner/result.ts +35 -0
  107. package/src/test-runner/serialization.ts +151 -0
  108. package/src/test-runner/types.ts +81 -0
  109. package/dist/generated-api/index.d.ts +0 -10
  110. package/dist/generated-api/index.d.ts.map +0 -1
  111. package/dist/generated-api/index.js +0 -274
  112. package/dist/generated-api/index.js.map +0 -1
  113. package/dist/generated-api/validateGeneratedApiCollection.d.ts +0 -3
  114. package/dist/generated-api/validateGeneratedApiCollection.d.ts.map +0 -1
  115. package/dist/generated-api/validateGeneratedApiCollection.js +0 -35
  116. package/dist/generated-api/validateGeneratedApiCollection.js.map +0 -1
  117. package/src/generated-api/index.test.ts +0 -173
  118. package/src/generated-api/index.ts +0 -414
  119. package/src/generated-api/validateGeneratedApiCollection.test.ts +0 -91
  120. package/src/generated-api/validateGeneratedApiCollection.ts +0 -76
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @ankhorage/data-sources
2
2
 
3
+ ## 2.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 5be6ff8: Consume canonical Contracts v8 API definitions directly, execute external REST and GraphQL APIs without database projection, and remove the generated-API data-source surface.
8
+
3
9
  ## 1.0.1
4
10
 
5
11
  ### Patch Changes
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # @ankhorage/data-sources
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v0.6.0](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v1.0.1](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
7
7
 
8
8
  Provider-neutral data source and endpoint system for APIs, databases, and runtime bindings.
9
9
 
@@ -15,46 +15,11 @@ Provider-neutral data source and endpoint system for APIs, databases, and runtim
15
15
  - [Architecture overview](././paradox/diagrams/architecture-overview.mmd)
16
16
  - [Module relationships](././paradox/diagrams/module-relationships.mmd)
17
17
  - [Export graph](././paradox/diagrams/export-graph.mmd)
18
- - [createGeneratedApiResourceSchema sequence](././paradox/diagrams/sequences/create-generated-api-resource-schema.mmd)
19
- - [createManualRestDataSource sequence](././paradox/diagrams/sequences/create-manual-rest-data-source.mmd)
18
+ - [createGraphQlApi sequence](././paradox/diagrams/sequences/create-graph-ql-api.mmd)
19
+ - [createManualRestApi sequence](././paradox/diagrams/sequences/create-manual-rest-api.mmd)
20
20
  - [createOpenApiDiscoveryCandidates sequence](././paradox/diagrams/sequences/create-open-api-discovery-candidates.mmd)
21
+ - [importOpenApiDocument sequence](././paradox/diagrams/sequences/import-open-api-document.mmd)
22
+ - [normalizeGraphQlApi sequence](././paradox/diagrams/sequences/normalize-graph-ql-api.mmd)
21
23
  - [normalizeGraphQlIntrospectionOperations sequence](././paradox/diagrams/sequences/normalize-graph-ql-introspection-operations.mmd)
22
- - [normalizeGraphQlIntrospectionSchemas sequence](././paradox/diagrams/sequences/normalize-graph-ql-introspection-schemas.mmd)
23
- - [normalizeManualRestDataSource sequence](././paradox/diagrams/sequences/normalize-manual-rest-data-source.mmd)
24
24
  - [normalizeOpenApiSchema sequence](././paradox/diagrams/sequences/normalize-open-api-schema.mmd)
25
- - [validateGeneratedApiDefinition sequence](././paradox/diagrams/sequences/validate-generated-api-definition.mmd)
26
- - [validateManualRestDataSource sequence](././paradox/diagrams/sequences/validate-manual-rest-data-source.mmd)
27
-
28
- ## Architecture preview
29
-
30
- <details>
31
- <summary>Architecture overview</summary>
32
-
33
- ```mermaid
34
- graph TD
35
- package__ankhorage_data_sources["@ankhorage/data-sources"]
36
- entrypoint_src_index_ts["src/index.ts"]
37
- package__ankhorage_data_sources --> entrypoint_src_index_ts
38
- module_src_ankh_provider_ts["src/ankh.provider.ts"]
39
- package__ankhorage_data_sources -.-> module_src_ankh_provider_ts
40
- module_src_ankh_provider_ts --> module_src_index_ts
41
- module_src_cli_index_ts["src/cli/index.ts"]
42
- package__ankhorage_data_sources -.-> module_src_cli_index_ts
43
- module_src_discovery_index_ts["src/discovery/index.ts"]
44
- package__ankhorage_data_sources -.-> module_src_discovery_index_ts
45
- module_src_discovery_index_ts --> module_src_graphql_index_ts
46
- module_src_discovery_index_ts --> module_src_openapi_index_ts
47
- module_src_generated_api_index_ts["src/generated-api/index.ts"]
48
- package__ankhorage_data_sources -.-> module_src_generated_api_index_ts
49
- module_src_graphql_index_ts["src/graphql/index.ts"]
50
- package__ankhorage_data_sources -.-> module_src_graphql_index_ts
51
- module_src_index_ts["src/index.ts"]
52
- module_src_openapi_index_ts["src/openapi/index.ts"]
53
- package__ankhorage_data_sources -.-> module_src_openapi_index_ts
54
- module_src_rest_index_ts["src/rest/index.ts"]
55
- package__ankhorage_data_sources -.-> module_src_rest_index_ts
56
- module_src_test_runner_index_ts["src/test-runner/index.ts"]
57
- package__ankhorage_data_sources -.-> module_src_test_runner_index_ts
58
- ```
59
-
60
- </details>
25
+ - [validateManualRestApi sequence](././paradox/diagrams/sequences/validate-manual-rest-api.mmd)
@@ -1,4 +1,4 @@
1
- import { DATA_SOURCES_PACKAGE_NAME, SUPPORTED_DATA_SOURCE_KINDS } from './index';
1
+ import { DATA_SOURCES_PACKAGE_NAME, SUPPORTED_DATA_SOURCE_KINDS } from './packageInfo';
2
2
  const DATA_SOURCES_PACKAGE_VERSION = '0.5.1';
3
3
  const DATA_SOURCES_COMMAND_CATEGORY = 'data-sources';
4
4
  const DATA_SOURCES_CAPABILITIES = [
@@ -1 +1 @@
1
- {"version":3,"file":"ankh.provider.js","sourceRoot":"","sources":["../src/ankh.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAEjF,MAAM,4BAA4B,GAAG,OAAO,CAAC;AAC7C,MAAM,6BAA6B,GAAG,cAAc,CAAC;AAErD,MAAM,yBAAyB,GAAG;IAChC,sBAAsB;IACtB,uBAAuB;IACvB,mBAAmB;IACnB,wBAAwB;CAChB,CAAC;AAEX,MAAM,QAAQ,GAAG;IACf;QACE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;QACtB,OAAO,EAAE,mCAAmC;QAC5C,UAAU,EAAE,sBAAsB;QAClC,OAAO,EAAE,CAAC,OAAO,CAAC;QAClB,QAAQ,EAAE,CAAC,6BAA6B,CAAC;KAC1C;IACD;QACE,IAAI,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC;QAC5B,OAAO,EAAE,8DAA8D;QACvE,UAAU,EAAE,uBAAuB;QACnC,QAAQ,EAAE,CAAC,sDAAsD,CAAC;KACnE;IACD;QACE,IAAI,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC;QAC1B,OAAO,EAAE,uDAAuD;QAChE,UAAU,EAAE,mBAAmB;QAC/B,QAAQ,EAAE,CAAC,6DAA6D,CAAC;KAC1E;IACD;QACE,IAAI,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC;QAC7B,OAAO,EAAE,+CAA+C;QACxD,UAAU,EAAE,wBAAwB;QACpC,QAAQ,EAAE,CAAC,mDAAmD,CAAC;KAChE;CACO,CAAC;AAEX,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC1C,IAAI,EAAE,OAAO,CAAC,IAAI;IAClB,OAAO,CAAC,OAIP;QACC,MAAM,cAAc,GAAG,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9D,OAAO,CAAC,OAAO,CAAC,WAAW,CACzB,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,mBAAmB,yBAAyB,IAAI;YACvE,oBAAoB,cAAc,KAAK,CAC1C,CAAC;QACF,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;CACF,CAAC,CAAC,CAAC;AAEJ,MAAM,QAAQ,GAAG;IACf,EAAE,EAAE,yBAAyB;IAC7B,QAAQ,EAAE,6BAA6B;IACvC,OAAO,EAAE,4BAA4B;IACrC,YAAY,EAAE,yBAAyB;IACvC,QAAQ;IACR,QAAQ;CACT,CAAC;AAEF,eAAe,QAAQ,CAAC","sourcesContent":["import { DATA_SOURCES_PACKAGE_NAME, SUPPORTED_DATA_SOURCE_KINDS } from './index';\n\nconst DATA_SOURCES_PACKAGE_VERSION = '0.5.1';\nconst DATA_SOURCES_COMMAND_CATEGORY = 'data-sources';\n\nconst DATA_SOURCES_CAPABILITIES = [\n 'data-sources.inspect',\n 'data-sources.validate',\n 'data-sources.test',\n 'data-sources.normalize',\n] as const;\n\nconst commands = [\n {\n path: ['kind', 'list'],\n summary: 'List supported data-source kinds.',\n capability: 'data-sources.inspect',\n aliases: ['kinds'],\n examples: ['ankh data-sources kind list'],\n },\n {\n path: ['config', 'validate'],\n summary: 'Validate a data-source config with the data-sources package.',\n capability: 'data-sources.validate',\n examples: ['ankh data-sources config validate ./data-source.json'],\n },\n {\n path: ['endpoint', 'test'],\n summary: 'Build or execute a data-source endpoint test request.',\n capability: 'data-sources.test',\n examples: ['ankh data-sources endpoint test orders listOrders --dry-run'],\n },\n {\n path: ['config', 'normalize'],\n summary: 'Normalize imported data-source config output.',\n capability: 'data-sources.normalize',\n examples: ['ankh data-sources config normalize ./openapi.json'],\n },\n] as const;\n\nconst handlers = commands.map((command) => ({\n path: command.path,\n handler(request: {\n readonly context: {\n writeStdout(text: string): void;\n };\n }) {\n const supportedKinds = SUPPORTED_DATA_SOURCE_KINDS.join(', ');\n request.context.writeStdout(\n `${command.path.join(' ')} is provided by ${DATA_SOURCES_PACKAGE_NAME}. ` +\n `Supported kinds: ${supportedKinds}.\\n`,\n );\n return { exitCode: 0 };\n },\n}));\n\nconst provider = {\n id: DATA_SOURCES_PACKAGE_NAME,\n category: DATA_SOURCES_COMMAND_CATEGORY,\n version: DATA_SOURCES_PACKAGE_VERSION,\n capabilities: DATA_SOURCES_CAPABILITIES,\n commands,\n handlers,\n};\n\nexport default provider;\n"]}
1
+ {"version":3,"file":"ankh.provider.js","sourceRoot":"","sources":["../src/ankh.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAEvF,MAAM,4BAA4B,GAAG,OAAO,CAAC;AAC7C,MAAM,6BAA6B,GAAG,cAAc,CAAC;AAErD,MAAM,yBAAyB,GAAG;IAChC,sBAAsB;IACtB,uBAAuB;IACvB,mBAAmB;IACnB,wBAAwB;CAChB,CAAC;AAEX,MAAM,QAAQ,GAAG;IACf;QACE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;QACtB,OAAO,EAAE,mCAAmC;QAC5C,UAAU,EAAE,sBAAsB;QAClC,OAAO,EAAE,CAAC,OAAO,CAAC;QAClB,QAAQ,EAAE,CAAC,6BAA6B,CAAC;KAC1C;IACD;QACE,IAAI,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC;QAC5B,OAAO,EAAE,8DAA8D;QACvE,UAAU,EAAE,uBAAuB;QACnC,QAAQ,EAAE,CAAC,sDAAsD,CAAC;KACnE;IACD;QACE,IAAI,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC;QAC1B,OAAO,EAAE,uDAAuD;QAChE,UAAU,EAAE,mBAAmB;QAC/B,QAAQ,EAAE,CAAC,6DAA6D,CAAC;KAC1E;IACD;QACE,IAAI,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC;QAC7B,OAAO,EAAE,+CAA+C;QACxD,UAAU,EAAE,wBAAwB;QACpC,QAAQ,EAAE,CAAC,mDAAmD,CAAC;KAChE;CACO,CAAC;AAEX,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC1C,IAAI,EAAE,OAAO,CAAC,IAAI;IAClB,OAAO,CAAC,OAIP;QACC,MAAM,cAAc,GAAG,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9D,OAAO,CAAC,OAAO,CAAC,WAAW,CACzB,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,mBAAmB,yBAAyB,IAAI;YACvE,oBAAoB,cAAc,KAAK,CAC1C,CAAC;QACF,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;CACF,CAAC,CAAC,CAAC;AAEJ,MAAM,QAAQ,GAAG;IACf,EAAE,EAAE,yBAAyB;IAC7B,QAAQ,EAAE,6BAA6B;IACvC,OAAO,EAAE,4BAA4B;IACrC,YAAY,EAAE,yBAAyB;IACvC,QAAQ;IACR,QAAQ;CACT,CAAC;AAEF,eAAe,QAAQ,CAAC","sourcesContent":["import { DATA_SOURCES_PACKAGE_NAME, SUPPORTED_DATA_SOURCE_KINDS } from './packageInfo';\n\nconst DATA_SOURCES_PACKAGE_VERSION = '0.5.1';\nconst DATA_SOURCES_COMMAND_CATEGORY = 'data-sources';\n\nconst DATA_SOURCES_CAPABILITIES = [\n 'data-sources.inspect',\n 'data-sources.validate',\n 'data-sources.test',\n 'data-sources.normalize',\n] as const;\n\nconst commands = [\n {\n path: ['kind', 'list'],\n summary: 'List supported data-source kinds.',\n capability: 'data-sources.inspect',\n aliases: ['kinds'],\n examples: ['ankh data-sources kind list'],\n },\n {\n path: ['config', 'validate'],\n summary: 'Validate a data-source config with the data-sources package.',\n capability: 'data-sources.validate',\n examples: ['ankh data-sources config validate ./data-source.json'],\n },\n {\n path: ['endpoint', 'test'],\n summary: 'Build or execute a data-source endpoint test request.',\n capability: 'data-sources.test',\n examples: ['ankh data-sources endpoint test orders listOrders --dry-run'],\n },\n {\n path: ['config', 'normalize'],\n summary: 'Normalize imported data-source config output.',\n capability: 'data-sources.normalize',\n examples: ['ankh data-sources config normalize ./openapi.json'],\n },\n] as const;\n\nconst handlers = commands.map((command) => ({\n path: command.path,\n handler(request: {\n readonly context: {\n writeStdout(text: string): void;\n };\n }) {\n const supportedKinds = SUPPORTED_DATA_SOURCE_KINDS.join(', ');\n request.context.writeStdout(\n `${command.path.join(' ')} is provided by ${DATA_SOURCES_PACKAGE_NAME}. ` +\n `Supported kinds: ${supportedKinds}.\\n`,\n );\n return { exitCode: 0 };\n },\n}));\n\nconst provider = {\n id: DATA_SOURCES_PACKAGE_NAME,\n category: DATA_SOURCES_COMMAND_CATEGORY,\n version: DATA_SOURCES_PACKAGE_VERSION,\n capabilities: DATA_SOURCES_CAPABILITIES,\n commands,\n handlers,\n};\n\nexport default provider;\n"]}
@@ -0,0 +1,10 @@
1
+ interface TextResponse {
2
+ text(): Promise<string>;
3
+ }
4
+ export declare function parseHttpUrl(rawUrl: string): URL | undefined;
5
+ export declare function normalizeCandidateUrl(url: URL): string;
6
+ export declare function isSuccessfulStatus(status: number): boolean;
7
+ export declare function parseJsonResponse(response: TextResponse): Promise<unknown>;
8
+ export declare function readRecord(value: unknown): Readonly<Record<string, unknown>> | undefined;
9
+ export {};
10
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/discovery/http.ts"],"names":[],"mappings":"AAAA,UAAU,YAAY;IACpB,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACzB;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAS5D;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAItD;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAMhF;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAIxF"}
@@ -0,0 +1,35 @@
1
+ export function parseHttpUrl(rawUrl) {
2
+ try {
3
+ const parsed = new URL(rawUrl.trim());
4
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')
5
+ return undefined;
6
+ if (parsed.username.length > 0 || parsed.password.length > 0)
7
+ return undefined;
8
+ return parsed;
9
+ }
10
+ catch {
11
+ return undefined;
12
+ }
13
+ }
14
+ export function normalizeCandidateUrl(url) {
15
+ const normalized = new URL(url.toString());
16
+ normalized.hash = '';
17
+ return normalized.toString();
18
+ }
19
+ export function isSuccessfulStatus(status) {
20
+ return status >= 200 && status < 300;
21
+ }
22
+ export async function parseJsonResponse(response) {
23
+ try {
24
+ return JSON.parse(await response.text());
25
+ }
26
+ catch {
27
+ return undefined;
28
+ }
29
+ }
30
+ export function readRecord(value) {
31
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
32
+ ? value
33
+ : undefined;
34
+ }
35
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/discovery/http.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACtC,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QAClF,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QAC/E,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAQ;IAC5C,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC3C,UAAU,CAAC,IAAI,GAAG,EAAE,CAAC;IACrB,OAAO,UAAU,CAAC,QAAQ,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,OAAO,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,QAAsB;IAC5D,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAY,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACzE,CAAC,CAAE,KAA2C;QAC9C,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC","sourcesContent":["interface TextResponse {\n text(): Promise<string>;\n}\n\nexport function parseHttpUrl(rawUrl: string): URL | undefined {\n try {\n const parsed = new URL(rawUrl.trim());\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return undefined;\n if (parsed.username.length > 0 || parsed.password.length > 0) return undefined;\n return parsed;\n } catch {\n return undefined;\n }\n}\n\nexport function normalizeCandidateUrl(url: URL): string {\n const normalized = new URL(url.toString());\n normalized.hash = '';\n return normalized.toString();\n}\n\nexport function isSuccessfulStatus(status: number): boolean {\n return status >= 200 && status < 300;\n}\n\nexport async function parseJsonResponse(response: TextResponse): Promise<unknown> {\n try {\n return JSON.parse(await response.text()) as unknown;\n } catch {\n return undefined;\n }\n}\n\nexport function readRecord(value: unknown): Readonly<Record<string, unknown>> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Readonly<Record<string, unknown>>)\n : undefined;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { CredentialRef, DataContractValue, DataSourceDiagnostic, ExternalGraphQlApiDataSourceConfig, ExternalRestApiDataSourceConfig } from '@ankhorage/contracts/data';
1
+ import type { CredentialRef, DataContractValue, DataSourceDiagnostic, ExternalGraphQlApiDefinition, ExternalRestApiDefinition } from '@ankhorage/contracts/data';
2
2
  export declare const DEFAULT_OPENAPI_DISCOVERY_PATHS: readonly ["openapi.json", "swagger.json", "api/openapi.json", "v3/api-docs"];
3
3
  export interface ExternalApiFetchInit {
4
4
  readonly method: 'GET' | 'POST';
@@ -16,7 +16,7 @@ export interface OpenApiDiscoveryAttempt {
16
16
  readonly outcome: OpenApiDiscoveryAttemptOutcome;
17
17
  readonly status?: number;
18
18
  }
19
- export interface DiscoverOpenApiDataSourceInput {
19
+ export interface DiscoverOpenApiInput {
20
20
  readonly id: string;
21
21
  readonly url: string;
22
22
  readonly fetch: ExternalApiFetch;
@@ -27,9 +27,9 @@ export interface DiscoverOpenApiDataSourceInput {
27
27
  readonly metadata?: DataContractValue;
28
28
  readonly conventionalPaths?: readonly string[];
29
29
  }
30
- export type DiscoverOpenApiDataSourceResult = {
30
+ export type DiscoverOpenApiResult = {
31
31
  readonly ok: true;
32
- readonly data: ExternalRestApiDataSourceConfig;
32
+ readonly data: ExternalRestApiDefinition;
33
33
  readonly documentUrl: string;
34
34
  readonly attempts: readonly OpenApiDiscoveryAttempt[];
35
35
  readonly diagnostics: readonly DataSourceDiagnostic[];
@@ -38,7 +38,7 @@ export type DiscoverOpenApiDataSourceResult = {
38
38
  readonly attempts: readonly OpenApiDiscoveryAttempt[];
39
39
  readonly diagnostics: readonly DataSourceDiagnostic[];
40
40
  };
41
- export interface IntrospectGraphQlDataSourceInput {
41
+ export interface IntrospectGraphQlApiInput {
42
42
  readonly id: string;
43
43
  readonly endpointUrl: string;
44
44
  readonly fetch: ExternalApiFetch;
@@ -49,9 +49,9 @@ export interface IntrospectGraphQlDataSourceInput {
49
49
  readonly schemaVersion?: string;
50
50
  readonly metadata?: DataContractValue;
51
51
  }
52
- export type IntrospectGraphQlDataSourceResult = {
52
+ export type IntrospectGraphQlApiResult = {
53
53
  readonly ok: true;
54
- readonly data: ExternalGraphQlApiDataSourceConfig;
54
+ readonly data: ExternalGraphQlApiDefinition;
55
55
  readonly diagnostics: readonly DataSourceDiagnostic[];
56
56
  } | {
57
57
  readonly ok: false;
@@ -59,6 +59,6 @@ export type IntrospectGraphQlDataSourceResult = {
59
59
  readonly status?: number;
60
60
  };
61
61
  export declare function createOpenApiDiscoveryCandidates(rawUrl: string, conventionalPaths?: readonly string[]): readonly string[];
62
- export declare function discoverOpenApiDataSource(input: DiscoverOpenApiDataSourceInput): Promise<DiscoverOpenApiDataSourceResult>;
63
- export declare function introspectGraphQlDataSource(input: IntrospectGraphQlDataSourceInput): Promise<IntrospectGraphQlDataSourceResult>;
62
+ export declare function discoverOpenApi(input: DiscoverOpenApiInput): Promise<DiscoverOpenApiResult>;
63
+ export declare function introspectGraphQlApi(input: IntrospectGraphQlApiInput): Promise<IntrospectGraphQlApiResult>;
64
64
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/discovery/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/discovery/index.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
- import { createGraphQlDataSource, createGraphQlIntrospectionRequest, } from '../graphql';
1
+ import { createGraphQlApi, createGraphQlIntrospectionRequest, } from '../graphql';
2
2
  import { importOpenApiDocument } from '../openapi';
3
+ import { isSuccessfulStatus, normalizeCandidateUrl, parseHttpUrl, parseJsonResponse, readRecord, } from './http';
3
4
  export const DEFAULT_OPENAPI_DISCOVERY_PATHS = [
4
5
  'openapi.json',
5
6
  'swagger.json',
@@ -22,7 +23,7 @@ export function createOpenApiDiscoveryCandidates(rawUrl, conventionalPaths = DEF
22
23
  }
23
24
  return [...new Set(candidates)];
24
25
  }
25
- export async function discoverOpenApiDataSource(input) {
26
+ export async function discoverOpenApi(input) {
26
27
  const candidates = createOpenApiDiscoveryCandidates(input.url, input.conventionalPaths);
27
28
  if (candidates.length === 0) {
28
29
  return discoveryFailure(input.id, [], 'OpenAPI discovery requires a valid HTTP or HTTPS URL.');
@@ -45,24 +46,13 @@ export async function discoverOpenApiDataSource(input) {
45
46
  }
46
47
  return discoveryFailure(input.id, attempts, 'No supported OpenAPI document was found at the supplied URL or conventional locations.');
47
48
  }
48
- export async function introspectGraphQlDataSource(input) {
49
+ export async function introspectGraphQlApi(input) {
49
50
  const endpoint = parseHttpUrl(input.endpointUrl);
50
51
  if (endpoint === undefined) {
51
52
  return graphqlFailure(input.id, 'GraphQL introspection requires a valid HTTP or HTTPS URL.');
52
53
  }
53
- let response;
54
- try {
55
- response = await input.fetch(normalizeCandidateUrl(endpoint), {
56
- method: 'POST',
57
- headers: {
58
- accept: 'application/json',
59
- 'content-type': 'application/json',
60
- ...(input.headers ?? {}),
61
- },
62
- body: JSON.stringify(createGraphQlIntrospectionRequest()),
63
- });
64
- }
65
- catch {
54
+ const response = await fetchGraphQlIntrospection(input, endpoint);
55
+ if (response === undefined) {
66
56
  return graphqlFailure(input.id, 'GraphQL introspection request failed.', 'network-error');
67
57
  }
68
58
  if (!isSuccessfulStatus(response.status)) {
@@ -75,7 +65,7 @@ export async function introspectGraphQlDataSource(input) {
75
65
  if (introspection === undefined) {
76
66
  return graphqlFailure(input.id, 'GraphQL introspection response did not contain data.__schema.', 'parse-error');
77
67
  }
78
- const result = createGraphQlDataSource({
68
+ const result = createGraphQlApi({
79
69
  id: input.id,
80
70
  endpointUrl: normalizeCandidateUrl(endpoint),
81
71
  credential: input.credential,
@@ -90,6 +80,22 @@ export async function introspectGraphQlDataSource(input) {
90
80
  ? { ok: true, data: result.data, diagnostics: result.diagnostics ?? [] }
91
81
  : { ok: false, diagnostics: result.diagnostics };
92
82
  }
83
+ async function fetchGraphQlIntrospection(input, endpoint) {
84
+ try {
85
+ return await input.fetch(normalizeCandidateUrl(endpoint), {
86
+ method: 'POST',
87
+ headers: {
88
+ accept: 'application/json',
89
+ 'content-type': 'application/json',
90
+ ...(input.headers ?? {}),
91
+ },
92
+ body: JSON.stringify(createGraphQlIntrospectionRequest()),
93
+ });
94
+ }
95
+ catch {
96
+ return undefined;
97
+ }
98
+ }
93
99
  async function probeOpenApiCandidate(input, candidate) {
94
100
  let response;
95
101
  try {
@@ -132,35 +138,6 @@ async function probeOpenApiCandidate(input, candidate) {
132
138
  result,
133
139
  };
134
140
  }
135
- function parseHttpUrl(rawUrl) {
136
- try {
137
- const parsed = new URL(rawUrl.trim());
138
- if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')
139
- return undefined;
140
- if (parsed.username.length > 0 || parsed.password.length > 0)
141
- return undefined;
142
- return parsed;
143
- }
144
- catch {
145
- return undefined;
146
- }
147
- }
148
- function normalizeCandidateUrl(url) {
149
- const normalized = new URL(url.toString());
150
- normalized.hash = '';
151
- return normalized.toString();
152
- }
153
- function isSuccessfulStatus(status) {
154
- return status >= 200 && status < 300;
155
- }
156
- async function parseJsonResponse(response) {
157
- try {
158
- return JSON.parse(await response.text());
159
- }
160
- catch {
161
- return undefined;
162
- }
163
- }
164
141
  function isOpenApiDocument(value) {
165
142
  const record = readRecord(value);
166
143
  return (record !== undefined &&
@@ -174,22 +151,17 @@ function readGraphQlIntrospection(value) {
174
151
  return undefined;
175
152
  return data;
176
153
  }
177
- function readRecord(value) {
178
- return typeof value === 'object' && value !== null && !Array.isArray(value)
179
- ? value
180
- : undefined;
181
- }
182
- function discoveryFailure(dataSourceId, attempts, message) {
154
+ function discoveryFailure(apiId, attempts, message) {
183
155
  return {
184
156
  ok: false,
185
157
  attempts,
186
- diagnostics: [{ code: 'missing-schema', dataSourceId, message, severity: 'error' }],
158
+ diagnostics: [{ code: 'missing-schema', apiId, message, severity: 'error' }],
187
159
  };
188
160
  }
189
- function graphqlFailure(dataSourceId, message, code = 'invalid-config') {
161
+ function graphqlFailure(apiId, message, code = 'invalid-config') {
190
162
  return {
191
163
  ok: false,
192
- diagnostics: [{ code, dataSourceId, message, severity: 'error' }],
164
+ diagnostics: [{ code, apiId, message, severity: 'error' }],
193
165
  };
194
166
  }
195
167
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/discovery/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CredentialRef,\n DataContractValue,\n DataSourceDiagnostic,\n ExternalGraphQlApiDataSourceConfig,\n ExternalRestApiDataSourceConfig,\n} from '@ankhorage/contracts/data';\n\nimport {\n createGraphQlDataSource,\n createGraphQlIntrospectionRequest,\n type GraphQlIntrospectionResult,\n} from '../graphql';\nimport { importOpenApiDocument, type OpenApiDocumentObject } from '../openapi';\n\nexport const DEFAULT_OPENAPI_DISCOVERY_PATHS = [\n 'openapi.json',\n 'swagger.json',\n 'api/openapi.json',\n 'v3/api-docs',\n] as const;\n\nexport interface ExternalApiFetchInit {\n readonly method: 'GET' | 'POST';\n readonly headers: Readonly<Record<string, string>>;\n readonly body?: string;\n}\n\nexport interface ExternalApiFetchResponse {\n readonly status: number;\n text(): Promise<string>;\n}\n\nexport type ExternalApiFetch = (\n url: string,\n init: ExternalApiFetchInit,\n) => Promise<ExternalApiFetchResponse>;\n\nexport type OpenApiDiscoveryAttemptOutcome =\n | 'http-error'\n | 'invalid-document'\n | 'matched'\n | 'network-error'\n | 'parse-error'\n | 'unsupported-document';\n\nexport interface OpenApiDiscoveryAttempt {\n readonly url: string;\n readonly outcome: OpenApiDiscoveryAttemptOutcome;\n readonly status?: number;\n}\n\nexport interface DiscoverOpenApiDataSourceInput {\n readonly id: string;\n readonly url: string;\n readonly fetch: ExternalApiFetch;\n readonly baseUrl?: string;\n readonly credential?: CredentialRef;\n readonly name?: string;\n readonly description?: string;\n readonly metadata?: DataContractValue;\n readonly conventionalPaths?: readonly string[];\n}\n\nexport type DiscoverOpenApiDataSourceResult =\n | {\n readonly ok: true;\n readonly data: ExternalRestApiDataSourceConfig;\n readonly documentUrl: string;\n readonly attempts: readonly OpenApiDiscoveryAttempt[];\n readonly diagnostics: readonly DataSourceDiagnostic[];\n }\n | {\n readonly ok: false;\n readonly attempts: readonly OpenApiDiscoveryAttempt[];\n readonly diagnostics: readonly DataSourceDiagnostic[];\n };\n\nexport interface IntrospectGraphQlDataSourceInput {\n readonly id: string;\n readonly endpointUrl: string;\n readonly fetch: ExternalApiFetch;\n readonly headers?: Readonly<Record<string, string>>;\n readonly credential?: CredentialRef;\n readonly name?: string;\n readonly description?: string;\n readonly schemaVersion?: string;\n readonly metadata?: DataContractValue;\n}\n\nexport type IntrospectGraphQlDataSourceResult =\n | {\n readonly ok: true;\n readonly data: ExternalGraphQlApiDataSourceConfig;\n readonly diagnostics: readonly DataSourceDiagnostic[];\n }\n | {\n readonly ok: false;\n readonly diagnostics: readonly DataSourceDiagnostic[];\n readonly status?: number;\n };\n\nexport function createOpenApiDiscoveryCandidates(\n rawUrl: string,\n conventionalPaths: readonly string[] = DEFAULT_OPENAPI_DISCOVERY_PATHS,\n): readonly string[] {\n const parsed = parseHttpUrl(rawUrl);\n if (parsed === undefined) return [];\n\n const exact = normalizeCandidateUrl(parsed);\n const serviceBase = new URL(exact);\n if (!serviceBase.pathname.endsWith('/')) serviceBase.pathname = `${serviceBase.pathname}/`;\n\n const candidates = [exact];\n for (const path of conventionalPaths) {\n const normalizedPath = path.replace(/^\\/+/, '');\n candidates.push(normalizeCandidateUrl(new URL(normalizedPath, serviceBase)));\n candidates.push(normalizeCandidateUrl(new URL(normalizedPath, `${parsed.origin}/`)));\n }\n\n return [...new Set(candidates)];\n}\n\nexport async function discoverOpenApiDataSource(\n input: DiscoverOpenApiDataSourceInput,\n): Promise<DiscoverOpenApiDataSourceResult> {\n const candidates = createOpenApiDiscoveryCandidates(input.url, input.conventionalPaths);\n if (candidates.length === 0) {\n return discoveryFailure(input.id, [], 'OpenAPI discovery requires a valid HTTP or HTTPS URL.');\n }\n\n const attempts: OpenApiDiscoveryAttempt[] = [];\n for (const candidate of candidates) {\n const probed = await probeOpenApiCandidate(input, candidate);\n attempts.push(probed.attempt);\n if (probed.result === undefined) continue;\n return probed.result.ok\n ? {\n ok: true,\n data: probed.result.data,\n documentUrl: candidate,\n attempts,\n diagnostics: probed.result.diagnostics ?? [],\n }\n : { ok: false, attempts, diagnostics: probed.result.diagnostics };\n }\n\n return discoveryFailure(\n input.id,\n attempts,\n 'No supported OpenAPI document was found at the supplied URL or conventional locations.',\n );\n}\n\nexport async function introspectGraphQlDataSource(\n input: IntrospectGraphQlDataSourceInput,\n): Promise<IntrospectGraphQlDataSourceResult> {\n const endpoint = parseHttpUrl(input.endpointUrl);\n if (endpoint === undefined) {\n return graphqlFailure(input.id, 'GraphQL introspection requires a valid HTTP or HTTPS URL.');\n }\n\n let response: ExternalApiFetchResponse;\n try {\n response = await input.fetch(normalizeCandidateUrl(endpoint), {\n method: 'POST',\n headers: {\n accept: 'application/json',\n 'content-type': 'application/json',\n ...(input.headers ?? {}),\n },\n body: JSON.stringify(createGraphQlIntrospectionRequest()),\n });\n } catch {\n return graphqlFailure(input.id, 'GraphQL introspection request failed.', 'network-error');\n }\n\n if (!isSuccessfulStatus(response.status)) {\n return {\n ...graphqlFailure(\n input.id,\n `GraphQL introspection returned HTTP status ${response.status}.`,\n 'network-error',\n ),\n status: response.status,\n };\n }\n\n const introspection = readGraphQlIntrospection(await parseJsonResponse(response));\n if (introspection === undefined) {\n return graphqlFailure(\n input.id,\n 'GraphQL introspection response did not contain data.__schema.',\n 'parse-error',\n );\n }\n\n const result = createGraphQlDataSource({\n id: input.id,\n endpointUrl: normalizeCandidateUrl(endpoint),\n credential: input.credential,\n name: input.name,\n description: input.description,\n introspection,\n introspectionEnabled: true,\n schemaVersion: input.schemaVersion,\n metadata: input.metadata,\n });\n\n return result.ok\n ? { ok: true, data: result.data, diagnostics: result.diagnostics ?? [] }\n : { ok: false, diagnostics: result.diagnostics };\n}\n\ninterface OpenApiProbeResult {\n readonly attempt: OpenApiDiscoveryAttempt;\n readonly result?: ReturnType<typeof importOpenApiDocument>;\n}\n\nasync function probeOpenApiCandidate(\n input: DiscoverOpenApiDataSourceInput,\n candidate: string,\n): Promise<OpenApiProbeResult> {\n let response: ExternalApiFetchResponse;\n try {\n response = await input.fetch(candidate, {\n method: 'GET',\n headers: { accept: 'application/json, application/vnd.oai.openapi+json' },\n });\n } catch {\n return { attempt: { url: candidate, outcome: 'network-error' } };\n }\n\n if (!isSuccessfulStatus(response.status)) {\n return { attempt: { url: candidate, outcome: 'http-error', status: response.status } };\n }\n\n const parsed = await parseJsonResponse(response);\n if (parsed === undefined) {\n return { attempt: { url: candidate, outcome: 'parse-error', status: response.status } };\n }\n if (!isOpenApiDocument(parsed)) {\n return {\n attempt: { url: candidate, outcome: 'unsupported-document', status: response.status },\n };\n }\n\n const result = importOpenApiDocument({\n id: input.id,\n document: parsed,\n baseUrl: input.baseUrl,\n credential: input.credential,\n documentUrl: candidate,\n name: input.name,\n description: input.description,\n metadata: input.metadata,\n });\n return {\n attempt: {\n url: candidate,\n outcome: result.ok ? 'matched' : 'invalid-document',\n status: response.status,\n },\n result,\n };\n}\n\nfunction parseHttpUrl(rawUrl: string): URL | undefined {\n try {\n const parsed = new URL(rawUrl.trim());\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return undefined;\n if (parsed.username.length > 0 || parsed.password.length > 0) return undefined;\n return parsed;\n } catch {\n return undefined;\n }\n}\n\nfunction normalizeCandidateUrl(url: URL): string {\n const normalized = new URL(url.toString());\n normalized.hash = '';\n return normalized.toString();\n}\n\nfunction isSuccessfulStatus(status: number): boolean {\n return status >= 200 && status < 300;\n}\n\nasync function parseJsonResponse(response: ExternalApiFetchResponse): Promise<unknown> {\n try {\n return JSON.parse(await response.text()) as unknown;\n } catch {\n return undefined;\n }\n}\n\nfunction isOpenApiDocument(value: unknown): value is OpenApiDocumentObject {\n const record = readRecord(value);\n return (\n record !== undefined &&\n typeof record.openapi === 'string' &&\n readRecord(record.paths) !== undefined\n );\n}\n\nfunction readGraphQlIntrospection(value: unknown): GraphQlIntrospectionResult | undefined {\n const payload = readRecord(value);\n const data = readRecord(payload?.data);\n if (readRecord(data?.__schema) === undefined) return undefined;\n return data;\n}\n\nfunction readRecord(value: unknown): Readonly<Record<string, unknown>> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Readonly<Record<string, unknown>>)\n : undefined;\n}\n\nfunction discoveryFailure(\n dataSourceId: string,\n attempts: readonly OpenApiDiscoveryAttempt[],\n message: string,\n): DiscoverOpenApiDataSourceResult {\n return {\n ok: false,\n attempts,\n diagnostics: [{ code: 'missing-schema', dataSourceId, message, severity: 'error' }],\n };\n}\n\nfunction graphqlFailure(\n dataSourceId: string,\n message: string,\n code: DataSourceDiagnostic['code'] = 'invalid-config',\n): Extract<IntrospectGraphQlDataSourceResult, { readonly ok: false }> {\n return {\n ok: false,\n diagnostics: [{ code, dataSourceId, message, severity: 'error' }],\n };\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/discovery/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CredentialRef,\n DataContractValue,\n DataSourceDiagnostic,\n ExternalGraphQlApiDefinition,\n ExternalRestApiDefinition,\n} from '@ankhorage/contracts/data';\n\nimport {\n createGraphQlApi,\n createGraphQlIntrospectionRequest,\n type GraphQlIntrospectionResult,\n} from '../graphql';\nimport { importOpenApiDocument, type OpenApiDocumentObject } from '../openapi';\nimport {\n isSuccessfulStatus,\n normalizeCandidateUrl,\n parseHttpUrl,\n parseJsonResponse,\n readRecord,\n} from './http';\n\nexport const DEFAULT_OPENAPI_DISCOVERY_PATHS = [\n 'openapi.json',\n 'swagger.json',\n 'api/openapi.json',\n 'v3/api-docs',\n] as const;\n\nexport interface ExternalApiFetchInit {\n readonly method: 'GET' | 'POST';\n readonly headers: Readonly<Record<string, string>>;\n readonly body?: string;\n}\n\nexport interface ExternalApiFetchResponse {\n readonly status: number;\n text(): Promise<string>;\n}\n\nexport type ExternalApiFetch = (\n url: string,\n init: ExternalApiFetchInit,\n) => Promise<ExternalApiFetchResponse>;\n\nexport type OpenApiDiscoveryAttemptOutcome =\n | 'http-error'\n | 'invalid-document'\n | 'matched'\n | 'network-error'\n | 'parse-error'\n | 'unsupported-document';\n\nexport interface OpenApiDiscoveryAttempt {\n readonly url: string;\n readonly outcome: OpenApiDiscoveryAttemptOutcome;\n readonly status?: number;\n}\n\nexport interface DiscoverOpenApiInput {\n readonly id: string;\n readonly url: string;\n readonly fetch: ExternalApiFetch;\n readonly baseUrl?: string;\n readonly credential?: CredentialRef;\n readonly name?: string;\n readonly description?: string;\n readonly metadata?: DataContractValue;\n readonly conventionalPaths?: readonly string[];\n}\n\nexport type DiscoverOpenApiResult =\n | {\n readonly ok: true;\n readonly data: ExternalRestApiDefinition;\n readonly documentUrl: string;\n readonly attempts: readonly OpenApiDiscoveryAttempt[];\n readonly diagnostics: readonly DataSourceDiagnostic[];\n }\n | {\n readonly ok: false;\n readonly attempts: readonly OpenApiDiscoveryAttempt[];\n readonly diagnostics: readonly DataSourceDiagnostic[];\n };\n\nexport interface IntrospectGraphQlApiInput {\n readonly id: string;\n readonly endpointUrl: string;\n readonly fetch: ExternalApiFetch;\n readonly headers?: Readonly<Record<string, string>>;\n readonly credential?: CredentialRef;\n readonly name?: string;\n readonly description?: string;\n readonly schemaVersion?: string;\n readonly metadata?: DataContractValue;\n}\n\nexport type IntrospectGraphQlApiResult =\n | {\n readonly ok: true;\n readonly data: ExternalGraphQlApiDefinition;\n readonly diagnostics: readonly DataSourceDiagnostic[];\n }\n | {\n readonly ok: false;\n readonly diagnostics: readonly DataSourceDiagnostic[];\n readonly status?: number;\n };\n\nexport function createOpenApiDiscoveryCandidates(\n rawUrl: string,\n conventionalPaths: readonly string[] = DEFAULT_OPENAPI_DISCOVERY_PATHS,\n): readonly string[] {\n const parsed = parseHttpUrl(rawUrl);\n if (parsed === undefined) return [];\n\n const exact = normalizeCandidateUrl(parsed);\n const serviceBase = new URL(exact);\n if (!serviceBase.pathname.endsWith('/')) serviceBase.pathname = `${serviceBase.pathname}/`;\n\n const candidates = [exact];\n for (const path of conventionalPaths) {\n const normalizedPath = path.replace(/^\\/+/, '');\n candidates.push(normalizeCandidateUrl(new URL(normalizedPath, serviceBase)));\n candidates.push(normalizeCandidateUrl(new URL(normalizedPath, `${parsed.origin}/`)));\n }\n\n return [...new Set(candidates)];\n}\n\nexport async function discoverOpenApi(input: DiscoverOpenApiInput): Promise<DiscoverOpenApiResult> {\n const candidates = createOpenApiDiscoveryCandidates(input.url, input.conventionalPaths);\n if (candidates.length === 0) {\n return discoveryFailure(input.id, [], 'OpenAPI discovery requires a valid HTTP or HTTPS URL.');\n }\n\n const attempts: OpenApiDiscoveryAttempt[] = [];\n for (const candidate of candidates) {\n const probed = await probeOpenApiCandidate(input, candidate);\n attempts.push(probed.attempt);\n if (probed.result === undefined) continue;\n return probed.result.ok\n ? {\n ok: true,\n data: probed.result.data,\n documentUrl: candidate,\n attempts,\n diagnostics: probed.result.diagnostics ?? [],\n }\n : { ok: false, attempts, diagnostics: probed.result.diagnostics };\n }\n\n return discoveryFailure(\n input.id,\n attempts,\n 'No supported OpenAPI document was found at the supplied URL or conventional locations.',\n );\n}\n\nexport async function introspectGraphQlApi(\n input: IntrospectGraphQlApiInput,\n): Promise<IntrospectGraphQlApiResult> {\n const endpoint = parseHttpUrl(input.endpointUrl);\n if (endpoint === undefined) {\n return graphqlFailure(input.id, 'GraphQL introspection requires a valid HTTP or HTTPS URL.');\n }\n\n const response = await fetchGraphQlIntrospection(input, endpoint);\n if (response === undefined) {\n return graphqlFailure(input.id, 'GraphQL introspection request failed.', 'network-error');\n }\n if (!isSuccessfulStatus(response.status)) {\n return {\n ...graphqlFailure(\n input.id,\n `GraphQL introspection returned HTTP status ${response.status}.`,\n 'network-error',\n ),\n status: response.status,\n };\n }\n\n const introspection = readGraphQlIntrospection(await parseJsonResponse(response));\n if (introspection === undefined) {\n return graphqlFailure(\n input.id,\n 'GraphQL introspection response did not contain data.__schema.',\n 'parse-error',\n );\n }\n\n const result = createGraphQlApi({\n id: input.id,\n endpointUrl: normalizeCandidateUrl(endpoint),\n credential: input.credential,\n name: input.name,\n description: input.description,\n introspection,\n introspectionEnabled: true,\n schemaVersion: input.schemaVersion,\n metadata: input.metadata,\n });\n return result.ok\n ? { ok: true, data: result.data, diagnostics: result.diagnostics ?? [] }\n : { ok: false, diagnostics: result.diagnostics };\n}\n\nasync function fetchGraphQlIntrospection(\n input: IntrospectGraphQlApiInput,\n endpoint: URL,\n): Promise<ExternalApiFetchResponse | undefined> {\n try {\n return await input.fetch(normalizeCandidateUrl(endpoint), {\n method: 'POST',\n headers: {\n accept: 'application/json',\n 'content-type': 'application/json',\n ...(input.headers ?? {}),\n },\n body: JSON.stringify(createGraphQlIntrospectionRequest()),\n });\n } catch {\n return undefined;\n }\n}\n\ninterface OpenApiProbeResult {\n readonly attempt: OpenApiDiscoveryAttempt;\n readonly result?: ReturnType<typeof importOpenApiDocument>;\n}\n\nasync function probeOpenApiCandidate(\n input: DiscoverOpenApiInput,\n candidate: string,\n): Promise<OpenApiProbeResult> {\n let response: ExternalApiFetchResponse;\n try {\n response = await input.fetch(candidate, {\n method: 'GET',\n headers: { accept: 'application/json, application/vnd.oai.openapi+json' },\n });\n } catch {\n return { attempt: { url: candidate, outcome: 'network-error' } };\n }\n\n if (!isSuccessfulStatus(response.status)) {\n return { attempt: { url: candidate, outcome: 'http-error', status: response.status } };\n }\n\n const parsed = await parseJsonResponse(response);\n if (parsed === undefined) {\n return { attempt: { url: candidate, outcome: 'parse-error', status: response.status } };\n }\n if (!isOpenApiDocument(parsed)) {\n return {\n attempt: { url: candidate, outcome: 'unsupported-document', status: response.status },\n };\n }\n\n const result = importOpenApiDocument({\n id: input.id,\n document: parsed,\n baseUrl: input.baseUrl,\n credential: input.credential,\n documentUrl: candidate,\n name: input.name,\n description: input.description,\n metadata: input.metadata,\n });\n return {\n attempt: {\n url: candidate,\n outcome: result.ok ? 'matched' : 'invalid-document',\n status: response.status,\n },\n result,\n };\n}\n\nfunction isOpenApiDocument(value: unknown): value is OpenApiDocumentObject {\n const record = readRecord(value);\n return (\n record !== undefined &&\n typeof record.openapi === 'string' &&\n readRecord(record.paths) !== undefined\n );\n}\n\nfunction readGraphQlIntrospection(value: unknown): GraphQlIntrospectionResult | undefined {\n const payload = readRecord(value);\n const data = readRecord(payload?.data);\n if (readRecord(data?.__schema) === undefined) return undefined;\n return data;\n}\n\nfunction discoveryFailure(\n apiId: string,\n attempts: readonly OpenApiDiscoveryAttempt[],\n message: string,\n): DiscoverOpenApiResult {\n return {\n ok: false,\n attempts,\n diagnostics: [{ code: 'missing-schema', apiId, message, severity: 'error' }],\n };\n}\n\nfunction graphqlFailure(\n apiId: string,\n message: string,\n code: DataSourceDiagnostic['code'] = 'invalid-config',\n): Extract<IntrospectGraphQlApiResult, { readonly ok: false }> {\n return {\n ok: false,\n diagnostics: [{ code, apiId, message, severity: 'error' }],\n };\n}\n"]}
@@ -1,83 +1,15 @@
1
- import type { CredentialRef, DataContractValue, DataSchema, DataSchemaRegistry, DataSourceDiagnostic, DataSourceDiagnosticResult, ExternalGraphQlApiDataSourceConfig, OperationId } from '@ankhorage/contracts/data';
1
+ import type { DataSourceDiagnostic, DataSourceDiagnosticResult, ExternalGraphQlApiDefinition } from '@ankhorage/contracts/data';
2
+ import type { GraphQlApiDefinition } from './types';
3
+ export { normalizeGraphQlIntrospectionOperations, normalizeGraphQlIntrospectionSchemas, } from './introspection';
4
+ export { normalizeGraphQlOperationId } from './operation';
5
+ export type * from './types';
2
6
  export declare const GRAPHQL_INTROSPECTION_QUERY = "query AnkhorageGraphQlIntrospection {\n __schema {\n queryType { name }\n mutationType { name }\n subscriptionType { name }\n types {\n kind\n name\n description\n fields {\n name\n description\n args {\n name\n description\n type { kind name ofType { kind name ofType { kind name ofType { kind name } } } }\n defaultValue\n }\n type { kind name ofType { kind name ofType { kind name ofType { kind name } } } }\n }\n inputFields {\n name\n description\n type { kind name ofType { kind name ofType { kind name ofType { kind name } } } }\n defaultValue\n }\n enumValues { name description }\n possibleTypes { kind name }\n }\n }\n}";
3
- export type GraphQlOperationKind = 'mutation' | 'query' | 'subscription';
4
- export interface GraphQlIntrospectionTypeRef {
5
- readonly kind: string;
6
- readonly name?: string | null;
7
- readonly ofType?: GraphQlIntrospectionTypeRef | null;
8
- }
9
- export interface GraphQlIntrospectionInputValue {
10
- readonly name: string;
11
- readonly description?: string | null;
12
- readonly type: GraphQlIntrospectionTypeRef;
13
- readonly defaultValue?: string | null;
14
- }
15
- export interface GraphQlIntrospectionField {
16
- readonly name: string;
17
- readonly description?: string | null;
18
- readonly args?: readonly GraphQlIntrospectionInputValue[] | null;
19
- readonly type: GraphQlIntrospectionTypeRef;
20
- }
21
- export interface GraphQlIntrospectionEnumValue {
22
- readonly name: string;
23
- readonly description?: string | null;
24
- }
25
- export interface GraphQlIntrospectionType {
26
- readonly kind: string;
27
- readonly name?: string | null;
28
- readonly description?: string | null;
29
- readonly fields?: readonly GraphQlIntrospectionField[] | null;
30
- readonly inputFields?: readonly GraphQlIntrospectionInputValue[] | null;
31
- readonly enumValues?: readonly GraphQlIntrospectionEnumValue[] | null;
32
- readonly possibleTypes?: readonly GraphQlIntrospectionTypeRef[] | null;
33
- }
34
- export interface GraphQlIntrospectionSchema {
35
- readonly queryType?: {
36
- readonly name?: string | null;
37
- } | null;
38
- readonly mutationType?: {
39
- readonly name?: string | null;
40
- } | null;
41
- readonly subscriptionType?: {
42
- readonly name?: string | null;
43
- } | null;
44
- readonly types?: readonly GraphQlIntrospectionType[] | null;
45
- }
46
- export interface GraphQlIntrospectionResult {
47
- readonly __schema?: GraphQlIntrospectionSchema;
48
- }
49
- export interface GraphQlOperationDefinition {
50
- readonly id: OperationId;
51
- readonly kind: GraphQlOperationKind;
52
- readonly name?: string;
53
- readonly description?: string;
54
- readonly document?: string;
55
- readonly variables?: DataSchema;
56
- readonly response?: DataSchema;
57
- readonly selectionPath?: string;
58
- readonly metadata?: DataContractValue;
59
- }
60
- export interface GraphQlDataSourceDefinition {
61
- readonly id: string;
62
- readonly endpointUrl: string;
63
- readonly name?: string;
64
- readonly description?: string;
65
- readonly credential?: CredentialRef;
66
- readonly introspection?: GraphQlIntrospectionResult;
67
- readonly introspectionEnabled?: boolean;
68
- readonly schemaVersion?: string;
69
- readonly operations?: readonly GraphQlOperationDefinition[];
70
- readonly metadata?: DataContractValue;
71
- }
72
7
  export interface GraphQlIntrospectionRequest {
73
8
  readonly query: typeof GRAPHQL_INTROSPECTION_QUERY;
74
9
  readonly operationName: 'AnkhorageGraphQlIntrospection';
75
10
  }
76
11
  export declare function createGraphQlIntrospectionRequest(): GraphQlIntrospectionRequest;
77
- export declare function normalizeGraphQlOperationId(kind: GraphQlOperationKind, name: string): OperationId;
78
- export declare function createGraphQlDataSource(definition: GraphQlDataSourceDefinition): DataSourceDiagnosticResult<ExternalGraphQlApiDataSourceConfig>;
79
- export declare function validateGraphQlDataSource(definition: GraphQlDataSourceDefinition): readonly DataSourceDiagnostic[];
80
- export declare function normalizeGraphQlDataSource(definition: GraphQlDataSourceDefinition): ExternalGraphQlApiDataSourceConfig;
81
- export declare function normalizeGraphQlIntrospectionSchemas(introspection: GraphQlIntrospectionResult | undefined): DataSchemaRegistry | undefined;
82
- export declare function normalizeGraphQlIntrospectionOperations(introspection: GraphQlIntrospectionResult | undefined): readonly GraphQlOperationDefinition[];
12
+ export declare function createGraphQlApi(definition: GraphQlApiDefinition): DataSourceDiagnosticResult<ExternalGraphQlApiDefinition>;
13
+ export declare function validateGraphQlApi(definition: GraphQlApiDefinition): readonly DataSourceDiagnostic[];
14
+ export declare function normalizeGraphQlApi(definition: GraphQlApiDefinition): ExternalGraphQlApiDefinition;
83
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/graphql/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EAKjB,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,0BAA0B,EAC1B,kCAAkC,EAClC,WAAW,EACZ,MAAM,2BAA2B,CAAC;AAEnC,eAAO,MAAM,2BAA2B,2xBA8BtC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,OAAO,GAAG,cAAc,CAAC;AAGzE,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;CACtD;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,2BAA2B,CAAC;IAC3C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,8BAA8B,EAAE,GAAG,IAAI,CAAC;IACjE,QAAQ,CAAC,IAAI,EAAE,2BAA2B,CAAC;CAC5C;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,yBAAyB,EAAE,GAAG,IAAI,CAAC;IAC9D,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,8BAA8B,EAAE,GAAG,IAAI,CAAC;IACxE,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,6BAA6B,EAAE,GAAG,IAAI,CAAC;IACtE,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,2BAA2B,EAAE,GAAG,IAAI,CAAC;CACxE;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IAC9D,QAAQ,CAAC,YAAY,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IACjE,QAAQ,CAAC,gBAAgB,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IACrE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,wBAAwB,EAAE,GAAG,IAAI,CAAC;CAC7D;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,0BAA0B,CAAC;CAChD;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAC/B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,aAAa,CAAC;IACpC,QAAQ,CAAC,aAAa,CAAC,EAAE,0BAA0B,CAAC;IACpD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IACxC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,0BAA0B,EAAE,CAAC;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,KAAK,EAAE,OAAO,2BAA2B,CAAC;IACnD,QAAQ,CAAC,aAAa,EAAE,+BAA+B,CAAC;CACzD;AAED,wBAAgB,iCAAiC,IAAI,2BAA2B,CAK/E;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAMjG;AAED,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,2BAA2B,GACtC,0BAA0B,CAAC,kCAAkC,CAAC,CAWhE;AAED,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,2BAA2B,GACtC,SAAS,oBAAoB,EAAE,CAmCjC;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,2BAA2B,GACtC,kCAAkC,CAmCpC;AAED,wBAAgB,oCAAoC,CAClD,aAAa,EAAE,0BAA0B,GAAG,SAAS,GACpD,kBAAkB,GAAG,SAAS,CAUhC;AAED,wBAAgB,uCAAuC,CACrD,aAAa,EAAE,0BAA0B,GAAG,SAAS,GACpD,SAAS,0BAA0B,EAAE,CAUvC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/graphql/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,oBAAoB,EACpB,0BAA0B,EAC1B,4BAA4B,EAC7B,MAAM,2BAA2B,CAAC;AAOnC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEpD,OAAO,EACL,uCAAuC,EACvC,oCAAoC,GACrC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAC1D,mBAAmB,SAAS,CAAC;AAE7B,eAAO,MAAM,2BAA2B,2xBA8BtC,CAAC;AAEH,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,KAAK,EAAE,OAAO,2BAA2B,CAAC;IACnD,QAAQ,CAAC,aAAa,EAAE,+BAA+B,CAAC;CACzD;AAED,wBAAgB,iCAAiC,IAAI,2BAA2B,CAK/E;AAED,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,oBAAoB,GAC/B,0BAA0B,CAAC,4BAA4B,CAAC,CAM1D;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,oBAAoB,GAC/B,SAAS,oBAAoB,EAAE,CAgCjC;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,oBAAoB,GAC/B,4BAA4B,CAgC9B"}