| @@ -9,6 +9,7 @@ import { · 8 unmodified lines |
| 9 | 9 | OpenApiParseError, |
| 10 | 10 | type Authentication, |
| 11 | 11 | type OpenApiIntegrationConfig, |
| 12 | + type ParsedDocument, |
| 12 | 13 | } from "@executor-js/plugin-openapi"; |
| 13 | 14 | |
| 14 | 15 | import { |
| @@ -41,6 +42,7 @@ export interface MicrosoftGraphSelectionInput { · 26 unmodified lines |
| 41 | 42 | |
| 42 | 43 | export interface MicrosoftGraphSpecBuild { |
| 43 | 44 | readonly specText: string; |
| 45 | + readonly parsedDocument?: ParsedDocument; |
| 44 | 46 | readonly specUrl: string; |
| 45 | 47 | readonly baseUrl?: string; |
| 46 | 48 | readonly authorizationUrl: string; |
| @@ -90,6 +92,8 @@ const MicrosoftGraphIntegrationConfigSchema = Schema.Struct({ · 43 unmodified lines |
| 90 | 92 | |
| 91 | 93 | const decodeMicrosoftConfig = Schema.decodeUnknownOption(MicrosoftGraphIntegrationConfigSchema); |
| 92 | 94 | |
| 95 | +type MicrosoftGraphOpenApiDocument = ParsedDocument & Record<string, unknown>; |
| 96 | + |
| 93 | 97 | export const decodeMicrosoftGraphIntegrationConfig = ( |
| 94 | 98 | value: unknown, |
| 95 | 99 | ): MicrosoftGraphIntegrationConfig | null => |
| @@ -478,7 +482,7 @@ export const fetchMicrosoftGraphPermissionsReference = Effect.fn( · 382 unmodified lines |
| 478 | 482 | |
| 479 | 483 | const parseMicrosoftGraphOpenApiDocument = ( |
| 480 | 484 | specText: string, |
| 481 | | −): Effect.Effect<Record<string, unknown>, OpenApiParseError> => |
| 485 | +): Effect.Effect<MicrosoftGraphOpenApiDocument, OpenApiParseError> => |
| 482 | 486 | Effect.gen(function* () { |
| 483 | 487 | const parsed = yield* Effect.try({ |
| 484 | 488 | try: () => YAML.parse(specText) as unknown, |
| @@ -492,11 +496,16 @@ const parseMicrosoftGraphOpenApiDocument = ( · 7 unmodified lines |
| 492 | 496 | message: "Microsoft Graph OpenAPI document must be an object", |
| 493 | 497 | }); |
| 494 | 498 | } |
| 495 | | − return parsed; |
| 499 | + if (typeof parsed.openapi !== "string" || !parsed.openapi.startsWith("3.")) { |
| 500 | + return yield* new OpenApiParseError({ |
| 501 | + message: "Microsoft Graph OpenAPI document must be OpenAPI 3.x", |
| 502 | + }); |
| 503 | + } |
| 504 | + return parsed as MicrosoftGraphOpenApiDocument; |
| 496 | 505 | }); |
| 497 | 506 | |
| 498 | | −export const buildFilteredMicrosoftGraphOpenApiSpec = ( |
| 499 | | − specText: string, |
| 507 | +export const buildFilteredMicrosoftGraphOpenApiSpecFromDocument = ( |
| 508 | + parsed: MicrosoftGraphOpenApiDocument, |
| 500 | 509 | options: { |
| 501 | 510 | readonly scopes: readonly string[]; |
| 502 | 511 | readonly exactPaths: readonly string[]; |
| @@ -510,7 +519,6 @@ export const buildFilteredMicrosoftGraphOpenApiSpec = ( · 7 unmodified lines |
| 510 | 519 | }, |
| 511 | 520 | ): Effect.Effect<MicrosoftGraphFilterResult, OpenApiParseError> => |
| 512 | 521 | Effect.gen(function* () { |
| 513 | | − const parsed = yield* parseMicrosoftGraphOpenApiDocument(specText); |
| 514 | 522 | const paths = parsed.paths; |
| 515 | 523 | if (!isRecord(paths)) { |
| 516 | 524 | return yield* new OpenApiParseError({ |
| @@ -578,6 +586,15 @@ export const buildFilteredMicrosoftGraphOpenApiSpec = ( · 61 unmodified lines |
| 578 | 586 | return { specText: filteredSpecText, scopes }; |
| 579 | 587 | }); |
| 580 | 588 | |
| 589 | +export const buildFilteredMicrosoftGraphOpenApiSpec = ( |
| 590 | + specText: string, |
| 591 | + options: Parameters<typeof buildFilteredMicrosoftGraphOpenApiSpecFromDocument>[1], |
| 592 | +): Effect.Effect<MicrosoftGraphFilterResult, OpenApiParseError> => |
| 593 | + Effect.gen(function* () { |
| 594 | + const parsed = yield* parseMicrosoftGraphOpenApiDocument(specText); |
| 595 | + return yield* buildFilteredMicrosoftGraphOpenApiSpecFromDocument(parsed, options); |
| 596 | + }); |
| 597 | + |
| 581 | 598 | export const filterMicrosoftGraphOpenApiSpec = ( |
| 582 | 599 | specText: string, |
| 583 | 600 | options: Parameters<typeof buildFilteredMicrosoftGraphOpenApiSpec>[1], |
| @@ -604,12 +621,32 @@ export const buildMicrosoftGraphOpenApiSpec = ( · 20 unmodified lines |
| 604 | 621 | : []; |
| 605 | 622 | const parsed = yield* parseMicrosoftGraphOpenApiDocument(sourceText); |
| 606 | 623 | const endpoints = resolveOAuthEndpoints(parsed, selection); |
| 607 | | − const filtered = yield* buildFilteredMicrosoftGraphOpenApiSpec(sourceText, { |
| 624 | + const graphPaths = parsed.paths; |
| 625 | + if (!isRecord(graphPaths)) { |
| 626 | + return yield* new OpenApiParseError({ |
| 627 | + message: "Microsoft Graph OpenAPI document is missing paths", |
| 628 | + }); |
| 629 | + } |
| 630 | + if (selection.coversFullGraph === true) { |
| 631 | + const scopes = selectedOAuthScopesForPaths( |
| 632 | + graphPaths, |
| 633 | + uniqueStrings([...MICROSOFT_GRAPH_BASE_SCOPES, ...selection.customScopes]), |
| 634 | + fullGraphScopes, |
| 635 | + ); |
| 636 | + return { |
| 637 | + ...selection, |
| 638 | + specText: sourceText, |
| 639 | + parsedDocument: parsed, |
| 640 | + scopes, |
| 641 | + authorizationUrl: endpoints.authorizationUrl, |
| 642 | + tokenUrl: endpoints.tokenUrl, |
| 643 | + clientCredentialsTokenUrl: endpoints.clientCredentialsTokenUrl, |
| 644 | + authenticationTemplate: microsoftOAuthTemplate(scopes, endpoints), |
| 645 | + }; |
| 646 | + } |
| 647 | + const filtered = yield* buildFilteredMicrosoftGraphOpenApiSpecFromDocument(parsed, { |
| 608 | 648 | ...selection, |
| 609 | | − scopes: |
| 610 | | − selection.coversFullGraph === true |
| 611 | | − ? uniqueStrings([...MICROSOFT_GRAPH_BASE_SCOPES, ...selection.customScopes]) |
| 612 | | − : selection.scopes, |
| 649 | + scopes: selection.scopes, |
| 613 | 650 | fullGraphScopes, |
| 614 | 651 | }); |
| 615 | 652 | return { |