Skip to content

Repository files navigation

Schema

Build Status

This repository holds JSON Schemas to validate each of the tables of the project.

The idea is that with small wrappers written in JS and Python, this can be an importable package that is used any time data is being updated.

This schema is for all data that will be held in the Parse Server/MongoDB database. Not all data will be held here: rather, only data that is expected to have frequent updates and have two-way synchronization.

For example, a weather forecast layer does not need to be in here, because the data is always going from server to client, and old data can be deleted. It should be simple enough for this kind of data to check timestamps on the server, and just automatically redownload if available during the syncing process.

This is a work in progress!

Installation

Python:

pip install git+https://github.com/nst-guide/schema --upgrade

JS:

npm install @nst-guide/schema --save

or

yarn add @nst-guide/schema

Usage

Python:

fromnstschemaimportvalidatetown= {
'name': 'town name'
}
validate(town, 'Town')

JS:

For simple validation, you can just use validate:

import{validate}from'@nst-guide/schema';consttown={name: 'town name',};validate(town,'Town');

Alternatively, if you have many things to validate, it could be faster to first use compile:

import{compile}from'@nst-guide/schema';constvalidate=compile('Town');consttown={name: 'town name',};constvalid=validate(town);if(!valid)throwvalidate.errors;

Table descriptions

Below is pseudocode/TypeScript for the schemas. Actual parsing happens in the JSON schema files, anything below is unofficial and just for documentation purposes.

Common types

These types are reused in several tables.

I'm planning to use Parse Server, an open source backend as a service, for my backend. This has a GeoPoint type. Consider GeoPoint to be a standard object with latitude and longitude keys. Parse adds __type: "GeoPoint", but this is not required if working outside Parse.

interfaceGeoPoint{__type?: string;latitude: number;longitude: number;}

For now, I'll say a Geometry is always a valid GeoJSON string. (Encoded as a string, not an object). Though it should be stored in Parse as a Parse.File and not part of an object.

typeGeometry=string;

Comments will be permitted on many types of waypoints. Let's define the default feedback as just an array of comments.

