Skip to content

Commit

Permalink
Implement new processing specification (#117)
Browse files Browse the repository at this point in the history
  • Loading branch information
Siegrift authored Nov 25, 2023
1 parent 7a4b59e commit 03afb37
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 1 deletion.
67 changes: 67 additions & 0 deletions src/ois.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
reservedParametersSchema,
packageVersionCompatibleSemverSchema,
fixedParameterSchema,
endpointSchema,
} from './ois';
import { version as packageVersion } from '../package.json';

Expand Down Expand Up @@ -717,3 +718,69 @@ describe('fixedOperationParameters', () => {
expect(() => fixedParameterSchema.parse(valueWithObject)).not.toThrow();
});
});

describe('processing specification', () => {
it('allows pre-processing and post-processing specifications with different version', () => {
const endpoint1 = { ...loadOisFixture().endpoints[0] };
endpoint1.preProcessingSpecifications = [
{
environment: 'Node',
timeoutMs: 5000,
value: 'output = input;',
},
];
endpoint1.postProcessingSpecificationV2 = {
environment: 'Node',
timeoutMs: 5000,
value: '(payload) => payload;',
};
const endpoint2 = { ...loadOisFixture().endpoints[0] };
endpoint2.preProcessingSpecificationV2 = {
environment: 'Node',
timeoutMs: 5000,
value: '(payload) => payload;',
};
endpoint2.postProcessingSpecifications = [
{
environment: 'Node',
timeoutMs: 5000,
value: 'output = input;',
},
];

expect(() => endpointSchema.parse(endpoint1)).not.toThrow();
expect(() => endpointSchema.parse(endpoint2)).not.toThrow();
});

it('throws when conflicting processing specifications are defined', () => {
const endpoint1 = { ...loadOisFixture().endpoints[0] };
endpoint1.preProcessingSpecifications = [
{
environment: 'Node',
timeoutMs: 5000,
value: 'output = input;',
},
];
endpoint1.preProcessingSpecificationV2 = {
environment: 'Node',
timeoutMs: 5000,
value: '(payload) => payload;',
};
const endpoint2 = { ...loadOisFixture().endpoints[0] };
endpoint2.postProcessingSpecifications = [
{
environment: 'Node',
timeoutMs: 5000,
value: 'output = input;',
},
];
endpoint2.postProcessingSpecificationV2 = {
environment: 'Node',
timeoutMs: 5000,
value: '(payload) => payload;',
};

expect(() => endpointSchema.parse(endpoint1)).toThrow();
expect(() => endpointSchema.parse(endpoint2)).toThrow();
});
});
42 changes: 41 additions & 1 deletion src/ois.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,14 @@ export const processingSpecificationSchema = z
})
.strict();

export const processingSpecificationSchemaV2 = z
.object({
environment: z.literal('Node'),
value: z.string(),
timeoutMs: nonNegativeIntSchema,
})
.strict();

const ensureUniqueEndpointParameterNames: SuperRefinement<EndpointParameter[]> = (parameters, ctx) => {
const groups = Object.values(groupBy(parameters, 'name'));
const duplicates = groups.filter((group) => group.length > 1).flatMap((group) => group.map((p) => p.name));
Expand Down Expand Up @@ -320,12 +328,44 @@ export const endpointSchema = z
preProcessingSpecifications: z.array(processingSpecificationSchema).optional(),
postProcessingSpecifications: z.array(processingSpecificationSchema).optional(),

// Post-processing only supported processing value, but there are use cases for processing timestamp as well. With
// the original processing specification, users needed to assign processed value to a special output variable and
// the schema supported multiple snippets that are composed together which is not necessary. For further information
// see: https://github.com/api3dao/commons/issues/27.
//
// A new processing implementation is created that addresses all the previously mentioned issues. The schemas remain
// optional, for the same reasons as in the original implementation.
preProcessingSpecificationV2: processingSpecificationSchemaV2.optional(),
postProcessingSpecificationV2: processingSpecificationSchemaV2.optional(),

// The following fields are ignored by Airnode
description: z.string().optional(),
externalDocs: z.string().optional(),
summary: z.string().optional(),
})
.strict();
.strict()
.superRefine((endpoint, ctx) => {
const {
preProcessingSpecificationV2,
preProcessingSpecifications,
postProcessingSpecificationV2,
postProcessingSpecifications,
} = endpoint;

if (preProcessingSpecificationV2 && preProcessingSpecifications) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'Only one of "preProcessingSpecificationV2" and "preProcessingSpecifications" can be defined',
});
}

if (postProcessingSpecificationV2 && postProcessingSpecifications) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'Only one of "postProcessingSpecificationV2" and "postProcessingSpecifications" can be defined',
});
}
});

const ensureSingleParameterUsagePerEndpoint: SuperRefinement<{
endpoints: Endpoint[];
Expand Down

0 comments on commit 03afb37

Please sign in to comment.