Skip to content

Commit 558fbec

Browse files
committed
reorg: split dashboard package into frontend and backend
1 parent 77fcf26 commit 558fbec

93 files changed

Lines changed: 397 additions & 101 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

core/runtime/sts-service/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ export async function verifyToken<R>(
349349
parseSchema: (payload: unknown): Result<R> => {
350350
return Result.Ok(payload as R);
351351
},
352-
fetch: (url, init) => globalThis.fetch(url, init),
352+
fetch: (...args: Parameters<typeof globalThis.fetch>) => globalThis.fetch(...args),
353353
verifyToken: async (token: string, pubKey: JWK): Promise<Result<{ payload: unknown }>> => {
354354
const rKey = await importJWK(pubKey);
355355
if (rKey.isErr()) {
@@ -390,6 +390,7 @@ export async function verifyToken<R>(
390390
case isFetchWellKnownJwksResultOk(pubKey):
391391
{
392392
for (const key of pubKey.keys) {
393+
console.log("Trying well-known JWKS key from", token, wellKnownUrls, key);
393394
const rVerify = await internVerifyToken(token, key, opts);
394395
if (rVerify.isOk()) {
395396
return rVerify;

dashboard/.dev.vars.sample

Lines changed: 0 additions & 3 deletions
This file was deleted.

dashboard/actions/base/action.yaml

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,60 @@ runs:
99
steps:
1010
- uses: ./actions/runtime
1111

12-
- name: install
12+
- name: FRONTEND install
1313
shell: bash
14-
working-directory: dashboard
14+
working-directory: dashboard/frontend
1515
run: pnpm install
1616

17-
- name: format-check
18-
working-directory: dashboard
17+
- name: FRONTEND format-check
18+
working-directory: dashboard/frontend
1919
shell: bash
2020
run: pnpm run format --check
2121

22-
- name: lint
22+
- name: FRONTEND lint
2323
shell: bash
24-
working-directory: dashboard
24+
working-directory: dashboard/frontend
2525
run: pnpm run lint
2626

27-
- name: build
27+
- name: FRONTEND build
2828
shell: bash
29-
working-directory: dashboard
29+
working-directory: dashboard/frontend
3030
env:
3131
VITE_CLERK_PUBLISHABLE_KEY: ${{ inputs.CLERK_PUBLISHABLE_KEY }}
3232
run: pnpm run build
3333

34-
- name: test
34+
- name: FRONTEND test
3535
shell: bash
36-
working-directory: dashboard
36+
working-directory: dashboard/frontend
3737
run: |
3838
pnpm run test
39+
40+
41+
- name: BACKEND install
42+
shell: bash
43+
working-directory: dashboard/backend
44+
run: pnpm install
45+
46+
- name: BACKEND format-check
47+
working-directory: dashboard/backend
48+
shell: bash
49+
run: pnpm run format --check
50+
51+
- name: BACKEND lint
52+
shell: bash
53+
working-directory: dashboard/backend
54+
run: pnpm run lint
55+
56+
- name: BACKEND build
57+
shell: bash
58+
working-directory: dashboard/backend
59+
env:
60+
VITE_CLERK_PUBLISHABLE_KEY: ${{ inputs.CLERK_PUBLISHABLE_KEY }}
61+
run: pnpm run build
62+
63+
- name: BACKEND test
64+
shell: bash
65+
working-directory: dashboard/backend
66+
run: |
67+
pnpm run test
68+

dashboard/actions/deploy/action.yaml

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ runs:
5252
using: "composite"
5353
steps:
5454
- name: Deploy Dashboard
55-
working-directory: dashboard
55+
working-directory: dashboard/frontend
5656
shell: bash
5757
env:
5858
# need for drizzle
@@ -77,7 +77,7 @@ runs:
7777
# need during build
7878
VITE_CLERK_PUBLISHABLE_KEY: ${{ inputs.CLERK_PUBLISHABLE_KEY }}
7979
run: |
80-
pnpm run drizzle:d1-remote
80+
(cd ../backend && pnpm run drizzle:d1-remote)
8181
pnpm exec core-cli wellKnown --jsons --presetKey "$CLERK_PUB_JWT_KEY" "$CLERK_PUB_JWT_URL" > key
8282
CLERK_PUB_JWT_KEY="$(cat key)"
8383
pnpm exec core-cli writeEnv --env ${{inputs.CLOUDFLARE_ENV}} --out /dev/stdout --json \
@@ -93,16 +93,6 @@ runs:
9393
--fromEnv CLOUD_SESSION_TOKEN_PUBLIC \
9494
--fromEnv DEVICE_ID_CA_PRIV_KEY \
9595
--fromEnv DEVICE_ID_CA_CERT | \
96-
pnpm exec wrangler -c ./wrangler.toml secret --env ${{inputs.CLOUDFLARE_ENV}} bulk
96+
pnpm exec wrangler -c ../backend/wrangler.toml secret --env ${{inputs.CLOUDFLARE_ENV}} bulk
9797
pnpm run deploy:cf --env ${{inputs.CLOUDFLARE_ENV}}
9898
99-
# - name: deploy to production
100-
# if: github.ref == 'refs/heads/main'
101-
# env:
102-
# CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
103-
# CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
104-
# CLOUDFLARE_DATABASE_ID: ${{ secrets.CLOUDFLARE_DATABASE_ID }}
105-
# run: |
106-
# pnpm run build
107-
# pnpm run drizzle:d1-remote
108-
# pnpm run deploy:cf --env production

dashboard/backend/api.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -242,13 +242,12 @@ export class FPApiSQL implements FPApiInterface {
242242
}
243243

244244
private async _authVerifyAuth(req: { readonly auth: DashAuthType }): Promise<Result<ClerkVerifyAuth>> {
245-
// console.log("_authVerify-1", req);
246245
const tokenApi = this.tokenApi[req.auth.type];
247-
// console.log("_authVerify-2", req);
248246
if (!tokenApi) {
249247
return Result.Err(`invalid auth type:[${req.auth.type}]`);
250248
}
251249
const rAuth = await tokenApi.verify(req.auth.token);
250+
// console.log("_authVerify-3", rAuth);
252251
if (rAuth.isErr()) {
253252
return Result.Err(rAuth.Err());
254253
}
@@ -261,7 +260,6 @@ export class FPApiSQL implements FPApiInterface {
261260

262261
// eslint-disable-next-line @typescript-eslint/no-unused-vars
263262
private async activeUser(req: WithAuth, status: UserStatus[] = ["active"]): Promise<Result<ActiveUser>> {
264-
// console.log("activeUser-1", req);
265263
const rAuth = await this._authVerifyAuth(req);
266264
if (rAuth.isErr()) {
267265
return Result.Err(rAuth.Err());
@@ -283,9 +281,7 @@ export class FPApiSQL implements FPApiInterface {
283281
}
284282

285283
async ensureUser(req: ReqEnsureUser): Promise<Result<ResEnsureUser>> {
286-
// console.log("ensureUser-1", req);
287284
const activeUser = await this.activeUser(req);
288-
// console.log("ensureUser-2", req);
289285
if (activeUser.isErr()) {
290286
return Result.Err(activeUser.Err());
291287
}

dashboard/backend/cf-serve.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,26 @@ export interface Env {
2020
}
2121

2222
export default {
23-
async fetch(request: Request, env: Env) {
23+
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
2424
const uri = URI.from(request.url);
2525
let ares: Promise<CFResponse>;
2626
switch (true) {
2727
case uri.pathname.startsWith("/api"):
2828
// console.log("cf-serve", request.url, env);
29-
ares = createHandler(drizzle(env.DB), env).then((fn) => fn(request) as unknown as Promise<CFResponse>);
29+
ares = createHandler(drizzle(env.DB), env).then((fn) => fn(request, (p) => {
30+
ctx.waitUntil(p);
31+
return p;
32+
// console.log("cf-serve - queued promise for execution context", p);
33+
// ctx.waitUntil(p);
34+
35+
// const { waitUntil } = ctx;
36+
// waitUntil.apply(ctx, [p]);
37+
// waitUntil.call(ctx, p);
38+
// const reboundWaitUntil = waitUntil.bind(ctx);
39+
// reboundWaitUntil(p);
40+
41+
// return p;
42+
}) as unknown as Promise<CFResponse>);
3043
break;
3144

3245
case uri.pathname.startsWith("/.well-known/jwks.json"):
@@ -39,6 +52,8 @@ export default {
3952
default:
4053
ares = env.ASSETS.fetch(uri.build().pathname("/").asURL(), request as unknown as CFRequest);
4154
}
55+
console.log("cf-serve - awaiting response for", request.url);
56+
ctx.waitUntil(ares);
4257
const res = await ares;
4358
return new Response(res.body as ReadableStream<Uint8Array>, {
4459
status: res.status,

dashboard/backend/create-handler.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ class ClerkApiToken implements FPApiToken {
3232
constructor(sthis: SuperThis) {
3333
this.sthis = sthis;
3434
}
35-
async verify(token: string): Promise<Result<VerifiedAuth>> {
35+
36+
readonly keysAndUrls = Lazy((): Result<{ keys: string[]; urls: string[] }> => {
3637
const keys: string[] = [];
3738
const urls: string[] = [];
3839
// eslint-disable-next-line no-constant-condition
39-
for (let idx = 0; true; idx++) {
40+
for (let idx = 0; true; idx++) {
4041
const suffix = !idx ? "" : `_${idx}`;
4142
const key = `CLERK_PUB_JWT_KEY${suffix}`;
4243
const url = `CLERK_PUB_JWT_URL${suffix}`;
@@ -64,6 +65,12 @@ class ClerkApiToken implements FPApiToken {
6465
);
6566
}
6667
}
68+
return Result.Ok({ keys, urls });
69+
})
70+
71+
async verify(token: string): Promise<Result<VerifiedAuth>> {
72+
const { keys, urls } = this.keysAndUrls().Ok();
73+
6774
const rt = await sts.verifyToken(token, keys, urls, {
6875
parseSchema: (payload: unknown): Result<FPClerkClaim> => {
6976
const r = FPClerkClaimSchema.safeParse(payload);
@@ -79,6 +86,7 @@ class ClerkApiToken implements FPApiToken {
7986
return Result.Err(rPublicKey);
8087
}
8188
const pem = await exportSPKI(rPublicKey.Ok().key);
89+
console.log("ClerkApiToken-verify", pem);
8290
const r = await exception2Result(() =>
8391
ClerkVerifyToken(token, {
8492
jwtKey: pem,
@@ -212,6 +220,7 @@ const tokenApi = Lazy(async (sthis: SuperThis) => {
212220
};
213221
});
214222

223+
export type BindPromise<T> = (promise: Promise<T>) => Promise<T>;
215224
// BaseSQLiteDatabase<'async', ResultSet, TSchema>
216225
export async function createHandler<T extends DashSqlite>(db: T, env: Record<string, string> | Env) {
217226
// const stream = new utils.ConsoleWriterStream();
@@ -269,7 +278,7 @@ export async function createHandler<T extends DashSqlite>(db: T, env: Record<str
269278
maxLedgers: coerceInt(env.MAX_LEDGERS, 5),
270279
deviceCA: rDeviceIdCA.Ok(),
271280
});
272-
return async (req: Request): Promise<Response> => {
281+
return async (req: Request, bindPromise: BindPromise<Result<unknown>> = (p) => p): Promise<Response> => {
273282
const startTime = performance.now();
274283
if (req.method === "OPTIONS") {
275284
return new Response("ok", {
@@ -359,7 +368,7 @@ export async function createHandler<T extends DashSqlite>(db: T, env: Record<str
359368
return new Response("Invalid request", { status: 400, headers: DefaultHttpHeaders() });
360369
}
361370
try {
362-
const rRes = await res;
371+
const rRes = await bindPromise(res);
363372
// console.log("Response", rRes);
364373
if (rRes.isErr()) {
365374
logger.Error().Any({ request: jso.type }).Err(rRes).Msg("Result-Error");

dashboard/backend/deno-serve.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ function getClient() {
1212
async function main() {
1313
Deno.serve({
1414
port: 7370,
15-
handler: await createHandler(getClient(), Deno.env.toObject()),
15+
handler: (await createHandler(getClient(), Deno.env.toObject())) as (req: Request) => Promise<Response>,
1616
});
1717
}
1818

dashboard/drizzle.d1-local-backend.config.ts renamed to dashboard/backend/drizzle.d1-local-backend.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ function getLocalD1DB(): string {
1717

1818
export default defineConfig({
1919
dialect: "sqlite",
20-
schema: "./backend/db-api-schema.ts",
20+
schema: "./db-api-schema.ts",
2121
out: "./dist",
2222
dbCredentials: {
2323
url: getLocalD1DB(),

dashboard/drizzle.d1-local-pages.config.ts renamed to dashboard/backend/drizzle.d1-local-pages.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function getLocalD1DB() {
1616

1717
export default defineConfig({
1818
dialect: "sqlite",
19-
schema: "./backend/db-api-schema.ts",
19+
schema: "./db-api-schema.ts",
2020
out: "./dist",
2121
dbCredentials: {
2222
url: getLocalD1DB(),

0 commit comments

Comments
 (0)