Skip to content

Commit

Permalink
Formatting, cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
JosephVolosin committed Dec 3, 2024
1 parent 9f90170 commit d25e67a
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 96 deletions.
54 changes: 23 additions & 31 deletions src/packages/external-source/external-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import type {
ExternalSourceTypeInsertInput,
CreateExternalSourceResponse,
ExternalEventTypeInsertInput,
ExternalEvent,
CreateExternalSourceEventTypeResponse,
GetSourceEventTypeAttributeSchemasResponse,
AttributeSchema,
DerivationGroupInsertInput,
ExternalSourceInsertInput,
ExternalSourceRequest,
ExternalEventRequest,
} from '../../types/external-source.js';
import Ajv from 'ajv';
import { getEnv } from '../../env.js';
Expand All @@ -34,44 +35,40 @@ const refreshLimiter = rateLimit({
});

export function updateSchemaWithDefs(defs: { event_types: any; source_type: any }): Ajv.ValidateFunction {
// build if statement
// Build if statement
const ifThenElse: { [key: string]: any } = {};
let ifThenElsePointer = ifThenElse;
const keys = Object.keys(defs.event_types);

// handling if there's only 1 event type (don't bother with $defs, just update attributes' properties directly)
// Handle single event type (don't bother with $defs, just update attributes' properties directly)
if (keys.length === 1) {
// no need for ifThenElse, simply create localSchemaCopy and update properties.events.items.properties.attributes
// to match the event type in defs, and verify the event_type_name matches the def name
const localSchemaCopy = structuredClone(baseExternalSourceSchema);

const event_type_name = keys[0];
const event_type_schema = {
...defs.event_types[event_type_name],

// additionally, restrict extra properties
additionalProperties: false,
};
const source_type_name = Object.keys(defs.source_type)[0];
const source_type_schema = {
...defs.source_type[source_type_name],

// additionally, restrict extra properties
additionalProperties: false,
};

localSchemaCopy.properties.events.items.properties.attributes = event_type_schema;
localSchemaCopy.properties.events.items.properties.event_type_name = { const: event_type_name };

// insert def for "source" attributes
// Insert def for "source" attributes
localSchemaCopy.properties.source.properties.attributes = source_type_schema;

const localAjv = new Ajv();
return localAjv.compile(localSchemaCopy);
}

// handle n event types
// HJandle n event types
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
// Create tree of if/else/then statements to support validating different types
ifThenElsePointer['if'] = {
properties: {
event_type_name: {
Expand All @@ -90,41 +87,35 @@ export function updateSchemaWithDefs(defs: { event_types: any; source_type: any
ifThenElsePointer = ifThenElsePointer['else'];
}

// fill in the final else with the last element
const key = keys[keys.length - 1];
ifThenElsePointer['properties'] = {
attributes: {
$ref: `#/$defs/event_types/${key}`,
},
};

// insert if statement into local copy of baseExternalSourceSchema
const localSchemaCopy = structuredClone(baseExternalSourceSchema);
localSchemaCopy.properties.events.items['if'] = ifThenElse['if'];
localSchemaCopy.properties.events.items['then'] = ifThenElse['then'];
localSchemaCopy.properties.events.items['else'] = ifThenElse['else'];

// insert def for "source" attributes
// Insert def for "source" attributes
const sourceTypeKey = Object.keys(defs.source_type)[0];
localSchemaCopy.properties.source.properties.attributes = { $ref: `#/$defs/source_type/${sourceTypeKey}` };

// add defs
// Add defs
localSchemaCopy.$defs = {
event_types: {},
source_type: {
[sourceTypeKey]: {
...defs.source_type[sourceTypeKey],

// additionally, restrict extra properties
additionalProperties: false,
},
},
};
for (const event_type of keys) {
localSchemaCopy.$defs.event_types[event_type] = {
...defs.event_types[event_type],

// additionally, restrict extra properties
additionalProperties: false,
};
}
Expand Down Expand Up @@ -199,19 +190,21 @@ async function uploadExternalSourceEventTypes(req: Request, res: Response) {
method: 'POST',
});

const jsonResponse = await response.json();
if (jsonResponse?.data !== undefined) {
res.json(jsonResponse.data as CreateExternalSourceEventTypeResponse);
const createExternalSourceEventTypesResponse = await response.json();
if (createExternalSourceEventTypesResponse?.data !== undefined) {
res.json(createExternalSourceEventTypesResponse.data as CreateExternalSourceEventTypeResponse);
} else {
res.json(jsonResponse as HasuraError);
res.json(createExternalSourceEventTypesResponse as HasuraError);
}
}

async function uploadExternalSource(req: Request, res: Response) {
const authorizationHeader = req.get('authorization');

const {
headers: { 'x-hasura-role': roleHeader, 'x-hasura-user-id': userHeader },
} = req;

const { body } = req;

if (typeof body !== 'object') {
Expand All @@ -224,8 +217,8 @@ async function uploadExternalSource(req: Request, res: Response) {
return;
}

let parsedSource;
let parsedExternalEvents: ExternalEvent[];
let parsedSource: ExternalSourceRequest;
let parsedExternalEvents: ExternalEventRequest[];
try {
const { source, events } = body;
parsedSource = JSON.parse(source);
Expand Down Expand Up @@ -316,8 +309,7 @@ async function uploadExternalSource(req: Request, res: Response) {
});

// Verify that this is a valid external source
let sourceIsValid: boolean = false;
sourceIsValid = await compiledExternalSourceMegaschema(externalSourceJson);
const sourceIsValid: boolean = await compiledExternalSourceMegaschema(externalSourceJson);
if (sourceIsValid) {
logger.info(`POST /uploadExternalSource: External Source ${key}'s formatting is valid`);
} else {
Expand Down Expand Up @@ -365,11 +357,11 @@ async function uploadExternalSource(req: Request, res: Response) {
method: 'POST',
});

const jsonResponse = await response.json();
if (jsonResponse?.data !== undefined) {
res.json(jsonResponse.data as CreateExternalSourceResponse);
const createExternalSourceResponse = await response.json();
if (createExternalSourceResponse?.data !== undefined) {
res.json(createExternalSourceResponse.data as CreateExternalSourceResponse);
} else {
res.json(jsonResponse as HasuraError);
res.json(createExternalSourceResponse as HasuraError);
}
}

Expand Down
29 changes: 14 additions & 15 deletions src/packages/external-source/gql.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export default {
// TODO: discuss upset for derivation group
CREATE_EXTERNAL_SOURCE: `#graphql
mutation CreateExternalSource(
$derivation_group: derivation_group_insert_input!,
Expand Down Expand Up @@ -28,7 +27,7 @@ export default {
}
`,
CREATE_EXTERNAL_SOURCE_EVENT_TYPES: `#graphql
mutation uploadAttributeSchemas($externalEventTypes: [external_event_type_insert_input!]!, $externalSourceTypes: [external_source_type_insert_input!]!) {
mutation UploadAttributeSchemas($externalEventTypes: [external_event_type_insert_input!]!, $externalSourceTypes: [external_source_type_insert_input!]!) {
createExternalEventTypes: insert_external_event_type(objects: $externalEventTypes) {
returning {
name
Expand All @@ -49,11 +48,11 @@ export default {
}
`,
GET_EXTERNAL_EVENT_TYPE_ATTRIBUTE_SCHEMA: `#graphql
query GetExternalEventTypeAttributeSchema($name: String!) {
external_event_type_by_pk(name: $name) {
attribute_schema
query GetExternalEventTypeAttributeSchema($name: String!) {
external_event_type_by_pk(name: $name) {
attribute_schema
}
}
}
`,
GET_EXTERNAL_SOURCE_TYPE_ATTRIBUTE_SCHEMA: `#graphql
query GetExternalSourceTypeAttributeSchema($name: String!) {
Expand All @@ -63,15 +62,15 @@ export default {
}
`,
GET_SOURCE_EVENT_TYPE_ATTRIBUTE_SCHEMAS: `#graphql
query getET($externalEventTypes: [String!]!, $externalSourceType: String!) {
external_event_type(where: {name: {_in: $externalEventTypes}}) {
name
attribute_schema
}
external_source_type(where: {name: {_eq: $externalSourceType}}) {
name
attribute_schema
query GetSourceEventTypeAttributeSchemas($externalEventTypes: [String!]!, $externalSourceType: String!) {
external_event_type(where: {name: {_in: $externalEventTypes}}) {
name
attribute_schema
}
external_source_type(where: {name: {_eq: $externalSourceType}}) {
name
attribute_schema
}
}
}
`,
};
42 changes: 12 additions & 30 deletions src/types/external-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,6 @@ export type ExternalSourceInsertInput = {
valid_at: string;
};

export type UploadExternalSourceJSON = {
events: ExternalEventJson[];
source: {
attributes: object;
key: string;
period: {
end_time: string;
start_time: string;
};
source_type: string;
valid_at: string;
};
};

export type CreateExternalSourceResponse = {
createExternalSource: { name: string };
};
Expand All @@ -54,28 +40,24 @@ export type CreateExternalSourceEventTypeResponse = {
createExternalSourceTypes: { returning: string[] };
};

export type ExternalEventInsertInput = {
attributes: object;
export type ExternalEventRequest = {
key: string;
event_type_name: string;
start_time: string;
duration: string;
event_type_name: string;
key: string;
};

export type ExternalEventJson = {
attributes: object;
duration: string;
event_type: string;
key: string;
start_time: string;
};

export type ExternalEvent = {
key: string;
event_type_name: string;
start_time: string;
duration: string;
export type ExternalSourceRequest = {
attributes: object;
derivation_group_name: string;
key: string;
period: {
end_time: string;
start_time: string;
};
source_type_name: string;
valid_at: string;
};

export type AttributeSchema = {
Expand Down
21 changes: 1 addition & 20 deletions src/util/time.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ParsedDoyString, ParsedYmdString } from '../types/time';
import parseInterval from 'postgres-interval';

function parseNumber(number: number | string): number {
return parseInt(`${number}`, 10);
Expand Down Expand Up @@ -93,7 +92,7 @@ export function convertDateToDoy(dateString: string, numDecimals = 6): string |
return null;
}

export function convertDoyToYmd(doyString: string, numDecimals = 6, includeMsecs = true): string | null {
function convertDoyToYmd(doyString: string, numDecimals = 6, includeMsecs = true): string | null {
const parsedDoy: ParsedDoyString = parseDoyOrYmdTime(doyString, numDecimals) as ParsedDoyString;

if (parsedDoy !== null) {
Expand Down Expand Up @@ -129,21 +128,3 @@ export function getTimeDifference(dateString1: string, dateString2: string, numD
}
return null;
}

/**
* Returns a Postgres Interval duration in milliseconds.
* If duration is null, undefined, or empty string then we just return 0.
* @note This function assumes 24-hour days.
*/
export function getIntervalInMs(interval: string | null | undefined): number {
if (interval !== null && interval !== undefined && interval !== '') {
const parsedInterval = parseInterval(interval);
const { days, hours, milliseconds, minutes, seconds } = parsedInterval;
const daysInMs = days * 24 * 60 * 60 * 1000;
const hoursInMs = hours * 60 * 60 * 1000;
const minutesInMs = minutes * 60 * 1000;
const secondsInMs = seconds * 1000;
return daysInMs + hoursInMs + minutesInMs + secondsInMs + milliseconds;
}
return 0;
}

0 comments on commit d25e67a

Please sign in to comment.