@meindesk/sdk 0.1.0

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.
@@ -0,0 +1,303 @@
1
+ interface User {
2
+ id: string;
3
+ email: string;
4
+ emailVerifiedAt?: string | null;
5
+ firstName?: string | null;
6
+ lastName?: string | null;
7
+ username?: string | null;
8
+ phoneNumber?: string | null;
9
+ imageUrl?: string | null;
10
+ status: string;
11
+ publicMetadata?: Record<string, unknown>;
12
+ unsafeMetadata?: Record<string, unknown>;
13
+ lastSignInAt?: string | null;
14
+ createdAt: string;
15
+ updatedAt: string;
16
+ }
17
+ interface Session {
18
+ id: string;
19
+ userId: string;
20
+ status: string;
21
+ expiresAt: string;
22
+ lastActiveAt: string;
23
+ createdAt: string;
24
+ ipAddress?: string | null;
25
+ userAgent?: string | null;
26
+ device?: string | null;
27
+ location?: string | null;
28
+ }
29
+ interface FormField {
30
+ name: string;
31
+ type: string;
32
+ label?: string;
33
+ placeholder?: string;
34
+ required?: boolean;
35
+ defaultValue?: string;
36
+ options?: Array<{
37
+ label: string;
38
+ value: string;
39
+ }>;
40
+ validation?: {
41
+ minLength?: number;
42
+ maxLength?: number;
43
+ pattern?: string;
44
+ message?: string;
45
+ };
46
+ }
47
+ interface FormSchema {
48
+ fields: FormField[];
49
+ submitLabel?: string;
50
+ title?: string;
51
+ description?: string;
52
+ }
53
+ interface AuthConfig {
54
+ applicationId?: string;
55
+ applicationName?: string;
56
+ environment?: string;
57
+ homeUrl?: string | null;
58
+ signInForm?: FormSchema | null;
59
+ signUpForm?: FormSchema | null;
60
+ forgotPasswordForm?: FormSchema | null;
61
+ resetPasswordForm?: FormSchema | null;
62
+ settings?: {
63
+ allowSignUp?: boolean;
64
+ requireEmailVerification?: boolean;
65
+ passwordMinLength?: number;
66
+ passwordEnabled?: boolean;
67
+ magicLinkEnabled?: boolean;
68
+ passkeysEnabled?: boolean;
69
+ phoneEnabled?: boolean;
70
+ mfaEnabled?: boolean;
71
+ [key: string]: unknown;
72
+ };
73
+ userProfile?: {
74
+ allowEditProfile?: boolean;
75
+ allowChangeEmail?: boolean;
76
+ allowChangePassword?: boolean;
77
+ };
78
+ providers?: Array<{
79
+ provider: string;
80
+ enabled: boolean;
81
+ scopes?: string[];
82
+ buttonLabel?: string | null;
83
+ position?: string | null;
84
+ sortOrder?: number | null;
85
+ }>;
86
+ /** Unified authentication experience config (shared with builder + SDK UI). */
87
+ experience?: Record<string, unknown> | null;
88
+ [key: string]: unknown;
89
+ }
90
+ interface AuthResult {
91
+ sessionToken: string;
92
+ user: User;
93
+ session: Session;
94
+ token?: string;
95
+ status?: "complete";
96
+ }
97
+ interface MfaRequiredResult {
98
+ status: "mfa_required";
99
+ mfaToken: string;
100
+ }
101
+ type SignInResult = AuthResult | MfaRequiredResult;
102
+ interface SignUpData {
103
+ email: string;
104
+ password: string;
105
+ firstName?: string;
106
+ lastName?: string;
107
+ username?: string;
108
+ phoneNumber?: string;
109
+ unsafeMetadata?: Record<string, unknown>;
110
+ [key: string]: unknown;
111
+ }
112
+ interface SignInData {
113
+ email: string;
114
+ password: string;
115
+ [key: string]: unknown;
116
+ }
117
+ interface ConnectedIdentity {
118
+ id: string;
119
+ provider: string;
120
+ email: string | null;
121
+ connectedAt: string;
122
+ }
123
+ interface ActivityItem {
124
+ id: string;
125
+ type: string;
126
+ createdAt: string;
127
+ ipAddress: string | null;
128
+ userAgent: string | null;
129
+ metadata: Record<string, unknown>;
130
+ }
131
+ interface MeindeskClientOptions {
132
+ publishableKey: string;
133
+ apiUrl?: string;
134
+ secretKey?: string;
135
+ }
136
+ interface ApiSuccessResponse<T> {
137
+ success: true;
138
+ data: T;
139
+ }
140
+ interface ApiErrorBody {
141
+ code: string;
142
+ message: string;
143
+ }
144
+ interface ApiErrorResponse {
145
+ success: false;
146
+ error: ApiErrorBody;
147
+ }
148
+ type ApiResponse<T> = ApiSuccessResponse<T> | ApiErrorResponse;
149
+ declare class MeindeskApiError extends Error {
150
+ readonly code: string;
151
+ readonly status: number;
152
+ constructor(code: string, message: string, status: number);
153
+ }
154
+
155
+ declare function getOrCreateDeviceId(): string | undefined;
156
+ declare class MeindeskClient {
157
+ readonly publishableKey: string;
158
+ readonly apiUrl: string;
159
+ readonly secretKey?: string;
160
+ constructor(options: MeindeskClientOptions);
161
+ private buildHeaders;
162
+ private request;
163
+ getConfig(): Promise<AuthConfig>;
164
+ signUp(data: SignUpData): Promise<AuthResult>;
165
+ signIn(data: SignInData): Promise<SignInResult>;
166
+ verifyMfa(data: {
167
+ mfaToken: string;
168
+ code: string;
169
+ }): Promise<AuthResult>;
170
+ getMfaStatus(sessionToken: string): Promise<{
171
+ enabled: boolean;
172
+ verifiedAt: string | null;
173
+ }>;
174
+ startTotpEnrollment(sessionToken: string): Promise<{
175
+ secret: string;
176
+ uri: string;
177
+ recoveryCodes: string[];
178
+ }>;
179
+ confirmTotpEnrollment(sessionToken: string, code: string): Promise<{
180
+ enabled: boolean;
181
+ }>;
182
+ disableTotp(sessionToken: string, data: {
183
+ password?: string;
184
+ recoveryCode?: string;
185
+ }): Promise<{
186
+ enabled: boolean;
187
+ }>;
188
+ listIdentities(sessionToken: string): Promise<{
189
+ identities: ConnectedIdentity[];
190
+ }>;
191
+ unlinkIdentity(sessionToken: string, provider: string): Promise<{
192
+ unlinked: boolean;
193
+ }>;
194
+ listActivity(sessionToken: string, options?: {
195
+ limit?: number;
196
+ }): Promise<{
197
+ activity: ActivityItem[];
198
+ }>;
199
+ /** Navigate the browser to the OAuth start URL (top-level redirect). */
200
+ startOAuth(provider: string, options?: {
201
+ redirectUrl?: string;
202
+ purpose?: "sign_in" | "link";
203
+ sessionToken?: string;
204
+ }): void;
205
+ startOAuthLink(provider: string, options: {
206
+ redirectUrl: string;
207
+ sessionToken: string;
208
+ }): Promise<string>;
209
+ exchangeOAuthCode(code: string): Promise<AuthResult>;
210
+ signOut(sessionToken: string): Promise<{
211
+ success: boolean;
212
+ } | void>;
213
+ getSession(sessionToken?: string): Promise<{
214
+ session: Session | null;
215
+ user: User | null;
216
+ sessionToken?: string;
217
+ }>;
218
+ getUser(sessionToken: string): Promise<User>;
219
+ updateUser(sessionToken: string, data: {
220
+ firstName?: string | null;
221
+ lastName?: string | null;
222
+ username?: string | null;
223
+ phoneNumber?: string | null;
224
+ imageUrl?: string | null;
225
+ }): Promise<User>;
226
+ updateUserEmail(sessionToken: string, email: string): Promise<User>;
227
+ changePassword(sessionToken: string, data: {
228
+ currentPassword: string;
229
+ newPassword: string;
230
+ }): Promise<{
231
+ success: boolean;
232
+ }>;
233
+ listSessions(sessionToken: string): Promise<{
234
+ sessions: Array<Session & {
235
+ ipAddress?: string | null;
236
+ userAgent?: string | null;
237
+ device?: string | null;
238
+ location?: string | null;
239
+ }>;
240
+ currentSessionId: string;
241
+ total: number;
242
+ }>;
243
+ revokeSession(sessionToken: string, sessionId: string): Promise<{
244
+ revoked: boolean;
245
+ }>;
246
+ requestMagicLink(data: {
247
+ email: string;
248
+ redirectUrl?: string;
249
+ }): Promise<{
250
+ sent: boolean;
251
+ }>;
252
+ verifyMagicLink(token: string): Promise<AuthResult>;
253
+ forgotPassword(data: {
254
+ email: string;
255
+ redirectUrl?: string;
256
+ }): Promise<{
257
+ sent: boolean;
258
+ }>;
259
+ resetPassword(data: {
260
+ token: string;
261
+ password: string;
262
+ }): Promise<{
263
+ success: boolean;
264
+ }>;
265
+ verifyEmail(token: string): Promise<{
266
+ verified: boolean;
267
+ }>;
268
+ }
269
+ declare function createMeindeskClient(options: MeindeskClientOptions): MeindeskClient;
270
+
271
+ declare const SESSION_COOKIE_NAME = "md_session";
272
+ interface StorageAdapter {
273
+ getItem(key: string): string | null;
274
+ setItem(key: string, value: string): void;
275
+ removeItem(key: string): void;
276
+ }
277
+ /** In-memory key/value store (SSR-safe, no persistence). */
278
+ declare function createMemoryStorage(): StorageAdapter;
279
+ interface CookieOptions {
280
+ days?: number;
281
+ path?: string;
282
+ sameSite?: "lax" | "strict" | "none";
283
+ secure?: boolean;
284
+ domain?: string;
285
+ }
286
+ /** Read a cookie value by name from `document.cookie`. */
287
+ declare function getCookie(name: string): string | null;
288
+ /** Write a cookie via `document.cookie`. */
289
+ declare function setCookie(name: string, value: string, options?: CookieOptions): void;
290
+ /** Clear a cookie by expiring it. */
291
+ declare function removeCookie(name: string, options?: Pick<CookieOptions, "path" | "domain">): void;
292
+ declare function getSessionTokenFromCookie(): string | null;
293
+ /**
294
+ * Persist session on the app origin for reload + Next middleware, and keep an
295
+ * in-memory mirror for same-tick Bearer auth. The API may also set an HttpOnly
296
+ * `md_session` on the API host for credentialed requests.
297
+ */
298
+ declare function setSessionTokenCookie(token: string, options?: CookieOptions): void;
299
+ declare function clearSessionTokenCookie(options?: Pick<CookieOptions, "path" | "domain">): void;
300
+ /** Browser cookie-backed storage for non-secret prefs only. */
301
+ declare function createCookieStorage(options?: CookieOptions): StorageAdapter;
302
+
303
+ export { type ActivityItem, type ApiErrorBody, type ApiErrorResponse, type ApiResponse, type ApiSuccessResponse, type AuthConfig, type AuthResult, type ConnectedIdentity, type CookieOptions, type FormField, type FormSchema, MeindeskApiError, MeindeskClient, type MeindeskClientOptions, type MfaRequiredResult, SESSION_COOKIE_NAME, type Session, type SignInData, type SignInResult, type SignUpData, type StorageAdapter, type User, clearSessionTokenCookie, createCookieStorage, createMeindeskClient, createMemoryStorage, getCookie, getOrCreateDeviceId, getSessionTokenFromCookie, removeCookie, setCookie, setSessionTokenCookie };
package/dist/index.js ADDED
@@ -0,0 +1,496 @@
1
+ // src/types.ts
2
+ var MeindeskApiError = class extends Error {
3
+ code;
4
+ status;
5
+ constructor(code, message, status) {
6
+ super(message);
7
+ this.name = "MeindeskApiError";
8
+ this.code = code;
9
+ this.status = status;
10
+ }
11
+ };
12
+
13
+ // src/client.ts
14
+ var DEVICE_ID_KEY = "meindesk_device_id";
15
+ function readEnv(name) {
16
+ const proc = globalThis.process;
17
+ return proc?.env?.[name];
18
+ }
19
+ function resolveApiUrl(apiUrl) {
20
+ if (apiUrl) return apiUrl.replace(/\/$/, "");
21
+ const fromEnv = readEnv("NEXT_PUBLIC_API_URL");
22
+ return (fromEnv || "http://localhost:4000").replace(/\/$/, "");
23
+ }
24
+ function getOrCreateDeviceId() {
25
+ if (typeof window === "undefined" || !window.localStorage) return void 0;
26
+ try {
27
+ let id = window.localStorage.getItem(DEVICE_ID_KEY);
28
+ if (!id) {
29
+ id = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `dev_${Math.random().toString(36).slice(2)}_${Date.now()}`;
30
+ window.localStorage.setItem(DEVICE_ID_KEY, id);
31
+ }
32
+ return id;
33
+ } catch {
34
+ return void 0;
35
+ }
36
+ }
37
+ var MeindeskClient = class {
38
+ publishableKey;
39
+ apiUrl;
40
+ secretKey;
41
+ constructor(options) {
42
+ if (!options.publishableKey) {
43
+ throw new Error("MeindeskClient requires a publishableKey");
44
+ }
45
+ this.publishableKey = options.publishableKey;
46
+ this.apiUrl = resolveApiUrl(options.apiUrl);
47
+ this.secretKey = options.secretKey;
48
+ }
49
+ buildHeaders(sessionToken) {
50
+ const headers = {
51
+ Accept: "application/json",
52
+ "Content-Type": "application/json",
53
+ "x-meindesk-publishable-key": this.publishableKey
54
+ };
55
+ if (this.secretKey && typeof window === "undefined") {
56
+ headers["x-meindesk-secret-key"] = this.secretKey;
57
+ }
58
+ if (sessionToken) {
59
+ headers.Authorization = `Bearer ${sessionToken}`;
60
+ }
61
+ const deviceId = getOrCreateDeviceId();
62
+ if (deviceId) {
63
+ headers["x-meindesk-device-id"] = deviceId;
64
+ }
65
+ return headers;
66
+ }
67
+ async request(path, init = {}) {
68
+ const { sessionToken, ...fetchInit } = init;
69
+ const url = `${this.apiUrl}${path.startsWith("/") ? path : `/${path}`}`;
70
+ const response = await fetch(url, {
71
+ ...fetchInit,
72
+ headers: {
73
+ ...this.buildHeaders(sessionToken),
74
+ ...fetchInit.headers
75
+ },
76
+ credentials: "include"
77
+ });
78
+ let body = null;
79
+ try {
80
+ body = await response.json();
81
+ } catch {
82
+ throw new MeindeskApiError(
83
+ "invalid_response",
84
+ `Request failed with status ${response.status}`,
85
+ response.status
86
+ );
87
+ }
88
+ if (!response.ok || !body || body.success !== true) {
89
+ const error = body && "error" in body && body.error ? body.error : { code: "request_failed", message: `Request failed (${response.status})` };
90
+ throw new MeindeskApiError(error.code, error.message, response.status);
91
+ }
92
+ return body.data;
93
+ }
94
+ async getConfig() {
95
+ const raw = await this.request("/v1/sdk/config", {
96
+ method: "GET"
97
+ });
98
+ return normalizeAuthConfig(raw);
99
+ }
100
+ async signUp(data) {
101
+ const raw = await this.request("/v1/sdk/sign-up", {
102
+ method: "POST",
103
+ body: JSON.stringify(data)
104
+ });
105
+ return normalizeAuthResult(raw);
106
+ }
107
+ async signIn(data) {
108
+ const raw = await this.request("/v1/sdk/sign-in", {
109
+ method: "POST",
110
+ body: JSON.stringify(data)
111
+ });
112
+ if (raw.status === "mfa_required" && typeof raw.mfaToken === "string") {
113
+ return { status: "mfa_required", mfaToken: raw.mfaToken };
114
+ }
115
+ return normalizeAuthResult(raw);
116
+ }
117
+ async verifyMfa(data) {
118
+ const raw = await this.request("/v1/sdk/mfa/verify", {
119
+ method: "POST",
120
+ body: JSON.stringify(data)
121
+ });
122
+ return normalizeAuthResult(raw);
123
+ }
124
+ async getMfaStatus(sessionToken) {
125
+ return this.request("/v1/sdk/mfa", { method: "GET", sessionToken });
126
+ }
127
+ async startTotpEnrollment(sessionToken) {
128
+ return this.request("/v1/sdk/mfa/totp/start", {
129
+ method: "POST",
130
+ sessionToken,
131
+ body: JSON.stringify({})
132
+ });
133
+ }
134
+ async confirmTotpEnrollment(sessionToken, code) {
135
+ return this.request("/v1/sdk/mfa/totp/confirm", {
136
+ method: "POST",
137
+ sessionToken,
138
+ body: JSON.stringify({ code })
139
+ });
140
+ }
141
+ async disableTotp(sessionToken, data) {
142
+ return this.request("/v1/sdk/mfa/totp/disable", {
143
+ method: "POST",
144
+ sessionToken,
145
+ body: JSON.stringify(data)
146
+ });
147
+ }
148
+ async listIdentities(sessionToken) {
149
+ return this.request("/v1/sdk/identities", {
150
+ method: "GET",
151
+ sessionToken
152
+ });
153
+ }
154
+ async unlinkIdentity(sessionToken, provider) {
155
+ return this.request(`/v1/sdk/identities/${encodeURIComponent(provider)}`, {
156
+ method: "DELETE",
157
+ sessionToken
158
+ });
159
+ }
160
+ async listActivity(sessionToken, options) {
161
+ const q = options?.limit != null ? `?limit=${encodeURIComponent(String(options.limit))}` : "";
162
+ return this.request(`/v1/sdk/activity${q}`, {
163
+ method: "GET",
164
+ sessionToken
165
+ });
166
+ }
167
+ /** Navigate the browser to the OAuth start URL (top-level redirect). */
168
+ startOAuth(provider, options) {
169
+ if (typeof window === "undefined") {
170
+ throw new Error("startOAuth can only be called in the browser");
171
+ }
172
+ const raw = options?.redirectUrl ?? `${window.location.origin}${window.location.pathname}`;
173
+ let redirectUrl = raw;
174
+ try {
175
+ redirectUrl = new URL(raw, window.location.origin).toString();
176
+ } catch {
177
+ }
178
+ const url = new URL(
179
+ `${this.apiUrl}/v1/sdk/oauth/${encodeURIComponent(provider)}/start`
180
+ );
181
+ url.searchParams.set("redirect_url", redirectUrl);
182
+ url.searchParams.set("publishable_key", this.publishableKey);
183
+ if (options?.purpose === "link") {
184
+ url.searchParams.set("purpose", "link");
185
+ }
186
+ getOrCreateDeviceId();
187
+ if (options?.purpose === "link" && options.sessionToken) {
188
+ void this.startOAuthLink(provider, {
189
+ redirectUrl,
190
+ sessionToken: options.sessionToken
191
+ }).then((authorizeUrl) => {
192
+ window.location.assign(authorizeUrl);
193
+ });
194
+ return;
195
+ }
196
+ window.location.assign(url.toString());
197
+ }
198
+ async startOAuthLink(provider, options) {
199
+ const data = await this.request(
200
+ `/v1/sdk/oauth/${encodeURIComponent(provider)}/start`,
201
+ {
202
+ method: "POST",
203
+ sessionToken: options.sessionToken,
204
+ body: JSON.stringify({
205
+ redirectUrl: options.redirectUrl,
206
+ purpose: "link"
207
+ })
208
+ }
209
+ );
210
+ return data.authorizeUrl;
211
+ }
212
+ async exchangeOAuthCode(code) {
213
+ const raw = await this.request(
214
+ "/v1/sdk/oauth/exchange",
215
+ {
216
+ method: "POST",
217
+ body: JSON.stringify({ code })
218
+ }
219
+ );
220
+ return normalizeAuthResult(raw);
221
+ }
222
+ async signOut(sessionToken) {
223
+ return this.request("/v1/sdk/sign-out", {
224
+ method: "POST",
225
+ sessionToken,
226
+ body: JSON.stringify({})
227
+ });
228
+ }
229
+ async getSession(sessionToken) {
230
+ return this.request("/v1/sdk/session", {
231
+ method: "GET",
232
+ ...sessionToken ? { sessionToken } : {}
233
+ });
234
+ }
235
+ async getUser(sessionToken) {
236
+ const data = await this.request("/v1/sdk/user", {
237
+ method: "GET",
238
+ sessionToken
239
+ });
240
+ if (data && typeof data === "object" && "user" in data) {
241
+ return data.user;
242
+ }
243
+ return data;
244
+ }
245
+ async updateUser(sessionToken, data) {
246
+ const res = await this.request("/v1/sdk/user", {
247
+ method: "PATCH",
248
+ sessionToken,
249
+ body: JSON.stringify(data)
250
+ });
251
+ return res.user;
252
+ }
253
+ async updateUserEmail(sessionToken, email) {
254
+ const res = await this.request("/v1/sdk/user/email", {
255
+ method: "PATCH",
256
+ sessionToken,
257
+ body: JSON.stringify({ email })
258
+ });
259
+ return res.user;
260
+ }
261
+ async changePassword(sessionToken, data) {
262
+ return this.request("/v1/sdk/user/password", {
263
+ method: "POST",
264
+ sessionToken,
265
+ body: JSON.stringify(data)
266
+ });
267
+ }
268
+ async listSessions(sessionToken) {
269
+ return this.request("/v1/sdk/sessions", {
270
+ method: "GET",
271
+ sessionToken
272
+ });
273
+ }
274
+ async revokeSession(sessionToken, sessionId) {
275
+ return this.request(`/v1/sdk/sessions/${sessionId}/revoke`, {
276
+ method: "POST",
277
+ sessionToken,
278
+ body: JSON.stringify({})
279
+ });
280
+ }
281
+ async requestMagicLink(data) {
282
+ return this.request("/v1/sdk/magic-link/request", {
283
+ method: "POST",
284
+ body: JSON.stringify(data)
285
+ });
286
+ }
287
+ async verifyMagicLink(token) {
288
+ const raw = await this.request(
289
+ "/v1/sdk/magic-link/verify",
290
+ {
291
+ method: "POST",
292
+ body: JSON.stringify({ token })
293
+ }
294
+ );
295
+ return normalizeAuthResult(raw);
296
+ }
297
+ async forgotPassword(data) {
298
+ return this.request("/v1/sdk/password/forgot", {
299
+ method: "POST",
300
+ body: JSON.stringify(data)
301
+ });
302
+ }
303
+ async resetPassword(data) {
304
+ return this.request("/v1/sdk/password/reset", {
305
+ method: "POST",
306
+ body: JSON.stringify(data)
307
+ });
308
+ }
309
+ async verifyEmail(token) {
310
+ return this.request("/v1/sdk/email/verify", {
311
+ method: "POST",
312
+ body: JSON.stringify({ token })
313
+ });
314
+ }
315
+ };
316
+ function createMeindeskClient(options) {
317
+ return new MeindeskClient(options);
318
+ }
319
+ function normalizeFormField(field) {
320
+ const name = String(field.name ?? field.id ?? "");
321
+ return {
322
+ name,
323
+ type: String(field.type ?? "text"),
324
+ label: field.label != null ? String(field.label) : void 0,
325
+ placeholder: field.placeholder != null ? String(field.placeholder) : void 0,
326
+ required: Boolean(field.required),
327
+ defaultValue: field.defaultValue != null ? String(field.defaultValue) : void 0,
328
+ options: Array.isArray(field.options) ? field.options : void 0,
329
+ validation: field.validation && typeof field.validation === "object" ? field.validation : field.minLength != null || field.maxLength != null ? {
330
+ minLength: field.minLength != null ? Number(field.minLength) : void 0,
331
+ maxLength: field.maxLength != null ? Number(field.maxLength) : void 0,
332
+ message: field.errorMessage != null ? String(field.errorMessage) : void 0
333
+ } : void 0
334
+ };
335
+ }
336
+ function normalizeFormSchema(schema) {
337
+ if (!schema || typeof schema !== "object") return null;
338
+ const s = schema;
339
+ const fields = Array.isArray(s.fields) ? s.fields.map((f) => normalizeFormField(f)) : [];
340
+ return {
341
+ fields,
342
+ title: s.title != null ? String(s.title) : void 0,
343
+ description: s.description != null ? String(s.description) : void 0,
344
+ submitLabel: s.submitLabel != null ? String(s.submitLabel) : void 0
345
+ };
346
+ }
347
+ function normalizeAuthConfig(raw) {
348
+ const application = raw.application && typeof raw.application === "object" ? raw.application : {};
349
+ const forms = Array.isArray(raw.forms) ? raw.forms : [];
350
+ const findForm = (type) => {
351
+ const match = forms.find(
352
+ (f) => f && typeof f === "object" && f.type === type
353
+ );
354
+ return normalizeFormSchema(match?.schema);
355
+ };
356
+ const settings = raw.settings && typeof raw.settings === "object" ? raw.settings : void 0;
357
+ return {
358
+ ...raw,
359
+ applicationId: application.id != null ? String(application.id) : void 0,
360
+ applicationName: application.name != null ? String(application.name) : void 0,
361
+ environment: application.environment != null ? String(application.environment) : void 0,
362
+ homeUrl: application.homeUrl != null ? String(application.homeUrl) : null,
363
+ signInForm: findForm("sign_in"),
364
+ signUpForm: findForm("sign_up"),
365
+ forgotPasswordForm: findForm("forgot_password"),
366
+ resetPasswordForm: findForm("reset_password"),
367
+ providers: Array.isArray(raw.providers) ? raw.providers : void 0,
368
+ experience: raw.experience && typeof raw.experience === "object" ? raw.experience : null,
369
+ userProfile: raw.userProfile && typeof raw.userProfile === "object" ? raw.userProfile : {
370
+ allowEditProfile: true,
371
+ allowChangeEmail: true,
372
+ allowChangePassword: true
373
+ },
374
+ settings: settings ? {
375
+ allowSignUp: true,
376
+ requireEmailVerification: Boolean(
377
+ settings.emailVerificationRequired
378
+ ),
379
+ passwordMinLength: settings.passwordMinLength != null ? Number(settings.passwordMinLength) : void 0,
380
+ ...settings
381
+ } : void 0
382
+ };
383
+ }
384
+ function normalizeAuthResult(raw) {
385
+ const sessionToken = String(raw.sessionToken ?? raw.token ?? "");
386
+ if (!sessionToken) {
387
+ throw new MeindeskApiError(
388
+ "invalid_response",
389
+ "Auth response missing session token",
390
+ 500
391
+ );
392
+ }
393
+ return {
394
+ sessionToken,
395
+ user: raw.user,
396
+ session: raw.session
397
+ };
398
+ }
399
+
400
+ // src/storage.ts
401
+ var SESSION_COOKIE_NAME = "md_session";
402
+ var memorySessionToken = null;
403
+ function createMemoryStorage() {
404
+ const store = /* @__PURE__ */ new Map();
405
+ return {
406
+ getItem(key) {
407
+ return store.has(key) ? store.get(key) ?? null : null;
408
+ },
409
+ setItem(key, value) {
410
+ store.set(key, value);
411
+ },
412
+ removeItem(key) {
413
+ store.delete(key);
414
+ }
415
+ };
416
+ }
417
+ function isBrowser() {
418
+ return typeof document !== "undefined";
419
+ }
420
+ function getCookie(name) {
421
+ if (!isBrowser()) return null;
422
+ const prefix = `${encodeURIComponent(name)}=`;
423
+ const parts = document.cookie.split("; ");
424
+ for (const part of parts) {
425
+ if (part.startsWith(prefix)) {
426
+ return decodeURIComponent(part.slice(prefix.length));
427
+ }
428
+ }
429
+ return null;
430
+ }
431
+ function setCookie(name, value, options = {}) {
432
+ if (!isBrowser()) return;
433
+ const {
434
+ days = 7,
435
+ path = "/",
436
+ sameSite = "lax",
437
+ secure = typeof location !== "undefined" && location.protocol === "https:",
438
+ domain
439
+ } = options;
440
+ const maxAge = Math.max(0, Math.floor(days * 24 * 60 * 60));
441
+ let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}; Path=${path}; Max-Age=${maxAge}; SameSite=${sameSite}`;
442
+ if (secure) cookie += "; Secure";
443
+ if (domain) cookie += `; Domain=${domain}`;
444
+ document.cookie = cookie;
445
+ }
446
+ function removeCookie(name, options = {}) {
447
+ if (!isBrowser()) return;
448
+ const { path = "/", domain } = options;
449
+ let cookie = `${encodeURIComponent(name)}=; Path=${path}; Max-Age=0; SameSite=lax`;
450
+ if (domain) cookie += `; Domain=${domain}`;
451
+ document.cookie = cookie;
452
+ }
453
+ function getSessionTokenFromCookie() {
454
+ if (memorySessionToken) return memorySessionToken;
455
+ return getCookie(SESSION_COOKIE_NAME);
456
+ }
457
+ function setSessionTokenCookie(token, options) {
458
+ memorySessionToken = token;
459
+ setCookie(SESSION_COOKIE_NAME, token, options);
460
+ }
461
+ function clearSessionTokenCookie(options) {
462
+ memorySessionToken = null;
463
+ removeCookie(SESSION_COOKIE_NAME, options);
464
+ }
465
+ function createCookieStorage(options = {}) {
466
+ return {
467
+ getItem(key) {
468
+ if (key === SESSION_COOKIE_NAME) return getSessionTokenFromCookie();
469
+ return getCookie(key);
470
+ },
471
+ setItem(key, value) {
472
+ if (key === SESSION_COOKIE_NAME) {
473
+ setSessionTokenCookie(value, options);
474
+ return;
475
+ }
476
+ setCookie(key, value, options);
477
+ },
478
+ removeItem(key) {
479
+ if (key === SESSION_COOKIE_NAME) {
480
+ clearSessionTokenCookie({
481
+ path: options.path,
482
+ domain: options.domain
483
+ });
484
+ return;
485
+ }
486
+ removeCookie(key, {
487
+ path: options.path,
488
+ domain: options.domain
489
+ });
490
+ }
491
+ };
492
+ }
493
+
494
+ export { MeindeskApiError, MeindeskClient, SESSION_COOKIE_NAME, clearSessionTokenCookie, createCookieStorage, createMeindeskClient, createMemoryStorage, getCookie, getOrCreateDeviceId, getSessionTokenFromCookie, removeCookie, setCookie, setSessionTokenCookie };
495
+ //# sourceMappingURL=index.js.map
496
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/client.ts","../src/storage.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export interface User {\n id: string;\n email: string;\n emailVerifiedAt?: string | null;\n firstName?: string | null;\n lastName?: string | null;\n username?: string | null;\n phoneNumber?: string | null;\n imageUrl?: string | null;\n status: string;\n publicMetadata?: Record<string, unknown>;\n unsafeMetadata?: Record<string, unknown>;\n lastSignInAt?: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface Session {\n id: string;\n userId: string;\n status: string;\n expiresAt: string;\n lastActiveAt: string;\n createdAt: string;\n ipAddress?: string | null;\n userAgent?: string | null;\n device?: string | null;\n location?: string | null;\n}\n\nexport interface FormField {\n name: string;\n type: string;\n label?: string;\n placeholder?: string;\n required?: boolean;\n defaultValue?: string;\n options?: Array<{ label: string; value: string }>;\n validation?: {\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n message?: string;\n };\n}\n\nexport interface FormSchema {\n fields: FormField[];\n submitLabel?: string;\n title?: string;\n description?: string;\n}\n\nexport interface AuthConfig {\n applicationId?: string;\n applicationName?: string;\n environment?: string;\n homeUrl?: string | null;\n signInForm?: FormSchema | null;\n signUpForm?: FormSchema | null;\n forgotPasswordForm?: FormSchema | null;\n resetPasswordForm?: FormSchema | null;\n settings?: {\n allowSignUp?: boolean;\n requireEmailVerification?: boolean;\n passwordMinLength?: number;\n passwordEnabled?: boolean;\n magicLinkEnabled?: boolean;\n passkeysEnabled?: boolean;\n phoneEnabled?: boolean;\n mfaEnabled?: boolean;\n [key: string]: unknown;\n };\n userProfile?: {\n allowEditProfile?: boolean;\n allowChangeEmail?: boolean;\n allowChangePassword?: boolean;\n };\n providers?: Array<{\n provider: string;\n enabled: boolean;\n scopes?: string[];\n buttonLabel?: string | null;\n position?: string | null;\n sortOrder?: number | null;\n }>;\n /** Unified authentication experience config (shared with builder + SDK UI). */\n experience?: Record<string, unknown> | null;\n [key: string]: unknown;\n}\n\nexport interface AuthResult {\n sessionToken: string;\n user: User;\n session: Session;\n token?: string;\n status?: \"complete\";\n}\n\nexport interface MfaRequiredResult {\n status: \"mfa_required\";\n mfaToken: string;\n}\n\nexport type SignInResult = AuthResult | MfaRequiredResult;\n\nexport interface SignUpData {\n email: string;\n password: string;\n firstName?: string;\n lastName?: string;\n username?: string;\n phoneNumber?: string;\n unsafeMetadata?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface SignInData {\n email: string;\n password: string;\n [key: string]: unknown;\n}\n\nexport interface ConnectedIdentity {\n id: string;\n provider: string;\n email: string | null;\n connectedAt: string;\n}\n\nexport interface ActivityItem {\n id: string;\n type: string;\n createdAt: string;\n ipAddress: string | null;\n userAgent: string | null;\n metadata: Record<string, unknown>;\n}\n\nexport interface MeindeskClientOptions {\n publishableKey: string;\n apiUrl?: string;\n secretKey?: string;\n}\n\nexport interface ApiSuccessResponse<T> {\n success: true;\n data: T;\n}\n\nexport interface ApiErrorBody {\n code: string;\n message: string;\n}\n\nexport interface ApiErrorResponse {\n success: false;\n error: ApiErrorBody;\n}\n\nexport type ApiResponse<T> = ApiSuccessResponse<T> | ApiErrorResponse;\n\nexport class MeindeskApiError extends Error {\n readonly code: string;\n readonly status: number;\n\n constructor(code: string, message: string, status: number) {\n super(message);\n this.name = \"MeindeskApiError\";\n this.code = code;\n this.status = status;\n }\n}\n","import type {\n AuthConfig,\n AuthResult,\n FormField,\n FormSchema,\n MeindeskClientOptions,\n Session,\n SignInData,\n SignInResult,\n SignUpData,\n User,\n ApiResponse,\n ConnectedIdentity,\n ActivityItem,\n} from \"./types\";\nimport { MeindeskApiError } from \"./types\";\n\nconst DEVICE_ID_KEY = \"meindesk_device_id\";\n\nfunction readEnv(name: string): string | undefined {\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } })\n .process;\n return proc?.env?.[name];\n}\n\nfunction resolveApiUrl(apiUrl?: string): string {\n if (apiUrl) return apiUrl.replace(/\\/$/, \"\");\n const fromEnv = readEnv(\"NEXT_PUBLIC_API_URL\");\n return (fromEnv || \"http://localhost:4000\").replace(/\\/$/, \"\");\n}\n\nexport function getOrCreateDeviceId(): string | undefined {\n if (typeof window === \"undefined\" || !window.localStorage) return undefined;\n try {\n let id = window.localStorage.getItem(DEVICE_ID_KEY);\n if (!id) {\n id =\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `dev_${Math.random().toString(36).slice(2)}_${Date.now()}`;\n window.localStorage.setItem(DEVICE_ID_KEY, id);\n }\n return id;\n } catch {\n return undefined;\n }\n}\n\nexport class MeindeskClient {\n readonly publishableKey: string;\n readonly apiUrl: string;\n readonly secretKey?: string;\n\n constructor(options: MeindeskClientOptions) {\n if (!options.publishableKey) {\n throw new Error(\"MeindeskClient requires a publishableKey\");\n }\n\n this.publishableKey = options.publishableKey;\n this.apiUrl = resolveApiUrl(options.apiUrl);\n this.secretKey = options.secretKey;\n }\n\n private buildHeaders(sessionToken?: string): HeadersInit {\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n \"x-meindesk-publishable-key\": this.publishableKey,\n };\n\n if (this.secretKey && typeof window === \"undefined\") {\n headers[\"x-meindesk-secret-key\"] = this.secretKey;\n }\n\n if (sessionToken) {\n headers.Authorization = `Bearer ${sessionToken}`;\n }\n\n const deviceId = getOrCreateDeviceId();\n if (deviceId) {\n headers[\"x-meindesk-device-id\"] = deviceId;\n }\n\n return headers;\n }\n\n private async request<T>(\n path: string,\n init: RequestInit & { sessionToken?: string } = {},\n ): Promise<T> {\n const { sessionToken, ...fetchInit } = init;\n const url = `${this.apiUrl}${path.startsWith(\"/\") ? path : `/${path}`}`;\n\n const response = await fetch(url, {\n ...fetchInit,\n headers: {\n ...this.buildHeaders(sessionToken),\n ...(fetchInit.headers as Record<string, string> | undefined),\n },\n credentials: \"include\",\n });\n\n let body: ApiResponse<T> | null = null;\n\n try {\n body = (await response.json()) as ApiResponse<T>;\n } catch {\n throw new MeindeskApiError(\n \"invalid_response\",\n `Request failed with status ${response.status}`,\n response.status,\n );\n }\n\n if (!response.ok || !body || body.success !== true) {\n const error =\n body && \"error\" in body && body.error\n ? body.error\n : { code: \"request_failed\", message: `Request failed (${response.status})` };\n\n throw new MeindeskApiError(error.code, error.message, response.status);\n }\n\n return body.data;\n }\n\n async getConfig(): Promise<AuthConfig> {\n const raw = await this.request<Record<string, unknown>>(\"/v1/sdk/config\", {\n method: \"GET\",\n });\n return normalizeAuthConfig(raw);\n }\n\n async signUp(data: SignUpData): Promise<AuthResult> {\n const raw = await this.request<Record<string, unknown>>(\"/v1/sdk/sign-up\", {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n return normalizeAuthResult(raw);\n }\n\n async signIn(data: SignInData): Promise<SignInResult> {\n const raw = await this.request<Record<string, unknown>>(\"/v1/sdk/sign-in\", {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n if (raw.status === \"mfa_required\" && typeof raw.mfaToken === \"string\") {\n return { status: \"mfa_required\", mfaToken: raw.mfaToken };\n }\n return normalizeAuthResult(raw);\n }\n\n async verifyMfa(data: {\n mfaToken: string;\n code: string;\n }): Promise<AuthResult> {\n const raw = await this.request<Record<string, unknown>>(\"/v1/sdk/mfa/verify\", {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n return normalizeAuthResult(raw);\n }\n\n async getMfaStatus(sessionToken: string): Promise<{\n enabled: boolean;\n verifiedAt: string | null;\n }> {\n return this.request(\"/v1/sdk/mfa\", { method: \"GET\", sessionToken });\n }\n\n async startTotpEnrollment(sessionToken: string): Promise<{\n secret: string;\n uri: string;\n recoveryCodes: string[];\n }> {\n return this.request(\"/v1/sdk/mfa/totp/start\", {\n method: \"POST\",\n sessionToken,\n body: JSON.stringify({}),\n });\n }\n\n async confirmTotpEnrollment(\n sessionToken: string,\n code: string,\n ): Promise<{ enabled: boolean }> {\n return this.request(\"/v1/sdk/mfa/totp/confirm\", {\n method: \"POST\",\n sessionToken,\n body: JSON.stringify({ code }),\n });\n }\n\n async disableTotp(\n sessionToken: string,\n data: { password?: string; recoveryCode?: string },\n ): Promise<{ enabled: boolean }> {\n return this.request(\"/v1/sdk/mfa/totp/disable\", {\n method: \"POST\",\n sessionToken,\n body: JSON.stringify(data),\n });\n }\n\n async listIdentities(\n sessionToken: string,\n ): Promise<{ identities: ConnectedIdentity[] }> {\n return this.request(\"/v1/sdk/identities\", {\n method: \"GET\",\n sessionToken,\n });\n }\n\n async unlinkIdentity(\n sessionToken: string,\n provider: string,\n ): Promise<{ unlinked: boolean }> {\n return this.request(`/v1/sdk/identities/${encodeURIComponent(provider)}`, {\n method: \"DELETE\",\n sessionToken,\n });\n }\n\n async listActivity(\n sessionToken: string,\n options?: { limit?: number },\n ): Promise<{ activity: ActivityItem[] }> {\n const q =\n options?.limit != null ? `?limit=${encodeURIComponent(String(options.limit))}` : \"\";\n return this.request(`/v1/sdk/activity${q}`, {\n method: \"GET\",\n sessionToken,\n });\n }\n\n /** Navigate the browser to the OAuth start URL (top-level redirect). */\n startOAuth(\n provider: string,\n options?: { redirectUrl?: string; purpose?: \"sign_in\" | \"link\"; sessionToken?: string },\n ): void {\n if (typeof window === \"undefined\") {\n throw new Error(\"startOAuth can only be called in the browser\");\n }\n const raw =\n options?.redirectUrl ??\n `${window.location.origin}${window.location.pathname}`;\n let redirectUrl = raw;\n try {\n redirectUrl = new URL(raw, window.location.origin).toString();\n } catch {\n // keep raw\n }\n const url = new URL(\n `${this.apiUrl}/v1/sdk/oauth/${encodeURIComponent(provider)}/start`,\n );\n url.searchParams.set(\"redirect_url\", redirectUrl);\n url.searchParams.set(\"publishable_key\", this.publishableKey);\n if (options?.purpose === \"link\") {\n url.searchParams.set(\"purpose\", \"link\");\n }\n const deviceId = getOrCreateDeviceId();\n if (deviceId) {\n // Cookie-less GET redirect cannot set custom headers; rely on stored state\n // via POST start when linking from the Account modal.\n }\n if (options?.purpose === \"link\" && options.sessionToken) {\n void this.startOAuthLink(provider, {\n redirectUrl,\n sessionToken: options.sessionToken,\n }).then((authorizeUrl) => {\n window.location.assign(authorizeUrl);\n });\n return;\n }\n window.location.assign(url.toString());\n }\n\n async startOAuthLink(\n provider: string,\n options: { redirectUrl: string; sessionToken: string },\n ): Promise<string> {\n const data = await this.request<{ authorizeUrl: string }>(\n `/v1/sdk/oauth/${encodeURIComponent(provider)}/start`,\n {\n method: \"POST\",\n sessionToken: options.sessionToken,\n body: JSON.stringify({\n redirectUrl: options.redirectUrl,\n purpose: \"link\",\n }),\n },\n );\n return data.authorizeUrl;\n }\n\n async exchangeOAuthCode(code: string): Promise<AuthResult> {\n const raw = await this.request<Record<string, unknown>>(\n \"/v1/sdk/oauth/exchange\",\n {\n method: \"POST\",\n body: JSON.stringify({ code }),\n },\n );\n return normalizeAuthResult(raw);\n }\n\n async signOut(sessionToken: string): Promise<{ success: boolean } | void> {\n return this.request<{ success: boolean } | void>(\"/v1/sdk/sign-out\", {\n method: \"POST\",\n sessionToken,\n body: JSON.stringify({}),\n });\n }\n\n async getSession(sessionToken?: string): Promise<{\n session: Session | null;\n user: User | null;\n sessionToken?: string;\n }> {\n return this.request<{\n session: Session | null;\n user: User | null;\n sessionToken?: string;\n }>(\"/v1/sdk/session\", {\n method: \"GET\",\n ...(sessionToken ? { sessionToken } : {}),\n });\n }\n\n async getUser(sessionToken: string): Promise<User> {\n const data = await this.request<User | { user: User }>(\"/v1/sdk/user\", {\n method: \"GET\",\n sessionToken,\n });\n\n if (data && typeof data === \"object\" && \"user\" in data) {\n return data.user;\n }\n\n return data as User;\n }\n\n async updateUser(\n sessionToken: string,\n data: {\n firstName?: string | null;\n lastName?: string | null;\n username?: string | null;\n phoneNumber?: string | null;\n imageUrl?: string | null;\n },\n ): Promise<User> {\n const res = await this.request<{ user: User }>(\"/v1/sdk/user\", {\n method: \"PATCH\",\n sessionToken,\n body: JSON.stringify(data),\n });\n return res.user;\n }\n\n async updateUserEmail(\n sessionToken: string,\n email: string,\n ): Promise<User> {\n const res = await this.request<{ user: User }>(\"/v1/sdk/user/email\", {\n method: \"PATCH\",\n sessionToken,\n body: JSON.stringify({ email }),\n });\n return res.user;\n }\n\n async changePassword(\n sessionToken: string,\n data: { currentPassword: string; newPassword: string },\n ): Promise<{ success: boolean }> {\n return this.request(\"/v1/sdk/user/password\", {\n method: \"POST\",\n sessionToken,\n body: JSON.stringify(data),\n });\n }\n\n async listSessions(sessionToken: string): Promise<{\n sessions: Array<\n Session & {\n ipAddress?: string | null;\n userAgent?: string | null;\n device?: string | null;\n location?: string | null;\n }\n >;\n currentSessionId: string;\n total: number;\n }> {\n return this.request(\"/v1/sdk/sessions\", {\n method: \"GET\",\n sessionToken,\n });\n }\n\n async revokeSession(\n sessionToken: string,\n sessionId: string,\n ): Promise<{ revoked: boolean }> {\n return this.request(`/v1/sdk/sessions/${sessionId}/revoke`, {\n method: \"POST\",\n sessionToken,\n body: JSON.stringify({}),\n });\n }\n\n async requestMagicLink(data: {\n email: string;\n redirectUrl?: string;\n }): Promise<{ sent: boolean }> {\n return this.request(\"/v1/sdk/magic-link/request\", {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n }\n\n async verifyMagicLink(token: string): Promise<AuthResult> {\n const raw = await this.request<Record<string, unknown>>(\n \"/v1/sdk/magic-link/verify\",\n {\n method: \"POST\",\n body: JSON.stringify({ token }),\n },\n );\n return normalizeAuthResult(raw);\n }\n\n async forgotPassword(data: {\n email: string;\n redirectUrl?: string;\n }): Promise<{ sent: boolean }> {\n return this.request(\"/v1/sdk/password/forgot\", {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n }\n\n async resetPassword(data: {\n token: string;\n password: string;\n }): Promise<{ success: boolean }> {\n return this.request(\"/v1/sdk/password/reset\", {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n }\n\n async verifyEmail(token: string): Promise<{ verified: boolean }> {\n return this.request(\"/v1/sdk/email/verify\", {\n method: \"POST\",\n body: JSON.stringify({ token }),\n });\n }\n}\n\nexport function createMeindeskClient(\n options: MeindeskClientOptions,\n): MeindeskClient {\n return new MeindeskClient(options);\n}\n\nfunction normalizeFormField(field: Record<string, unknown>): FormField {\n const name = String(field.name ?? field.id ?? \"\");\n return {\n name,\n type: String(field.type ?? \"text\"),\n label: field.label != null ? String(field.label) : undefined,\n placeholder: field.placeholder != null ? String(field.placeholder) : undefined,\n required: Boolean(field.required),\n defaultValue: field.defaultValue != null ? String(field.defaultValue) : undefined,\n options: Array.isArray(field.options)\n ? (field.options as FormField[\"options\"])\n : undefined,\n validation:\n field.validation && typeof field.validation === \"object\"\n ? (field.validation as FormField[\"validation\"])\n : field.minLength != null || field.maxLength != null\n ? {\n minLength:\n field.minLength != null ? Number(field.minLength) : undefined,\n maxLength:\n field.maxLength != null ? Number(field.maxLength) : undefined,\n message:\n field.errorMessage != null\n ? String(field.errorMessage)\n : undefined,\n }\n : undefined,\n };\n}\n\nfunction normalizeFormSchema(schema: unknown): FormSchema | null {\n if (!schema || typeof schema !== \"object\") return null;\n const s = schema as Record<string, unknown>;\n const fields = Array.isArray(s.fields)\n ? s.fields.map((f) => normalizeFormField(f as Record<string, unknown>))\n : [];\n return {\n fields,\n title: s.title != null ? String(s.title) : undefined,\n description: s.description != null ? String(s.description) : undefined,\n submitLabel: s.submitLabel != null ? String(s.submitLabel) : undefined,\n };\n}\n\nfunction normalizeAuthConfig(raw: Record<string, unknown>): AuthConfig {\n const application =\n raw.application && typeof raw.application === \"object\"\n ? (raw.application as Record<string, unknown>)\n : {};\n const forms = Array.isArray(raw.forms) ? raw.forms : [];\n const findForm = (type: string) => {\n const match = forms.find(\n (f) => f && typeof f === \"object\" && (f as { type?: string }).type === type,\n ) as { schema?: unknown } | undefined;\n return normalizeFormSchema(match?.schema);\n };\n\n const settings =\n raw.settings && typeof raw.settings === \"object\"\n ? (raw.settings as Record<string, unknown>)\n : undefined;\n\n return {\n ...raw,\n applicationId: application.id != null ? String(application.id) : undefined,\n applicationName:\n application.name != null ? String(application.name) : undefined,\n environment:\n application.environment != null\n ? String(application.environment)\n : undefined,\n homeUrl:\n application.homeUrl != null ? String(application.homeUrl) : null,\n signInForm: findForm(\"sign_in\"),\n signUpForm: findForm(\"sign_up\"),\n forgotPasswordForm: findForm(\"forgot_password\"),\n resetPasswordForm: findForm(\"reset_password\"),\n providers: Array.isArray(raw.providers)\n ? (raw.providers as AuthConfig[\"providers\"])\n : undefined,\n experience:\n raw.experience && typeof raw.experience === \"object\"\n ? (raw.experience as Record<string, unknown>)\n : null,\n userProfile:\n raw.userProfile && typeof raw.userProfile === \"object\"\n ? (raw.userProfile as AuthConfig[\"userProfile\"])\n : {\n allowEditProfile: true,\n allowChangeEmail: true,\n allowChangePassword: true,\n },\n settings: settings\n ? {\n allowSignUp: true,\n requireEmailVerification: Boolean(\n settings.emailVerificationRequired,\n ),\n passwordMinLength:\n settings.passwordMinLength != null\n ? Number(settings.passwordMinLength)\n : undefined,\n ...settings,\n }\n : undefined,\n };\n}\n\nfunction normalizeAuthResult(raw: Record<string, unknown>): AuthResult {\n const sessionToken = String(raw.sessionToken ?? raw.token ?? \"\");\n if (!sessionToken) {\n throw new MeindeskApiError(\n \"invalid_response\",\n \"Auth response missing session token\",\n 500,\n );\n }\n\n return {\n sessionToken,\n user: raw.user as User,\n session: raw.session as Session,\n };\n}\n","export const SESSION_COOKIE_NAME = \"md_session\";\n\n/** In-memory mirror of the session token for same-tick Bearer auth. */\nlet memorySessionToken: string | null = null;\n\nexport interface StorageAdapter {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\n/** In-memory key/value store (SSR-safe, no persistence). */\nexport function createMemoryStorage(): StorageAdapter {\n const store = new Map<string, string>();\n\n return {\n getItem(key: string) {\n return store.has(key) ? (store.get(key) ?? null) : null;\n },\n setItem(key: string, value: string) {\n store.set(key, value);\n },\n removeItem(key: string) {\n store.delete(key);\n },\n };\n}\n\nexport interface CookieOptions {\n days?: number;\n path?: string;\n sameSite?: \"lax\" | \"strict\" | \"none\";\n secure?: boolean;\n domain?: string;\n}\n\nfunction isBrowser(): boolean {\n return typeof document !== \"undefined\";\n}\n\n/** Read a cookie value by name from `document.cookie`. */\nexport function getCookie(name: string): string | null {\n if (!isBrowser()) return null;\n\n const prefix = `${encodeURIComponent(name)}=`;\n const parts = document.cookie.split(\"; \");\n\n for (const part of parts) {\n if (part.startsWith(prefix)) {\n return decodeURIComponent(part.slice(prefix.length));\n }\n }\n\n return null;\n}\n\n/** Write a cookie via `document.cookie`. */\nexport function setCookie(\n name: string,\n value: string,\n options: CookieOptions = {},\n): void {\n if (!isBrowser()) return;\n\n const {\n days = 7,\n path = \"/\",\n sameSite = \"lax\",\n secure = typeof location !== \"undefined\" && location.protocol === \"https:\",\n domain,\n } = options;\n\n const maxAge = Math.max(0, Math.floor(days * 24 * 60 * 60));\n let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}; Path=${path}; Max-Age=${maxAge}; SameSite=${sameSite}`;\n\n if (secure) cookie += \"; Secure\";\n if (domain) cookie += `; Domain=${domain}`;\n\n document.cookie = cookie;\n}\n\n/** Clear a cookie by expiring it. */\nexport function removeCookie(\n name: string,\n options: Pick<CookieOptions, \"path\" | \"domain\"> = {},\n): void {\n if (!isBrowser()) return;\n\n const { path = \"/\", domain } = options;\n let cookie = `${encodeURIComponent(name)}=; Path=${path}; Max-Age=0; SameSite=lax`;\n if (domain) cookie += `; Domain=${domain}`;\n document.cookie = cookie;\n}\n\nexport function getSessionTokenFromCookie(): string | null {\n if (memorySessionToken) return memorySessionToken;\n return getCookie(SESSION_COOKIE_NAME);\n}\n\n/**\n * Persist session on the app origin for reload + Next middleware, and keep an\n * in-memory mirror for same-tick Bearer auth. The API may also set an HttpOnly\n * `md_session` on the API host for credentialed requests.\n */\nexport function setSessionTokenCookie(\n token: string,\n options?: CookieOptions,\n): void {\n memorySessionToken = token;\n setCookie(SESSION_COOKIE_NAME, token, options);\n}\n\nexport function clearSessionTokenCookie(\n options?: Pick<CookieOptions, \"path\" | \"domain\">,\n): void {\n memorySessionToken = null;\n removeCookie(SESSION_COOKIE_NAME, options);\n}\n\n/** Browser cookie-backed storage for non-secret prefs only. */\nexport function createCookieStorage(\n options: CookieOptions = {},\n): StorageAdapter {\n return {\n getItem(key: string) {\n if (key === SESSION_COOKIE_NAME) return getSessionTokenFromCookie();\n return getCookie(key);\n },\n setItem(key: string, value: string) {\n if (key === SESSION_COOKIE_NAME) {\n setSessionTokenCookie(value, options);\n return;\n }\n setCookie(key, value, options);\n },\n removeItem(key: string) {\n if (key === SESSION_COOKIE_NAME) {\n clearSessionTokenCookie({\n path: options.path,\n domain: options.domain,\n });\n return;\n }\n removeCookie(key, {\n path: options.path,\n domain: options.domain,\n });\n },\n };\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@meindesk/sdk",
3
+ "version": "0.1.0",
4
+ "description": "Meindesk Auth JavaScript/TypeScript SDK",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "^22.15.29",
22
+ "typescript": "^5.8.3",
23
+ "@meindesk/typescript-config": "0.0.0"
24
+ },
25
+ "scripts": {
26
+ "build": "tsup",
27
+ "lint": "tsc --noEmit"
28
+ },
29
+ "main": "./dist/index.js",
30
+ "types": "./dist/index.d.ts"
31
+ }