prism
prism copied to clipboard
honor x-schema-faker settings when mocking from Ninja (aka hosted)
follow-up to investigate Pass x- settings to Prism when mocking from Ninja
Goal
When a workspace-project-branch OAS specification includes x-schema-faker
options, the mock responses to ninja by the mocks component should honor those options.
Two possible implementation strategies, both with significant drawbacks:
-
Pass a pre-configured JSF instance into Prism's
mock()
function. In mocks, cache pre-configured JSF instances based on workspace-project-branch, and figure out how to invalidate this cache when each specification changes. Drawback: This exposes Prism implementation details (that JSF is used) to its client, mocks. -
Introduce the concepts of workspace, project, and branch into Prism (or at the very least the notion of distinct Prism configurations). This also requires that the configuration (or a placeholder/key) be supplied along with requests. Drawback: Prism should not know anything about multiple configurations, especially regarding workspaces, projects, and branches.
Note: This probably requires changes to both mocks and prism regardless of the implementation strategy.
Background
mocks uses prism to generate mock reponses. prism in turn uses json-schema-faker (JSF). Specifically, prism:
- uses a single, global instance of JSF,
- lacks any contextual knowledge (workspace, project, or branch), and
- isn't passed any "top level" specification information that could be used to configure the JSF instance appropriately
The current code-path is traced in detail below.
in mocks, handleRequest()
in platform-internal/packages/mocks/src/index.ts, handleRequest()
calls
validateInputAndMock()
function handleRequest(
req: IncomingMessage,
{ workspaceSlug, projectSlug, serviceNodeId,
prismUrl, branchName: branch }: ApiLocationInfo,
config: IHttpOperationConfig,
) {
...
TE.bindW('response', ({ input, resolved }) => TE.fromEither(validateInputAndMock(resolved, input, config)(logger))),
...
in mocks, validateInputAndMock()
in platform-internal/packages/mocks/src/index.ts, validateInputAndMock()
calls mock()
import mock from '@stoplight/prism-http/dist/mocker';
function validateInputAndMock(
resource: IHttpOperation,
element: IHttpRequest,
config: IHttpOperationConfig
) {
logger.error('validateInputAndMock()');
return pipe(
validateInput({ resource, element }),
E.fold<IPrismDiagnostic[], unknown, IPrismDiagnostic[]>(
validations => validations,
() => [],
),
validations => mock({
resource,
input: { data: element, validations },
config
}),
);
}
in prism, mock()
Notice that Prism lacks any concept of workspaces, projects, or branches. Furthermore, Prism lacks any way to retrieve that information.
in prism/packages/http/src/mocker/index.ts, mock()
calls generate()
import { generate, generateStatic } from './generator/JSONSchema';
const mock = (...) => {
const payloadGenerator: PayloadGenerator = config.dynamic
? partial(generate, resource['__bundled__'])
: partial(generateStatic, resource);
}
Prism uses a single, global instance of json-schema-faker (JSF). This works well when it's started from the command line, but when run from mocks, we need a JSF instance configured per workspace-project-branch.
in prism, generate()
in prism/packages/http/src/mocker/generator/JSONSchema.ts, generate()
calls json-schema-faker's generate()
import * as jsf from 'json-schema-faker';
jsf.extend('faker', () => faker);
jsf.option({
failOnInvalidTypes: false,
failOnInvalidFormat: false,
alwaysFakeOptionals: true,
optionalsProbability: 1 as any,
fixedProbabilities: true,
ignoreMissingRefs: true,
maxItems: 20,
maxLength: 100,
});
generateKeyPair(...) {
jsf.generate( ... )
}
gz#8423
(related to Zendesk ticket #8423)
gz#6772
(related to Zendesk ticket #6772)
gz#8775
(related to Zendesk ticket #8775)
gz#9701
(related to Zendesk ticket #9701)
Consider:
- Option 1, w/o cache: 8
- If performance is bad, add cache: 5