Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/typescript-generator-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,29 @@ jobs:
run: yarn generate:api-types:output
env:
OUTPUT_PATH_TYPES: src/app/services/feeds/generated/types.ts

- name: Generate TypeScript gbfs validator types
working-directory: web-app
run: yarn generate:gbfs-validator-types:output
env:
OUTPUT_PATH_TYPES: src/app/services/feeds/generated/gbfs-validator-types.ts

- name: Upload generated types
uses: actions/upload-artifact@v4
with:
name: generated_types.ts
path: web-app/src/app/services/feeds/generated/types.ts

- name: Upload generated gbfs types
uses: actions/upload-artifact@v4
with:
name: generated_types.ts
path: web-app/src/app/services/feeds/generated/gbfs-validator-types.ts

- name: Compare TypeScript types with existing types
working-directory: web-app
run: diff src/app/services/feeds/generated/types.ts src/app/services/feeds/types.ts || (echo "Types are different!" && exit 1)

- name: Compare gbfs validator TypeScript types with existing types
working-directory: web-app
run: diff src/app/services/feeds/generated/gbfs-validator-types.ts src/app/services/feeds/gbfs-validator-types.ts || (echo "Gbfs Validator Types are different!" && exit 1)
167 changes: 167 additions & 0 deletions docs/GbfsValidator.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
openapi: 3.0.0
info:
title: GBFS Validator API
version: "0.1"
paths:
/validate:
post:
summary: Validate GBFS feed
requestBody:
$ref: '#/components/requestBodies/ValidateRequestBody'
responses:
'200':
description: Validation result
content:
application/json:
schema:
$ref: "#/components/schemas/ValidationResult"

components:
requestBodies:
ValidateRequestBody:
required: true
content:
application/json:
schema:
type: object
required:
- feedUrl
properties:
feedUrl:
type: string
example: "https://example.com/gbfs.json"
auth:
oneOf:
- $ref: '#/components/schemas/BasicAuth'
- $ref: '#/components/schemas/BearerTokenAuth'
- $ref: '#/components/schemas/OAuthClientCredentialsGrantAuth'
discriminator:
propertyName: authType
mapping:
basicAuth: '#/components/schemas/BasicAuth'
bearerToken: '#/components/schemas/BearerTokenAuth'
oauthClientCredentialsGrant: '#/components/schemas/OAuthClientCredentialsGrantAuth'

schemas:
BasicAuth:
type: object
properties:
authType:
type: string
example: "BasicAuth"
username:
type: string
example: username
password:
type: string
example: password

BearerTokenAuth:
type: object
properties:
authType:
type: string
example: bearerToken
token:
type: string
example: "THE_TOKEN"

OAuthClientCredentialsGrantAuth:
type: object
properties:
authType:
type: string
example: "OAuthClientCredentialsGrantAuth"
clientId:
type: string
example: "CLIENT_ID"
clientSecret:
type: string
example: "THE_SECRET"
tokenUrl:
type: string
example: "https://token.example.com"

FileError:
type: object
properties:
keyword:
type: string
description: |
Possible known keywords: type, enum, format, required, minimum, maximum, pattern.
instancePath:
type: string
description: |
The JSON Pointer path to the part of the instance that failed validation.
schemaPath:
type: string
description: |
The JSON Pointer path to the part of the schema that triggered the error.
message:
type: string
description: |
Human-readable message describing the error.
required:
- keyword
- instancePath
- schemaPath
- message

SystemError:
type: object
properties:
error:
type: string
description: "Error code or identifier for the system error. Examples: HTTP_ERROR_404, PARSE_ERROR, CONNECTION_ERROR, FILE_NOT_FOUND."
message:
type: string
description: "Human-readable message describing the system error."
required:
- error
- message

GbfsFile:
type: object
properties:
name:
type: string
description: |
Key identifying the type of feed this is. The key MUST be the base file name defined in the spec for the corresponding feed type ( system_information for system_information.json file, station_information for station_information.json file).
example: gbfs
url:
type: string
format: url
example: https://www.example.com/gbfs/v3/gbfs.json
version:
type: string
example: "3.0"
language:
type: string
nullable: true
example: "en"
description: "Only relevant for pre-v3 files"
errors:
type: array
items:
$ref: "#/components/schemas/FileError"
schema:
type: object
systemErrors:
type: array
items:
$ref: "#/components/schemas/SystemError"
description: "System errors that occurred while processing this file, such as fetch failures or parsing errors. These are not validation errors but rather issues that prevented proper validation."

