| @@ -529,20 +529,29 @@ const targetScopeForBinding = ( · 528 unmodified lines |
| 529 | 529 | ); |
| 530 | 530 | }; |
| 531 | 531 | |
| 532 | | −const resolveEffectiveSourceConfig = ( |
| 532 | +const findOuterSource = ( |
| 533 | 533 | ctx: PluginCtx<OpenapiStore>, |
| 534 | | − base: StoredSource, |
| 535 | | −): Effect.Effect<EffectiveSourceConfig, StorageFailure> => |
| 534 | + namespace: string, |
| 535 | + scope: string, |
| 536 | +): Effect.Effect<StoredSource | null, StorageFailure> => |
| 536 | 537 | Effect.gen(function* () { |
| 537 | 538 | const ranks = scopeRanks(ctx); |
| 538 | | − const baseRank = scopeRank(ranks, base.scope); |
| 539 | | − let fallback: StoredSource | null = null; |
| 539 | + const baseRank = scopeRank(ranks, scope); |
| 540 | 540 | for (let index = baseRank + 1; index < ctx.scopes.length; index++) { |
| 541 | | − const scope = ctx.scopes[index]; |
| 542 | | − if (!scope) continue; |
| 543 | | − fallback = yield* ctx.storage.getSource(base.namespace, scope.id); |
| 544 | | − if (fallback) break; |
| 541 | + const candidateScope = ctx.scopes[index]; |
| 542 | + if (!candidateScope) continue; |
| 543 | + const source = yield* ctx.storage.getSource(namespace, candidateScope.id); |
| 544 | + if (source) return source; |
| 545 | 545 | } |
| 546 | + return null; |
| 547 | + }); |
| 548 | + |
| 549 | +const resolveEffectiveSourceConfig = ( |
| 550 | + ctx: PluginCtx<OpenapiStore>, |
| 551 | + base: StoredSource, |
| 552 | +): Effect.Effect<EffectiveSourceConfig, StorageFailure> => |
| 553 | + Effect.gen(function* () { |
| 554 | + const fallback = yield* findOuterSource(ctx, base.namespace, base.scope); |
| 546 | 555 | |
| 547 | 556 | if (!fallback) { |
| 548 | 557 | return { |
| @@ -561,7 +570,7 @@ const resolveEffectiveSourceConfig = ( · 12 unmodified lines |
| 561 | 570 | config: { |
| 562 | 571 | ...base.config, |
| 563 | 572 | sourceUrl: base.config.sourceUrl ?? fallback.config.sourceUrl, |
| 564 | | − baseUrl: base.config.baseUrl || fallback.config.baseUrl, |
| 573 | + baseUrl: fallback.config.baseUrl, |
| 565 | 574 | namespace: base.config.namespace ?? fallback.config.namespace, |
| 566 | 575 | headers: hasBaseHeaders ? base.config.headers : fallback.config.headers, |
| 567 | 576 | queryParams: hasBaseQueryParams ? base.config.queryParams : fallback.config.queryParams, |
| @@ -806,6 +815,12 @@ export const openApiPlugin = definePlugin((options?: OpenApiPluginOptions) => { · 238 unmodified lines |
| 806 | 815 | Option.getOrElse(result.title, () => "api") |
| 807 | 816 | .toLowerCase() |
| 808 | 817 | .replace(/[^a-z0-9]+/g, "_"); |
| 818 | + const outerSource = yield* findOuterSource(ctx, namespace, input.scope); |
| 819 | + if (outerSource && input.baseUrl !== undefined && input.baseUrl.trim() !== "") { |
| 820 | + return yield* new OpenApiOAuthError({ |
| 821 | + message: "OpenAPI source shadows inherit the outer source base URL", |
| 822 | + }); |
| 823 | + } |
| 809 | 824 | |
| 810 | 825 | const hoistedDefs: Record<string, unknown> = {}; |
| 811 | 826 | if (doc.components?.schemas) { |
| @@ -814,7 +829,7 @@ export const openApiPlugin = definePlugin((options?: OpenApiPluginOptions) => { · 2 unmodified lines |
| 814 | 829 | } |
| 815 | 830 | } |
| 816 | 831 | |
| 817 | | − const baseUrl = input.baseUrl ?? resolveBaseUrl(result.servers); |
| 832 | + const baseUrl = outerSource ? undefined : (input.baseUrl ?? resolveBaseUrl(result.servers)); |
| 818 | 833 | const canonicalHeaders = canonicalizeHeaders(input.headers); |
| 819 | 834 | const canonicalQueryParams = canonicalizeCredentialMap( |
| 820 | 835 | input.queryParams, |
| @@ -1073,6 +1088,14 @@ export const openApiPlugin = definePlugin((options?: OpenApiPluginOptions) => { · 252 unmodified lines |
| 1073 | 1088 | ...(input.oauth2 !== undefined ? ["oauth2:"] : []), |
| 1074 | 1089 | ]; |
| 1075 | 1090 | const targetScope = input.credentialTargetScope ?? scope; |
| 1091 | + if (input.baseUrl !== undefined && input.baseUrl.trim() !== "") { |
| 1092 | + const outerSource = yield* findOuterSource(ctx, namespace, scope); |
| 1093 | + if (outerSource) { |
| 1094 | + return yield* new OpenApiOAuthError({ |
| 1095 | + message: "OpenAPI source shadows inherit the outer source base URL", |
| 1096 | + }); |
| 1097 | + } |
| 1098 | + } |
| 1076 | 1099 | if (affectedPrefixes.length > 0 || directBindings.length > 0) { |
| 1077 | 1100 | yield* validateOpenApiBindingTarget(ctx, { |
| 1078 | 1101 | sourceId: namespace, |