@softr/sdk 0.0.69-alpha.0 → 0.0.69
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/dist/auth/methods/utils.d.ts +1 -1
- package/dist/auth/platform.js +2 -9
- package/dist/auth/server.d.ts +0 -2
- package/dist/auth/server.js +0 -2
- package/dist/auth/session.js +1 -11
- package/dist/auth/user.d.ts +0 -4
- package/dist/auth/user.js +1 -3
- package/dist/codegen/datasource-docs.js +1 -1
- package/dist/codegen/write-datasource-docs.js +13 -6
- package/dist/default-error-overlay.d.ts +2 -2
- package/dist/mcp.d.ts +2 -2
- package/dist/package.js +1 -1
- package/dist/pwa.d.ts +2 -2
- package/package.json +1 -1
- package/skills/softr-sdk/SKILL.md +1 -1
- package/skills/softr-sdk/auth/SKILL.md +10 -29
- package/skills/softr-sdk/charts-and-metrics/SKILL.md +1 -1
- package/skills/softr-sdk/current-user/SKILL.md +1 -3
- package/skills/softr-sdk/file-uploads/SKILL.md +1 -1
- package/skills/softr-sdk/formatting/SKILL.md +1 -1
- package/skills/softr-sdk/integrations/SKILL.md +1 -1
- package/skills/softr-sdk/mcp/SKILL.md +1 -1
- package/skills/softr-sdk/pwa/SKILL.md +1 -1
- package/skills/softr-sdk/record-mutations/SKILL.md +1 -1
- package/skills/softr-sdk/record-queries/SKILL.md +1 -1
- package/skills/softr-sdk/region-visibility/SKILL.md +1 -1
- package/skills/softr-sdk/routes-and-visibility/SKILL.md +1 -1
- package/skills/softr-sdk/workflows/SKILL.md +1 -1
- package/dist/auth/methods/profile.d.ts +0 -26
- package/dist/auth/methods/profile.js +0 -52
|
@@ -10,6 +10,6 @@ type AuthError = {
|
|
|
10
10
|
code: AuthErrorCode;
|
|
11
11
|
message: string;
|
|
12
12
|
};
|
|
13
|
-
type AuthErrorCode = "invalidCredentials" | "tooManyAttempts" | "emailTaken" | "invalidDetails" | "invalidCode" | "notAuthenticated" | "emailDomainNotAllowed" | "linkExpired"
|
|
13
|
+
type AuthErrorCode = "invalidCredentials" | "tooManyAttempts" | "emailTaken" | "invalidDetails" | "invalidCode" | "notAuthenticated" | "emailDomainNotAllowed" | "linkExpired";
|
|
14
14
|
//#endregion
|
|
15
15
|
export { AuthError, Result };
|
package/dist/auth/platform.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { panic } from "../assertions.js";
|
|
2
2
|
import { fetch } from "../fetch.js";
|
|
3
3
|
import { permissionsSchema } from "./permissions.js";
|
|
4
4
|
import { sessionConfig } from "./config.js";
|
|
@@ -267,11 +267,6 @@ function makePlatform(applicationId) {
|
|
|
267
267
|
token,
|
|
268
268
|
json: { code }
|
|
269
269
|
}, z.null()),
|
|
270
|
-
updateProfile: (token, form) => request(`/v1/vibe/applications/${applicationId}/users/me/profile`, {
|
|
271
|
-
method: "PATCH",
|
|
272
|
-
token,
|
|
273
|
-
form
|
|
274
|
-
}, userSchema),
|
|
275
270
|
signOut: (token) => request(`/v1/applications/${applicationId}/users/sign-out`, {
|
|
276
271
|
method: "POST",
|
|
277
272
|
token
|
|
@@ -280,7 +275,6 @@ function makePlatform(applicationId) {
|
|
|
280
275
|
}
|
|
281
276
|
const errorSchema = z.object({ message: z.string() });
|
|
282
277
|
async function request(path, init, schema, parse = (response$1) => response$1.json()) {
|
|
283
|
-
assert(init.json === void 0 || init.form === void 0, "A platform request carries a JSON body or a form, not both");
|
|
284
278
|
const response = await fetch(`${await platformApiUrl()}${path}`, {
|
|
285
279
|
method: init.method,
|
|
286
280
|
headers: {
|
|
@@ -288,8 +282,7 @@ async function request(path, init, schema, parse = (response$1) => response$1.js
|
|
|
288
282
|
...init.json === void 0 ? {} : { "content-type": "application/json" },
|
|
289
283
|
...init.token ? { authorization: `Bearer ${init.token}` } : {}
|
|
290
284
|
},
|
|
291
|
-
...init.json === void 0 ? {} : { body: JSON.stringify(init.json) }
|
|
292
|
-
...init.form === void 0 ? {} : { body: init.form }
|
|
285
|
+
...init.json === void 0 ? {} : { body: JSON.stringify(init.json) }
|
|
293
286
|
});
|
|
294
287
|
if (!response.ok) {
|
|
295
288
|
const error = errorSchema.safeParse(await response.json().catch(() => null));
|
package/dist/auth/server.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ import { checkPasswordLink, requestPasswordReset, setPasswordWithLink } from "./
|
|
|
6
6
|
import { settings } from "./methods/settings.js";
|
|
7
7
|
import { confirmSignUp, signUp } from "./methods/signup.js";
|
|
8
8
|
import { signInWithGoogle } from "./methods/social.js";
|
|
9
|
-
import { updateProfile } from "./methods/profile.js";
|
|
10
9
|
import { currentUserRow } from "./current-user-row.js";
|
|
11
10
|
import "@tanstack/react-start/server-only";
|
|
12
11
|
|
|
@@ -35,7 +34,6 @@ declare const auth: {
|
|
|
35
34
|
resetAuthenticator: typeof resetAuthenticator;
|
|
36
35
|
removeAuthenticator: typeof removeAuthenticator;
|
|
37
36
|
settings: typeof settings;
|
|
38
|
-
updateProfile: typeof updateProfile;
|
|
39
37
|
currentUserRow: typeof currentUserRow;
|
|
40
38
|
};
|
|
41
39
|
//#endregion
|
package/dist/auth/server.js
CHANGED
|
@@ -6,7 +6,6 @@ import { signIn, signOut } from "./methods/password.js";
|
|
|
6
6
|
import { checkPasswordLink, requestPasswordReset, setPasswordWithLink } from "./methods/passwordLink.js";
|
|
7
7
|
import { confirmSignUp, signUp } from "./methods/signup.js";
|
|
8
8
|
import { signInWithGoogle } from "./methods/social.js";
|
|
9
|
-
import { updateProfile } from "./methods/profile.js";
|
|
10
9
|
import { currentUserRow } from "./current-user-row.js";
|
|
11
10
|
import "@tanstack/react-start/server-only";
|
|
12
11
|
|
|
@@ -34,7 +33,6 @@ const auth = {
|
|
|
34
33
|
resetAuthenticator,
|
|
35
34
|
removeAuthenticator,
|
|
36
35
|
settings,
|
|
37
|
-
updateProfile,
|
|
38
36
|
currentUserRow
|
|
39
37
|
};
|
|
40
38
|
|
package/dist/auth/session.js
CHANGED
|
@@ -118,16 +118,6 @@ function clearSession() {
|
|
|
118
118
|
PENDING_AUTH
|
|
119
119
|
]);
|
|
120
120
|
}
|
|
121
|
-
/**
|
|
122
|
-
* Drops the cached visitor and leaves the session signed in, so the next
|
|
123
|
-
* request needing a visitor re-reads one from the platform.
|
|
124
|
-
*
|
|
125
|
-
* For a mutation to what the visitor's own record holds — their name, their
|
|
126
|
-
* groups — which the cache would otherwise answer stale for up to five minutes.
|
|
127
|
-
*/
|
|
128
|
-
function clearSessionData() {
|
|
129
|
-
clearCookies([SESSION_DATA]);
|
|
130
|
-
}
|
|
131
121
|
const standInToken = new AsyncLocalStorage();
|
|
132
122
|
const sessionDataSchema = z.object({
|
|
133
123
|
user: userSchema.nullable(),
|
|
@@ -220,4 +210,4 @@ function openEnvelope(raw, purpose) {
|
|
|
220
210
|
}
|
|
221
211
|
|
|
222
212
|
//#endregion
|
|
223
|
-
export { clearPendingAuth, clearSession,
|
|
213
|
+
export { clearPendingAuth, clearSession, makePendingAuthCookie, makeSessionDataCookie, makeSessionTokenCookie, readPendingAuthToken, readSessionData, readSessionToken, withSessionToken };
|
package/dist/auth/user.d.ts
CHANGED
|
@@ -19,10 +19,6 @@ type User = {
|
|
|
19
19
|
email: string;
|
|
20
20
|
fullName: string;
|
|
21
21
|
userGroupIds: Array<SoftrUserGroupId>;
|
|
22
|
-
/** Their photo, or `null` when they have none. Show their initials then. */
|
|
23
|
-
avatarUrl: string | null;
|
|
24
|
-
/** Whether `auth.updateProfile` can change their photo in this app. */
|
|
25
|
-
avatarEditable: boolean;
|
|
26
22
|
};
|
|
27
23
|
//#endregion
|
|
28
24
|
export { SoftrUserGroupId, SoftrUserGroups, User };
|
package/dist/auth/user.js
CHANGED
|
@@ -5,9 +5,7 @@ const userSchema = z.object({
|
|
|
5
5
|
id: z.string(),
|
|
6
6
|
email: z.string(),
|
|
7
7
|
fullName: z.string(),
|
|
8
|
-
userGroupIds: z.array(z.string())
|
|
9
|
-
avatarUrl: z.string().nullable().default(null),
|
|
10
|
-
avatarEditable: z.boolean().default(false)
|
|
8
|
+
userGroupIds: z.array(z.string())
|
|
11
9
|
});
|
|
12
10
|
|
|
13
11
|
//#endregion
|
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
import { requireDefined } from "../assertions.js";
|
|
2
|
-
import { renderDatasourceDoc, renderDatasourceIndex } from "./datasource-docs.js";
|
|
2
|
+
import { DOC_NOTE, renderDatasourceDoc, renderDatasourceIndex } from "./datasource-docs.js";
|
|
3
3
|
import { renderDatasourceSchema } from "./datasource-schema.js";
|
|
4
4
|
import { docFileNames } from "./doc-file-names.js";
|
|
5
5
|
import { writeIfChanged } from "./write-if-changed.js";
|
|
6
|
+
import { existsSync, readFileSync, readdirSync, rmSync } from "node:fs";
|
|
6
7
|
import path from "node:path";
|
|
7
8
|
|
|
8
9
|
//#region src/codegen/write-datasource-docs.ts
|
|
9
10
|
/**
|
|
10
|
-
* Writes the index, and one doc and one schema JSON per datasource, and
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* wrote now reads differently.
|
|
11
|
+
* Writes the index, and one doc and one schema JSON per datasource, and removes the doc and schema
|
|
12
|
+
* of a datasource no longer registered. It removes only a doc that carries the generated note: the
|
|
13
|
+
* caller resolves `docsDir` against `process.cwd()`, which can be any directory a developer ran the
|
|
14
|
+
* bin from. `changed` is true when any file it wrote now reads differently, or it removed one.
|
|
14
15
|
*/
|
|
15
16
|
function writeDatasourceDocs(datasources, docsDir) {
|
|
16
17
|
const context = {
|
|
17
18
|
datasources: new Map(datasources.map((datasource) => [datasource.id, datasource])),
|
|
18
19
|
fileNames: docFileNames(datasources)
|
|
19
20
|
};
|
|
21
|
+
const current = new Set(context.fileNames.values());
|
|
22
|
+
const stale = (existsSync(docsDir) ? readdirSync(docsDir, { withFileTypes: true }) : []).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).map((entry) => entry.name).filter((name) => !current.has(name) && readFileSync(path.join(docsDir, name), "utf8").includes(DOC_NOTE));
|
|
23
|
+
for (const name of stale) {
|
|
24
|
+
rmSync(path.join(docsDir, name));
|
|
25
|
+
rmSync(path.join(docsDir, name.replace(/\.md$/, ".json")), { force: true });
|
|
26
|
+
}
|
|
20
27
|
const writes = [
|
|
21
28
|
writeIfChanged(path.join(docsDir, "README.md"), renderDatasourceIndex(datasources, context)),
|
|
22
29
|
...datasources.map((datasource) => writeIfChanged(path.join(docsDir, requireDefined(context.fileNames.get(datasource.id))), renderDatasourceDoc(datasource, context))),
|
|
@@ -24,7 +31,7 @@ function writeDatasourceDocs(datasources, docsDir) {
|
|
|
24
31
|
];
|
|
25
32
|
return {
|
|
26
33
|
fileNames: context.fileNames,
|
|
27
|
-
changed: writes.includes(true)
|
|
34
|
+
changed: stale.length > 0 || writes.includes(true)
|
|
28
35
|
};
|
|
29
36
|
}
|
|
30
37
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react6 from "react";
|
|
2
2
|
|
|
3
3
|
//#region src/default-error-overlay.d.ts
|
|
4
4
|
type Props = {
|
|
@@ -8,6 +8,6 @@ type Props = {
|
|
|
8
8
|
declare function DefaultErrorOverlay({
|
|
9
9
|
error,
|
|
10
10
|
reset
|
|
11
|
-
}: Props):
|
|
11
|
+
}: Props): react6.JSX.Element;
|
|
12
12
|
//#endregion
|
|
13
13
|
export { DefaultErrorOverlay };
|
package/dist/mcp.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DatasourceAction } from "./action.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as _tanstack_react_start4 from "@tanstack/react-start";
|
|
3
3
|
|
|
4
4
|
//#region src/mcp.d.ts
|
|
5
5
|
|
|
@@ -31,6 +31,6 @@ type SoftrMcpOptions = {
|
|
|
31
31
|
* ],
|
|
32
32
|
* }))
|
|
33
33
|
*/
|
|
34
|
-
declare function softrMcpMiddleware(options?: SoftrMcpOptions):
|
|
34
|
+
declare function softrMcpMiddleware(options?: SoftrMcpOptions): _tanstack_react_start4.RequestMiddlewareAfterServer<{}, undefined, undefined>;
|
|
35
35
|
//#endregion
|
|
36
36
|
export { softrMcpMiddleware };
|
package/dist/package.js
CHANGED
package/dist/pwa.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react4 from "react";
|
|
2
2
|
import "@tanstack/react-start";
|
|
3
3
|
|
|
4
4
|
//#region src/pwa.d.ts
|
|
@@ -23,7 +23,7 @@ import "@tanstack/react-start";
|
|
|
23
23
|
* )
|
|
24
24
|
* }
|
|
25
25
|
*/
|
|
26
|
-
declare function SoftrPwaHead():
|
|
26
|
+
declare function SoftrPwaHead(): react4.FunctionComponentElement<react4.FragmentProps>;
|
|
27
27
|
type PwaPlatform = "ios" | "android" | "desktop";
|
|
28
28
|
type PwaInstall = {
|
|
29
29
|
available: false;
|
package/package.json
CHANGED
|
@@ -7,18 +7,19 @@ description: >-
|
|
|
7
7
|
sign-in (verifyAuthenticator, startAuthenticatorSetup,
|
|
8
8
|
confirmAuthenticatorSetup, skipAuthenticatorSetup) and the ones that change an
|
|
9
9
|
authenticator from a settings page (sendAuthenticatorResetCode,
|
|
10
|
-
resetAuthenticator, removeAuthenticator),
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
visitor is signed in, and toReturnPath for where to land after
|
|
10
|
+
resetAuthenticator, removeAuthenticator), the emailed password links
|
|
11
|
+
(requestPasswordReset, checkPasswordLink, setPasswordWithLink), and
|
|
12
|
+
getAuthSettings, AuthSettingsProvider and useAuthSettings for which sign-in
|
|
13
|
+
and sign-up methods the app has enabled. Covers the Result shape they answer
|
|
14
|
+
with and its codes invalidCredentials, tooManyAttempts, emailTaken,
|
|
15
|
+
invalidDetails, invalidCode, notAuthenticated, emailDomainNotAllowed and
|
|
16
|
+
linkExpired, the two-step sign-up, why a successful sign-in does not always
|
|
17
|
+
mean the visitor is signed in, and toReturnPath for where to land after
|
|
18
|
+
signing in.
|
|
18
19
|
metadata:
|
|
19
20
|
type: sub-skill
|
|
20
21
|
library: softr-sdk
|
|
21
|
-
library_version: 0.0.69
|
|
22
|
+
library_version: 0.0.69
|
|
22
23
|
---
|
|
23
24
|
|
|
24
25
|
**Boundary.** `auth` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build.
|
|
@@ -81,12 +82,6 @@ Changing an authenticator from a settings page:
|
|
|
81
82
|
| `auth.resetAuthenticator({ code })` | Unpairs the app, so a new one can be enrolled |
|
|
82
83
|
| `auth.removeAuthenticator({ code })` | Turns the authenticator off |
|
|
83
84
|
|
|
84
|
-
Changing the visitor's own profile:
|
|
85
|
-
|
|
86
|
-
| Call | Does |
|
|
87
|
-
| --- | --- |
|
|
88
|
-
| `auth.updateProfile({ fullName?, avatar? })` | Changes their name, their photo, or both. `avatar: null` removes the photo |
|
|
89
|
-
|
|
90
85
|
## Setup
|
|
91
86
|
|
|
92
87
|
`auth` is server-only, so every call sits inside a `createServerFn` handler:
|
|
@@ -456,20 +451,6 @@ All three need a signed-in visitor and answer `notAuthenticated` when there is n
|
|
|
456
451
|
|
|
457
452
|
After a reset, enrol the new app with `startAuthenticatorSetup` and `confirmAuthenticatorSetup`, which is also where the new backup codes come from. After a removal, an app that requires an authenticator asks the visitor to set one up again on their next sign-in.
|
|
458
453
|
|
|
459
|
-
### Changing the visitor's name and photo
|
|
460
|
-
|
|
461
|
-
```ts
|
|
462
|
-
const result = await auth.updateProfile({ fullName: 'Ann Lee' })
|
|
463
|
-
const result = await auth.updateProfile({ avatar: file }) // a File from an <input type="file">
|
|
464
|
-
const result = await auth.updateProfile({ avatar: null }) // removes the photo
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
It answers with the updated `User`. Pass the file through a server function that takes `FormData`. The photo must be a PNG, JPEG or GIF of at most 5 MB, or it answers `notAnImage` or `fileTooLarge`. A blank or unacceptable name answers `invalidName`.
|
|
468
|
-
|
|
469
|
-
Only some apps can store a photo. Show the photo controls only when `user.avatarEditable` is true; elsewhere a photo answers `avatarNotSupported`.
|
|
470
|
-
|
|
471
|
-
The page keeps showing the old name and photo until its route context loads again, so call `router.invalidate()` after a success.
|
|
472
|
-
|
|
473
454
|
## References
|
|
474
455
|
|
|
475
456
|
- [current-user/SKILL.md](../current-user/SKILL.md): reading the visitor these calls establish
|
|
@@ -12,7 +12,7 @@ description: >-
|
|
|
12
12
|
metadata:
|
|
13
13
|
type: sub-skill
|
|
14
14
|
library: softr-sdk
|
|
15
|
-
library_version: 0.0.69
|
|
15
|
+
library_version: 0.0.69
|
|
16
16
|
---
|
|
17
17
|
|
|
18
18
|
**Boundary.** `ds` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler or a server-side route hook — importing it into a component fails the build. `defineQuery` and every type come from `@softr/sdk` and can be imported anywhere.
|
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
metadata:
|
|
10
10
|
type: sub-skill
|
|
11
11
|
library: softr-sdk
|
|
12
|
-
library_version: 0.0.69
|
|
12
|
+
library_version: 0.0.69
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
# The current user
|
|
@@ -31,8 +31,6 @@ type User = {
|
|
|
31
31
|
email: string
|
|
32
32
|
fullName: string
|
|
33
33
|
userGroupIds: Array<SoftrUserGroupId> // the app's own group ids
|
|
34
|
-
avatarUrl: string | null // their photo; show their initials when null
|
|
35
|
-
avatarEditable: boolean // whether auth.updateProfile can change the photo
|
|
36
34
|
}
|
|
37
35
|
```
|
|
38
36
|
|
|
@@ -10,7 +10,7 @@ description: >-
|
|
|
10
10
|
metadata:
|
|
11
11
|
type: sub-skill
|
|
12
12
|
library: softr-sdk
|
|
13
|
-
library_version: 0.0.69
|
|
13
|
+
library_version: 0.0.69
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
**Boundary.** `upload` lives on `@softr/sdk/server` and runs inside server functions. `useFileUpload` and `FileItem` live on `@softr/sdk` and run in components. `FileAttachment` comes from `@softr/sdk` and can be imported anywhere.
|
|
@@ -10,7 +10,7 @@ description: >-
|
|
|
10
10
|
metadata:
|
|
11
11
|
type: sub-skill
|
|
12
12
|
library: softr-sdk
|
|
13
|
-
library_version: 0.0.69
|
|
13
|
+
library_version: 0.0.69
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
**Boundary.** `integration` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build. `defineIntegration` and every type come from `@softr/sdk` and can be imported anywhere.
|
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
metadata:
|
|
10
10
|
type: sub-skill
|
|
11
11
|
library: softr-sdk
|
|
12
|
-
library_version: 0.0.69
|
|
12
|
+
library_version: 0.0.69
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
**Boundary.** `softrMcpMiddleware` lives on `@softr/sdk` and is registered once, in `src/start.ts`. The actions you hand it are the same `defineQuery` / `defineMutation` values the app's own pages use — declared wherever they already live, not duplicated for MCP.
|
|
@@ -11,7 +11,7 @@ description: >-
|
|
|
11
11
|
metadata:
|
|
12
12
|
type: sub-skill
|
|
13
13
|
library: softr-sdk
|
|
14
|
-
library_version: 0.0.69
|
|
14
|
+
library_version: 0.0.69
|
|
15
15
|
---
|
|
16
16
|
|
|
17
17
|
**Boundary.** `ds` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build. `defineMutation` and every type come from `@softr/sdk` and can be imported anywhere.
|
|
@@ -13,7 +13,7 @@ description: >-
|
|
|
13
13
|
metadata:
|
|
14
14
|
type: sub-skill
|
|
15
15
|
library: softr-sdk
|
|
16
|
-
library_version: 0.0.69
|
|
16
|
+
library_version: 0.0.69
|
|
17
17
|
---
|
|
18
18
|
|
|
19
19
|
**Boundary.** `ds` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler or a server-side route hook — importing it into a component fails the build. The same holds for any helper that calls `ds`: declare it inside the handler. A function at module level that calls `ds` keeps the server-only import in the browser bundle, and every page stops loading until it moves. `defineQuery` and every type come from `@softr/sdk` and can be imported anywhere.
|
|
@@ -13,7 +13,7 @@ description: >-
|
|
|
13
13
|
metadata:
|
|
14
14
|
type: sub-skill
|
|
15
15
|
library: softr-sdk
|
|
16
|
-
library_version: 0.0.69
|
|
16
|
+
library_version: 0.0.69
|
|
17
17
|
---
|
|
18
18
|
|
|
19
19
|
**Boundary.** `defineVisibility`, the access functions and the error predicates come from `@softr/sdk` and work anywhere.
|
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
metadata:
|
|
10
10
|
type: sub-skill
|
|
11
11
|
library: softr-sdk
|
|
12
|
-
library_version: 0.0.69
|
|
12
|
+
library_version: 0.0.69
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
**Boundary.** `workflow` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build. `defineWorkflow` and every type come from `@softr/sdk` and can be imported anywhere.
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { User } from "../user.js";
|
|
2
|
-
import { AuthError, Result } from "./utils.js";
|
|
3
|
-
|
|
4
|
-
//#region src/auth/methods/profile.d.ts
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Changes the signed-in visitor's own name, photo, or both. A field left out
|
|
8
|
-
* stays as it is, and `avatar: null` removes the photo.
|
|
9
|
-
*
|
|
10
|
-
* The photo can change only where `user.avatarEditable` is true. Elsewhere a
|
|
11
|
-
* photo answers `avatarNotSupported`, so hide the photo controls instead.
|
|
12
|
-
*
|
|
13
|
-
* Answers with the visitor as they are now. The page keeps showing what it
|
|
14
|
-
* loaded until its route context loads again, so call `router.invalidate()`
|
|
15
|
-
* after a success.
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* const result = await auth.updateProfile({ fullName: 'Ann Lee' })
|
|
19
|
-
* const result = await auth.updateProfile({ avatar: file })
|
|
20
|
-
*/
|
|
21
|
-
declare function updateProfile(changes: {
|
|
22
|
-
fullName?: string;
|
|
23
|
-
avatar?: File | null;
|
|
24
|
-
}): Promise<Result<User, AuthError>>;
|
|
25
|
-
//#endregion
|
|
26
|
-
export { updateProfile };
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { assert, panic } from "../../assertions.js";
|
|
2
|
-
import { sessionConfig } from "../config.js";
|
|
3
|
-
import { clearSessionData, readSessionToken } from "../session.js";
|
|
4
|
-
import { makePlatform } from "../platform.js";
|
|
5
|
-
import { authError } from "./utils.js";
|
|
6
|
-
|
|
7
|
-
//#region src/auth/methods/profile.ts
|
|
8
|
-
/**
|
|
9
|
-
* Changes the signed-in visitor's own name, photo, or both. A field left out
|
|
10
|
-
* stays as it is, and `avatar: null` removes the photo.
|
|
11
|
-
*
|
|
12
|
-
* The photo can change only where `user.avatarEditable` is true. Elsewhere a
|
|
13
|
-
* photo answers `avatarNotSupported`, so hide the photo controls instead.
|
|
14
|
-
*
|
|
15
|
-
* Answers with the visitor as they are now. The page keeps showing what it
|
|
16
|
-
* loaded until its route context loads again, so call `router.invalidate()`
|
|
17
|
-
* after a success.
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* const result = await auth.updateProfile({ fullName: 'Ann Lee' })
|
|
21
|
-
* const result = await auth.updateProfile({ avatar: file })
|
|
22
|
-
*/
|
|
23
|
-
async function updateProfile(changes) {
|
|
24
|
-
assert(changes.fullName !== void 0 || changes.avatar !== void 0, "updateProfile needs a name or a photo to change");
|
|
25
|
-
const token = readSessionToken();
|
|
26
|
-
if (token === null) return authError("notAuthenticated", "Nobody is signed in.");
|
|
27
|
-
const form = new FormData();
|
|
28
|
-
if (changes.fullName !== void 0) form.set("fullName", changes.fullName);
|
|
29
|
-
if (changes.avatar === null) form.set("removeAvatar", "true");
|
|
30
|
-
if (changes.avatar) form.set("avatar", changes.avatar);
|
|
31
|
-
const result = await makePlatform(sessionConfig().applicationId).updateProfile(token, form);
|
|
32
|
-
if (!result.ok) {
|
|
33
|
-
switch (result.status) {
|
|
34
|
-
case 400: return authError("invalidName", result.message);
|
|
35
|
-
case 401: return authError("notAuthenticated", result.message);
|
|
36
|
-
case 409: return authError("avatarNotSupported", result.message);
|
|
37
|
-
case 413: return authError("fileTooLarge", result.message);
|
|
38
|
-
case 415: return authError("notAnImage", result.message);
|
|
39
|
-
case 429: return authError("tooManyAttempts", result.message);
|
|
40
|
-
}
|
|
41
|
-
if (result.status >= 500) panic(`Expected the profile to update, but got ${result.status}: ` + result.message);
|
|
42
|
-
throw new Error(`${result.message}. Check SOFTR_APPLICATION_ID.`);
|
|
43
|
-
}
|
|
44
|
-
clearSessionData();
|
|
45
|
-
return {
|
|
46
|
-
success: true,
|
|
47
|
-
data: result.data
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
//#endregion
|
|
52
|
-
export { updateProfile };
|