@ankhorage/data-sources 1.0.1 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/CHANGELOG.md +12 -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 +12 -13
  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
@@ -1,3 +1,7 @@
1
+ import { normalizeGraphQlIntrospectionOperations, normalizeGraphQlIntrospectionSchemas, } from './introspection';
2
+ import { normalizeGraphQlOperation } from './operation';
3
+ export { normalizeGraphQlIntrospectionOperations, normalizeGraphQlIntrospectionSchemas, } from './introspection';
4
+ export { normalizeGraphQlOperationId } from './operation';
1
5
  export const GRAPHQL_INTROSPECTION_QUERY = `query AnkhorageGraphQlIntrospection {
2
6
  __schema {
3
7
  queryType { name }
@@ -35,31 +39,20 @@ export function createGraphQlIntrospectionRequest() {
35
39
  operationName: 'AnkhorageGraphQlIntrospection',
36
40
  };
37
41
  }
38
- export function normalizeGraphQlOperationId(kind, name) {
39
- const normalizedName = name
40
- .replace(/[^A-Za-z0-9]+/g, '-')
41
- .replace(/^-+|-+$/g, '')
42
- .toLowerCase();
43
- return normalizedName.length > 0 ? `${kind}.${normalizedName}` : `${kind}.operation`;
44
- }
45
- export function createGraphQlDataSource(definition) {
46
- const diagnostics = validateGraphQlDataSource(definition);
42
+ export function createGraphQlApi(definition) {
43
+ const diagnostics = validateGraphQlApi(definition);
47
44
  if (diagnostics.some((diagnostic) => diagnostic.severity === 'error')) {
48
45
  return { ok: false, diagnostics };
49
46
  }
50
- return {
51
- ok: true,
52
- data: normalizeGraphQlDataSource(definition),
53
- diagnostics,
54
- };
47
+ return { ok: true, data: normalizeGraphQlApi(definition), diagnostics };
55
48
  }
56
- export function validateGraphQlDataSource(definition) {
49
+ export function validateGraphQlApi(definition) {
57
50
  const diagnostics = [];
58
51
  if (definition.endpointUrl.trim().length === 0) {
59
52
  diagnostics.push({
60
53
  code: 'invalid-config',
61
- dataSourceId: definition.id,
62
- message: 'GraphQL data source requires a non-empty endpointUrl.',
54
+ apiId: definition.id,
55
+ message: 'GraphQL API requires a non-empty endpointUrl.',
63
56
  path: 'endpointUrl',
64
57
  severity: 'error',
65
58
  });
@@ -67,7 +60,7 @@ export function validateGraphQlDataSource(definition) {
67
60
  if (definition.introspectionEnabled === false && definition.introspection !== undefined) {
68
61
  diagnostics.push({
69
62
  code: 'invalid-config',
70
- dataSourceId: definition.id,
63
+ apiId: definition.id,
71
64
  message: 'GraphQL introspection data was provided while introspection is disabled.',
72
65
  path: 'introspection',
73
66
  severity: 'warning',
@@ -76,7 +69,7 @@ export function validateGraphQlDataSource(definition) {
76
69
  if (definition.introspectionEnabled !== false && definition.introspection === undefined) {
77
70
  diagnostics.push({
78
71
  code: 'missing-schema',
79
- dataSourceId: definition.id,
72
+ apiId: definition.id,
80
73
  message: 'GraphQL introspection result was not provided. Manual operations can still be used.',
81
74
  path: 'introspection',
82
75
  severity: 'info',
@@ -84,24 +77,22 @@ export function validateGraphQlDataSource(definition) {
84
77
  }
85
78
  return diagnostics;
86
79
  }
87
- export function normalizeGraphQlDataSource(definition) {
80
+ export function normalizeGraphQlApi(definition) {
88
81
  const schemas = normalizeGraphQlIntrospectionSchemas(definition.introspection);
89
82
  const discovered = normalizeGraphQlIntrospectionOperations(definition.introspection);
90
- const operations = {};
91
- for (const operation of [...discovered, ...(definition.operations ?? [])]) {
92
- operations[operation.id] = normalizeGraphQlOperation(operation);
93
- }
83
+ const operations = Object.fromEntries([...discovered, ...(definition.operations ?? [])].map((operation) => [
84
+ operation.id,
85
+ normalizeGraphQlOperation(operation),
86
+ ]));
94
87
  const endpoint = {
95
88
  id: 'graphql',
96
89
  kind: 'graphql',
97
- baseUrl: definition.endpointUrl,
98
90
  credential: definition.credential,
99
91
  operations,
100
92
  metadata: { source: 'graphql' },
101
93
  };
102
94
  return {
103
95
  id: definition.id,
104
- kind: 'api',
105
96
  origin: 'external',
106
97
  protocol: 'graphql',
107
98
  name: definition.name,
@@ -117,175 +108,4 @@ export function normalizeGraphQlDataSource(definition) {
117
108
  metadata: definition.metadata,
118
109
  };
119
110
  }
120
- export function normalizeGraphQlIntrospectionSchemas(introspection) {
121
- const types = introspection?.__schema?.types?.filter(isNamedGraphQlType) ?? [];
122
- if (types.length === 0)
123
- return undefined;
124
- const schemas = {};
125
- for (const type of types) {
126
- if (type.name === undefined || type.name === null || type.name.startsWith('__'))
127
- continue;
128
- schemas[type.name] = normalizeGraphQlType(type);
129
- }
130
- return schemas;
131
- }
132
- export function normalizeGraphQlIntrospectionOperations(introspection) {
133
- const schema = introspection?.__schema;
134
- if (schema === undefined)
135
- return [];
136
- const types = schema.types?.filter(isNamedGraphQlType) ?? [];
137
- const operations = [];
138
- appendRootOperations(operations, 'query', schema.queryType?.name, types);
139
- appendRootOperations(operations, 'mutation', schema.mutationType?.name, types);
140
- appendRootOperations(operations, 'subscription', schema.subscriptionType?.name, types);
141
- return operations;
142
- }
143
- function appendRootOperations(operations, kind, rootTypeName, types) {
144
- if (rootTypeName === undefined || rootTypeName === null)
145
- return;
146
- const rootType = types.find((type) => type.name === rootTypeName);
147
- for (const field of rootType?.fields ?? []) {
148
- operations.push({
149
- id: normalizeGraphQlOperationId(kind, field.name),
150
- kind,
151
- name: field.name,
152
- description: field.description ?? undefined,
153
- variables: normalizeGraphQlVariablesSchema(field.args ?? []),
154
- response: normalizeGraphQlTypeRef(field.type),
155
- selectionPath: `$.data.${field.name}`,
156
- metadata: { rootType: rootTypeName, source: 'introspection' },
157
- });
158
- }
159
- }
160
- function normalizeGraphQlOperation(operation) {
161
- const response = operation.response === undefined ? undefined : { schema: operation.response };
162
- return {
163
- id: operation.id,
164
- endpointId: 'graphql',
165
- name: operation.name,
166
- description: operation.description,
167
- protocol: 'graphql',
168
- intent: mapGraphQlOperationKindToIntent(operation.kind),
169
- request: { schema: operation.variables },
170
- response,
171
- metadata: createGraphQlOperationMetadata(operation),
172
- };
173
- }
174
- function mapGraphQlOperationKindToIntent(kind) {
175
- return kind === 'query' || kind === 'subscription' ? 'read' : 'action';
176
- }
177
- function normalizeGraphQlVariablesSchema(args) {
178
- const properties = {};
179
- const required = [];
180
- for (const arg of args) {
181
- properties[arg.name] = {
182
- ...normalizeGraphQlTypeRef(arg.type),
183
- description: arg.description ?? undefined,
184
- default: arg.defaultValue ?? undefined,
185
- };
186
- if (isGraphQlNonNull(arg.type))
187
- required.push(arg.name);
188
- }
189
- return {
190
- type: 'object',
191
- required: required.length > 0 ? required : undefined,
192
- properties,
193
- };
194
- }
195
- function normalizeGraphQlType(type) {
196
- if (type.kind === 'OBJECT' || type.kind === 'INTERFACE' || type.kind === 'INPUT_OBJECT') {
197
- return normalizeGraphQlObjectType(type);
198
- }
199
- if (type.kind === 'ENUM') {
200
- return {
201
- type: 'string',
202
- title: type.name ?? undefined,
203
- description: type.description ?? undefined,
204
- enum: type.enumValues?.map((value) => value.name),
205
- };
206
- }
207
- if (type.kind === 'SCALAR') {
208
- return {
209
- ...normalizeGraphQlNamedScalar(type.name),
210
- title: type.name ?? undefined,
211
- description: type.description ?? undefined,
212
- };
213
- }
214
- if (type.kind === 'UNION') {
215
- return {
216
- title: type.name ?? undefined,
217
- description: type.description ?? undefined,
218
- anyOf: type.possibleTypes?.map(normalizeGraphQlTypeRef),
219
- };
220
- }
221
- return { title: type.name ?? undefined, description: type.description ?? undefined };
222
- }
223
- function normalizeGraphQlObjectType(type) {
224
- const fields = type.kind === 'INPUT_OBJECT' ? type.inputFields : type.fields;
225
- const properties = {};
226
- const required = [];
227
- for (const field of fields ?? []) {
228
- const fieldType = field.type;
229
- properties[field.name] = {
230
- ...normalizeGraphQlTypeRef(fieldType),
231
- description: field.description ?? undefined,
232
- };
233
- if (isGraphQlNonNull(fieldType))
234
- required.push(field.name);
235
- }
236
- return {
237
- type: 'object',
238
- title: type.name ?? undefined,
239
- description: type.description ?? undefined,
240
- required: required.length > 0 ? required : undefined,
241
- properties,
242
- };
243
- }
244
- function normalizeGraphQlTypeRef(type) {
245
- if (type.kind === 'NON_NULL' && type.ofType !== undefined && type.ofType !== null) {
246
- return { ...normalizeGraphQlTypeRef(type.ofType), nullable: false };
247
- }
248
- if (type.kind === 'LIST' && type.ofType !== undefined && type.ofType !== null) {
249
- return { type: 'array', items: normalizeGraphQlTypeRef(type.ofType) };
250
- }
251
- if (type.kind === 'SCALAR')
252
- return normalizeGraphQlNamedScalar(type.name);
253
- if (type.name !== undefined && type.name !== null)
254
- return { ref: { id: type.name } };
255
- return {};
256
- }
257
- function normalizeGraphQlNamedScalar(name) {
258
- if (name === 'Boolean')
259
- return { type: 'boolean' };
260
- if (name === 'Float')
261
- return { type: 'number' };
262
- if (name === 'ID' || name === 'String')
263
- return { type: 'string' };
264
- if (name === 'Int')
265
- return { type: 'integer' };
266
- return { type: 'string', format: name ?? undefined };
267
- }
268
- function isGraphQlNonNull(type) {
269
- return type.kind === 'NON_NULL';
270
- }
271
- function isNamedGraphQlType(type) {
272
- return type.name !== undefined && type.name !== null;
273
- }
274
- function createGraphQlOperationMetadata(operation) {
275
- const metadata = toMetadataRecord(operation.metadata);
276
- metadata.kind = operation.kind;
277
- if (operation.document !== undefined)
278
- metadata.document = operation.document;
279
- if (operation.selectionPath !== undefined)
280
- metadata.selectionPath = operation.selectionPath;
281
- return metadata;
282
- }
283
- function toMetadataRecord(value) {
284
- if (!isDataContractRecord(value))
285
- return {};
286
- return { ...value };
287
- }
288
- function isDataContractRecord(value) {
289
- return (value !== undefined && typeof value === 'object' && value !== null && !Array.isArray(value));
290
- }
291
111
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/graphql/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CredentialRef,\n DataContractValue,\n DataEndpointConfig,\n DataOperationConfig,\n DataOperationIntent,\n DataOperationResponse,\n DataSchema,\n DataSchemaRegistry,\n DataSourceDiagnostic,\n DataSourceDiagnosticResult,\n ExternalGraphQlApiDataSourceConfig,\n OperationId,\n} from '@ankhorage/contracts/data';\n\nexport 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}`;\n\nexport type GraphQlOperationKind = 'mutation' | 'query' | 'subscription';\ntype DataContractRecord = Record<string, DataContractValue>;\n\nexport interface GraphQlIntrospectionTypeRef {\n readonly kind: string;\n readonly name?: string | null;\n readonly ofType?: GraphQlIntrospectionTypeRef | null;\n}\n\nexport interface GraphQlIntrospectionInputValue {\n readonly name: string;\n readonly description?: string | null;\n readonly type: GraphQlIntrospectionTypeRef;\n readonly defaultValue?: string | null;\n}\n\nexport interface GraphQlIntrospectionField {\n readonly name: string;\n readonly description?: string | null;\n readonly args?: readonly GraphQlIntrospectionInputValue[] | null;\n readonly type: GraphQlIntrospectionTypeRef;\n}\n\nexport interface GraphQlIntrospectionEnumValue {\n readonly name: string;\n readonly description?: string | null;\n}\n\nexport interface GraphQlIntrospectionType {\n readonly kind: string;\n readonly name?: string | null;\n readonly description?: string | null;\n readonly fields?: readonly GraphQlIntrospectionField[] | null;\n readonly inputFields?: readonly GraphQlIntrospectionInputValue[] | null;\n readonly enumValues?: readonly GraphQlIntrospectionEnumValue[] | null;\n readonly possibleTypes?: readonly GraphQlIntrospectionTypeRef[] | null;\n}\n\nexport interface GraphQlIntrospectionSchema {\n readonly queryType?: { readonly name?: string | null } | null;\n readonly mutationType?: { readonly name?: string | null } | null;\n readonly subscriptionType?: { readonly name?: string | null } | null;\n readonly types?: readonly GraphQlIntrospectionType[] | null;\n}\n\nexport interface GraphQlIntrospectionResult {\n readonly __schema?: GraphQlIntrospectionSchema;\n}\n\nexport interface GraphQlOperationDefinition {\n readonly id: OperationId;\n readonly kind: GraphQlOperationKind;\n readonly name?: string;\n readonly description?: string;\n readonly document?: string;\n readonly variables?: DataSchema;\n readonly response?: DataSchema;\n readonly selectionPath?: string;\n readonly metadata?: DataContractValue;\n}\n\nexport interface GraphQlDataSourceDefinition {\n readonly id: string;\n readonly endpointUrl: string;\n readonly name?: string;\n readonly description?: string;\n readonly credential?: CredentialRef;\n readonly introspection?: GraphQlIntrospectionResult;\n readonly introspectionEnabled?: boolean;\n readonly schemaVersion?: string;\n readonly operations?: readonly GraphQlOperationDefinition[];\n readonly metadata?: DataContractValue;\n}\n\nexport interface GraphQlIntrospectionRequest {\n readonly query: typeof GRAPHQL_INTROSPECTION_QUERY;\n readonly operationName: 'AnkhorageGraphQlIntrospection';\n}\n\nexport function createGraphQlIntrospectionRequest(): GraphQlIntrospectionRequest {\n return {\n query: GRAPHQL_INTROSPECTION_QUERY,\n operationName: 'AnkhorageGraphQlIntrospection',\n };\n}\n\nexport function normalizeGraphQlOperationId(kind: GraphQlOperationKind, name: string): OperationId {\n const normalizedName = name\n .replace(/[^A-Za-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .toLowerCase();\n return normalizedName.length > 0 ? `${kind}.${normalizedName}` : `${kind}.operation`;\n}\n\nexport function createGraphQlDataSource(\n definition: GraphQlDataSourceDefinition,\n): DataSourceDiagnosticResult<ExternalGraphQlApiDataSourceConfig> {\n const diagnostics = validateGraphQlDataSource(definition);\n if (diagnostics.some((diagnostic) => diagnostic.severity === 'error')) {\n return { ok: false, diagnostics };\n }\n\n return {\n ok: true,\n data: normalizeGraphQlDataSource(definition),\n diagnostics,\n };\n}\n\nexport function validateGraphQlDataSource(\n definition: GraphQlDataSourceDefinition,\n): readonly DataSourceDiagnostic[] {\n const diagnostics: DataSourceDiagnostic[] = [];\n\n if (definition.endpointUrl.trim().length === 0) {\n diagnostics.push({\n code: 'invalid-config',\n dataSourceId: definition.id,\n message: 'GraphQL data source requires a non-empty endpointUrl.',\n path: 'endpointUrl',\n severity: 'error',\n });\n }\n\n if (definition.introspectionEnabled === false && definition.introspection !== undefined) {\n diagnostics.push({\n code: 'invalid-config',\n dataSourceId: definition.id,\n message: 'GraphQL introspection data was provided while introspection is disabled.',\n path: 'introspection',\n severity: 'warning',\n });\n }\n\n if (definition.introspectionEnabled !== false && definition.introspection === undefined) {\n diagnostics.push({\n code: 'missing-schema',\n dataSourceId: definition.id,\n message:\n 'GraphQL introspection result was not provided. Manual operations can still be used.',\n path: 'introspection',\n severity: 'info',\n });\n }\n\n return diagnostics;\n}\n\nexport function normalizeGraphQlDataSource(\n definition: GraphQlDataSourceDefinition,\n): ExternalGraphQlApiDataSourceConfig {\n const schemas = normalizeGraphQlIntrospectionSchemas(definition.introspection);\n const discovered = normalizeGraphQlIntrospectionOperations(definition.introspection);\n const operations: Record<OperationId, DataOperationConfig> = {};\n\n for (const operation of [...discovered, ...(definition.operations ?? [])]) {\n operations[operation.id] = normalizeGraphQlOperation(operation);\n }\n\n const endpoint: DataEndpointConfig = {\n id: 'graphql',\n kind: 'graphql',\n baseUrl: definition.endpointUrl,\n credential: definition.credential,\n operations,\n metadata: { source: 'graphql' },\n };\n\n return {\n id: definition.id,\n kind: 'api',\n origin: 'external',\n protocol: 'graphql',\n name: definition.name,\n description: definition.description,\n endpointUrl: definition.endpointUrl,\n credential: definition.credential,\n endpoints: { graphql: endpoint },\n schemas,\n introspection: {\n enabled: definition.introspectionEnabled ?? definition.introspection !== undefined,\n schemaVersion: definition.schemaVersion,\n },\n metadata: definition.metadata,\n };\n}\n\nexport function normalizeGraphQlIntrospectionSchemas(\n introspection: GraphQlIntrospectionResult | undefined,\n): DataSchemaRegistry | undefined {\n const types = introspection?.__schema?.types?.filter(isNamedGraphQlType) ?? [];\n if (types.length === 0) return undefined;\n\n const schemas: Record<string, DataSchema> = {};\n for (const type of types) {\n if (type.name === undefined || type.name === null || type.name.startsWith('__')) continue;\n schemas[type.name] = normalizeGraphQlType(type);\n }\n return schemas;\n}\n\nexport function normalizeGraphQlIntrospectionOperations(\n introspection: GraphQlIntrospectionResult | undefined,\n): readonly GraphQlOperationDefinition[] {\n const schema = introspection?.__schema;\n if (schema === undefined) return [];\n\n const types = schema.types?.filter(isNamedGraphQlType) ?? [];\n const operations: GraphQlOperationDefinition[] = [];\n appendRootOperations(operations, 'query', schema.queryType?.name, types);\n appendRootOperations(operations, 'mutation', schema.mutationType?.name, types);\n appendRootOperations(operations, 'subscription', schema.subscriptionType?.name, types);\n return operations;\n}\n\nfunction appendRootOperations(\n operations: GraphQlOperationDefinition[],\n kind: GraphQlOperationKind,\n rootTypeName: string | null | undefined,\n types: readonly GraphQlIntrospectionType[],\n): void {\n if (rootTypeName === undefined || rootTypeName === null) return;\n const rootType = types.find((type) => type.name === rootTypeName);\n\n for (const field of rootType?.fields ?? []) {\n operations.push({\n id: normalizeGraphQlOperationId(kind, field.name),\n kind,\n name: field.name,\n description: field.description ?? undefined,\n variables: normalizeGraphQlVariablesSchema(field.args ?? []),\n response: normalizeGraphQlTypeRef(field.type),\n selectionPath: `$.data.${field.name}`,\n metadata: { rootType: rootTypeName, source: 'introspection' },\n });\n }\n}\n\nfunction normalizeGraphQlOperation(operation: GraphQlOperationDefinition): DataOperationConfig {\n const response: DataOperationResponse | undefined =\n operation.response === undefined ? undefined : { schema: operation.response };\n\n return {\n id: operation.id,\n endpointId: 'graphql',\n name: operation.name,\n description: operation.description,\n protocol: 'graphql',\n intent: mapGraphQlOperationKindToIntent(operation.kind),\n request: { schema: operation.variables },\n response,\n metadata: createGraphQlOperationMetadata(operation),\n };\n}\n\nfunction mapGraphQlOperationKindToIntent(kind: GraphQlOperationKind): DataOperationIntent {\n return kind === 'query' || kind === 'subscription' ? 'read' : 'action';\n}\n\nfunction normalizeGraphQlVariablesSchema(\n args: readonly GraphQlIntrospectionInputValue[],\n): DataSchema {\n const properties: Record<string, DataSchema> = {};\n const required: string[] = [];\n\n for (const arg of args) {\n properties[arg.name] = {\n ...normalizeGraphQlTypeRef(arg.type),\n description: arg.description ?? undefined,\n default: arg.defaultValue ?? undefined,\n };\n if (isGraphQlNonNull(arg.type)) required.push(arg.name);\n }\n\n return {\n type: 'object',\n required: required.length > 0 ? required : undefined,\n properties,\n };\n}\n\nfunction normalizeGraphQlType(type: GraphQlIntrospectionType): DataSchema {\n if (type.kind === 'OBJECT' || type.kind === 'INTERFACE' || type.kind === 'INPUT_OBJECT') {\n return normalizeGraphQlObjectType(type);\n }\n if (type.kind === 'ENUM') {\n return {\n type: 'string',\n title: type.name ?? undefined,\n description: type.description ?? undefined,\n enum: type.enumValues?.map((value) => value.name),\n };\n }\n if (type.kind === 'SCALAR') {\n return {\n ...normalizeGraphQlNamedScalar(type.name),\n title: type.name ?? undefined,\n description: type.description ?? undefined,\n };\n }\n if (type.kind === 'UNION') {\n return {\n title: type.name ?? undefined,\n description: type.description ?? undefined,\n anyOf: type.possibleTypes?.map(normalizeGraphQlTypeRef),\n };\n }\n return { title: type.name ?? undefined, description: type.description ?? undefined };\n}\n\nfunction normalizeGraphQlObjectType(type: GraphQlIntrospectionType): DataSchema {\n const fields = type.kind === 'INPUT_OBJECT' ? type.inputFields : type.fields;\n const properties: Record<string, DataSchema> = {};\n const required: string[] = [];\n\n for (const field of fields ?? []) {\n const fieldType = field.type;\n properties[field.name] = {\n ...normalizeGraphQlTypeRef(fieldType),\n description: field.description ?? undefined,\n };\n if (isGraphQlNonNull(fieldType)) required.push(field.name);\n }\n\n return {\n type: 'object',\n title: type.name ?? undefined,\n description: type.description ?? undefined,\n required: required.length > 0 ? required : undefined,\n properties,\n };\n}\n\nfunction normalizeGraphQlTypeRef(type: GraphQlIntrospectionTypeRef): DataSchema {\n if (type.kind === 'NON_NULL' && type.ofType !== undefined && type.ofType !== null) {\n return { ...normalizeGraphQlTypeRef(type.ofType), nullable: false };\n }\n if (type.kind === 'LIST' && type.ofType !== undefined && type.ofType !== null) {\n return { type: 'array', items: normalizeGraphQlTypeRef(type.ofType) };\n }\n if (type.kind === 'SCALAR') return normalizeGraphQlNamedScalar(type.name);\n if (type.name !== undefined && type.name !== null) return { ref: { id: type.name } };\n return {};\n}\n\nfunction normalizeGraphQlNamedScalar(name: string | null | undefined): DataSchema {\n if (name === 'Boolean') return { type: 'boolean' };\n if (name === 'Float') return { type: 'number' };\n if (name === 'ID' || name === 'String') return { type: 'string' };\n if (name === 'Int') return { type: 'integer' };\n return { type: 'string', format: name ?? undefined };\n}\n\nfunction isGraphQlNonNull(type: GraphQlIntrospectionTypeRef): boolean {\n return type.kind === 'NON_NULL';\n}\n\nfunction isNamedGraphQlType(type: GraphQlIntrospectionType): boolean {\n return type.name !== undefined && type.name !== null;\n}\n\nfunction createGraphQlOperationMetadata(operation: GraphQlOperationDefinition): DataContractRecord {\n const metadata = toMetadataRecord(operation.metadata);\n metadata.kind = operation.kind;\n if (operation.document !== undefined) metadata.document = operation.document;\n if (operation.selectionPath !== undefined) metadata.selectionPath = operation.selectionPath;\n return metadata;\n}\n\nfunction toMetadataRecord(value: DataContractValue | undefined): DataContractRecord {\n if (!isDataContractRecord(value)) return {};\n return { ...value };\n}\n\nfunction isDataContractRecord(value: DataContractValue | undefined): value is DataContractRecord {\n return (\n value !== undefined && typeof value === 'object' && value !== null && !Array.isArray(value)\n );\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/graphql/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n DataEndpointConfig,\n DataSourceDiagnostic,\n DataSourceDiagnosticResult,\n ExternalGraphQlApiDefinition,\n} from '@ankhorage/contracts/data';\n\nimport {\n normalizeGraphQlIntrospectionOperations,\n normalizeGraphQlIntrospectionSchemas,\n} from './introspection';\nimport { normalizeGraphQlOperation } from './operation';\nimport type { GraphQlApiDefinition } from './types';\n\nexport {\n normalizeGraphQlIntrospectionOperations,\n normalizeGraphQlIntrospectionSchemas,\n} from './introspection';\nexport { normalizeGraphQlOperationId } from './operation';\nexport type * from './types';\n\nexport 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}`;\n\nexport interface GraphQlIntrospectionRequest {\n readonly query: typeof GRAPHQL_INTROSPECTION_QUERY;\n readonly operationName: 'AnkhorageGraphQlIntrospection';\n}\n\nexport function createGraphQlIntrospectionRequest(): GraphQlIntrospectionRequest {\n return {\n query: GRAPHQL_INTROSPECTION_QUERY,\n operationName: 'AnkhorageGraphQlIntrospection',\n };\n}\n\nexport function createGraphQlApi(\n definition: GraphQlApiDefinition,\n): DataSourceDiagnosticResult<ExternalGraphQlApiDefinition> {\n const diagnostics = validateGraphQlApi(definition);\n if (diagnostics.some((diagnostic) => diagnostic.severity === 'error')) {\n return { ok: false, diagnostics };\n }\n return { ok: true, data: normalizeGraphQlApi(definition), diagnostics };\n}\n\nexport function validateGraphQlApi(\n definition: GraphQlApiDefinition,\n): readonly DataSourceDiagnostic[] {\n const diagnostics: DataSourceDiagnostic[] = [];\n\n if (definition.endpointUrl.trim().length === 0) {\n diagnostics.push({\n code: 'invalid-config',\n apiId: definition.id,\n message: 'GraphQL API requires a non-empty endpointUrl.',\n path: 'endpointUrl',\n severity: 'error',\n });\n }\n if (definition.introspectionEnabled === false && definition.introspection !== undefined) {\n diagnostics.push({\n code: 'invalid-config',\n apiId: definition.id,\n message: 'GraphQL introspection data was provided while introspection is disabled.',\n path: 'introspection',\n severity: 'warning',\n });\n }\n if (definition.introspectionEnabled !== false && definition.introspection === undefined) {\n diagnostics.push({\n code: 'missing-schema',\n apiId: definition.id,\n message:\n 'GraphQL introspection result was not provided. Manual operations can still be used.',\n path: 'introspection',\n severity: 'info',\n });\n }\n return diagnostics;\n}\n\nexport function normalizeGraphQlApi(\n definition: GraphQlApiDefinition,\n): ExternalGraphQlApiDefinition {\n const schemas = normalizeGraphQlIntrospectionSchemas(definition.introspection);\n const discovered = normalizeGraphQlIntrospectionOperations(definition.introspection);\n const operations = Object.fromEntries(\n [...discovered, ...(definition.operations ?? [])].map((operation) => [\n operation.id,\n normalizeGraphQlOperation(operation),\n ]),\n );\n const endpoint: DataEndpointConfig = {\n id: 'graphql',\n kind: 'graphql',\n credential: definition.credential,\n operations,\n metadata: { source: 'graphql' },\n };\n return {\n id: definition.id,\n origin: 'external',\n protocol: 'graphql',\n name: definition.name,\n description: definition.description,\n endpointUrl: definition.endpointUrl,\n credential: definition.credential,\n endpoints: { graphql: endpoint },\n schemas,\n introspection: {\n enabled: definition.introspectionEnabled ?? definition.introspection !== undefined,\n schemaVersion: definition.schemaVersion,\n },\n metadata: definition.metadata,\n };\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import type { DataSchemaRegistry } from '@ankhorage/contracts/data';
2
+ import type { GraphQlIntrospectionResult, GraphQlOperationDefinition } from './types';
3
+ export declare function normalizeGraphQlIntrospectionSchemas(introspection: GraphQlIntrospectionResult | undefined): DataSchemaRegistry | undefined;
4
+ export declare function normalizeGraphQlIntrospectionOperations(introspection: GraphQlIntrospectionResult | undefined): readonly GraphQlOperationDefinition[];
5
+ //# sourceMappingURL=introspection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspection.d.ts","sourceRoot":"","sources":["../../src/graphql/introspection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGhF,OAAO,KAAK,EAEV,0BAA0B,EAG1B,0BAA0B,EAE3B,MAAM,SAAS,CAAC;AAIjB,wBAAgB,oCAAoC,CAClD,aAAa,EAAE,0BAA0B,GAAG,SAAS,GACpD,kBAAkB,GAAG,SAAS,CAQhC;AAED,wBAAgB,uCAAuC,CACrD,aAAa,EAAE,0BAA0B,GAAG,SAAS,GACpD,SAAS,0BAA0B,EAAE,CAUvC"}
@@ -0,0 +1,136 @@
1
+ import { normalizeGraphQlOperationId } from './operation';
2
+ const OBJECT_TYPE_KINDS = new Set(['OBJECT', 'INTERFACE', 'INPUT_OBJECT']);
3
+ export function normalizeGraphQlIntrospectionSchemas(introspection) {
4
+ const types = introspection?.__schema?.types?.filter(isNamedGraphQlType) ?? [];
5
+ const entries = types.flatMap((type) => {
6
+ const { name } = type;
7
+ if (name === undefined || name === null || name.startsWith('__'))
8
+ return [];
9
+ return [[name, normalizeGraphQlType(type)]];
10
+ });
11
+ return entries.length === 0 ? undefined : Object.fromEntries(entries);
12
+ }
13
+ export function normalizeGraphQlIntrospectionOperations(introspection) {
14
+ const schema = introspection?.__schema;
15
+ if (schema === undefined)
16
+ return [];
17
+ const types = schema.types?.filter(isNamedGraphQlType) ?? [];
18
+ return [
19
+ ...normalizeRootOperations('query', schema.queryType?.name, types),
20
+ ...normalizeRootOperations('mutation', schema.mutationType?.name, types),
21
+ ...normalizeRootOperations('subscription', schema.subscriptionType?.name, types),
22
+ ];
23
+ }
24
+ function normalizeRootOperations(kind, rootTypeName, types) {
25
+ if (rootTypeName === undefined || rootTypeName === null)
26
+ return [];
27
+ const rootType = types.find((type) => type.name === rootTypeName);
28
+ return (rootType?.fields ?? []).map((field) => ({
29
+ id: normalizeGraphQlOperationId(kind, field.name),
30
+ kind,
31
+ name: field.name,
32
+ description: field.description ?? undefined,
33
+ variables: normalizeGraphQlVariablesSchema(field.args ?? []),
34
+ response: normalizeGraphQlTypeRef(field.type),
35
+ selectionPath: `$.data.${field.name}`,
36
+ metadata: { rootType: rootTypeName, source: 'introspection' },
37
+ }));
38
+ }
39
+ function normalizeGraphQlVariablesSchema(args) {
40
+ const properties = Object.fromEntries(args.map((arg) => [
41
+ arg.name,
42
+ {
43
+ ...normalizeGraphQlTypeRef(arg.type),
44
+ description: arg.description ?? undefined,
45
+ default: arg.defaultValue ?? undefined,
46
+ },
47
+ ]));
48
+ const required = args.filter((arg) => isGraphQlNonNull(arg.type)).map((arg) => arg.name);
49
+ return {
50
+ type: 'object',
51
+ required: required.length > 0 ? required : undefined,
52
+ properties,
53
+ };
54
+ }
55
+ function normalizeGraphQlType(type) {
56
+ if (OBJECT_TYPE_KINDS.has(type.kind))
57
+ return normalizeGraphQlObjectType(type);
58
+ if (type.kind === 'ENUM')
59
+ return normalizeGraphQlEnumType(type);
60
+ if (type.kind === 'SCALAR')
61
+ return normalizeGraphQlScalarType(type);
62
+ if (type.kind === 'UNION')
63
+ return normalizeGraphQlUnionType(type);
64
+ return { title: type.name ?? undefined, description: type.description ?? undefined };
65
+ }
66
+ function normalizeGraphQlEnumType(type) {
67
+ return {
68
+ type: 'string',
69
+ title: type.name ?? undefined,
70
+ description: type.description ?? undefined,
71
+ enum: type.enumValues?.map((value) => value.name),
72
+ };
73
+ }
74
+ function normalizeGraphQlScalarType(type) {
75
+ return {
76
+ ...normalizeGraphQlNamedScalar(type.name),
77
+ title: type.name ?? undefined,
78
+ description: type.description ?? undefined,
79
+ };
80
+ }
81
+ function normalizeGraphQlUnionType(type) {
82
+ return {
83
+ title: type.name ?? undefined,
84
+ description: type.description ?? undefined,
85
+ anyOf: type.possibleTypes?.map(normalizeGraphQlTypeRef),
86
+ };
87
+ }
88
+ function normalizeGraphQlObjectType(type) {
89
+ const fields = type.kind === 'INPUT_OBJECT' ? type.inputFields : type.fields;
90
+ const entries = (fields ?? []).map((field) => [
91
+ field.name,
92
+ {
93
+ ...normalizeGraphQlTypeRef(field.type),
94
+ description: field.description ?? undefined,
95
+ },
96
+ ]);
97
+ const required = (fields ?? [])
98
+ .filter((field) => isGraphQlNonNull(field.type))
99
+ .map((field) => field.name);
100
+ return {
101
+ type: 'object',
102
+ title: type.name ?? undefined,
103
+ description: type.description ?? undefined,
104
+ required: required.length > 0 ? required : undefined,
105
+ properties: Object.fromEntries(entries),
106
+ };
107
+ }
108
+ function normalizeGraphQlTypeRef(type) {
109
+ if (type.kind === 'NON_NULL' && type.ofType !== undefined && type.ofType !== null) {
110
+ return { ...normalizeGraphQlTypeRef(type.ofType), nullable: false };
111
+ }
112
+ if (type.kind === 'LIST' && type.ofType !== undefined && type.ofType !== null) {
113
+ return { type: 'array', items: normalizeGraphQlTypeRef(type.ofType) };
114
+ }
115
+ if (type.kind === 'SCALAR')
116
+ return normalizeGraphQlNamedScalar(type.name);
117
+ return type.name === undefined || type.name === null ? {} : { ref: { id: type.name } };
118
+ }
119
+ function normalizeGraphQlNamedScalar(name) {
120
+ if (name === 'Boolean')
121
+ return { type: 'boolean' };
122
+ if (name === 'Float')
123
+ return { type: 'number' };
124
+ if (name === 'ID' || name === 'String')
125
+ return { type: 'string' };
126
+ if (name === 'Int')
127
+ return { type: 'integer' };
128
+ return { type: 'string', format: name ?? undefined };
129
+ }
130
+ function isGraphQlNonNull(type) {
131
+ return type.kind === 'NON_NULL';
132
+ }
133
+ function isNamedGraphQlType(type) {
134
+ return type.name !== undefined && type.name !== null;
135
+ }
136
+ //# sourceMappingURL=introspection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspection.js","sourceRoot":"","sources":["../../src/graphql/introspection.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DataSchema, DataSchemaRegistry } from '@ankhorage/contracts/data';\n\nimport { normalizeGraphQlOperationId } from './operation';\nimport type {\n GraphQlIntrospectionInputValue,\n GraphQlIntrospectionResult,\n GraphQlIntrospectionType,\n GraphQlIntrospectionTypeRef,\n GraphQlOperationDefinition,\n GraphQlOperationKind,\n} from './types';\n\nconst OBJECT_TYPE_KINDS = new Set(['OBJECT', 'INTERFACE', 'INPUT_OBJECT']);\n\nexport function normalizeGraphQlIntrospectionSchemas(\n introspection: GraphQlIntrospectionResult | undefined,\n): DataSchemaRegistry | undefined {\n const types = introspection?.__schema?.types?.filter(isNamedGraphQlType) ?? [];\n const entries = types.flatMap((type) => {\n const { name } = type;\n if (name === undefined || name === null || name.startsWith('__')) return [];\n return [[name, normalizeGraphQlType(type)] as const];\n });\n return entries.length === 0 ? undefined : Object.fromEntries(entries);\n}\n\nexport function normalizeGraphQlIntrospectionOperations(\n introspection: GraphQlIntrospectionResult | undefined,\n): readonly GraphQlOperationDefinition[] {\n const schema = introspection?.__schema;\n if (schema === undefined) return [];\n\n const types = schema.types?.filter(isNamedGraphQlType) ?? [];\n return [\n ...normalizeRootOperations('query', schema.queryType?.name, types),\n ...normalizeRootOperations('mutation', schema.mutationType?.name, types),\n ...normalizeRootOperations('subscription', schema.subscriptionType?.name, types),\n ];\n}\n\nfunction normalizeRootOperations(\n kind: GraphQlOperationKind,\n rootTypeName: string | null | undefined,\n types: readonly GraphQlIntrospectionType[],\n): readonly GraphQlOperationDefinition[] {\n if (rootTypeName === undefined || rootTypeName === null) return [];\n const rootType = types.find((type) => type.name === rootTypeName);\n return (rootType?.fields ?? []).map((field) => ({\n id: normalizeGraphQlOperationId(kind, field.name),\n kind,\n name: field.name,\n description: field.description ?? undefined,\n variables: normalizeGraphQlVariablesSchema(field.args ?? []),\n response: normalizeGraphQlTypeRef(field.type),\n selectionPath: `$.data.${field.name}`,\n metadata: { rootType: rootTypeName, source: 'introspection' },\n }));\n}\n\nfunction normalizeGraphQlVariablesSchema(\n args: readonly GraphQlIntrospectionInputValue[],\n): DataSchema {\n const properties = Object.fromEntries(\n args.map((arg) => [\n arg.name,\n {\n ...normalizeGraphQlTypeRef(arg.type),\n description: arg.description ?? undefined,\n default: arg.defaultValue ?? undefined,\n },\n ]),\n );\n const required = args.filter((arg) => isGraphQlNonNull(arg.type)).map((arg) => arg.name);\n return {\n type: 'object',\n required: required.length > 0 ? required : undefined,\n properties,\n };\n}\n\nfunction normalizeGraphQlType(type: GraphQlIntrospectionType): DataSchema {\n if (OBJECT_TYPE_KINDS.has(type.kind)) return normalizeGraphQlObjectType(type);\n if (type.kind === 'ENUM') return normalizeGraphQlEnumType(type);\n if (type.kind === 'SCALAR') return normalizeGraphQlScalarType(type);\n if (type.kind === 'UNION') return normalizeGraphQlUnionType(type);\n return { title: type.name ?? undefined, description: type.description ?? undefined };\n}\n\nfunction normalizeGraphQlEnumType(type: GraphQlIntrospectionType): DataSchema {\n return {\n type: 'string',\n title: type.name ?? undefined,\n description: type.description ?? undefined,\n enum: type.enumValues?.map((value) => value.name),\n };\n}\n\nfunction normalizeGraphQlScalarType(type: GraphQlIntrospectionType): DataSchema {\n return {\n ...normalizeGraphQlNamedScalar(type.name),\n title: type.name ?? undefined,\n description: type.description ?? undefined,\n };\n}\n\nfunction normalizeGraphQlUnionType(type: GraphQlIntrospectionType): DataSchema {\n return {\n title: type.name ?? undefined,\n description: type.description ?? undefined,\n anyOf: type.possibleTypes?.map(normalizeGraphQlTypeRef),\n };\n}\n\nfunction normalizeGraphQlObjectType(type: GraphQlIntrospectionType): DataSchema {\n const fields = type.kind === 'INPUT_OBJECT' ? type.inputFields : type.fields;\n const entries = (fields ?? []).map(\n (field) =>\n [\n field.name,\n {\n ...normalizeGraphQlTypeRef(field.type),\n description: field.description ?? undefined,\n },\n ] as const,\n );\n const required = (fields ?? [])\n .filter((field) => isGraphQlNonNull(field.type))\n .map((field) => field.name);\n return {\n type: 'object',\n title: type.name ?? undefined,\n description: type.description ?? undefined,\n required: required.length > 0 ? required : undefined,\n properties: Object.fromEntries(entries),\n };\n}\n\nfunction normalizeGraphQlTypeRef(type: GraphQlIntrospectionTypeRef): DataSchema {\n if (type.kind === 'NON_NULL' && type.ofType !== undefined && type.ofType !== null) {\n return { ...normalizeGraphQlTypeRef(type.ofType), nullable: false };\n }\n if (type.kind === 'LIST' && type.ofType !== undefined && type.ofType !== null) {\n return { type: 'array', items: normalizeGraphQlTypeRef(type.ofType) };\n }\n if (type.kind === 'SCALAR') return normalizeGraphQlNamedScalar(type.name);\n return type.name === undefined || type.name === null ? {} : { ref: { id: type.name } };\n}\n\nfunction normalizeGraphQlNamedScalar(name: string | null | undefined): DataSchema {\n if (name === 'Boolean') return { type: 'boolean' };\n if (name === 'Float') return { type: 'number' };\n if (name === 'ID' || name === 'String') return { type: 'string' };\n if (name === 'Int') return { type: 'integer' };\n return { type: 'string', format: name ?? undefined };\n}\n\nfunction isGraphQlNonNull(type: GraphQlIntrospectionTypeRef): boolean {\n return type.kind === 'NON_NULL';\n}\n\nfunction isNamedGraphQlType(type: GraphQlIntrospectionType): boolean {\n return type.name !== undefined && type.name !== null;\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import type { DataOperationConfig, OperationId } from '@ankhorage/contracts/data';
2
+ import type { GraphQlOperationDefinition, GraphQlOperationKind } from './types';
3
+ export declare function normalizeGraphQlOperationId(kind: GraphQlOperationKind, name: string): OperationId;
4
+ export declare function normalizeGraphQlOperation(operation: GraphQlOperationDefinition): DataOperationConfig;
5
+ //# sourceMappingURL=operation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation.d.ts","sourceRoot":"","sources":["../../src/graphql/operation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,mBAAmB,EAGnB,WAAW,EACZ,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAIhF,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAMjG;AAED,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,0BAA0B,GACpC,mBAAmB,CAcrB"}
@@ -0,0 +1,39 @@
1
+ export function normalizeGraphQlOperationId(kind, name) {
2
+ const normalizedName = name
3
+ .replace(/[^A-Za-z0-9]+/g, '-')
4
+ .replace(/^-+|-+$/g, '')
5
+ .toLowerCase();
6
+ return normalizedName.length > 0 ? `${kind}.${normalizedName}` : `${kind}.operation`;
7
+ }
8
+ export function normalizeGraphQlOperation(operation) {
9
+ const response = operation.response === undefined ? undefined : { schema: operation.response };
10
+ return {
11
+ id: operation.id,
12
+ endpointId: 'graphql',
13
+ name: operation.name,
14
+ description: operation.description,
15
+ protocol: 'graphql',
16
+ intent: mapGraphQlOperationKindToIntent(operation.kind),
17
+ request: { schema: operation.variables },
18
+ response,
19
+ metadata: createGraphQlOperationMetadata(operation),
20
+ };
21
+ }
22
+ function mapGraphQlOperationKindToIntent(kind) {
23
+ return kind === 'query' || kind === 'subscription' ? 'read' : 'action';
24
+ }
25
+ function createGraphQlOperationMetadata(operation) {
26
+ return {
27
+ ...toMetadataRecord(operation.metadata),
28
+ kind: operation.kind,
29
+ ...(operation.document === undefined ? {} : { document: operation.document }),
30
+ ...(operation.selectionPath === undefined ? {} : { selectionPath: operation.selectionPath }),
31
+ };
32
+ }
33
+ function toMetadataRecord(value) {
34
+ return isDataContractRecord(value) ? { ...value } : {};
35
+ }
36
+ function isDataContractRecord(value) {
37
+ return (value !== undefined && typeof value === 'object' && value !== null && !Array.isArray(value));
38
+ }
39
+ //# sourceMappingURL=operation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation.js","sourceRoot":"","sources":["../../src/graphql/operation.ts"],"names":[],"mappings":"AAYA,MAAM,UAAU,2BAA2B,CAAC,IAA0B,EAAE,IAAY;IAClF,MAAM,cAAc,GAAG,IAAI;SACxB,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC;SAC9B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,WAAW,EAAE,CAAC;IACjB,OAAO,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,cAAc,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,YAAY,CAAC;AACvF,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,SAAqC;IAErC,MAAM,QAAQ,GACZ,SAAS,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC;IAChF,OAAO;QACL,EAAE,EAAE,SAAS,CAAC,EAAE;QAChB,UAAU,EAAE,SAAS;QACrB,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,WAAW,EAAE,SAAS,CAAC,WAAW;QAClC,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,+BAA+B,CAAC,SAAS,CAAC,IAAI,CAAC;QACvD,OAAO,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,EAAE;QACxC,QAAQ;QACR,QAAQ,EAAE,8BAA8B,CAAC,SAAS,CAAC;KACpD,CAAC;AACJ,CAAC;AAED,SAAS,+BAA+B,CAAC,IAA0B;IACjE,OAAO,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AACzE,CAAC;AAED,SAAS,8BAA8B,CAAC,SAAqC;IAC3E,OAAO;QACL,GAAG,gBAAgB,CAAC,SAAS,CAAC,QAAQ,CAAC;QACvC,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,GAAG,CAAC,SAAS,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC;QAC7E,GAAG,CAAC,SAAS,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,SAAS,CAAC,aAAa,EAAE,CAAC;KAC7F,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAoC;IAC5D,OAAO,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACzD,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAoC;IAChE,OAAO,CACL,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAC5F,CAAC;AACJ,CAAC","sourcesContent":["import type {\n DataContractValue,\n DataOperationConfig,\n DataOperationIntent,\n DataOperationResponse,\n OperationId,\n} from '@ankhorage/contracts/data';\n\nimport type { GraphQlOperationDefinition, GraphQlOperationKind } from './types';\n\ntype DataContractRecord = Record<string, DataContractValue>;\n\nexport function normalizeGraphQlOperationId(kind: GraphQlOperationKind, name: string): OperationId {\n const normalizedName = name\n .replace(/[^A-Za-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .toLowerCase();\n return normalizedName.length > 0 ? `${kind}.${normalizedName}` : `${kind}.operation`;\n}\n\nexport function normalizeGraphQlOperation(\n operation: GraphQlOperationDefinition,\n): DataOperationConfig {\n const response: DataOperationResponse | undefined =\n operation.response === undefined ? undefined : { schema: operation.response };\n return {\n id: operation.id,\n endpointId: 'graphql',\n name: operation.name,\n description: operation.description,\n protocol: 'graphql',\n intent: mapGraphQlOperationKindToIntent(operation.kind),\n request: { schema: operation.variables },\n response,\n metadata: createGraphQlOperationMetadata(operation),\n };\n}\n\nfunction mapGraphQlOperationKindToIntent(kind: GraphQlOperationKind): DataOperationIntent {\n return kind === 'query' || kind === 'subscription' ? 'read' : 'action';\n}\n\nfunction createGraphQlOperationMetadata(operation: GraphQlOperationDefinition): DataContractRecord {\n return {\n ...toMetadataRecord(operation.metadata),\n kind: operation.kind,\n ...(operation.document === undefined ? {} : { document: operation.document }),\n ...(operation.selectionPath === undefined ? {} : { selectionPath: operation.selectionPath }),\n };\n}\n\nfunction toMetadataRecord(value: DataContractValue | undefined): DataContractRecord {\n return isDataContractRecord(value) ? { ...value } : {};\n}\n\nfunction isDataContractRecord(value: DataContractValue | undefined): value is DataContractRecord {\n return (\n value !== undefined && typeof value === 'object' && value !== null && !Array.isArray(value)\n );\n}\n"]}
@@ -0,0 +1,71 @@
1
+ import type { CredentialRef, DataContractValue, DataSchema, OperationId } from '@ankhorage/contracts/data';
2
+ export type GraphQlOperationKind = 'mutation' | 'query' | 'subscription';
3
+ export interface GraphQlIntrospectionTypeRef {
4
+ readonly kind: string;
5
+ readonly name?: string | null;
6
+ readonly ofType?: GraphQlIntrospectionTypeRef | null;
7
+ }
8
+ export interface GraphQlIntrospectionInputValue {
9
+ readonly name: string;
10
+ readonly description?: string | null;
11
+ readonly type: GraphQlIntrospectionTypeRef;
12
+ readonly defaultValue?: string | null;
13
+ }
14
+ export interface GraphQlIntrospectionField {
15
+ readonly name: string;
16
+ readonly description?: string | null;
17
+ readonly args?: readonly GraphQlIntrospectionInputValue[] | null;
18
+ readonly type: GraphQlIntrospectionTypeRef;
19
+ }
20
+ export interface GraphQlIntrospectionEnumValue {
21
+ readonly name: string;
22
+ readonly description?: string | null;
23
+ }
24
+ export interface GraphQlIntrospectionType {
25
+ readonly kind: string;
26
+ readonly name?: string | null;
27
+ readonly description?: string | null;
28
+ readonly fields?: readonly GraphQlIntrospectionField[] | null;
29
+ readonly inputFields?: readonly GraphQlIntrospectionInputValue[] | null;
30
+ readonly enumValues?: readonly GraphQlIntrospectionEnumValue[] | null;
31
+ readonly possibleTypes?: readonly GraphQlIntrospectionTypeRef[] | null;
32
+ }
33
+ export interface GraphQlIntrospectionSchema {
34
+ readonly queryType?: {
35
+ readonly name?: string | null;
36
+ } | null;
37
+ readonly mutationType?: {
38
+ readonly name?: string | null;
39
+ } | null;
40
+ readonly subscriptionType?: {
41
+ readonly name?: string | null;
42
+ } | null;
43
+ readonly types?: readonly GraphQlIntrospectionType[] | null;
44
+ }
45
+ export interface GraphQlIntrospectionResult {
46
+ readonly __schema?: GraphQlIntrospectionSchema;
47
+ }
48
+ export interface GraphQlOperationDefinition {
49
+ readonly id: OperationId;
50
+ readonly kind: GraphQlOperationKind;
51
+ readonly name?: string;
52
+ readonly description?: string;
53
+ readonly document?: string;
54
+ readonly variables?: DataSchema;
55
+ readonly response?: DataSchema;
56
+ readonly selectionPath?: string;
57
+ readonly metadata?: DataContractValue;
58
+ }
59
+ export interface GraphQlApiDefinition {
60
+ readonly id: string;
61
+ readonly endpointUrl: string;
62
+ readonly name?: string;
63
+ readonly description?: string;
64
+ readonly credential?: CredentialRef;
65
+ readonly introspection?: GraphQlIntrospectionResult;
66
+ readonly introspectionEnabled?: boolean;
67
+ readonly schemaVersion?: string;
68
+ readonly operations?: readonly GraphQlOperationDefinition[];
69
+ readonly metadata?: DataContractValue;
70
+ }
71
+ //# sourceMappingURL=types.d.ts.map