ValidationResult:
type: object
properties:
summary:
type: object
properties:
validatorVersion:
type: string
example: "v1.2"
files:
type: array
items:
$ref: "#/components/schemas/GbfsFile"
4 changes: 3 additions & 1 deletion web-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@
"cypress:open": "cypress open",
"firebase:auth:emulator:dev": "firebase emulators:start --only auth --project mobility-feeds-dev",
"generate:api-types:output": "npx openapi-typescript ../docs/DatabaseCatalogAPI.yaml -o $OUTPUT_PATH_TYPES && eslint $OUTPUT_PATH_TYPES --fix",
"generate:api-types": "OUTPUT_PATH_TYPES=src/app/services/feeds/types.ts npm run generate:api-types:output"
"generate:api-types": "OUTPUT_PATH_TYPES=src/app/services/feeds/types.ts npm run generate:api-types:output",
"generate:gbfs-validator-types:output": "npx openapi-typescript ../docs/GbfsValidator.yaml -o $OUTPUT_PATH_TYPES && eslint $OUTPUT_PATH_TYPES --fix",
"generate:gbfs-validator-types": "OUTPUT_PATH_TYPES=src/app/services/feeds/gbfs-validator-types.ts npm run generate:gbfs-validator-types:output"
},
"eslintConfig": {
"extends": [
Expand Down
2 changes: 1 addition & 1 deletion web-app/src/app/Theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ const darkPalette = {
main: '#96a1ff',
dark: '#4a5dff',
light: '#e7e8ff',
contrastText: '#E3E3E3',
contrastText: '#1D1717',
},
secondary: {
main: '#3959fa',
Expand Down
2 changes: 1 addition & 1 deletion web-app/src/app/screens/Feed/Feed.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const ctaContainerStyle: SxProps<Theme> = (theme) => ({
});

export const featureChipsStyle: SxProps<Theme> = (theme) => ({
color: theme.palette.primary.contrastText,
color: theme.palette.secondary.contrastText,
backgroundColor: theme.palette.secondary.dark,
border: `2px solid transparent`,
':hover': {
Expand Down
2 changes: 1 addition & 1 deletion web-app/src/app/screens/Feed/components/GbfsVersions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export default function GbfsVersions({
label={t('gbfsVersionsJson')}
sx={{
backgroundColor: theme.palette.primary.dark,
color: theme.palette.primary.contrastText,
color: theme.palette.secondary.contrastText,
}}
variant='filled'
></Chip>
Expand Down
2 changes: 1 addition & 1 deletion web-app/src/app/screens/Feeds/AdvancedSearchTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ const renderGBFSDetails = (
border: selectedGbfsVersions.includes('v' + version)
? `2px solid ${theme.palette.primary.main}`
: '',
color: 'black',
color: theme.palette.text.primary,
}}
/>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ export default function GbfsFeedSearchInput(): React.ReactElement {
// navigate to /gbfs-validator?AutoDiscoveryUrl=url&auth details
// store the auth details in context
// let the GbfsValidator component handle the loading state
console.log('Validating GBFS Feed for URL: ', autoDiscoveryUrlInput);
// I'm sure if a query param exists, instead of navigation, we will update the param, and have a useEffect to call the new feed to validate
navigate(
`/gbfs-validator?AutoDiscoveryUrl=${encodeURIComponent(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Box, styled } from '@mui/material';
import {
Box,
styled,
Typography,
type SxProps,
type Theme,
} from '@mui/material';
import { type CSSProperties } from 'react';

export const gbfsValidatorHeroBg = {
backgroundColor: '#43e0ff',
Expand Down Expand Up @@ -34,3 +41,49 @@ export const PromotionTextColumn = styled(Box)(({ theme }) => ({
textAlign: 'center',
},
}));

export const ValidationReportTableStyles: SxProps<Theme> = (theme) => ({
backgroundColor: theme.palette.background.paper,
height: 'fit-content',
position: 'sticky',
top: theme.spacing(10),
alignSelf: 'flex-start',
width: '300px',
minWidth: '300px',
borderRadius: 1,
overflow: 'visible',
maxHeight: 'calc(100vh - 80px)',
display: { xs: 'none', md: 'block' },
});

export const ValidationElementCardStyles = (
theme: Theme,
index: number,
): SxProps<Theme> => ({
mx: 2,
mb: 2,
display: 'block',
textDecoration: 'none',
bgcolor: 'background.default',
transition: 'box-shadow 0.3s ease',
mt: index === 0 ? 0.5 : 0,
'&:focus': {
boxShadow: `0 0 0 3px ${theme.palette.primary.main}`,
},
});

export const ValidationErrorPathStyles = (theme: Theme): CSSProperties => ({
padding: theme.spacing(0.5),
background: theme.palette.background.paper,
width: '100%',
overflowX: 'auto',
fontSize: '0.875em',
});

export const ContentTitle = styled(Typography)(({ theme }) => ({
color: theme.palette.text.secondary,
fontSize: theme.typography.subtitle2.fontSize,
padding: `0 ${theme.spacing(2)}`,
lineHeight: '48px',
fontWeight: 500,
}));
Loading
Loading