lecodes-sdk 2.0.4 → 2.0.5

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.
Files changed (72) hide show
  1. package/README.md +104 -76
  2. package/dist/global.d.ts +2 -5
  3. package/dist/host.d.ts +3 -0
  4. package/dist/types/inject.d.ts +3 -3
  5. package/dist/types/runtime/device.d.ts +7 -0
  6. package/dist/types/runtime/rpc.d.ts +11 -17
  7. package/dist/types/runtime/wire.d.ts +53 -0
  8. package/dist/types/server/auth/api.d.ts +42 -0
  9. package/dist/types/server/auth/appConfig.d.ts +1 -5
  10. package/dist/types/server/auth/models.d.ts +119 -70
  11. package/dist/types/server/auth/types.d.ts +19 -43
  12. package/dist/types/server/channel.d.ts +57 -19
  13. package/dist/types/server/context.d.ts +2 -2
  14. package/dist/types/server/db/defineDb.d.ts +10 -0
  15. package/dist/types/server/db/index.d.ts +1 -1
  16. package/dist/types/server/db/types.d.ts +76 -6
  17. package/dist/types/server/inject.d.ts +0 -1
  18. package/dist/types/ui/UINode.d.ts +19 -5
  19. package/dist/types/ui/UIScreen.d.ts +1 -0
  20. package/dist/types/ui/UITabs.d.ts +8 -6
  21. package/dist/types/ui/theme.d.ts +48 -13
  22. package/dist/types/version.d.ts +1 -1
  23. package/dist/types.json +1 -1
  24. package/package.json +3 -2
  25. package/prompts/README.md +1 -1
  26. package/prompts/design.md +19 -19
  27. package/prompts/dist/2d-game.md +45 -31
  28. package/prompts/dist/3d-app.md +45 -31
  29. package/prompts/dist/ar-app.md +45 -31
  30. package/prompts/dist/design.md +25 -24
  31. package/prompts/dist/ui-app.md +45 -31
  32. package/prompts/ui-design.md +6 -5
  33. package/prompts/ui.md +25 -22
  34. package/src/bridges/device.d.ts +9 -0
  35. package/src/bridges/tree.d.ts +5 -0
  36. package/src/chisel.ts +1 -1
  37. package/src/compile/bundler.ts +6 -0
  38. package/src/compile/compileProject.ts +3 -1
  39. package/src/compile/index.ts +3 -1
  40. package/src/compile/serverSplit.ts +58 -11
  41. package/src/compile/serverTypes.ts +189 -8
  42. package/src/host.d.ts +3 -0
  43. package/src/inject.ts +6 -6
  44. package/src/runtime/device.ts +12 -0
  45. package/src/runtime/rpc.ts +101 -40
  46. package/src/runtime/wire.ts +35 -0
  47. package/src/server/auth/api.ts +94 -0
  48. package/src/server/auth/appConfig.ts +2 -3
  49. package/src/server/auth/host.ts +244 -174
  50. package/src/server/auth/models.ts +45 -62
  51. package/src/server/auth/types.ts +19 -34
  52. package/src/server/channel.ts +97 -29
  53. package/src/server/channelHub.ts +153 -0
  54. package/src/server/context.ts +2 -2
  55. package/src/server/db/defineDb.ts +96 -36
  56. package/src/server/db/index.ts +1 -1
  57. package/src/server/db/types.ts +76 -8
  58. package/src/server/host.ts +25 -10
  59. package/src/server/inject.ts +2 -2
  60. package/src/server/runtime.ts +34 -12
  61. package/src/ui/UINode.ts +22 -5
  62. package/src/ui/UIScreen.ts +5 -0
  63. package/src/ui/UITabs.ts +19 -17
  64. package/src/ui/styleColor.ts +10 -1
  65. package/src/ui/theme.ts +96 -41
  66. package/src/version.ts +1 -1
  67. package/tests/helpers/fakeTree.ts +1 -0
  68. package/dist/types/plugins/oauth.d.ts +0 -25
  69. package/dist/types/server/auth/global.d.ts +0 -56
  70. package/src/plugins/oauth.ts +0 -61
  71. package/src/server/auth/global.ts +0 -80
  72. package/tests/helpers/memoryMarci.ts +0 -124
