@softr/sdk 0.0.10 → 0.0.11
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/index.js +1 -1
- package/dist/server.js +6 -12
- package/dist/{session-Blx62HHJ.js → session-GUEI96C8.js} +36 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as readSessionToken, c as writeCookies, i as readSessionData, l as assert, n as makeSessionDataCookie, o as fetchVisitor, t as clearSession } from "./session-
|
|
1
|
+
import { a as readSessionToken, c as writeCookies, i as readSessionData, l as assert, n as makeSessionDataCookie, o as fetchVisitor, t as clearSession } from "./session-GUEI96C8.js";
|
|
2
2
|
import { redirect } from "@tanstack/react-router";
|
|
3
3
|
import { createMiddleware, createServerFn, getGlobalStartContext } from "@tanstack/react-start";
|
|
4
4
|
|
package/dist/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as readSessionToken, c as writeCookies, d as softAssert, f as todo, n as makeSessionDataCookie, o as fetchVisitor, r as makeSessionTokenCookie, s as
|
|
1
|
+
import { a as readSessionToken, c as writeCookies, d as softAssert, f as todo, n as makeSessionDataCookie, o as fetchVisitor, r as makeSessionTokenCookie, s as platformFetch, t as clearSession, u as panic } from "./session-GUEI96C8.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import "@tanstack/react-start/server-only";
|
|
4
4
|
|
|
@@ -18,9 +18,6 @@ async function describe(response, action) {
|
|
|
18
18
|
const said = body.success && body.data.message ? body.data.message : response.statusText;
|
|
19
19
|
return `Softr platform refused the ${action}: ${response.status} ${said}`.trim();
|
|
20
20
|
}
|
|
21
|
-
function endpoint(config, path) {
|
|
22
|
-
return `${config.platformApiUrl}/v1/applications/${config.applicationId}/users/${path}`;
|
|
23
|
-
}
|
|
24
21
|
|
|
25
22
|
//#endregion
|
|
26
23
|
//#region src/auth/methods/password.ts
|
|
@@ -35,8 +32,7 @@ const signInBody = z.object({
|
|
|
35
32
|
* so the next request costs no round-trip.
|
|
36
33
|
*/
|
|
37
34
|
async function signIn(credentials) {
|
|
38
|
-
const
|
|
39
|
-
const response = await fetch(endpoint(config, "sign-in"), {
|
|
35
|
+
const response = await platformFetch("sign-in", {
|
|
40
36
|
method: "POST",
|
|
41
37
|
headers: {
|
|
42
38
|
"content-type": "application/json",
|
|
@@ -73,11 +69,10 @@ async function signIn(credentials) {
|
|
|
73
69
|
* because the local half already succeeded.
|
|
74
70
|
*/
|
|
75
71
|
async function signOut() {
|
|
76
|
-
const config = sessionConfig();
|
|
77
72
|
const token = readSessionToken();
|
|
78
73
|
clearSession();
|
|
79
74
|
if (!token) return;
|
|
80
|
-
const response = await
|
|
75
|
+
const response = await platformFetch("sign-out", {
|
|
81
76
|
method: "POST",
|
|
82
77
|
headers: {
|
|
83
78
|
authorization: `Bearer ${token}`,
|
|
@@ -95,7 +90,7 @@ async function signOut() {
|
|
|
95
90
|
* User only exists once `confirmSignUp` returns the code.
|
|
96
91
|
*/
|
|
97
92
|
async function signUp(details) {
|
|
98
|
-
const response = await
|
|
93
|
+
const response = await platformFetch("sign-up", {
|
|
99
94
|
method: "POST",
|
|
100
95
|
headers: {
|
|
101
96
|
"content-type": "application/json",
|
|
@@ -120,8 +115,7 @@ async function signUp(details) {
|
|
|
120
115
|
* `users/new`.
|
|
121
116
|
*/
|
|
122
117
|
async function confirmSignUp(details) {
|
|
123
|
-
const
|
|
124
|
-
const verified = await fetch(endpoint(config, "sign-up"), {
|
|
118
|
+
const verified = await platformFetch("sign-up", {
|
|
125
119
|
method: "POST",
|
|
126
120
|
headers: {
|
|
127
121
|
"content-type": "application/json",
|
|
@@ -138,7 +132,7 @@ async function confirmSignUp(details) {
|
|
|
138
132
|
const verifiedBody = await verified.text();
|
|
139
133
|
let token = tokenBody.parse(verifiedBody.length === 0 ? {} : JSON.parse(verifiedBody)).jwt;
|
|
140
134
|
if (!token) {
|
|
141
|
-
const created = await
|
|
135
|
+
const created = await platformFetch("new", {
|
|
142
136
|
method: "POST",
|
|
143
137
|
headers: {
|
|
144
138
|
"content-type": "application/json",
|
|
@@ -103,19 +103,14 @@ function writeCookies(cookies) {
|
|
|
103
103
|
//#endregion
|
|
104
104
|
//#region src/auth/config.ts
|
|
105
105
|
const DEFAULT_SESSION_MAX_AGE = 2160 * 60 * 60;
|
|
106
|
-
/** 32 bytes, hex encoded. */
|
|
107
|
-
const SESSION_SECRET = /^[0-9a-f]{64}$/i;
|
|
108
106
|
function loadSessionConfig() {
|
|
109
107
|
const missing = [];
|
|
110
108
|
const applicationId = process.env.SOFTR_APPLICATION_ID;
|
|
111
109
|
if (!applicationId) missing.push("SOFTR_APPLICATION_ID");
|
|
112
110
|
const sessionSecret = process.env.SOFTR_SESSION_SECRET;
|
|
113
111
|
if (!sessionSecret) missing.push("SOFTR_SESSION_SECRET");
|
|
114
|
-
const platformApiUrl = process.env.SOFTR_PLATFORM_API_URL;
|
|
115
|
-
if (!platformApiUrl) missing.push("SOFTR_PLATFORM_API_URL");
|
|
116
112
|
if (missing.length > 0) throw new Error(`Softr auth is not configured: missing ${missing.join(", ")}.`);
|
|
117
|
-
assert(applicationId && sessionSecret
|
|
118
|
-
if (!SESSION_SECRET.test(sessionSecret)) throw new Error("SOFTR_SESSION_SECRET must be 32 random bytes encoded as hex.\nGenerate one with: openssl rand -hex 32");
|
|
113
|
+
assert(applicationId && sessionSecret);
|
|
119
114
|
const rawMaxAge = process.env.SOFTR_SESSION_MAX_AGE;
|
|
120
115
|
let sessionMaxAge = DEFAULT_SESSION_MAX_AGE;
|
|
121
116
|
if (rawMaxAge) {
|
|
@@ -125,7 +120,6 @@ function loadSessionConfig() {
|
|
|
125
120
|
return {
|
|
126
121
|
applicationId,
|
|
127
122
|
sessionSecret,
|
|
128
|
-
platformApiUrl,
|
|
129
123
|
sessionMaxAge
|
|
130
124
|
};
|
|
131
125
|
}
|
|
@@ -135,6 +129,39 @@ function sessionConfig() {
|
|
|
135
129
|
return cached;
|
|
136
130
|
}
|
|
137
131
|
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/auth/platform.ts
|
|
134
|
+
const contextSchema = z.object({ platformApiUrl: z.string() });
|
|
135
|
+
/** Calls one of this app's user endpoints on the Softr platform. */
|
|
136
|
+
async function platformFetch(path, init) {
|
|
137
|
+
const { applicationId } = sessionConfig();
|
|
138
|
+
const origin = await platformApiUrl();
|
|
139
|
+
return fetch(`${origin}/v1/applications/${applicationId}/users/${path}`, init);
|
|
140
|
+
}
|
|
141
|
+
/** Origin of the Softr platform API, with no trailing slash. */
|
|
142
|
+
async function platformApiUrl() {
|
|
143
|
+
const pinned = process.env.SOFTR_PLATFORM_API_URL;
|
|
144
|
+
if (pinned) return withoutTrailingSlash(pinned);
|
|
145
|
+
const studioApiUrl = process.env.SOFTR_STUDIO_API_URL;
|
|
146
|
+
if (!studioApiUrl || process.env.NODE_ENV === "production") panic("Softr auth is not configured: SOFTR_PLATFORM_API_URL is not set.");
|
|
147
|
+
const { applicationId } = sessionConfig();
|
|
148
|
+
const url = `${withoutTrailingSlash(studioApiUrl)}/v1/api/applications/${applicationId}/context/public`;
|
|
149
|
+
let response;
|
|
150
|
+
try {
|
|
151
|
+
response = await fetch(url, { headers: { accept: "application/json" } });
|
|
152
|
+
} catch {
|
|
153
|
+
panic(`Could not reach studio-api: ${url}`);
|
|
154
|
+
}
|
|
155
|
+
if (response.status === 404) panic(`studio-api does not know application ${applicationId}`);
|
|
156
|
+
if (!response.ok) panic(`studio-api answered ${response.status} for ${url}`);
|
|
157
|
+
const body = contextSchema.safeParse(await response.json().catch(() => null));
|
|
158
|
+
if (!body.success) panic(`studio-api returned no platformApiUrl: ${url}`);
|
|
159
|
+
return withoutTrailingSlash(body.data.platformApiUrl);
|
|
160
|
+
}
|
|
161
|
+
function withoutTrailingSlash(url) {
|
|
162
|
+
return url.replace(/\/+$/, "");
|
|
163
|
+
}
|
|
164
|
+
|
|
138
165
|
//#endregion
|
|
139
166
|
//#region src/auth/me.ts
|
|
140
167
|
/**
|
|
@@ -143,8 +170,7 @@ function sessionConfig() {
|
|
|
143
170
|
* informative. Anything else that is not a 200 throws.
|
|
144
171
|
*/
|
|
145
172
|
async function fetchVisitor(token) {
|
|
146
|
-
const
|
|
147
|
-
const response = await fetch(`${config.platformApiUrl}/v1/applications/${config.applicationId}/users/me`, {
|
|
173
|
+
const response = await platformFetch("me", {
|
|
148
174
|
method: "GET",
|
|
149
175
|
headers: {
|
|
150
176
|
authorization: `Bearer ${token}`,
|
|
@@ -331,4 +357,4 @@ function openEnvelope(raw, purpose) {
|
|
|
331
357
|
}
|
|
332
358
|
|
|
333
359
|
//#endregion
|
|
334
|
-
export { readSessionToken as a, writeCookies as c, softAssert as d, todo as f, readSessionData as i, assert as l, makeSessionDataCookie as n, fetchVisitor as o, makeSessionTokenCookie as r,
|
|
360
|
+
export { readSessionToken as a, writeCookies as c, softAssert as d, todo as f, readSessionData as i, assert as l, makeSessionDataCookie as n, fetchVisitor as o, makeSessionTokenCookie as r, platformFetch as s, clearSession as t, panic as u };
|