| @@ -9,6 +9,7 @@ import { · 8 unmodified lines |
| 9 | OpenApiParseError, | 9 | OpenApiParseError, |
| 10 | type Authentication, | 10 | type Authentication, |
| 11 | type OpenApiIntegrationConfig, | 11 | type OpenApiIntegrationConfig, |
| | 12 | type ParsedDocument, |
| 12 | } from "@executor-js/plugin-openapi"; | 13 | } from "@executor-js/plugin-openapi"; |
| 13 | | 14 | |
| 14 | import { | 15 | import { |
| @@ -41,6 +42,7 @@ export interface MicrosoftGraphSelectionInput { · 26 unmodified lines |
| 41 | | 42 | |
| 42 | export interface MicrosoftGraphSpecBuild { | 43 | export interface MicrosoftGraphSpecBuild { |
| 43 | readonly specText: string; | 44 | readonly specText: string; |
| | 45 | readonly parsedDocument?: ParsedDocument; |
| 44 | readonly specUrl: string; | 46 | readonly specUrl: string; |
| 45 | readonly baseUrl?: string; | 47 | readonly baseUrl?: string; |
| 46 | readonly authorizationUrl: string; | 48 | readonly authorizationUrl: string; |
| @@ -90,6 +92,8 @@ const MicrosoftGraphIntegrationConfigSchema = Schema.Struct({ · 43 unmodified lines |
| 90 | | 92 | |
| 91 | const decodeMicrosoftConfig = Schema.decodeUnknownOption(MicrosoftGraphIntegrationConfigSchema); | 93 | const decodeMicrosoftConfig = Schema.decodeUnknownOption(MicrosoftGraphIntegrationConfigSchema); |
| 92 | | 94 | |
| | 95 | type MicrosoftGraphOpenApiDocument = ParsedDocument & Record<string, unknown>; |
| | 96 | |
| 93 | export const decodeMicrosoftGraphIntegrationConfig = ( | 97 | export const decodeMicrosoftGraphIntegrationConfig = ( |
| 94 | value: unknown, | 98 | value: unknown, |
| 95 | ): MicrosoftGraphIntegrationConfig | null => | 99 | ): MicrosoftGraphIntegrationConfig | null => |
| @@ -478,7 +482,7 @@ export const fetchMicrosoftGraphPermissionsReference = Effect.fn( · 382 unmodified lines |
| 478 | | 482 | |
| 479 | const parseMicrosoftGraphOpenApiDocument = ( | 483 | const parseMicrosoftGraphOpenApiDocument = ( |
| 480 | specText: string, | 484 | specText: string, |
| 481 | ): Effect.Effect<Record<string, unknown>, OpenApiParseError> => | 485 | ): Effect.Effect<MicrosoftGraphOpenApiDocument, OpenApiParseError> => |
| 482 | Effect.gen(function* () { | 486 | Effect.gen(function* () { |
| 483 | const parsed = yield* Effect.try({ | 487 | const parsed = yield* Effect.try({ |
| 484 | try: () => YAML.parse(specText) as unknown, | 488 | try: () => YAML.parse(specText) as unknown, |
| @@ -492,11 +496,16 @@ const parseMicrosoftGraphOpenApiDocument = ( · 7 unmodified lines |
| 492 | message: "Microsoft Graph OpenAPI document must be an object", | 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 = ( | 507 | export const buildFilteredMicrosoftGraphOpenApiSpecFromDocument = ( |
| 499 | specText: string, | 508 | parsed: MicrosoftGraphOpenApiDocument, |
| 500 | options: { | 509 | options: { |
| 501 | readonly scopes: readonly string[]; | 510 | readonly scopes: readonly string[]; |
| 502 | readonly exactPaths: readonly string[]; | 511 | readonly exactPaths: readonly string[]; |
| @@ -510,7 +519,6 @@ export const buildFilteredMicrosoftGraphOpenApiSpec = ( · 7 unmodified lines |
| 510 | }, | 519 | }, |
| 511 | ): Effect.Effect<MicrosoftGraphFilterResult, OpenApiParseError> => | 520 | ): Effect.Effect<MicrosoftGraphFilterResult, OpenApiParseError> => |
| 512 | Effect.gen(function* () { | 521 | Effect.gen(function* () { |
| 513 | const parsed = yield* parseMicrosoftGraphOpenApiDocument(specText); | | |
| 514 | const paths = parsed.paths; | 522 | const paths = parsed.paths; |
| 515 | if (!isRecord(paths)) { | 523 | if (!isRecord(paths)) { |
| 516 | return yield* new OpenApiParseError({ | 524 | return yield* new OpenApiParseError({ |
| @@ -578,6 +586,15 @@ export const buildFilteredMicrosoftGraphOpenApiSpec = ( · 61 unmodified lines |
| 578 | return { specText: filteredSpecText, scopes }; | 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 | export const filterMicrosoftGraphOpenApiSpec = ( | 598 | export const filterMicrosoftGraphOpenApiSpec = ( |
| 582 | specText: string, | 599 | specText: string, |
| 583 | options: Parameters<typeof buildFilteredMicrosoftGraphOpenApiSpec>[1], | 600 | options: Parameters<typeof buildFilteredMicrosoftGraphOpenApiSpec>[1], |
| @@ -604,12 +621,32 @@ export const buildMicrosoftGraphOpenApiSpec = ( · 20 unmodified lines |
| 604 | : []; | 621 | : []; |
| 605 | const parsed = yield* parseMicrosoftGraphOpenApiDocument(sourceText); | 622 | const parsed = yield* parseMicrosoftGraphOpenApiDocument(sourceText); |
| 606 | const endpoints = resolveOAuthEndpoints(parsed, selection); | 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 | ...selection, | 648 | ...selection, |
| 609 | scopes: | 649 | scopes: selection.scopes, |
| 610 | selection.coversFullGraph === true | | |
| 611 | ? uniqueStrings([...MICROSOFT_GRAPH_BASE_SCOPES, ...selection.customScopes]) | | |
| 612 | : selection.scopes, | | |
| 613 | fullGraphScopes, | 650 | fullGraphScopes, |
| 614 | }); | 651 | }); |
| 615 | return { | 652 | return { |