Skip to content

Instantly share code, notes, and snippets.

@AlexFrazer
Created January 8, 2019 13:52
Embed
What would you like to do?
import axios, { AxiosInstance } from 'axios';
import moment from 'moment';
import * as readline from 'readline';
const FIELDS = ['applicant', 'location', 'DayOrder', 'start24', 'end24'];
const serializeFields = (fields: string[]) =>
fields.map(field => `\`${field}\``).join(',');
const range = (start: number, end: number) =>
Array.from({ length: end - start }, (_, i) => i + start);
const getDateFilter = () => {
const now = moment();
const mapHourToString = (hour: number) => moment()
.startOf('day')
.set('hour', hour)
.format('HH:mm')
const startHours = range(0, now.hour()).map(mapHourToString);
const endHours = range(now.add(1, 'hour').hour(), 24).map(mapHourToString);
const startHourQuery = startHours.map(hour => `start24='${hour}'`).join(' OR ');
const endHourQuery = endHours.map(hour => `end24='${hour}'`).join(' OR ');
return `(${startHourQuery}) AND (${endHourQuery})`;
};
/**
* Resource for food trucks.
*/
class FoodTrucks {
private instance: AxiosInstance;
constructor(resource: string) {
// Create an individual scoped axios instance for this food truck instance.
this.instance = axios.create({
baseURL: resource,
});
}
getPage(page: number, increment: number = 10) {
return this.instance.get('/', {
params: {
DayOrder: moment().day(),
$where: getDateFilter(),
$limit: increment,
$offset: page * increment,
$select: serializeFields(FIELDS),
$order: 'applicant',
},
});
}
async *[Symbol.asyncIterator]() {
let page = 0;
while (true) {
const { status, data } = await this.getPage(page);
if (data.length && status === 200) {
yield { data, page };
}
page += 1;
}
}
}
/**
* Starts the CLI and prompts for input.
*/
async function start() {
const trucks = new FoodTrucks('https://data.sfgov.org/resource/bbb8-hzi6.json');
const cli = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
// Promisify
const prompt = () =>
new Promise((resolve, reject) => {
cli.question('Load more? ("next" to load more)\t', answer => {
if (answer === 'next') {
resolve();
// If not "yes" specifically, will exit.
} else {
reject(new Error('Unrecognized command'));
}
});
});
try {
for await (const { data, page } of trucks) {
console.log('Page', page);
console.table(data);
await prompt();
}
console.log('No more results');
// Not sure of the intended behavior here. Assume close and exit.
cli.close();
process.exit();
} catch (e) {
console.log(e.message);
cli.close();
}
}
start();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment