diff --git a/.speakeasy/workflow.yaml b/.speakeasy/workflow.yaml index 6e3084fd..1586eb0e 100644 --- a/.speakeasy/workflow.yaml +++ b/.speakeasy/workflow.yaml @@ -12,6 +12,7 @@ sources: - location: overlays/strip-headers-overlay.yaml - location: overlays/client-modifications-overlay.yaml - location: overlays/indexing-modifications-overlay.yaml + - location: overlays/custom-metadata-modifications-overlay.yaml - location: overlays/agent-modifications-overlay.yaml - location: overlays/admin-modifications-overlay.yaml output: overlayed_specs/glean-merged-spec.yaml @@ -58,5 +59,6 @@ sources: - location: overlays/info-name-overlay.yaml - location: overlays/strip-headers-overlay.yaml - location: overlays/indexing-modifications-overlay.yaml + - location: overlays/custom-metadata-modifications-overlay.yaml output: overlayed_specs/glean-indexing-api-specs.yaml targets: {} diff --git a/overlays/custom-metadata-modifications-overlay.yaml b/overlays/custom-metadata-modifications-overlay.yaml new file mode 100644 index 00000000..8535344d --- /dev/null +++ b/overlays/custom-metadata-modifications-overlay.yaml @@ -0,0 +1,69 @@ +overlay: 1.0.0 +x-speakeasy-jsonpath: rfc9535 +info: + title: Speakeasy Modifications - Custom Metadata + version: 0.0.1 + +actions: + # Custom Metadata - SDK grouping and method names + - target: $["paths"]["/rest/api/index/document/{docId}/custom-metadata/{groupName}"]["put"] + update: + x-speakeasy-name-override: upsert + x-speakeasy-group: indexing.customMetadata + + - target: $["paths"]["/rest/api/index/document/{docId}/custom-metadata/{groupName}"]["delete"] + update: + x-speakeasy-name-override: delete + x-speakeasy-group: indexing.customMetadata + + - target: $["paths"]["/rest/api/index/custom-metadata/schema/{groupName}"]["get"] + update: + x-speakeasy-name-override: getSchema + x-speakeasy-group: indexing.customMetadata + + - target: $["paths"]["/rest/api/index/custom-metadata/schema/{groupName}"]["put"] + update: + x-speakeasy-name-override: upsertSchema + x-speakeasy-group: indexing.customMetadata + + - target: $["paths"]["/rest/api/index/custom-metadata/schema/{groupName}"]["delete"] + update: + x-speakeasy-name-override: deleteSchema + x-speakeasy-group: indexing.customMetadata + + # Introduce a Custom Metadata-specific PropertyDefinition schema that exposes only + # the fields applicable to Custom Metadata. The shared PropertyDefinition schema + # (used by the Datasource / Custom Properties API) carries fields like displayLabel, + # displayLabelPlural, uiOptions, hideUiFacet, uiFacetOrder, and group that are not + # relevant to Custom Metadata. We cannot strip those fields from PropertyDefinition + # itself without affecting the Indexing API surface, so we create a + # narrower schema scoped to Custom Metadata and re-point CustomMetadataSchema to it. + - target: $["components"]["schemas"] + update: + CustomMetadataPropertyDefinition: + type: object + description: The definition for a key within a Custom Metadata schema. Only the fields applicable to Custom Metadata are exposed. + properties: + name: + type: string + description: The name of the metadata key. + propertyType: + type: string + enum: + - TEXT + - PICKLIST + - TEXTLIST + - MULTIPICKLIST + description: The type of metadata key. This governs the search and faceting behavior. + skipIndexing: + type: boolean + description: If true then the property will not be indexed for retrieval and ranking. + required: + - name + - propertyType + + # Re-point CustomMetadataSchema.metadataKeys to the narrower schema above. + - target: $["components"]["schemas"]["CustomMetadataSchema"]["properties"]["metadataKeys"] + update: + items: + $ref: '#/components/schemas/CustomMetadataPropertyDefinition' diff --git a/tests/post_transform_smoke.test.js b/tests/post_transform_smoke.test.js index ae27ef52..0ef3439f 100644 --- a/tests/post_transform_smoke.test.js +++ b/tests/post_transform_smoke.test.js @@ -55,7 +55,12 @@ describe('Post-transformation smoke tests', () => { expect(paths.length).toBeGreaterThan(0); - const allowedPrefixes = ['/rest/api/v1', '/api/index/v1', '/api/']; + const allowedPrefixes = [ + '/rest/api/v1', + '/api/index/v1', + '/api/', + '/rest/api/index/', + ]; const hasUnexpected = paths.some( (p) => !allowedPrefixes.some((prefix) => p.startsWith(prefix)), ); diff --git a/tests/source-spec-transformer.test.js b/tests/source-spec-transformer.test.js index 652f59c0..a0b3d74b 100644 --- a/tests/source-spec-transformer.test.js +++ b/tests/source-spec-transformer.test.js @@ -89,8 +89,26 @@ describe('OpenAPI YAML Transformer', () => { expect(transformedPaths.length).toBe(originalPaths.length); + // A path may declare its own `servers:` block; in that case the transformer + // prefixes the path with that path-level basePath rather than the global one. + const expectedBasePathFor = (pathValue) => { + const pathServers = pathValue?.servers; + if (Array.isArray(pathServers) && pathServers.length > 0) { + const candidate = extractBasePath(pathServers[0].url ?? ''); + if (candidate) return candidate; + } + return originalBasePath; + }; + + const allExpectedBasePaths = new Set(); + for (const originalPath of originalPaths) { - const expectedTransformedPath = `${originalBasePath}${originalPath}`; + const expectedBasePath = expectedBasePathFor( + originalSpec.paths[originalPath], + ); + allExpectedBasePaths.add(expectedBasePath); + + const expectedTransformedPath = `${expectedBasePath}${originalPath}`; expect(transformedSpec.paths).toHaveProperty(expectedTransformedPath); const originalOperations = originalSpec.paths[originalPath]; @@ -103,7 +121,10 @@ describe('OpenAPI YAML Transformer', () => { } for (const path of transformedPaths) { - expect(path.startsWith(originalBasePath)).toBe(true); + const matchesSomeBasePath = [...allExpectedBasePaths].some((prefix) => + path.startsWith(prefix), + ); + expect(matchesSomeBasePath).toBe(true); } if (