Closed chronark closed 10 months ago
Temp fix at: /apps/(landing)/page.tsx
const [workspaces, apis, keys] = await Promise.all([
db
.select({ count: sql<number>`count(*)` })
.from(schema.workspaces)
.then((res) => res.at(0)?.count ?? 0),
db
.select({ count: sql<number>`count(*)` })
.from(schema.apis)
.then((res) => res.at(0)?.count ?? 0),
db
.select({ count: sql<number>`count(*)` })
.from(schema.keys)
.then((res) => res.at(0)?.count ?? 0)
// getTotalVerifications({}).then((res) => {
// return res.data.reduce((acc, curr) => acc + curr.verifications, 0);
// }),
]);
function NumbersServed() {
return (
<div className="mt-24 rounded-4xl sm:mt-32 lg:mt-32">
<Container className="">
<FadeIn className="flex items-center gap-x-8">
<h2 className="mb-8 text-2xl font-semibold tracking-wider text-center text-black font-display sm:text-left">
We serve
</h2>
<div className="flex-auto h-px" />
</FadeIn>
<FadeInStagger faster>
<StatList>
<StatListItem
value={Intl.NumberFormat("en", { notation: "compact" }).format(workspaces)}
label="Workspaces"
/>
<StatListItem
value={Intl.NumberFormat("en", { notation: "compact" }).format(apis)}
label="APIs"
/>
<StatListItem
value={Intl.NumberFormat("en", { notation: "compact" }).format(keys)}
label="Keys"
/>
{/* <StatListItem
value={Intl.NumberFormat("en", { notation: "compact" }).format(totalVerifications)}
label="Verifications"
/> */}
</StatList>
</FadeInStagger>
</Container>
</div>
);
}
Tinybird functions are called in various places.
It depends on how you want to handle Tinybird as an optional part of the dev environment @chronark, but a sleek solution imo is to mock the Tinybird class. I would suggest adding a more specific env
var rather than just checking against 'development'.
const meta = z.object({
name: z.string(),
type: z.string(),
});
const pipeResponseWithoutData = z.object({
meta: z.array(meta),
// rows: z.number().optional(),
// rows_before_limit_at_least: z.number().optional(),
// statistics: z
// .object({
// elapsed: z.number().optional(),
// rows_read: z.number().optional(),
// bytes_read: z.number().optional(),
// })
// .optional(),
});
class DudTinyBird {
constructor() {}
public buildPipe<
TParameters extends Record<string, unknown>,
TData extends Record<string, unknown>
>(req: {
pipe: string;
parameters?: z.ZodSchema<TParameters>;
data: z.ZodSchema<TData, any, any>;
opts?: {
cache?: RequestCache;
revalidate?: number;
};
}): (
params: TParameters
) => Promise<z.infer<typeof pipeResponseWithoutData> & { data: TData[] }> {
const outputSchema = pipeResponseWithoutData.setKey(
"data",
z.array(req.data)
);
return async () => {
const res = outputSchema.safeParse({ data: [], meta: [] })
if (!res.success) {
throw new Error(res.error.message)
}
return res.data
}
}
}
const tb =
env().VERCEL_ENV === "development"
? new DudTinyBird()
: new Tinybird({ token: env().TINYBIRD_TOKEN });
I wanted to preserve the core structure of buildPipe
in this quick wip, but let me know your thoughts!
(this does work)
Or... we can apply a patch directly to the package which checks if the token is empty, if it is, we can ignore the fetch call and return an empty data set + put in a log to warn the user there is no token so it will return no data. I think that's probably a better approach.
Definitely prefer a Noop class here cause tinybird would basically break all pages with charts
Let me add that to the upstream https://github.com/chronark/zod-bird and then we can use it here
ok @chronark/zod-bird
latest now has a NoopTinybird
import { Tinybird, NoopTinybird } from "@chronark/zod-bird"
const tb =
env().VERCEL_ENV === "development"
? new NoopTinybird()
: new Tinybird({ token: env().TINYBIRD_TOKEN });
Sorry had to expedite this myself for james' video it's now optional
From SyncLinear.com | KEY-256