@@ -0,0 +1,94 @@
1
+ /**
2
+ * `db.auth` — the BUNDLE side of sign-in, what `*.server.ts` code calls on a db made with
3
+ * `defineDb({...}).withAuth({ model: "User" })`:
4
+ *
5
+ * const db = defineDb({ User, Post }).withAuth({ model: "User" })
6
+ *
7
+ * export async function register(login: string, password: string, name: string) {
8
+ * await db.auth.signUpWithPassword(login, password, { name })
9
+ * }
10
+ * export async function me() { return db.auth.user().select({ id: true, name: true }) }
11
+ * export async function removePost(id: number) {
12
+ * await db.auth.requireUser({ role: "admin" }).select({ id: true })
13
+ * …
14
+ * }
15
+ *
16
+ * The platform knows a request's session and the ID of its user (the host resolved the token before
17
+ * the endpoint ran). Everything else about a user is a row of the project's own model, and is READ:
18
+ * `user()` / `requireUser()` are queries over that model — typed by it, run when awaited — narrowed to
19
+ * the user of the request. Sign-in operations forward to the host's `AuthOps` on
20
+ * `globalThis.__lecodesAuth` (a seam: the compiled bundle carries its own SDK copy).
21
+ */
22
+
23
+ import { currentRequest, type RequestContext } from "../context"
24
+ import { ApiError } from "../errors"
25
+ import type { AuthOps, AuthState } from "./types"
26
+
27
+ /** The collections of a db with auth, by role (defineDb.ts). */
28
+ export type AuthCollections = { model: string, user: any, session: any, identity: any }
29
+
30
+ const seam = globalThis as unknown as { __lecodesAuth?: AuthOps }
31
+ const ops = (): AuthOps => {
32
+ const o = seam.__lecodesAuth
33
+ if (!o) throw new Error("db.auth: not available — the host did not install the auth runtime (globalThis.__lecodesAuth)")
34
+ return o
35
+ }
36
+ const ctx = (): RequestContext => {
37
+ const c = currentRequest()
38
+ if (!c) throw new Error("db.auth: no current request — it is only available while handling an endpoint or a channel join")
39
+ return c
40
+ }
41
+ const state = (): AuthState => {
42
+ const s = ctx().auth as AuthState | undefined
43
+ if (!s) throw new Error("db.auth: the request carries no session — the host runs no auth for this db")
44
+ return s
45
+ }
46
+
47
+ /** A select of the id alone: the answer is in the session already. */
48
+ const onlyId = (shape: Record<string, unknown> | undefined): boolean => {
49
+ if (!shape) return false
50
+ const keys = Object.keys(shape)
51
+ return keys.length === 1 && keys[0] === "id" && shape.id === true
52
+ }
53
+
54
+ export const createAuthApi = (tables: () => AuthCollections) => {
55
+ // The user of the request as a query: nothing runs until it is awaited. `required` = a guest is a
56
+ // 401 instead of null; `where` narrows it (a check of access: no row is a 403).
57
+ // The request is taken when the query is MADE (inside the endpoint), not when it is awaited: an endpoint
58
+ // may hand the query back unawaited (`me = () => db.auth.user()`), and it then runs outside the request's scope.
59
+ const userQuery = (of: RequestContext | undefined, required: boolean, where?: Record<string, unknown>, shape?: Record<string, unknown>): any => {
60
+ const run = async () => {
61
+ const s = (of?.auth as AuthState | undefined) ?? state()
62
+ if (s.userId === null) {
63
+ if (required) throw new ApiError(401, "Sign in required")
64
+ return null
65
+ }
66
+ if (!where && onlyId(shape)) return { id: s.userId }
67
+ let q = tables().user.where({ id: s.userId })
68
+ if (where) q = q.where(where)
69
+ const row = await (shape ? q.select(shape) : q).first()
70
+ if (!row && required) throw new ApiError(where ? 403 : 401, where ? "Forbidden" : "Sign in required")
71
+ return row
72
+ }
73
+ return {
74
+ select: (next: Record<string, unknown>) => userQuery(of, required, where, next),
75
+ then: (onFulfilled?: any, onRejected?: any) => run().then(onFulfilled, onRejected),
76
+ }
77
+ }
78
+
79
+ return {
80
+ user: () => userQuery(currentRequest(), false),
81
+ requireUser: (where?: Record<string, unknown>) => userQuery(currentRequest(), true, where),
82
+ get sessionId(): number { return state().sessionId },
83
+
84
+ signUpWithPassword: (login: string, password: string, data?: Record<string, unknown>) => ops().signUpWithPassword(ctx(), login, password, data),
85
+ signInWithPassword: (login: string, password: string) => ops().signInWithPassword(ctx(), login, password),
86
+ setPassword: (password: string) => ops().setPassword(ctx(), password),
87
+ sendCode: (email: string) => ops().sendCode(ctx(), email),
88
+ signInWithCode: (email: string, code: string) => ops().signInWithCode(ctx(), email, code),
89
+ signIn: (userId: number) => ops().signIn(ctx(), userId),
90
+ signOut: () => ops().signOut(ctx()),
91
+ get sessions() { return ops().sessions(ctx()) },
92
+ get identities() { return ops().identities(ctx()) },
93
+ }
94
+ }
@@ -1,12 +1,11 @@
1
1
  /**
2
- * The project's `app.json` subset the server runtime reads (name, auth providers).
2
+ * The project's `app.json` subset the server runtime reads: the app's name (the sign-in mail).
3
3
  *
4
4
  * This module is a placeholder the COMPILER REPLACES: `compileServerBundle({ app })` puts a module with the
5
5
  * real values at this same path in chisel's file map (project files win over SDK files), so every SDK module
6
6
  * that imports `app` gets the project's config as a plain dependency — no globals, no evaluation-order games.
7
7
  * Outside a compiled bundle (tests, tooling) `globalThis.__lecodesApp` can stand in.
8
8
  */
9
- export type AuthProvider = "email" | "google" | "apple" | "yandex" | "vk"
10
- export type AppConfig = { name?: string, auth?: { providers?: AuthProvider[] } }
9
+ export type AppConfig = { name?: string }
11
10
 
12
11
  export const app: AppConfig = {}