lakebed 0.0.17 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/package.json +5 -5
- package/src/anonymous.js +3 -2
- package/src/auth.js +2 -3
- package/src/cli.js +31 -4
- package/src/client.d.ts +0 -1
- package/src/client.js +2 -2
- package/src/server.d.ts +0 -1
- package/src/version.js +1 -1
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ export default capsule({
|
|
|
61
61
|
|
|
62
62
|
## Auth
|
|
63
63
|
|
|
64
|
-
Every app starts with local guest auth. To let users sign in with Google, render the built-in button. Lakebed
|
|
64
|
+
Every app starts with local guest auth. To let users sign in with Google, render the built-in button. Lakebed asks Shoo for profile fields and exposes the user's name and avatar through `auth.displayName` and `auth.picture`.
|
|
65
65
|
Check `auth.isLoading` before showing signed-out UI, because Lakebed may still be confirming a stored session.
|
|
66
66
|
|
|
67
67
|
```tsx
|
|
@@ -69,7 +69,7 @@ import { SignInWithGoogle, signOut, useAuth } from "lakebed/client";
|
|
|
69
69
|
|
|
70
70
|
export function App() {
|
|
71
71
|
const auth = useAuth();
|
|
72
|
-
const authLabel = auth.
|
|
72
|
+
const authLabel = auth.displayName;
|
|
73
73
|
|
|
74
74
|
if (auth.isLoading) {
|
|
75
75
|
return <p>Checking session</p>;
|
|
@@ -78,7 +78,8 @@ export function App() {
|
|
|
78
78
|
return auth.isGuest ? (
|
|
79
79
|
<SignInWithGoogle />
|
|
80
80
|
) : (
|
|
81
|
-
<button type="button" onClick={() => signOut()}>
|
|
81
|
+
<button className="inline-flex items-center gap-2" type="button" onClick={() => signOut()}>
|
|
82
|
+
{auth.picture ? <img alt="" className="h-6 w-6 rounded-full" referrerPolicy="no-referrer" src={auth.picture} /> : null}
|
|
82
83
|
Sign out {authLabel}
|
|
83
84
|
</button>
|
|
84
85
|
);
|
|
@@ -90,7 +91,7 @@ After sign-in, server handlers receive the verified Google identity through `ctx
|
|
|
90
91
|
```ts
|
|
91
92
|
mutations: {
|
|
92
93
|
save: mutation((ctx) => {
|
|
93
|
-
ctx.log.info("signed in user", { userId: ctx.auth.userId,
|
|
94
|
+
ctx.log.info("signed in user", { userId: ctx.auth.userId, displayName: ctx.auth.displayName });
|
|
94
95
|
});
|
|
95
96
|
}
|
|
96
97
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lakebed",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"description": "Agent-native CLI and runtime for building and deploying Lakebed capsules.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -52,9 +52,6 @@
|
|
|
52
52
|
"publishConfig": {
|
|
53
53
|
"access": "public"
|
|
54
54
|
},
|
|
55
|
-
"scripts": {
|
|
56
|
-
"check": "node --check src/cli.js && node --check src/runtime.js && node --check src/server.js && node --check src/client.js && node --check src/source-store.js && node --check src/source-runtime.js && node --check src/source-runtime-worker.js && node --check src/source-runtime-loader.mjs && node --check src/anonymous.js && node --check src/anonymous-server.js && node --check src/auth.js && node --check src/version.js"
|
|
57
|
-
},
|
|
58
55
|
"dependencies": {
|
|
59
56
|
"esbuild": "^0.27.1",
|
|
60
57
|
"pg": "^8.16.3",
|
|
@@ -63,5 +60,8 @@
|
|
|
63
60
|
},
|
|
64
61
|
"devDependencies": {
|
|
65
62
|
"@types/ws": "^8.18.1"
|
|
63
|
+
},
|
|
64
|
+
"scripts": {
|
|
65
|
+
"check": "node --check src/cli.js && node --check src/runtime.js && node --check src/server.js && node --check src/client.js && node --check src/source-store.js && node --check src/source-runtime.js && node --check src/source-runtime-worker.js && node --check src/source-runtime-loader.mjs && node --check src/anonymous.js && node --check src/anonymous-server.js && node --check src/auth.js && node --check src/version.js"
|
|
66
66
|
}
|
|
67
|
-
}
|
|
67
|
+
}
|
package/src/anonymous.js
CHANGED
|
@@ -29,7 +29,7 @@ export const DEFAULT_ANONYMOUS_LIMITS = {
|
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
const expressionOps = new Set(["arg", "auth", "call", "row"]);
|
|
32
|
-
const authFields = new Set(["displayName", "email", "emailVerified", "isAuthenticated", "isGuest", "
|
|
32
|
+
const authFields = new Set(["displayName", "email", "emailVerified", "isAuthenticated", "isGuest", "picture", "provider", "userId"]);
|
|
33
33
|
const sourceModuleCache = new Map();
|
|
34
34
|
|
|
35
35
|
export class AnonymousCompilerError extends Error {
|
|
@@ -228,7 +228,6 @@ function createSymbolicAuth() {
|
|
|
228
228
|
emailVerified: new SymbolicValue(["auth", "emailVerified"], true),
|
|
229
229
|
isAuthenticated: new SymbolicValue(["auth", "isAuthenticated"], true),
|
|
230
230
|
isGuest: new SymbolicValue(["auth", "isGuest"], false),
|
|
231
|
-
name: new SymbolicValue(["auth", "name"], "Trace Guest"),
|
|
232
231
|
picture: new SymbolicValue(["auth", "picture"], "https://example.test/avatar.png"),
|
|
233
232
|
provider: new SymbolicValue(["auth", "provider"], "google"),
|
|
234
233
|
userId: new SymbolicValue(["auth", "userId"], "guest:trace")
|
|
@@ -248,6 +247,8 @@ function createSymbolicRow({ auth, idExpr, scanId, schema, tableName }) {
|
|
|
248
247
|
row[fieldName] = auth.userId;
|
|
249
248
|
} else if (fieldName === "authorName") {
|
|
250
249
|
row[fieldName] = auth.displayName;
|
|
250
|
+
} else if (fieldName === "authorPicture") {
|
|
251
|
+
row[fieldName] = auth.picture;
|
|
251
252
|
} else if (field.kind === "boolean") {
|
|
252
253
|
row[fieldName] = true;
|
|
253
254
|
} else {
|
package/src/auth.js
CHANGED
|
@@ -81,15 +81,14 @@ function authFromClaims(claims) {
|
|
|
81
81
|
return null;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
const name = stringClaim(claims, "name");
|
|
84
|
+
const name = stringClaim(claims, "name")?.trim();
|
|
85
85
|
const email = stringClaim(claims, "email");
|
|
86
86
|
return {
|
|
87
|
-
displayName: name
|
|
87
|
+
displayName: name || "Google User",
|
|
88
88
|
email,
|
|
89
89
|
emailVerified: booleanClaim(claims, "email_verified"),
|
|
90
90
|
isAuthenticated: true,
|
|
91
91
|
isGuest: false,
|
|
92
|
-
name,
|
|
93
92
|
picture: stringClaim(claims, "picture"),
|
|
94
93
|
provider: "google",
|
|
95
94
|
userId: `google:${pairwiseSub}`
|
package/src/cli.js
CHANGED
|
@@ -1609,11 +1609,35 @@ export default capsule({
|
|
|
1609
1609
|
"client/index.tsx": `import { SignInWithGoogle, signOut, useAuth, useMutation, useQuery } from "lakebed/client";
|
|
1610
1610
|
import { cleanTodoText, type Todo } from "../shared/todo";
|
|
1611
1611
|
|
|
1612
|
+
function AuthAvatar({ label, picture }: { label: string; picture?: string }) {
|
|
1613
|
+
const initial = label.trim().slice(0, 1).toUpperCase() || "?";
|
|
1614
|
+
|
|
1615
|
+
if (picture) {
|
|
1616
|
+
return (
|
|
1617
|
+
<img
|
|
1618
|
+
alt=""
|
|
1619
|
+
className="h-7 w-7 shrink-0 rounded-full border border-neutral-800 bg-neutral-900 object-cover"
|
|
1620
|
+
referrerPolicy="no-referrer"
|
|
1621
|
+
src={picture}
|
|
1622
|
+
/>
|
|
1623
|
+
);
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
return (
|
|
1627
|
+
<span
|
|
1628
|
+
aria-hidden="true"
|
|
1629
|
+
className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full border border-neutral-800 bg-neutral-900 text-xs font-medium text-neutral-300"
|
|
1630
|
+
>
|
|
1631
|
+
{initial}
|
|
1632
|
+
</span>
|
|
1633
|
+
);
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1612
1636
|
export function App() {
|
|
1613
1637
|
const auth = useAuth();
|
|
1614
1638
|
const todos = useQuery<Todo[]>("todos");
|
|
1615
1639
|
const addTodo = useMutation<[text: string], void>("addTodo");
|
|
1616
|
-
const authLabel = auth.
|
|
1640
|
+
const authLabel = auth.displayName;
|
|
1617
1641
|
const authStatus = auth.isLoading && auth.isGuest ? "checking session" : "signed in as " + authLabel;
|
|
1618
1642
|
|
|
1619
1643
|
async function onSubmit(event: SubmitEvent) {
|
|
@@ -1633,11 +1657,14 @@ export function App() {
|
|
|
1633
1657
|
<main className="min-h-screen bg-black px-6 py-10 text-white">
|
|
1634
1658
|
<section className="mx-auto max-w-2xl">
|
|
1635
1659
|
<div className="mb-3 flex items-center justify-between gap-3">
|
|
1636
|
-
<
|
|
1660
|
+
<div className="flex min-w-0 items-center gap-2">
|
|
1661
|
+
{!auth.isLoading ? <AuthAvatar label={authLabel} picture={auth.picture} /> : null}
|
|
1662
|
+
<p className="min-w-0 truncate font-mono text-sm text-neutral-500">{authStatus}</p>
|
|
1663
|
+
</div>
|
|
1637
1664
|
{!auth.isLoading && auth.isGuest ? (
|
|
1638
|
-
<SignInWithGoogle className="border border-neutral-700 px-3 py-1.5 text-sm font-medium text-neutral-200 hover:border-white hover:text-white" />
|
|
1665
|
+
<SignInWithGoogle className="shrink-0 border border-neutral-700 px-3 py-1.5 text-sm font-medium text-neutral-200 hover:border-white hover:text-white" />
|
|
1639
1666
|
) : !auth.isLoading ? (
|
|
1640
|
-
<button className="text-sm text-neutral-400 hover:text-white" type="button" onClick={() => signOut()}>
|
|
1667
|
+
<button className="shrink-0 text-sm text-neutral-400 hover:text-white" type="button" onClick={() => signOut()}>
|
|
1641
1668
|
Sign out
|
|
1642
1669
|
</button>
|
|
1643
1670
|
) : null}
|
package/src/client.d.ts
CHANGED
package/src/client.js
CHANGED
|
@@ -349,13 +349,13 @@ function createGoogleAuthFromToken(token) {
|
|
|
349
349
|
return null;
|
|
350
350
|
}
|
|
351
351
|
|
|
352
|
+
const displayName = typeof claims.name === "string" && claims.name.trim() ? claims.name.trim() : "Google User";
|
|
352
353
|
return {
|
|
353
|
-
displayName
|
|
354
|
+
displayName,
|
|
354
355
|
email: claims.email,
|
|
355
356
|
emailVerified: claims.email_verified,
|
|
356
357
|
isAuthenticated: true,
|
|
357
358
|
isGuest: false,
|
|
358
|
-
name: claims.name,
|
|
359
359
|
picture: claims.picture,
|
|
360
360
|
provider: "google",
|
|
361
361
|
userId: `google:${pairwiseSub}`
|
package/src/server.d.ts
CHANGED
package/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const LAKEBED_VERSION = "0.0.
|
|
1
|
+
export const LAKEBED_VERSION = "0.0.18";
|