@sylphx/sdk 0.10.7 → 0.11.1
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 +6 -0
- package/dist/health/index.d.ts +681 -0
- package/dist/health/index.mjs.map +1 -1
- package/dist/index.d.ts +1677 -1349
- package/dist/index.mjs +2310 -1146
- package/dist/index.mjs.map +1 -1
- package/dist/nextjs/index.d.ts +19 -0
- package/dist/nextjs/index.mjs +55 -12
- package/dist/nextjs/index.mjs.map +1 -1
- package/dist/react/index.d.ts +6 -10
- package/dist/react/index.mjs +61 -43
- package/dist/react/index.mjs.map +1 -1
- package/dist/server/index.d.ts +17 -3
- package/dist/server/index.mjs +34 -3
- package/dist/server/index.mjs.map +1 -1
- package/dist/web-analytics.d.ts +90 -0
- package/package.json +5 -5
package/dist/nextjs/index.d.ts
CHANGED
|
@@ -116,6 +116,25 @@ interface SylphxMiddlewareConfig {
|
|
|
116
116
|
* @default process.env.SYLPHX_SECRET_URL
|
|
117
117
|
*/
|
|
118
118
|
secretUrl?: string;
|
|
119
|
+
/**
|
|
120
|
+
* Publishable key for browser-safe auth routes.
|
|
121
|
+
*
|
|
122
|
+
* Public auth handlers (`/auth/login`, `/auth/oauth-providers`,
|
|
123
|
+
* `/auth/oauth/authorize`, password reset, passkeys) call runtime routes
|
|
124
|
+
* guarded by projectAuth, which accepts pk_* only.
|
|
125
|
+
*
|
|
126
|
+
* @default credential parsed from process.env.SYLPHX_URL or
|
|
127
|
+
* process.env.NEXT_PUBLIC_SYLPHX_URL
|
|
128
|
+
*/
|
|
129
|
+
publishableKey?: string;
|
|
130
|
+
/**
|
|
131
|
+
* Public connection URL for browser-safe auth routes.
|
|
132
|
+
*
|
|
133
|
+
* Format: sylphx://pk_<env>_<hex>@<tenant>.api.sylphx.com
|
|
134
|
+
*
|
|
135
|
+
* @default process.env.SYLPHX_URL or process.env.NEXT_PUBLIC_SYLPHX_URL
|
|
136
|
+
*/
|
|
137
|
+
publicUrl?: string;
|
|
119
138
|
/**
|
|
120
139
|
* Platform URL for API calls.
|
|
121
140
|
* Override for self-hosted or same-origin deployments.
|
package/dist/nextjs/index.mjs
CHANGED
|
@@ -3,7 +3,9 @@ import { NextResponse } from "next/server";
|
|
|
3
3
|
|
|
4
4
|
// src/constants.ts
|
|
5
5
|
var ENV_URL = "SYLPHX_URL";
|
|
6
|
+
var ENV_PUBLIC_URL = "NEXT_PUBLIC_SYLPHX_URL";
|
|
6
7
|
var ENV_SECRET_URL = "SYLPHX_SECRET_URL";
|
|
8
|
+
var SDK_API_PATH = `/v1`;
|
|
7
9
|
var DEFAULT_SDK_API_HOST = "api.sylphx.com";
|
|
8
10
|
var SDK_PLATFORM = typeof window !== "undefined" ? "browser" : typeof process !== "undefined" && process.versions?.node ? "node" : "unknown";
|
|
9
11
|
var TOKEN_EXPIRY_BUFFER_MS = 3e4;
|
|
@@ -127,6 +129,12 @@ function validateKeyForType(key, keyType, pattern, envVarName) {
|
|
|
127
129
|
function validatePublicKey(key) {
|
|
128
130
|
return validateKeyForType(key, "publicKey", PUBLIC_KEY_PATTERN, "publishable credential");
|
|
129
131
|
}
|
|
132
|
+
function validateAndSanitizePublicKey(key) {
|
|
133
|
+
const result = validatePublicKey(key);
|
|
134
|
+
if (!result.valid) throw new Error(result.error);
|
|
135
|
+
if (result.warning) console.warn(result.warning);
|
|
136
|
+
return result.sanitizedKey;
|
|
137
|
+
}
|
|
130
138
|
function validateAppId(key) {
|
|
131
139
|
return validateKeyForType(key, "appId", APP_ID_PATTERN, "NEXT_PUBLIC_SYLPHX_APP_ID");
|
|
132
140
|
}
|
|
@@ -427,6 +435,11 @@ function secretKeyFromConnectionUrl(value) {
|
|
|
427
435
|
if (!parsed || parsed.credentialType !== "sk") return null;
|
|
428
436
|
return parsed.credential;
|
|
429
437
|
}
|
|
438
|
+
function publishableKeyFromConnectionUrl(value) {
|
|
439
|
+
const parsed = parseConnection(value);
|
|
440
|
+
if (!parsed || parsed.credentialType !== "pk") return null;
|
|
441
|
+
return parsed.credential;
|
|
442
|
+
}
|
|
430
443
|
function resolveNextjsPlatformUrl(options) {
|
|
431
444
|
if (options.explicitPlatformUrl) return normalizePlatformUrl(options.explicitPlatformUrl);
|
|
432
445
|
const fromExplicitSecretUrl = platformUrlFromConnectionUrl(options.secretUrl);
|
|
@@ -451,6 +464,16 @@ function resolveNextjsSecretKey(options) {
|
|
|
451
464
|
if (fromGenericUrl) return fromGenericUrl;
|
|
452
465
|
return null;
|
|
453
466
|
}
|
|
467
|
+
function resolveNextjsPublishableKey(options) {
|
|
468
|
+
if (options.explicitPublishableKey?.trim()) return options.explicitPublishableKey.trim();
|
|
469
|
+
const fromExplicitPublicUrl = publishableKeyFromConnectionUrl(options.explicitPublicUrl);
|
|
470
|
+
if (fromExplicitPublicUrl) return fromExplicitPublicUrl;
|
|
471
|
+
const fromPublicUrl = publishableKeyFromConnectionUrl(process.env[ENV_URL]);
|
|
472
|
+
if (fromPublicUrl) return fromPublicUrl;
|
|
473
|
+
const fromNextPublicUrl = publishableKeyFromConnectionUrl(process.env[ENV_PUBLIC_URL]);
|
|
474
|
+
if (fromNextPublicUrl) return fromNextPublicUrl;
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
454
477
|
|
|
455
478
|
// src/nextjs/middleware.ts
|
|
456
479
|
var OAUTH_PKCE_TTL_SECONDS = 10 * 60;
|
|
@@ -639,10 +662,10 @@ function authCookieJsonResponse(ctx, data) {
|
|
|
639
662
|
setAuthCookiesMiddleware(response, ctx.namespace, data);
|
|
640
663
|
return response;
|
|
641
664
|
}
|
|
642
|
-
function
|
|
665
|
+
function headersForProjectAuth(ctx) {
|
|
643
666
|
return {
|
|
644
667
|
"Content-Type": "application/json",
|
|
645
|
-
"x-app-secret": ctx.
|
|
668
|
+
"x-app-secret": ctx.publishableKey
|
|
646
669
|
};
|
|
647
670
|
}
|
|
648
671
|
async function handleRegister(request, ctx) {
|
|
@@ -652,7 +675,7 @@ async function handleRegister(request, ctx) {
|
|
|
652
675
|
const body = await parseJsonObject(request);
|
|
653
676
|
const res = await fetch(`${ctx.platformUrl}/v1/auth/register`, {
|
|
654
677
|
method: "POST",
|
|
655
|
-
headers:
|
|
678
|
+
headers: headersForProjectAuth(ctx),
|
|
656
679
|
body: JSON.stringify(body ?? {})
|
|
657
680
|
});
|
|
658
681
|
const data = await res.json().catch(() => ({}));
|
|
@@ -670,7 +693,7 @@ async function handleLogin(request, ctx) {
|
|
|
670
693
|
}
|
|
671
694
|
const res = await fetch(`${ctx.platformUrl}/v1/auth/login`, {
|
|
672
695
|
method: "POST",
|
|
673
|
-
headers:
|
|
696
|
+
headers: headersForProjectAuth(ctx),
|
|
674
697
|
body: JSON.stringify({ email, password })
|
|
675
698
|
});
|
|
676
699
|
const data = await res.json().catch(() => ({}));
|
|
@@ -696,7 +719,7 @@ async function handleVerifyEmail(request, ctx) {
|
|
|
696
719
|
}
|
|
697
720
|
const res = await fetch(`${ctx.platformUrl}/v1/auth/verify-email`, {
|
|
698
721
|
method: "POST",
|
|
699
|
-
headers:
|
|
722
|
+
headers: headersForProjectAuth(ctx),
|
|
700
723
|
body: JSON.stringify({ token })
|
|
701
724
|
});
|
|
702
725
|
const data = await res.json().catch(() => ({}));
|
|
@@ -714,7 +737,7 @@ async function handleVerifyTwoFactor(request, ctx) {
|
|
|
714
737
|
}
|
|
715
738
|
const res = await fetch(`${ctx.platformUrl}/v1/auth/verify-2fa`, {
|
|
716
739
|
method: "POST",
|
|
717
|
-
headers:
|
|
740
|
+
headers: headersForProjectAuth(ctx),
|
|
718
741
|
body: JSON.stringify({ userId, code })
|
|
719
742
|
});
|
|
720
743
|
const data = await res.json().catch(() => ({}));
|
|
@@ -759,7 +782,7 @@ function handleSession(request, ctx) {
|
|
|
759
782
|
async function handleOAuthProviders(ctx) {
|
|
760
783
|
const res = await fetch(`${ctx.platformUrl}/v1/auth/oauth-providers`, {
|
|
761
784
|
method: "GET",
|
|
762
|
-
headers:
|
|
785
|
+
headers: headersForProjectAuth(ctx)
|
|
763
786
|
});
|
|
764
787
|
const data = await res.json().catch(() => ({}));
|
|
765
788
|
return NextResponse.json(data, { status: res.status });
|
|
@@ -782,7 +805,7 @@ async function handleOAuthAuthorize(request, ctx) {
|
|
|
782
805
|
const scopes = Array.isArray(body?.scopes) ? body.scopes.filter((scope) => typeof scope === "string") : void 0;
|
|
783
806
|
const res = await fetch(`${ctx.platformUrl}/v1/oauth/authorize`, {
|
|
784
807
|
method: "POST",
|
|
785
|
-
headers:
|
|
808
|
+
headers: headersForProjectAuth(ctx),
|
|
786
809
|
body: JSON.stringify({
|
|
787
810
|
provider,
|
|
788
811
|
redirect_uri: redirectUri.toString(),
|
|
@@ -811,7 +834,7 @@ async function handlePasskeyOptions(request, ctx) {
|
|
|
811
834
|
const body = await parseJsonObject(request);
|
|
812
835
|
const res = await fetch(`${ctx.platformUrl}/v1/auth/passkey/options`, {
|
|
813
836
|
method: "POST",
|
|
814
|
-
headers:
|
|
837
|
+
headers: headersForProjectAuth(ctx),
|
|
815
838
|
body: JSON.stringify(body ?? {})
|
|
816
839
|
});
|
|
817
840
|
const data = await res.json().catch(() => ({}));
|
|
@@ -824,7 +847,7 @@ async function handlePasskeyAuthenticate(request, ctx) {
|
|
|
824
847
|
const body = await parseJsonObject(request);
|
|
825
848
|
const res = await fetch(`${ctx.platformUrl}/v1/auth/passkey/authenticate`, {
|
|
826
849
|
method: "POST",
|
|
827
|
-
headers:
|
|
850
|
+
headers: headersForProjectAuth(ctx),
|
|
828
851
|
body: JSON.stringify(body ?? {})
|
|
829
852
|
});
|
|
830
853
|
const data = await res.json().catch(() => ({}));
|
|
@@ -852,7 +875,7 @@ async function handleForgotPassword(request, ctx) {
|
|
|
852
875
|
}
|
|
853
876
|
const res = await fetch(`${ctx.platformUrl}/v1/auth/forgot-password`, {
|
|
854
877
|
method: "POST",
|
|
855
|
-
headers:
|
|
878
|
+
headers: headersForProjectAuth(ctx),
|
|
856
879
|
body: JSON.stringify({ email, redirectUrl })
|
|
857
880
|
});
|
|
858
881
|
const data = await res.json().catch(() => ({}));
|
|
@@ -870,7 +893,7 @@ async function handleResetPassword(request, ctx) {
|
|
|
870
893
|
}
|
|
871
894
|
const res = await fetch(`${ctx.platformUrl}/v1/auth/reset-password`, {
|
|
872
895
|
method: "POST",
|
|
873
|
-
headers:
|
|
896
|
+
headers: headersForProjectAuth(ctx),
|
|
874
897
|
body: JSON.stringify({ token, password })
|
|
875
898
|
});
|
|
876
899
|
const data = await res.json().catch(() => ({}));
|
|
@@ -1281,6 +1304,21 @@ function createSylphxMiddleware(userConfig = {}) {
|
|
|
1281
1304
|
secretKey = validateAndSanitizeSecretKey(rawSecretKey);
|
|
1282
1305
|
return secretKey;
|
|
1283
1306
|
}
|
|
1307
|
+
let publishableKey = null;
|
|
1308
|
+
function resolvePublishableKey() {
|
|
1309
|
+
if (publishableKey) return publishableKey;
|
|
1310
|
+
const rawPublishableKey = resolveNextjsPublishableKey({
|
|
1311
|
+
explicitPublishableKey: userConfig.publishableKey,
|
|
1312
|
+
explicitPublicUrl: userConfig.publicUrl
|
|
1313
|
+
});
|
|
1314
|
+
if (!rawPublishableKey) {
|
|
1315
|
+
throw new Error(
|
|
1316
|
+
"[Sylphx] Publishable connection URL is required for public auth routes.\nEither pass publicUrl/publishableKey in config or set SYLPHX_URL/NEXT_PUBLIC_SYLPHX_URL."
|
|
1317
|
+
);
|
|
1318
|
+
}
|
|
1319
|
+
publishableKey = validateAndSanitizePublicKey(rawPublishableKey);
|
|
1320
|
+
return publishableKey;
|
|
1321
|
+
}
|
|
1284
1322
|
let platformUrl;
|
|
1285
1323
|
let namespace;
|
|
1286
1324
|
let cookieNames;
|
|
@@ -1328,6 +1366,9 @@ function createSylphxMiddleware(userConfig = {}) {
|
|
|
1328
1366
|
get secretKey() {
|
|
1329
1367
|
return secretKey;
|
|
1330
1368
|
},
|
|
1369
|
+
get publishableKey() {
|
|
1370
|
+
return resolvePublishableKey();
|
|
1371
|
+
},
|
|
1331
1372
|
get platformUrl() {
|
|
1332
1373
|
return platformUrl;
|
|
1333
1374
|
},
|
|
@@ -2661,6 +2702,8 @@ function decodeUserId(prefixedId) {
|
|
|
2661
2702
|
}
|
|
2662
2703
|
|
|
2663
2704
|
// src/server/index.ts
|
|
2705
|
+
var PLATFORM_CONSOLE_SLUG = "keen-wave-x3m9p2";
|
|
2706
|
+
var PLATFORM_TENANT_BAAS_URL = `https://${PLATFORM_CONSOLE_SLUG}.${DEFAULT_SDK_API_HOST}${SDK_API_PATH}`;
|
|
2664
2707
|
function isJwksResponse(data) {
|
|
2665
2708
|
return typeof data === "object" && data !== null && "keys" in data && Array.isArray(data.keys);
|
|
2666
2709
|
}
|