interfaceDefaultFeedback{comments: Comment[];}interfaceComment{userId: string;userName: string;body: string;// true == "northbound", where northbound is usually defined as south to// north, but could be defined as the "standard" way for an east-west facing// trail, like the Colorado Trail.direction?: boolean;date: Date;}

Address:

interfaceAddress{housenumber?: string;street?: string;// comparable to address line 2flats?: string;postcode?: string;city?: string;state?: string;}

Town

Rows should be unique among towns. A "town" can include resupply areas that are not generally considered towns. For example, a lodge in Oregon that's just off the trail but remote could be considered its own Town.

interfaceTown{// Unique identifier for townid: number,// Common name for townname: string,// Type of towntype: TownType,// Geographic centroid of town. I think this probably is meant to be more of// a "representative point" in Shapely's parlance. A centroid may be outside// of a polygon; it would be nice if the centroid argument is always within// the Town, but this is not required.centroid: GeoPoint,// Actual geometry of town. While centroid may be used when zoomed out,// geometry should be a more accurate geometric representation of the town.geometry?: Geometry,// trails that this Town is a part of. I.e. [PCT]trails: string[],feedback: TownFeedback,// associate elevation with the town in general instead of with individual town waypoints for simplicityelevation: number,}enumTownType{cityresort}interfaceTownFeedback{comments: Comments[]}

TownWaypoint

interfaceTownWaypoint{id: number,// Reference to Town tabletownId: number,name: string,// descriptiondesc?: string,// information about the type of waypoint this istype: TownWaypointTypesubtype: TownWaypointSubtype// location: most town waypoints will be Pointsgeopoint: GeoPoint// Optionally, more accurate waypointgeometry?: Geometry// object that holds OSM informationosm: TownWaypointOSM,// attributes that are not pinned to OSMattrs: TownWaypointAttributes,feedback: TownWaypointFeedback,}// TODO figure out waypoint type and subtypeenumTownWaypointType{food,lodging,finance,store,medical,
...
}typeTownWaypointSubtype=FoodSubtype||LodgingSubtype||FinanceSubtype||StoreSubtype||MedicalSubtype;enumFoodSubtype{fastFood,cafe,restaurant,bar,}enumLodgingSubtype{hotel,motel,camping,}enumFinanceSubtype{atm,bank,}enumStoreSubtype{outdoorsStore,grocery,}enumMedicalSubtype{hospital,pharmacy}interfaceTownWaypointOSM{nodeId?: number,wayId?: number,relationId?: number,// showers, toilets and laundry are values within the amenity and shop keysamenity?: string,shop?: string,// Opening hours should conform to OSM opening hours standard. Parsers:// Python: https://github.com/rezemika/humanized_opening_hours// JS: https://github.com/opening-hours/opening_hours.jsopening_hours?: string,phone?: string,website?: string,// OSM has both email= and contact:email= tag keysemail?: string,contact_email?: string,// internet_access==wlaninternet_access?: boolean,internet_access_fee?: boolean,toilets_disposal?: string,drinking_water?: boolean,}interfaceTownWaypointAttributes{wifi?: boolean,phone?: string,website?: string,// power outletspower?: boolean,shower?: boolean,showerFee?: string,laundry?: boolean,laundryFee?: string,toilets?: boolean,toiletsFlush?: boolean,acceptsResupply?: booleanacceptsResupplyFee?: string,acceptsResupplyProvider?: ResupplyProvider,acceptsResupplyAddress?: ResupplyAddress[],sendsResupply?: boolean,sendsResupplyProvider?: ResupplyProvider,}interfaceResupplyProvider{ups?: boolean,usps?: boolean,fedex?: boolean,}interfaceResupplyAddress{provider: ResupplyProvider,address: Address,}interfaceTownWaypointFeedbackextendsDefaultFeedback{votes: FeedbackVote[]}

Trail

An overall, named hiking trail, like the Pacific Crest Trail, or Appalachian Trail.

interfaceTrail{trailCode: string;name: string;desc: string;// Link to TrailSectiontrailSections: string[];}

TrailSection

A smaller part of a larger Trail.

interfaceTrailSection{id: number;alternate: boolean;}

TrailWaypoint

Waypoints that are part of a TrailSection and are trail-focused. A resupply location should be a TownWaypoint.

Every TrailWaypoint contains a collection of TrailSubWaypoints

interfaceTrailWaypoint{id: number,name?: string,desc?: string,type: TrailWaypointType[],subtype: TrailWaypointSubtype[],subWaypoints: TrailSubWaypoints[],feedback: TrailWaypointFeedback,// Location of waypoint itselfgeometry: GeoPoint,// Elevation in **meters**elevation: number,osm: TrailWaypointOSM,attrs: TrailWaypointAttributes,}enumTrailWaypointType{Water,Camp,Natural,// transportationTrans,// TODO: Not sure if these should be hereToilet,Shower,}typeTrailWaypointSubtype=WaterSubtype||CampSubtype||NaturalSubtype||TransSubtype;enumWaterSubtype{// Natural LineString water sourceStream,// Natural polygon water sourceLake,// Natural point water sourceSpring,// non-natural water source that must be refilled.Cache,// an always?-running man-made water source. Doesn't need to be refilled,// but may sometimes be turned off.Faucet}enumCampSubtype{// wilderness campsitecampsite,// designated campground with multiple sitescampground,// fully enclosed shelterenclosedShelter,// shelter that is not fully enclosedunenclosedShelter,}enumNaturalSubtype{Pass,Peak,}enumTransSubtype{Highway,PavedRoad,DirtRoad,TrailJunction,}typeTrailWaypointFeedback=WaterFeedback||CampFeedback||DefaultFeedback;typeWaterFeedback=StreamFeedback||LakeFeedback||SpringFeedback||CacheFeedback||FaucetFeedback;interfaceStreamFeedbackextendsDefaultFeedback{}interfaceLakeFeedbackextendsDefaultFeedback{}interfaceSpringFeedbackextendsDefaultFeedback{}interfaceCacheFeedbackextendsDefaultFeedback{}interfaceFaucetFeedbackextendsDefaultFeedback{}interfaceCampFeedbackextendsDefaultFeedback{}interfaceStreamFeedbackItem{date: Date,userId: number,flowing: FlowingwaterQuality: WaterQuality}interfaceCampFeedbackItem{date: Date,userId: number,// Number of tent sites the user thinks comfortably fitcampsiteFits: number,}interfaceHitchFeedbackItem{date: Date,userId: number,// Time reported spent waiting for a hitchtimeHitching: TimeHitching,}enumFlowing{flowingtrickledry}enumWaterQuality{GreatGoodOkPoor}enumTimeHitching{"<15","15-30","30-45","45-60",">60"}

User

interfaceUser{// Doesn't have to be their real name// Must not include any characters that are invalid in URLsuserName: string;// Not sure whether to make this required or notemail: string;// password hashed (or to be hashed)password: string;// unitsunits;social: UserSocial;}interfaceUserSocial{facebook: string;twitter: string;youtube: string;instagram: string;reddit: string;}

Tests

Test data is defined in tests/{schema}/*.json, where schema is the name of the schema the data is to be tested against.

tests/test_schemas.js is the JS test script, using Ajv, and tests/test_schemas.py is the Python test script, using the jsonschema package. You can run the JS tests with yarn test and the Python tests with pytest.

To Do

  • How to name tables so that they're easiest to download for offline usage in Parse. I think Parse generally downloads an entire table. Should all tables be prefixed by PCT_?
  • locations for each subwaypoint, but connected when clicked
  • How to link trail waypoints to the trail itself? The waypoints can be off trail, but I should probably keep track of the mile marker of the closest trail location?
  • Where should you keep waypoint responses? Do you want to separate these from what gets recursively downloaded? On the one hand, it's more data than is needed to show the user the current state, on the other, if you're already downloading the comments, downloading these is not that much more. Maybe make the schema work either way?

About

JSON Schemas for data

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages