Conversation
🚀 Package Preview Available!Install this PR's preview build with npm: npm i @base44-preview/cli@0.0.45-pr.406.b61b272Prefer not to change any import paths? Install using npm alias so your code still imports npm i "base44@npm:@base44-preview/cli@0.0.45-pr.406.b61b272"Or add it to your {
"dependencies": {
"base44": "npm:@base44-preview/cli@0.0.45-pr.406.b61b272"
}
}
Preview published to npm registry — try new features instantly! |
04e8a12 to
f8afa4a
Compare
11c2912 to
f7b1fa4
Compare
| /** @public - called by Commander internally via command dispatch */ | ||
| override action( | ||
| // biome-ignore lint/suspicious/noExplicitAny: must match Commander.js action() signature | ||
| // biome-ignore lint/suspicious/noConfusingVoidType: must match Commander.js action() signature |
There was a problem hiding this comment.
Not related to my PR, but started to fail for me.
Ignoring
| const result = validator.validate({ name: "Alice" }, schema); | ||
|
|
||
| expect(result.hasError).toBe(false); | ||
| expect(() => validator.validate({ name: "Alice" }, schema)).not.toThrow(); |
There was a problem hiding this comment.
Validator is now throwing an error, instead of returning object that describes the error.
Updating tests to handle it.
Here and below.
| ); | ||
| if (requiredFieldsResponse.hasError) { | ||
| return requiredFieldsResponse; | ||
| throw new EntityValidationError(requiredFieldsResponse.error); |
There was a problem hiding this comment.
I found that it's more convenient to throw the error, rather than return an object that describes the error.
So I decided to refactor it a bit.
44675f2 to
2d12f4c
Compare
| private normalizeName(entityName: string): string { | ||
| return entityName.toLowerCase(); | ||
| } |
There was a problem hiding this comment.
Behind the scenes production is treating entity name as case-insensitive: "User" and "user" are the same.
kfirstri
left a comment
There was a problem hiding this comment.
Looks good, i'm not sure i understand some stuff in the entities-user-router..
Also, can we resolve the user with the auth token and not with readAuth somehow? I see we added a check to assert the api calls has a Bearer.. so maybe we can parse the token?
| return; | ||
| } | ||
| next(); | ||
| }); |
There was a problem hiding this comment.
So every request to the dev-server must have an authorization header. Is this also how the apper/ backend works? It won't allow anonymous calls at all?
| let result: Record<string, unknown> | undefined; | ||
|
|
||
| if (req.params.id === "me") { | ||
| const userInfo = await readAuth(); |
There was a problem hiding this comment.
Wont the request at this point will have a authorization token that we can read some user data from? then we don't need the readAuth call
| const now = getNowISOTimestamp(); | ||
|
|
||
| // Production is not allowing to add user entity directly. | ||
| // In case developer tries to do it - backend silently fails. |
There was a problem hiding this comment.
I don't understand this whole POST / endpoint .. we're validating the developing (since we're using readAuth), and if we found the developer account we just return an object, but not really save it? so basically it's just a mock.. but production also does not allow it?
| router.post("/bulk", async (_req, res) => { | ||
| // not supported in direct call: NO-OP | ||
| res.json({}); | ||
| }); |
There was a problem hiding this comment.
Is this a noop endpoint because we just don't want to support it? can't we just delete it and it will return 404?
| const userInfo = await readAuth(); | ||
| const collection = db.getCollection(USER_COLLECTION); | ||
| const userRecord = await collection?.findOneAsync({ | ||
| email: userInfo.email, | ||
| }); |
There was a problem hiding this comment.
If this is really how we will get the developer account (raising it again - do we have it as an auth header maybe?), then this is the 3rd time we're doing this in this file, so maybe refactor to another function
| return; | ||
| } | ||
| logger.error( | ||
| `Error in PUT /${USER_COLLECTION}/${req.params.id}:`, |
There was a problem hiding this comment.
This error looks weird, no need to use USER_COLLECTION inside the url that we're printing
| res.status(404).json({ error: `User record not found` }); | ||
| } | ||
| } else { | ||
| res.json({}); |
There was a problem hiding this comment.
IF the user can only update himself and not others, shouldn't we return some errors? this is how apper behaves? :S
| router.delete("/:id", async (_req, res) => { | ||
| // not supported in direct call: NO-OP | ||
| res.json({}); | ||
| }); |
There was a problem hiding this comment.
same question like in /bulk route, maybe we can just remove it? what does "direct call" mean?
| return { | ||
| name: "User", | ||
| type: "object", | ||
| properties: { ...builtInFields, role: { type: "string" } }, |
There was a problem hiding this comment.
"role" is also a built-in field https://docs.base44.com/developers/backend/resources/entities/user-schema#built-in-fields
Note
Description
This PR adds local User entity support to the dev server, replacing the previous behavior of proxying
/Userrequests to production. The authenticated user is now automatically seeded into an in-memoryusercollection on startup, and a dedicated router handles User CRUD operations locally with production-compatible semantics. The validator is also refactored from a return-value pattern to throw-based errors for cleaner call sites.Related Issue
None
Type of Change
Changes Made
Database.load()now seeds ausercollection pre-populated with the current authenticated user's info (email, name, role, etc.), eliminating the need to proxy/Usercalls to productionentities-user-router.ts: Dedicated Express router for/Userendpoints — GET by id or"me", PUT for"me"only, POST/DELETE/bulk as no-ops matching production behaviorValidator.validate()now throwsEntityValidationErrorinstead of returning aValidationResponseobject; all call sites and tests updated accordinglynormalizeName()main.tsrequiring aBearertoken on all requestsutils.ts: ExtractedstripInternalFieldsandgetNowISOTimestamphelpers into a shareddev-server/utils.tsmoduleroutes/entities.tsrenamed toroutes/entities/entities-router.ts;remoteProxydependency removed fromcreateEntityRoutesTesting
npm test)Checklist
docs/(AGENTS.md) if I made architectural changesAdditional Notes
The User entity is treated as a built-in collection with reserved fields (
full_name,email). If an app defines a customUserentity schema containing these fields, loading will throw an error at startup to prevent conflicts. The POST/Userendpoint silently returns a fake record (matching production behavior where direct user creation is not permitted).🤖 Generated by Claude | 2026-03-18 12:45 UTC