krisspy-sdk 0.9.3 → 1.2.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.
package/dist/index.d.mts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Krisspy SDK Types
3
3
  */
4
4
  interface KrisspyClientOptions {
5
- /** Base URL of the Krisspy API (default: https://krisspy-cloud-backend.thankfulhill-66fc9e74.westeurope.azurecontainerapps.io) */
5
+ /** Base URL of the Krisspy API (default: https://api.prod.krisspy.ai) */
6
6
  url?: string;
7
7
  /** Backend ID for this client */
8
8
  backendId: string;
@@ -87,6 +87,27 @@ interface OAuthProvider {
87
87
  provider: 'google' | 'github' | 'microsoft';
88
88
  redirectTo?: string;
89
89
  }
90
+ interface SignInWithOtpCredentials {
91
+ email: string;
92
+ options?: {
93
+ /** If false, don't create a user when one doesn't exist yet. (Advisory; default true.) */
94
+ shouldCreateUser?: boolean;
95
+ /** Where to redirect after the magic link is followed. */
96
+ emailRedirectTo?: string;
97
+ /** Delivery channel: 'magiclink' (default) emails a link, 'otp' emails a 6-digit code. */
98
+ channel?: 'magiclink' | 'otp';
99
+ };
100
+ }
101
+ interface VerifyOtpParams {
102
+ email: string;
103
+ token: string;
104
+ /** 'magiclink' verifies a magic-link token, 'otp' verifies a 6-digit code, 'email' confirms verification. */
105
+ type?: 'magiclink' | 'otp' | 'email';
106
+ }
107
+ interface ResendParams {
108
+ type: 'signup' | 'email_change';
109
+ email: string;
110
+ }
90
111
  interface QueryResponse<T = any> {
91
112
  data: T[] | null;
92
113
  error: KrisspyError | null;
@@ -339,11 +360,36 @@ declare class KrisspyAuth {
339
360
  error: KrisspyError | null;
340
361
  }>;
341
362
  /**
342
- * Request password reset
363
+ * Request password reset email
343
364
  */
344
365
  resetPasswordForEmail(email: string): Promise<{
345
366
  error: KrisspyError | null;
346
367
  }>;
368
+ /**
369
+ * Complete a password reset using the token from the reset email.
370
+ */
371
+ updatePasswordWithToken(params: {
372
+ token: string;
373
+ password: string;
374
+ }): Promise<{
375
+ error: KrisspyError | null;
376
+ }>;
377
+ /**
378
+ * Passwordless sign-in: emails a magic link (default) or a one-time code.
379
+ * No session is returned here — call verifyOtp() with the link token / code.
380
+ */
381
+ signInWithOtp(credentials: SignInWithOtpCredentials): Promise<AuthResponse>;
382
+ /**
383
+ * Verify a magic-link token or a one-time code and establish a session.
384
+ */
385
+ verifyOtp(params: VerifyOtpParams): Promise<AuthResponse>;
386
+ /**
387
+ * Resend a verification email.
388
+ */
389
+ resend(params: ResendParams): Promise<{
390
+ data: Record<string, never>;
391
+ error: KrisspyError | null;
392
+ }>;
347
393
  /**
348
394
  * Listen for auth state changes
349
395
  */
@@ -640,13 +686,19 @@ interface RealtimePayload<T = any> {
640
686
  }
641
687
  type RealtimeCallback<T = any> = (payload: RealtimePayload<T>) => void;
642
688
  type ChannelState = 'closed' | 'connecting' | 'connected' | 'error';
689
+ interface ChannelSubscription {
690
+ type: 'postgres_changes';
691
+ config: PostgresChangesConfig;
692
+ callback: RealtimeCallback;
693
+ }
643
694
  /**
644
695
  * Realtime Channel - represents a subscription to database changes
645
696
  */
646
697
  declare class RealtimeChannel {
647
698
  private name;
648
699
  private realtime;
649
- private subscriptions;
700
+ /** @internal — read by KrisspyRealtime to re-subscribe after reconnect */
701
+ subscriptions: ChannelSubscription[];
650
702
  private _state;
651
703
  constructor(name: string, realtime: KrisspyRealtime);
652
704
  /**
@@ -1040,6 +1092,47 @@ declare class KrisspyNotifications {
1040
1092
  }>;
1041
1093
  }
1042
1094
 
1095
+ /**
1096
+ * Email Module — send custom templated emails to your app's end users.
1097
+ *
1098
+ * Templates are created/managed in the Krisspy dashboard (per backend). From the
1099
+ * SDK you reference a template by slug and pass variables to interpolate.
1100
+ *
1101
+ * @example
1102
+ * await krisspy.email.send({
1103
+ * template: 'welcome',
1104
+ * to: 'user@example.com',
1105
+ * variables: { name: 'Sam', plan: 'Pro' },
1106
+ * })
1107
+ */
1108
+
1109
+ interface SendEmailParams {
1110
+ /** Slug of a template configured in the dashboard. */
1111
+ template: string;
1112
+ to: string;
1113
+ variables?: Record<string, any>;
1114
+ /** Optional sender override (honored on BYO providers; the Krisspy default keeps its locked address). */
1115
+ from?: {
1116
+ email: string;
1117
+ name?: string;
1118
+ };
1119
+ }
1120
+ interface SendEmailResponse {
1121
+ data: {
1122
+ source: string;
1123
+ } | null;
1124
+ error: KrisspyError | null;
1125
+ }
1126
+ declare class KrisspyEmail {
1127
+ private http;
1128
+ private backendId;
1129
+ constructor(http: HttpClient, backendId: string);
1130
+ /**
1131
+ * Render a dashboard template with the given variables and send it.
1132
+ */
1133
+ send(params: SendEmailParams): Promise<SendEmailResponse>;
1134
+ }
1135
+
1043
1136
  /**
1044
1137
  * Query Builder - Supabase-style fluent API for database queries
1045
1138
  */
@@ -1224,6 +1317,7 @@ declare class KrisspyClient {
1224
1317
  private _realtime;
1225
1318
  private _analytics;
1226
1319
  private _notifications;
1320
+ private _email;
1227
1321
  private dataMode;
1228
1322
  private debug;
1229
1323
  constructor(options: KrisspyClientOptions);
@@ -1283,6 +1377,17 @@ declare class KrisspyClient {
1283
1377
  * const { error } = await krisspy.storage.from('uploads').remove(['old.jpg'])
1284
1378
  */
1285
1379
  get storage(): KrisspyStorage;
1380
+ /**
1381
+ * Email module — send custom templated emails to your end users.
1382
+ *
1383
+ * @example
1384
+ * await krisspy.email.send({
1385
+ * template: 'welcome',
1386
+ * to: 'user@example.com',
1387
+ * variables: { name: 'Sam' },
1388
+ * })
1389
+ */
1390
+ get email(): KrisspyEmail;
1286
1391
  /**
1287
1392
  * Analytics module for event tracking
1288
1393
  *
@@ -1513,4 +1618,4 @@ declare class KrisspyClient {
1513
1618
  */
1514
1619
  declare function createClient(options: KrisspyClientOptions): KrisspyClient;
1515
1620
 
1516
- export { type AnalyticsEvent, type AnalyticsInitOptions, type AuthChangeEvent, type AuthResponse, type ChannelState, type FileObject, type FileUploadOptions, type Filter, type FilterOperator, type FunctionInvokeOptions, type FunctionResponse, HttpClient, KrisspyAnalytics, KrisspyAuth, KrisspyClient, type KrisspyClientOptions, type KrisspyError, KrisspyNotifications, KrisspyRealtime, KrisspyStorage, type MutationResponse, type NotificationTicket, type OAuthProvider, type OrderBy, type PostgresChangesConfig, type PushToken, QueryBuilder, type QueryOptions, type QueryResponse, RealtimeChannel, type RealtimeEvent, type RealtimePayload, type SendNotificationParams, type Session, type SignInCredentials, type SignUpCredentials, type SingleResponse, type StorageAdapter, StorageBucket, type UploadAndLinkOptions, type UploadAndLinkResponse, type User, createClient, isBrowser, isReactNative };
1621
+ export { type AnalyticsEvent, type AnalyticsInitOptions, type AuthChangeEvent, type AuthResponse, type ChannelState, type FileObject, type FileUploadOptions, type Filter, type FilterOperator, type FunctionInvokeOptions, type FunctionResponse, HttpClient, KrisspyAnalytics, KrisspyAuth, KrisspyClient, type KrisspyClientOptions, KrisspyEmail, type KrisspyError, KrisspyNotifications, KrisspyRealtime, KrisspyStorage, type MutationResponse, type NotificationTicket, type OAuthProvider, type OrderBy, type PostgresChangesConfig, type PushToken, QueryBuilder, type QueryOptions, type QueryResponse, RealtimeChannel, type RealtimeEvent, type RealtimePayload, type ResendParams, type SendEmailParams, type SendEmailResponse, type SendNotificationParams, type Session, type SignInCredentials, type SignInWithOtpCredentials, type SignUpCredentials, type SingleResponse, type StorageAdapter, StorageBucket, type UploadAndLinkOptions, type UploadAndLinkResponse, type User, type VerifyOtpParams, createClient, isBrowser, isReactNative };
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Krisspy SDK Types
3
3
  */
4
4
  interface KrisspyClientOptions {
5
- /** Base URL of the Krisspy API (default: https://krisspy-cloud-backend.thankfulhill-66fc9e74.westeurope.azurecontainerapps.io) */
5
+ /** Base URL of the Krisspy API (default: https://api.prod.krisspy.ai) */
6
6
  url?: string;
7
7
  /** Backend ID for this client */
8
8
  backendId: string;
@@ -87,6 +87,27 @@ interface OAuthProvider {
87
87
  provider: 'google' | 'github' | 'microsoft';
88
88
  redirectTo?: string;
89
89
  }
90
+ interface SignInWithOtpCredentials {
91
+ email: string;
92
+ options?: {
93
+ /** If false, don't create a user when one doesn't exist yet. (Advisory; default true.) */
94
+ shouldCreateUser?: boolean;
95
+ /** Where to redirect after the magic link is followed. */
96
+ emailRedirectTo?: string;
97
+ /** Delivery channel: 'magiclink' (default) emails a link, 'otp' emails a 6-digit code. */
98
+ channel?: 'magiclink' | 'otp';
99
+ };
100
+ }
101
+ interface VerifyOtpParams {
102
+ email: string;
103
+ token: string;
104
+ /** 'magiclink' verifies a magic-link token, 'otp' verifies a 6-digit code, 'email' confirms verification. */
105
+ type?: 'magiclink' | 'otp' | 'email';
106
+ }
107
+ interface ResendParams {
108
+ type: 'signup' | 'email_change';
109
+ email: string;
110
+ }
90
111
  interface QueryResponse<T = any> {
91
112
  data: T[] | null;
92
113
  error: KrisspyError | null;
@@ -339,11 +360,36 @@ declare class KrisspyAuth {
339
360
  error: KrisspyError | null;
340
361
  }>;
341
362
  /**
342
- * Request password reset
363
+ * Request password reset email
343
364
  */
344
365
  resetPasswordForEmail(email: string): Promise<{
345
366
  error: KrisspyError | null;
346
367
  }>;
368
+ /**
369
+ * Complete a password reset using the token from the reset email.
370
+ */
371
+ updatePasswordWithToken(params: {
372
+ token: string;
373
+ password: string;
374
+ }): Promise<{
375
+ error: KrisspyError | null;
376
+ }>;
377
+ /**
378
+ * Passwordless sign-in: emails a magic link (default) or a one-time code.
379
+ * No session is returned here — call verifyOtp() with the link token / code.
380
+ */
381
+ signInWithOtp(credentials: SignInWithOtpCredentials): Promise<AuthResponse>;
382
+ /**
383
+ * Verify a magic-link token or a one-time code and establish a session.
384
+ */
385
+ verifyOtp(params: VerifyOtpParams): Promise<AuthResponse>;
386
+ /**
387
+ * Resend a verification email.
388
+ */
389
+ resend(params: ResendParams): Promise<{
390
+ data: Record<string, never>;
391
+ error: KrisspyError | null;
392
+ }>;
347
393
  /**
348
394
  * Listen for auth state changes
349
395
  */
@@ -640,13 +686,19 @@ interface RealtimePayload<T = any> {
640
686
  }
641
687
  type RealtimeCallback<T = any> = (payload: RealtimePayload<T>) => void;
642
688
  type ChannelState = 'closed' | 'connecting' | 'connected' | 'error';
689
+ interface ChannelSubscription {
690
+ type: 'postgres_changes';
691
+ config: PostgresChangesConfig;
692
+ callback: RealtimeCallback;
693
+ }
643
694
  /**
644
695
  * Realtime Channel - represents a subscription to database changes
645
696
  */
646
697
  declare class RealtimeChannel {
647
698
  private name;
648
699
  private realtime;
649
- private subscriptions;
700
+ /** @internal — read by KrisspyRealtime to re-subscribe after reconnect */
701
+ subscriptions: ChannelSubscription[];
650
702
  private _state;
651
703
  constructor(name: string, realtime: KrisspyRealtime);
652
704
  /**
@@ -1040,6 +1092,47 @@ declare class KrisspyNotifications {
1040
1092
  }>;
1041
1093
  }
1042
1094
 
1095
+ /**
1096
+ * Email Module — send custom templated emails to your app's end users.
1097
+ *
1098
+ * Templates are created/managed in the Krisspy dashboard (per backend). From the
1099
+ * SDK you reference a template by slug and pass variables to interpolate.
1100
+ *
1101
+ * @example
1102
+ * await krisspy.email.send({
1103
+ * template: 'welcome',
1104
+ * to: 'user@example.com',
1105
+ * variables: { name: 'Sam', plan: 'Pro' },
1106
+ * })
1107
+ */
1108
+
1109
+ interface SendEmailParams {
1110
+ /** Slug of a template configured in the dashboard. */
1111
+ template: string;
1112
+ to: string;
1113
+ variables?: Record<string, any>;
1114
+ /** Optional sender override (honored on BYO providers; the Krisspy default keeps its locked address). */
1115
+ from?: {
1116
+ email: string;
1117
+ name?: string;
1118
+ };
1119
+ }
1120
+ interface SendEmailResponse {
1121
+ data: {
1122
+ source: string;
1123
+ } | null;
1124
+ error: KrisspyError | null;
1125
+ }
1126
+ declare class KrisspyEmail {
1127
+ private http;
1128
+ private backendId;
1129
+ constructor(http: HttpClient, backendId: string);
1130
+ /**
1131
+ * Render a dashboard template with the given variables and send it.
1132
+ */
1133
+ send(params: SendEmailParams): Promise<SendEmailResponse>;
1134
+ }
1135
+
1043
1136
  /**
1044
1137
  * Query Builder - Supabase-style fluent API for database queries
1045
1138
  */
@@ -1224,6 +1317,7 @@ declare class KrisspyClient {
1224
1317
  private _realtime;
1225
1318
  private _analytics;
1226
1319
  private _notifications;
1320
+ private _email;
1227
1321
  private dataMode;
1228
1322
  private debug;
1229
1323
  constructor(options: KrisspyClientOptions);
@@ -1283,6 +1377,17 @@ declare class KrisspyClient {
1283
1377
  * const { error } = await krisspy.storage.from('uploads').remove(['old.jpg'])
1284
1378
  */
1285
1379
  get storage(): KrisspyStorage;
1380
+ /**
1381
+ * Email module — send custom templated emails to your end users.
1382
+ *
1383
+ * @example
1384
+ * await krisspy.email.send({
1385
+ * template: 'welcome',
1386
+ * to: 'user@example.com',
1387
+ * variables: { name: 'Sam' },
1388
+ * })
1389
+ */
1390
+ get email(): KrisspyEmail;
1286
1391
  /**
1287
1392
  * Analytics module for event tracking
1288
1393
  *
@@ -1513,4 +1618,4 @@ declare class KrisspyClient {
1513
1618
  */
1514
1619
  declare function createClient(options: KrisspyClientOptions): KrisspyClient;
1515
1620
 
1516
- export { type AnalyticsEvent, type AnalyticsInitOptions, type AuthChangeEvent, type AuthResponse, type ChannelState, type FileObject, type FileUploadOptions, type Filter, type FilterOperator, type FunctionInvokeOptions, type FunctionResponse, HttpClient, KrisspyAnalytics, KrisspyAuth, KrisspyClient, type KrisspyClientOptions, type KrisspyError, KrisspyNotifications, KrisspyRealtime, KrisspyStorage, type MutationResponse, type NotificationTicket, type OAuthProvider, type OrderBy, type PostgresChangesConfig, type PushToken, QueryBuilder, type QueryOptions, type QueryResponse, RealtimeChannel, type RealtimeEvent, type RealtimePayload, type SendNotificationParams, type Session, type SignInCredentials, type SignUpCredentials, type SingleResponse, type StorageAdapter, StorageBucket, type UploadAndLinkOptions, type UploadAndLinkResponse, type User, createClient, isBrowser, isReactNative };
1621
+ export { type AnalyticsEvent, type AnalyticsInitOptions, type AuthChangeEvent, type AuthResponse, type ChannelState, type FileObject, type FileUploadOptions, type Filter, type FilterOperator, type FunctionInvokeOptions, type FunctionResponse, HttpClient, KrisspyAnalytics, KrisspyAuth, KrisspyClient, type KrisspyClientOptions, KrisspyEmail, type KrisspyError, KrisspyNotifications, KrisspyRealtime, KrisspyStorage, type MutationResponse, type NotificationTicket, type OAuthProvider, type OrderBy, type PostgresChangesConfig, type PushToken, QueryBuilder, type QueryOptions, type QueryResponse, RealtimeChannel, type RealtimeEvent, type RealtimePayload, type ResendParams, type SendEmailParams, type SendEmailResponse, type SendNotificationParams, type Session, type SignInCredentials, type SignInWithOtpCredentials, type SignUpCredentials, type SingleResponse, type StorageAdapter, StorageBucket, type UploadAndLinkOptions, type UploadAndLinkResponse, type User, type VerifyOtpParams, createClient, isBrowser, isReactNative };
package/dist/index.js CHANGED
@@ -51,6 +51,7 @@ __export(index_exports, {
51
51
  KrisspyAnalytics: () => KrisspyAnalytics,
52
52
  KrisspyAuth: () => KrisspyAuth,
53
53
  KrisspyClient: () => KrisspyClient,
54
+ KrisspyEmail: () => KrisspyEmail,
54
55
  KrisspyNotifications: () => KrisspyNotifications,
55
56
  KrisspyRealtime: () => KrisspyRealtime,
56
57
  KrisspyStorage: () => KrisspyStorage,
@@ -562,13 +563,77 @@ var KrisspyAuth = class {
562
563
  return { data: { user: (_c = (_b = response.data) == null ? void 0 : _b.user) != null ? _c : null }, error: null };
563
564
  }
564
565
  /**
565
- * Request password reset
566
+ * Request password reset email
566
567
  */
567
568
  async resetPasswordForEmail(email) {
568
569
  const path = `/api/v1/cloud-backends/${this.backendId}/auth/reset-password`;
569
570
  const response = await this.http.post(path, { email });
570
571
  return { error: response.error };
571
572
  }
573
+ /**
574
+ * Complete a password reset using the token from the reset email.
575
+ */
576
+ async updatePasswordWithToken(params) {
577
+ const path = `/api/v1/cloud-backends/${this.backendId}/auth/reset-password/confirm`;
578
+ const response = await this.http.post(path, {
579
+ token: params.token,
580
+ password: params.password
581
+ });
582
+ return { error: response.error };
583
+ }
584
+ /**
585
+ * Passwordless sign-in: emails a magic link (default) or a one-time code.
586
+ * No session is returned here — call verifyOtp() with the link token / code.
587
+ */
588
+ async signInWithOtp(credentials) {
589
+ var _a, _b, _c;
590
+ const channel = (_b = (_a = credentials.options) == null ? void 0 : _a.channel) != null ? _b : "magiclink";
591
+ const path = channel === "otp" ? `/api/v1/cloud-backends/${this.backendId}/auth/otp` : `/api/v1/cloud-backends/${this.backendId}/auth/magic-link`;
592
+ const response = await this.http.post(path, {
593
+ email: credentials.email,
594
+ redirectTo: (_c = credentials.options) == null ? void 0 : _c.emailRedirectTo
595
+ });
596
+ return {
597
+ data: { user: null, session: null },
598
+ error: response.error
599
+ };
600
+ }
601
+ /**
602
+ * Verify a magic-link token or a one-time code and establish a session.
603
+ */
604
+ async verifyOtp(params) {
605
+ var _a, _b, _c, _d, _e, _f;
606
+ const type = (_a = params.type) != null ? _a : "otp";
607
+ if (type === "email") {
608
+ const path2 = `/api/v1/cloud-backends/${this.backendId}/auth/verify-email`;
609
+ const response2 = await this.http.post(path2, { token: params.token });
610
+ return { data: { user: null, session: null }, error: response2.error };
611
+ }
612
+ const path = type === "magiclink" ? `/api/v1/cloud-backends/${this.backendId}/auth/magic-link/verify` : `/api/v1/cloud-backends/${this.backendId}/auth/otp/verify`;
613
+ const body = type === "magiclink" ? { token: params.token } : { email: params.email, token: params.token };
614
+ const response = await this.http.post(path, body);
615
+ if (response.error) {
616
+ return { data: { user: null, session: null }, error: response.error };
617
+ }
618
+ if ((_b = response.data) == null ? void 0 : _b.session) {
619
+ this.setSession(response.data.session);
620
+ }
621
+ return {
622
+ data: {
623
+ user: (_d = (_c = response.data) == null ? void 0 : _c.user) != null ? _d : null,
624
+ session: (_f = (_e = response.data) == null ? void 0 : _e.session) != null ? _f : null
625
+ },
626
+ error: null
627
+ };
628
+ }
629
+ /**
630
+ * Resend a verification email.
631
+ */
632
+ async resend(params) {
633
+ const path = `/api/v1/cloud-backends/${this.backendId}/auth/verify-email/resend`;
634
+ const response = await this.http.post(path, { email: params.email });
635
+ return { data: {}, error: response.error };
636
+ }
572
637
  /**
573
638
  * Listen for auth state changes
574
639
  */
@@ -1018,6 +1083,7 @@ var KrisspyStorage = class {
1018
1083
  // src/realtime.ts
1019
1084
  var RealtimeChannel = class {
1020
1085
  constructor(name, realtime) {
1086
+ /** @internal — read by KrisspyRealtime to re-subscribe after reconnect */
1021
1087
  this.subscriptions = [];
1022
1088
  this._state = "closed";
1023
1089
  this.name = name;
@@ -1286,8 +1352,14 @@ var KrisspyRealtime = class {
1286
1352
  this.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
1287
1353
  setTimeout(() => {
1288
1354
  this.connect().then(() => {
1355
+ if (this.token) {
1356
+ this.send({ type: "auth", token: this.token });
1357
+ }
1289
1358
  for (const [name, channel] of this.channels) {
1290
1359
  this.log(`Re-subscribing to channel: ${name}`);
1360
+ for (const sub of channel.subscriptions) {
1361
+ this.sendSubscribe(name, sub.config);
1362
+ }
1291
1363
  }
1292
1364
  }).catch((error) => {
1293
1365
  console.error("[Krisspy Realtime] Reconnect failed:", error);
@@ -1755,6 +1827,31 @@ var KrisspyNotifications = class {
1755
1827
  }
1756
1828
  };
1757
1829
 
1830
+ // src/email.ts
1831
+ var KrisspyEmail = class {
1832
+ constructor(http, backendId) {
1833
+ this.http = http;
1834
+ this.backendId = backendId;
1835
+ }
1836
+ /**
1837
+ * Render a dashboard template with the given variables and send it.
1838
+ */
1839
+ async send(params) {
1840
+ var _a, _b;
1841
+ const path = `/api/v1/cloud-backends/${this.backendId}/email/send`;
1842
+ const response = await this.http.post(path, {
1843
+ template: params.template,
1844
+ to: params.to,
1845
+ variables: params.variables,
1846
+ from: params.from
1847
+ });
1848
+ if (response.error) {
1849
+ return { data: null, error: response.error };
1850
+ }
1851
+ return { data: { source: (_b = (_a = response.data) == null ? void 0 : _a.source) != null ? _b : "unknown" }, error: null };
1852
+ }
1853
+ };
1854
+
1758
1855
  // src/query-builder.ts
1759
1856
  var MutationFilterBuilder = class {
1760
1857
  constructor(http, path, method, body, initialParams) {
@@ -2099,7 +2196,7 @@ var QueryBuilder = class {
2099
2196
  var KrisspyClient = class {
2100
2197
  constructor(options) {
2101
2198
  var _a;
2102
- this.baseUrl = options.url || "https://api.preprod.krisspy.ai";
2199
+ this.baseUrl = options.url || "https://api.prod.krisspy.ai";
2103
2200
  this.backendId = options.backendId;
2104
2201
  this.debug = options.debug || false;
2105
2202
  this.functionsUrl = ((_a = options.functionsUrl) == null ? void 0 : _a.replace(/\/$/, "")) || null;
@@ -2126,6 +2223,7 @@ var KrisspyClient = class {
2126
2223
  this._realtime = new KrisspyRealtime(this.baseUrl, this.backendId, this.debug);
2127
2224
  this._analytics = new KrisspyAnalytics(this.http, this.backendId);
2128
2225
  this._notifications = new KrisspyNotifications(this.http, this.backendId);
2226
+ this._email = new KrisspyEmail(this.http, this.backendId);
2129
2227
  this._auth.onAuthStateChange((event) => {
2130
2228
  if (event === "SIGNED_IN") {
2131
2229
  const session = this._auth.session();
@@ -2199,6 +2297,19 @@ var KrisspyClient = class {
2199
2297
  get storage() {
2200
2298
  return this._storage;
2201
2299
  }
2300
+ /**
2301
+ * Email module — send custom templated emails to your end users.
2302
+ *
2303
+ * @example
2304
+ * await krisspy.email.send({
2305
+ * template: 'welcome',
2306
+ * to: 'user@example.com',
2307
+ * variables: { name: 'Sam' },
2308
+ * })
2309
+ */
2310
+ get email() {
2311
+ return this._email;
2312
+ }
2202
2313
  /**
2203
2314
  * Analytics module for event tracking
2204
2315
  *
package/dist/index.mjs CHANGED
@@ -517,13 +517,77 @@ var KrisspyAuth = class {
517
517
  return { data: { user: (_c = (_b = response.data) == null ? void 0 : _b.user) != null ? _c : null }, error: null };
518
518
  }
519
519
  /**
520
- * Request password reset
520
+ * Request password reset email
521
521
  */
522
522
  async resetPasswordForEmail(email) {
523
523
  const path = `/api/v1/cloud-backends/${this.backendId}/auth/reset-password`;
524
524
  const response = await this.http.post(path, { email });
525
525
  return { error: response.error };
526
526
  }
527
+ /**
528
+ * Complete a password reset using the token from the reset email.
529
+ */
530
+ async updatePasswordWithToken(params) {
531
+ const path = `/api/v1/cloud-backends/${this.backendId}/auth/reset-password/confirm`;
532
+ const response = await this.http.post(path, {
533
+ token: params.token,
534
+ password: params.password
535
+ });
536
+ return { error: response.error };
537
+ }
538
+ /**
539
+ * Passwordless sign-in: emails a magic link (default) or a one-time code.
540
+ * No session is returned here — call verifyOtp() with the link token / code.
541
+ */
542
+ async signInWithOtp(credentials) {
543
+ var _a, _b, _c;
544
+ const channel = (_b = (_a = credentials.options) == null ? void 0 : _a.channel) != null ? _b : "magiclink";
545
+ const path = channel === "otp" ? `/api/v1/cloud-backends/${this.backendId}/auth/otp` : `/api/v1/cloud-backends/${this.backendId}/auth/magic-link`;
546
+ const response = await this.http.post(path, {
547
+ email: credentials.email,
548
+ redirectTo: (_c = credentials.options) == null ? void 0 : _c.emailRedirectTo
549
+ });
550
+ return {
551
+ data: { user: null, session: null },
552
+ error: response.error
553
+ };
554
+ }
555
+ /**
556
+ * Verify a magic-link token or a one-time code and establish a session.
557
+ */
558
+ async verifyOtp(params) {
559
+ var _a, _b, _c, _d, _e, _f;
560
+ const type = (_a = params.type) != null ? _a : "otp";
561
+ if (type === "email") {
562
+ const path2 = `/api/v1/cloud-backends/${this.backendId}/auth/verify-email`;
563
+ const response2 = await this.http.post(path2, { token: params.token });
564
+ return { data: { user: null, session: null }, error: response2.error };
565
+ }
566
+ const path = type === "magiclink" ? `/api/v1/cloud-backends/${this.backendId}/auth/magic-link/verify` : `/api/v1/cloud-backends/${this.backendId}/auth/otp/verify`;
567
+ const body = type === "magiclink" ? { token: params.token } : { email: params.email, token: params.token };
568
+ const response = await this.http.post(path, body);
569
+ if (response.error) {
570
+ return { data: { user: null, session: null }, error: response.error };
571
+ }
572
+ if ((_b = response.data) == null ? void 0 : _b.session) {
573
+ this.setSession(response.data.session);
574
+ }
575
+ return {
576
+ data: {
577
+ user: (_d = (_c = response.data) == null ? void 0 : _c.user) != null ? _d : null,
578
+ session: (_f = (_e = response.data) == null ? void 0 : _e.session) != null ? _f : null
579
+ },
580
+ error: null
581
+ };
582
+ }
583
+ /**
584
+ * Resend a verification email.
585
+ */
586
+ async resend(params) {
587
+ const path = `/api/v1/cloud-backends/${this.backendId}/auth/verify-email/resend`;
588
+ const response = await this.http.post(path, { email: params.email });
589
+ return { data: {}, error: response.error };
590
+ }
527
591
  /**
528
592
  * Listen for auth state changes
529
593
  */
@@ -973,6 +1037,7 @@ var KrisspyStorage = class {
973
1037
  // src/realtime.ts
974
1038
  var RealtimeChannel = class {
975
1039
  constructor(name, realtime) {
1040
+ /** @internal — read by KrisspyRealtime to re-subscribe after reconnect */
976
1041
  this.subscriptions = [];
977
1042
  this._state = "closed";
978
1043
  this.name = name;
@@ -1241,8 +1306,14 @@ var KrisspyRealtime = class {
1241
1306
  this.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
1242
1307
  setTimeout(() => {
1243
1308
  this.connect().then(() => {
1309
+ if (this.token) {
1310
+ this.send({ type: "auth", token: this.token });
1311
+ }
1244
1312
  for (const [name, channel] of this.channels) {
1245
1313
  this.log(`Re-subscribing to channel: ${name}`);
1314
+ for (const sub of channel.subscriptions) {
1315
+ this.sendSubscribe(name, sub.config);
1316
+ }
1246
1317
  }
1247
1318
  }).catch((error) => {
1248
1319
  console.error("[Krisspy Realtime] Reconnect failed:", error);
@@ -1710,6 +1781,31 @@ var KrisspyNotifications = class {
1710
1781
  }
1711
1782
  };
1712
1783
 
1784
+ // src/email.ts
1785
+ var KrisspyEmail = class {
1786
+ constructor(http, backendId) {
1787
+ this.http = http;
1788
+ this.backendId = backendId;
1789
+ }
1790
+ /**
1791
+ * Render a dashboard template with the given variables and send it.
1792
+ */
1793
+ async send(params) {
1794
+ var _a, _b;
1795
+ const path = `/api/v1/cloud-backends/${this.backendId}/email/send`;
1796
+ const response = await this.http.post(path, {
1797
+ template: params.template,
1798
+ to: params.to,
1799
+ variables: params.variables,
1800
+ from: params.from
1801
+ });
1802
+ if (response.error) {
1803
+ return { data: null, error: response.error };
1804
+ }
1805
+ return { data: { source: (_b = (_a = response.data) == null ? void 0 : _a.source) != null ? _b : "unknown" }, error: null };
1806
+ }
1807
+ };
1808
+
1713
1809
  // src/query-builder.ts
1714
1810
  var MutationFilterBuilder = class {
1715
1811
  constructor(http, path, method, body, initialParams) {
@@ -2054,7 +2150,7 @@ var QueryBuilder = class {
2054
2150
  var KrisspyClient = class {
2055
2151
  constructor(options) {
2056
2152
  var _a;
2057
- this.baseUrl = options.url || "https://api.preprod.krisspy.ai";
2153
+ this.baseUrl = options.url || "https://api.prod.krisspy.ai";
2058
2154
  this.backendId = options.backendId;
2059
2155
  this.debug = options.debug || false;
2060
2156
  this.functionsUrl = ((_a = options.functionsUrl) == null ? void 0 : _a.replace(/\/$/, "")) || null;
@@ -2081,6 +2177,7 @@ var KrisspyClient = class {
2081
2177
  this._realtime = new KrisspyRealtime(this.baseUrl, this.backendId, this.debug);
2082
2178
  this._analytics = new KrisspyAnalytics(this.http, this.backendId);
2083
2179
  this._notifications = new KrisspyNotifications(this.http, this.backendId);
2180
+ this._email = new KrisspyEmail(this.http, this.backendId);
2084
2181
  this._auth.onAuthStateChange((event) => {
2085
2182
  if (event === "SIGNED_IN") {
2086
2183
  const session = this._auth.session();
@@ -2154,6 +2251,19 @@ var KrisspyClient = class {
2154
2251
  get storage() {
2155
2252
  return this._storage;
2156
2253
  }
2254
+ /**
2255
+ * Email module — send custom templated emails to your end users.
2256
+ *
2257
+ * @example
2258
+ * await krisspy.email.send({
2259
+ * template: 'welcome',
2260
+ * to: 'user@example.com',
2261
+ * variables: { name: 'Sam' },
2262
+ * })
2263
+ */
2264
+ get email() {
2265
+ return this._email;
2266
+ }
2157
2267
  /**
2158
2268
  * Analytics module for event tracking
2159
2269
  *
@@ -2391,6 +2501,7 @@ export {
2391
2501
  KrisspyAnalytics,
2392
2502
  KrisspyAuth,
2393
2503
  KrisspyClient,
2504
+ KrisspyEmail,
2394
2505
  KrisspyNotifications,
2395
2506
  KrisspyRealtime,
2396
2507
  KrisspyStorage,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "krisspy-sdk",
3
- "version": "0.9.3",
3
+ "version": "1.2.0",
4
4
  "description": "Krisspy Cloud SDK - Database, Auth, Storage, and Functions for your apps",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",