hydrousdb 3.5.1 → 3.5.2

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.cts CHANGED
@@ -57,6 +57,35 @@ interface LoginOptions {
57
57
  email: string;
58
58
  password: string;
59
59
  }
60
+ /**
61
+ * Options for `auth.continueWithGoogle()`.
62
+ *
63
+ * Pass the Google ID token returned by the Google Sign-In SDK.
64
+ * Your server verifies this token — the SDK never calls Google APIs directly.
65
+ *
66
+ * How to get the idToken:
67
+ * Web (Google Identity Services):
68
+ * `google.accounts.id.initialize({ callback: ({ credential }) => ... })`
69
+ * → credential IS the idToken
70
+ * React Native (@react-native-google-signin/google-signin):
71
+ * `const { idToken } = await GoogleSignin.signIn()`
72
+ * Flutter (google_sign_in):
73
+ * `final idToken = (await account.authentication).idToken`
74
+ */
75
+ interface GoogleSignInOptions {
76
+ idToken: string;
77
+ }
78
+ /**
79
+ * Options for `auth.linkGoogle()`.
80
+ * Links a Google account to an existing email/password account so the
81
+ * user can sign in with either method going forward.
82
+ */
83
+ interface GoogleLinkOptions {
84
+ /** Active session ID of the currently signed-in user. */
85
+ sessionId: string;
86
+ /** Google ID token from the Google Sign-In SDK. */
87
+ idToken: string;
88
+ }
60
89
  interface UserRecord {
61
90
  id: string;
62
91
  email: string;
@@ -67,6 +96,24 @@ interface UserRecord {
67
96
  createdAt: number;
68
97
  updatedAt: number;
69
98
  metadata?: Record<string, unknown>;
99
+ /**
100
+ * Primary authentication provider for this account.
101
+ * 'email' — signed up with email + password
102
+ * 'google' — signed up via Google (no password unless added later)
103
+ */
104
+ authProvider?: 'email' | 'google' | 'github';
105
+ /**
106
+ * Google profile picture URL.
107
+ * Present for users who signed up or linked Google.
108
+ * Refreshed automatically on each Google sign-in.
109
+ */
110
+ picture?: string | null;
111
+ /**
112
+ * Stable Google user ID (the `sub` claim from the Google ID token).
113
+ * Never changes even if the user changes their Google email.
114
+ * Only present for users with Google linked.
115
+ */
116
+ googleId?: string;
70
117
  [key: string]: unknown;
71
118
  }
72
119
  interface Session {
@@ -81,6 +128,19 @@ interface Session {
81
128
  interface AuthResult {
82
129
  user: UserRecord;
83
130
  session: Session;
131
+ /**
132
+ * `true` when this is the very first sign-in (account was just created).
133
+ * `false` for returning users.
134
+ * Present for all auth methods — signup, login, and continueWithGoogle.
135
+ *
136
+ * Use to drive onboarding flows:
137
+ * ```ts
138
+ * const { user, session, isNew } = await auth.continueWithGoogle({ idToken });
139
+ * if (isNew) router.push('/onboarding');
140
+ * else router.push('/dashboard');
141
+ * ```
142
+ */
143
+ isNew?: boolean;
84
144
  }
85
145
  interface UpdateUserOptions {
86
146
  sessionId: string;
@@ -152,6 +212,30 @@ interface QueryOptions {
152
212
  * await posts.query({ timeScope: '_day_260305' });
153
213
  */
154
214
  timeScope?: string;
215
+ /**
216
+ * Start of a date range — inclusive. ISO date string (YYYY-MM-DD).
217
+ * Maps to `?startDate=` on the server.
218
+ * @example '2026-01-01'
219
+ */
220
+ startDate?: string;
221
+ /**
222
+ * End of a date range — inclusive. ISO date string (YYYY-MM-DD).
223
+ * Maps to `?endDate=` on the server.
224
+ * @example '2026-12-31'
225
+ */
226
+ endDate?: string;
227
+ /**
228
+ * Restrict the monthly walk to a specific two-digit year.
229
+ * Maps to `?year=` on the server.
230
+ * @example '26' for 2026
231
+ */
232
+ year?: string;
233
+ /**
234
+ * Field to sort by. Maps to `?sortBy=` on the server.
235
+ * Works on every query path — sorting is always done in-memory after hydration
236
+ * so any field name is accepted, not just indexed ones.
237
+ */
238
+ sortBy?: string;
155
239
  }
156
240
  interface QueryResult<T = RecordData> {
157
241
  records: (T & RecordResult)[];
@@ -414,6 +498,83 @@ declare class AuthClient {
414
498
  sessionId: string;
415
499
  allDevices?: boolean;
416
500
  }): Promise<void>;
501
+ /**
502
+ * Sign in or create an account using a Google ID token.
503
+ *
504
+ * Pass the `idToken` from the Google Sign-In SDK. Your server verifies the
505
+ * token against Google's public keys, then either creates a new account or
506
+ * signs in the returning user. No password is ever set or required.
507
+ *
508
+ * The returned `AuthResult` is identical in shape to `login()` and `signup()`.
509
+ * Sessions from Google sign-in work with `validateSession`, `refreshSession`,
510
+ * and `logout` — nothing changes after the initial sign-in.
511
+ *
512
+ * Use `isNew` to drive onboarding flows.
513
+ *
514
+ * @example
515
+ * ```ts
516
+ * // Web — Google Identity Services
517
+ * google.accounts.id.initialize({
518
+ * client_id: 'YOUR_GOOGLE_CLIENT_ID',
519
+ * callback: async ({ credential }) => {
520
+ * const { user, session, isNew } = await db.auth().continueWithGoogle({
521
+ * idToken: credential,
522
+ * });
523
+ * if (isNew) router.push('/onboarding');
524
+ * else router.push('/dashboard');
525
+ * },
526
+ * });
527
+ *
528
+ * // React Native
529
+ * const { idToken } = await GoogleSignin.signIn();
530
+ * const { user, session, isNew } = await db.auth().continueWithGoogle({ idToken });
531
+ * ```
532
+ *
533
+ * Server: POST /api/auth/google
534
+ * Body: { idToken }
535
+ */
536
+ continueWithGoogle(options: GoogleSignInOptions): Promise<AuthResult>;
537
+ /**
538
+ * Link a Google account to the currently signed-in user.
539
+ *
540
+ * After linking, the user can sign in with either their email + password
541
+ * or with Google — both produce valid sessions.
542
+ *
543
+ * The server is idempotent — calling this when Google is already linked
544
+ * returns the updated user without creating duplicate entries.
545
+ *
546
+ * @example
547
+ * ```ts
548
+ * // User is signed in with email. They click "Connect Google" in settings.
549
+ * const { idToken } = await GoogleSignin.signIn();
550
+ * const updatedUser = await db.auth().linkGoogle({
551
+ * sessionId: currentSession.sessionId,
552
+ * idToken,
553
+ * });
554
+ * ```
555
+ *
556
+ * Server: POST /api/auth/google/link
557
+ * Body: { sessionId, idToken }
558
+ */
559
+ linkGoogle(options: GoogleLinkOptions): Promise<UserRecord>;
560
+ /**
561
+ * Unlink Google from the currently signed-in user's account.
562
+ *
563
+ * Only succeeds if the user has a password set — you cannot remove the only
564
+ * sign-in method. If the account was created via Google and has no password,
565
+ * call `changePassword` first.
566
+ *
567
+ * @example
568
+ * ```ts
569
+ * await db.auth().unlinkGoogle({ sessionId: currentSession.sessionId });
570
+ * ```
571
+ *
572
+ * Server: DELETE /api/auth/google/unlink
573
+ * Body: { sessionId }
574
+ */
575
+ unlinkGoogle(options: {
576
+ sessionId: string;
577
+ }): Promise<void>;
417
578
  /**
418
579
  * Validate an existing session and retrieve the current user.
419
580
  *
@@ -1203,114 +1364,64 @@ declare class HydrousClient {
1203
1364
  */
1204
1365
  declare function createClient(config: HydrousConfig): HydrousClient;
1205
1366
 
1206
- /**
1207
- * routes.ts — Single source of truth for every API path in the HydrousDB SDK.
1208
- *
1209
- * Base URL: https://db-api-82687684612.us-central1.run.app
1210
- *
1211
- * Mount points (from server.js):
1212
- * /api → records router (X-Api-Key: bucketSecurityKey)
1213
- * /api/analytics → analytics router (X-Api-Key: bucketSecurityKey)
1214
- * /api/auth → auth router (X-Api-Key: authKey)
1215
- * /storage → storage router (X-Storage-Key: ssk_…)
1216
- *
1217
- * ⚠️ Keys MUST be sent in headers — NEVER in URLs or query strings.
1218
- * Records + Analytics: X-Api-Key (or Authorization: Bearer …)
1219
- * Storage: X-Storage-Key (or Authorization: Bearer …)
1220
- */
1221
1367
  declare const RECORDS: {
1222
- /** GET|POST|PATCH|DELETE|HEAD /api/:bucketKey */
1368
+ /** Base path for a bucket: GET|POST /api/:bucketKey */
1223
1369
  readonly bucket: (bucketKey: string) => string;
1224
- /** POST /api/:bucketKey/batch/insert */
1370
+ /** Batch insert: POST /api/:bucketKey/batch/insert */
1225
1371
  readonly batchInsert: (bucketKey: string) => string;
1226
- /** POST /api/:bucketKey/batch/update */
1372
+ /** Batch update: POST /api/:bucketKey/batch/update */
1227
1373
  readonly batchUpdate: (bucketKey: string) => string;
1228
- /** POST /api/:bucketKey/batch/delete */
1374
+ /** Batch delete: POST /api/:bucketKey/batch/delete */
1229
1375
  readonly batchDelete: (bucketKey: string) => string;
1230
1376
  };
1231
1377
  declare const ANALYTICS: {
1232
- /** POST /api/analytics/:bucketKey */
1378
+ /** Analytics query: POST /api/analytics/:bucketKey */
1233
1379
  readonly query: (bucketKey: string) => string;
1234
1380
  };
1235
1381
  declare const AUTH: {
1236
- /** POST /api/auth/signup body: { email, password, fullName?, ...extra } */
1237
1382
  readonly signup: "/api/auth/signup";
1238
- /** POST /api/auth/signin body: { email, password } */
1239
1383
  readonly signin: "/api/auth/signin";
1240
- /** POST /api/auth/signout body: { sessionId, allDevices? } */
1241
1384
  readonly signout: "/api/auth/signout";
1242
- /** POST /api/auth/session/validate body: { sessionId } */
1385
+ readonly googleSignIn: "/api/auth/google";
1386
+ readonly googleLink: "/api/auth/google/link";
1387
+ readonly googleUnlink: "/api/auth/google/unlink";
1243
1388
  readonly sessionValidate: "/api/auth/session/validate";
1244
- /** POST /api/auth/session/refresh body: { refreshToken } */
1245
1389
  readonly sessionRefresh: "/api/auth/session/refresh";
1246
- /** GET /api/auth/user?userId=... */
1247
1390
  readonly getUser: "/api/auth/user";
1248
- /** GET /api/auth/users?limit=&cursor= */
1249
- readonly listUsers: "/api/auth/users";
1250
- /** PATCH /api/auth/user body: { sessionId, userId, updates: {...} } */
1251
1391
  readonly updateUser: "/api/auth/user";
1252
- /** DELETE /api/auth/user?userId=... body: { sessionId } */
1253
1392
  readonly deleteUser: "/api/auth/user";
1254
- /** DELETE /api/auth/user/hard?userId=... body: { sessionId } */
1393
+ readonly listUsers: "/api/auth/users";
1255
1394
  readonly hardDeleteUser: "/api/auth/user/hard";
1256
- /** DELETE /api/auth/users/bulk body: { userIds, hard?, sessionId } */
1257
1395
  readonly bulkDeleteUsers: "/api/auth/users/bulk";
1258
- /** POST /api/auth/password/change body: { sessionId, userId, oldPassword, newPassword } */
1396
+ readonly accountLock: "/api/auth/account/lock";
1397
+ readonly accountUnlock: "/api/auth/account/unlock";
1259
1398
  readonly passwordChange: "/api/auth/password/change";
1260
- /** POST /api/auth/password/reset/request body: { email } */
1261
1399
  readonly passwordResetRequest: "/api/auth/password/reset/request";
1262
- /** POST /api/auth/password/reset/confirm body: { resetToken, newPassword } */
1263
1400
  readonly passwordResetConfirm: "/api/auth/password/reset/confirm";
1264
- /** POST /api/auth/email/verify/request body: { userId } */
1265
1401
  readonly emailVerifyRequest: "/api/auth/email/verify/request";
1266
- /** POST /api/auth/email/verify/confirm body: { verifyToken } */
1267
1402
  readonly emailVerifyConfirm: "/api/auth/email/verify/confirm";
1268
- /** POST /api/auth/account/lock body: { sessionId, userId, duration? } */
1269
- readonly accountLock: "/api/auth/account/lock";
1270
- /** POST /api/auth/account/unlock body: { sessionId, userId } */
1271
- readonly accountUnlock: "/api/auth/account/unlock";
1272
1403
  };
1273
1404
  declare const STORAGE: {
1274
- /** GET /storage/info — no auth required */
1275
- readonly info: "/storage/info";
1276
- /** GET /storage/public/:fullScopedPath — no auth required */
1277
- readonly publicFile: (fullScopedPath: string) => string;
1278
- /** POST /storage/upload-url body: { path, mimeType, size, isPublic?, overwrite?, expiresIn? } */
1279
- readonly uploadUrl: "/storage/upload-url";
1280
- /** POST /storage/batch-upload-urls body: { files: [...], expiresIn? } */
1281
- readonly batchUploadUrls: "/storage/batch-upload-urls";
1282
- /** POST /storage/confirm body: { path, mimeType, isPublic? } */
1283
- readonly confirm: "/storage/confirm";
1284
- /** POST /storage/batch-confirm body: { files: [...] } */
1285
- readonly batchConfirm: "/storage/batch-confirm";
1286
- /** POST /storage/upload multipart/form-data: file, path, mimeType, isPublic, overwrite */
1405
+ readonly base: "/storage";
1287
1406
  readonly upload: "/storage/upload";
1288
- /** POST /storage/upload-raw body: { path, content, mimeType?, isPublic?, overwrite? } */
1289
- readonly uploadRaw: "/storage/upload-raw";
1290
- /** GET /storage/list?prefix=&limit=&cursor= */
1407
+ readonly uploadRaw: "/storage/upload/raw";
1408
+ readonly uploadUrl: "/storage/upload/url";
1409
+ readonly confirm: "/storage/upload/confirm";
1410
+ readonly batchUploadUrls: "/storage/upload/batch/urls";
1411
+ readonly batchConfirm: "/storage/upload/batch/confirm";
1412
+ readonly download: (encodedPath: string) => string;
1413
+ readonly batchDownload: "/storage/download/batch";
1291
1414
  readonly list: "/storage/list";
1292
- /** GET /storage/download/:path — requires X-Storage-Key */
1293
- readonly download: (filePath: string) => string;
1294
- /** POST /storage/batch-download body: { paths: [...], concurrency? } */
1295
- readonly batchDownload: "/storage/batch-download";
1296
- /** GET /storage/metadata/:path */
1297
- readonly metadata: (filePath: string) => string;
1298
- /** POST /storage/signed-url body: { path, expiresIn? } */
1415
+ readonly metadata: (encodedPath: string) => string;
1299
1416
  readonly signedUrl: "/storage/signed-url";
1300
- /** PATCH /storage/visibility body: { path, isPublic } */
1301
1417
  readonly visibility: "/storage/visibility";
1302
- /** POST /storage/folder body: { path } */
1303
1418
  readonly folder: "/storage/folder";
1304
- /** DELETE /storage/file body: { path } */
1305
1419
  readonly file: "/storage/file";
1306
- /** DELETE /storage/folder body: { path } */
1307
- readonly folderDelete: "/storage/folder";
1308
- /** POST /storage/move body: { from, to } */
1420
+ readonly folderDelete: "/storage/folder/delete";
1309
1421
  readonly move: "/storage/move";
1310
- /** POST /storage/copy body: { from, to } */
1311
1422
  readonly copy: "/storage/copy";
1312
- /** GET /storage/stats */
1313
1423
  readonly stats: "/storage/stats";
1424
+ readonly info: "/storage/info";
1314
1425
  };
1315
1426
 
1316
1427
  declare class HydrousError extends Error {
@@ -1341,4 +1452,4 @@ declare class NetworkError extends HydrousError {
1341
1452
  constructor(message: string, cause?: unknown);
1342
1453
  }
1343
1454
 
1344
- export { ANALYTICS, AUTH, type Aggregation, AnalyticsClient, AnalyticsError, type AnalyticsFilter, type AnalyticsQuery, type AnalyticsResult, AuthClient, AuthError, type AuthResult, type BatchCreateOptions, type BatchDownloadResult, type BatchUploadItem, type BatchUploadUrlResult, type ChangePasswordOptions, type CountResult, type CreateRecordOptions, type CrossBucketRow, DEFAULT_BASE_URL, type DateRange, type DistributionRow, type FieldStats, type FieldTimeSeriesRow, type FileEntry, type FileMetadata, type Granularity, HttpClient, HydrousClient, type HydrousConfig, HydrousError, type ListOptions, type ListResult, type ListUsersOptions, type ListUsersResult, type LoginOptions, type MetricDefinition, type MultiMetricResult, NetworkError, type PatchRecordOptions, type QueryFilter, type QueryOptions, type QueryResult, type QueryType, RECORDS, type RecordData, RecordError, type RecordHistoryEntry, type RecordResult, RecordsClient, STORAGE, ScopedStorage, type Session, type SignedUrlResult, type SignupOptions, type SortOrder, StorageError, type StorageKeys, StorageManager, type StorageStats, type StorageStatsResult, type SumRow, type TimeSeriesRow, type TopNRow, type UpdateUserOptions, type UploadOptions, type UploadResult, type UploadUrlResult, type UserRecord, ValidationError, createClient };
1455
+ export { ANALYTICS, AUTH, type Aggregation, AnalyticsClient, AnalyticsError, type AnalyticsFilter, type AnalyticsQuery, type AnalyticsResult, AuthClient, AuthError, type AuthResult, type BatchCreateOptions, type BatchDownloadResult, type BatchUploadItem, type BatchUploadUrlResult, type ChangePasswordOptions, type CountResult, type CreateRecordOptions, type CrossBucketRow, DEFAULT_BASE_URL, type DateRange, type DistributionRow, type FieldStats, type FieldTimeSeriesRow, type FileEntry, type FileMetadata, type GoogleLinkOptions, type GoogleSignInOptions, type Granularity, HttpClient, HydrousClient, type HydrousConfig, HydrousError, type ListOptions, type ListResult, type ListUsersOptions, type ListUsersResult, type LoginOptions, type MetricDefinition, type MultiMetricResult, NetworkError, type PatchRecordOptions, type QueryFilter, type QueryOptions, type QueryResult, type QueryType, RECORDS, type RecordData, RecordError, type RecordHistoryEntry, type RecordResult, RecordsClient, STORAGE, ScopedStorage, type Session, type SignedUrlResult, type SignupOptions, type SortOrder, StorageError, type StorageKeys, StorageManager, type StorageStats, type StorageStatsResult, type SumRow, type TimeSeriesRow, type TopNRow, type UpdateUserOptions, type UploadOptions, type UploadResult, type UploadUrlResult, type UserRecord, ValidationError, createClient };