Skip to content

Commit

Permalink
feat: query calories
Browse files Browse the repository at this point in the history
  • Loading branch information
scarf005 committed Oct 9, 2023
1 parent 62f9195 commit d501a6f
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 2 deletions.
2 changes: 1 addition & 1 deletion deps/cliffy.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { Command } from "https://deno.land/x/cliffy@v1.0.0-rc.3/command/mod.ts"
export * from "https://deno.land/x/cliffy@v1.0.0-rc.3/command/mod.ts"
73 changes: 73 additions & 0 deletions examples/calories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Command, EnumType } from "../deps/cliffy.ts"
import { z } from "../mod.ts"
import { cliOptions } from "../utils/cli.ts"
import { readRecursively } from "../utils/parse.ts"
import { outputTo } from "../utils/query.ts"
import { makeTimeits } from "../utils/timeit.ts"
import { schemaFilter } from "../utils/transform.ts"

const name = z.union([
z.string(),
z.object({ str_sp: z.string() }).transform((x) => x.str_sp),
z.object({ str: z.string() }).transform((x) => x.str),
])

type Portion = Pick<Food, "calories">

const compareByPortion = (a: Portion, b: Portion) => b.calories - a.calories
const compareByTotal = (a: Food, b: Food) => b.total - a.total

type Food = z.infer<typeof food>
const food = z
.object({
id: z.string().optional(),
name,
calories: z.coerce.number(),
charges: z.number().default(1),
})
.transform((x) => ({ ...x, total: x.calories * x.charges }))

const queryType = new EnumType(["portion", "total"])

const main = () =>
new Command()
.name("calories")
.type("query", queryType)
.option(...cliOptions.quiet)
.option(...cliOptions.path)
.option(...cliOptions.output)
.option("--limit <amount:integer>", "Limit number of entries to display.", { default: 30 })
.option("--no-limit", "Display all entries.")
.option("--sort-by <compare:query>", "Sort by individual portion or total", { default: "portion" as const })
.description("Query food calories.")
.action(async ({ path, output, sortBy, limit, quiet = false }) => {
const { timeit, timeitSync } = makeTimeits(quiet)

const filter = schemaFilter(food)
const entries = await readRecursively(path)
const query = () =>
entries.flatMap(({ text, path }) => {
try {
return filter(text)
} catch (e) {
console.log(path, e)
return []
}
})

const queried = timeitSync({ name: "querying foods", fn: query })
if (queried.length === 0) {
return console.log("no matching entries found.")
}

const cmp = sortBy === "portion" ? compareByPortion : compareByTotal
const result = timeitSync({ name: "sorting by calories", fn: () => queried.toSorted(cmp) })
if (output) {
return outputTo(timeit)(result, output)
}
console.table(result.slice(0, limit || undefined))
})

if (import.meta.main) {
await main().parse(Deno.args)
}
2 changes: 1 addition & 1 deletion utils/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const queryCli = <const Schema extends z.ZodTypeAny>(
return outputTo(timeit)(mapped, output)
})

const outputTo = (timeit: Timeit) => async (data: unknown, path?: string) => {
export const outputTo = (timeit: Timeit) => async (data: unknown, path?: string) => {
const output = JSON.stringify(data, null, 2)
if (!path) {
return console.log(output)
Expand Down

0 comments on commit d501a6f

Please sign in to comment.