@spacelr/sdk 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -1
- package/dist/index.d.mts +236 -1
- package/dist/index.d.ts +236 -1
- package/dist/index.js +247 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +239 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,9 +42,41 @@ spacelr.db.subscribe('my-collection', {
|
|
|
42
42
|
| --- | --- |
|
|
43
43
|
| `auth` | Login, registration, OAuth2 PKCE flow, token management, 2FA |
|
|
44
44
|
| `storage` | File upload (including multipart), download, sharing, quota |
|
|
45
|
-
| `db` | Database operations with realtime subscriptions via WebSocket |
|
|
45
|
+
| `db` | Database operations with realtime subscriptions via WebSocket; `db.timeline` for cold-tier history reads |
|
|
46
46
|
| `notifications` | Web Push notification subscription management |
|
|
47
47
|
|
|
48
|
+
## Cold-tier history (`db.timeline`)
|
|
49
|
+
|
|
50
|
+
Collections can enable **cold-tier** archival: aged documents are moved to
|
|
51
|
+
object storage and purged from the live (hot) MongoDB tier. The normal query
|
|
52
|
+
methods (`find`, `findById`, `count`, `search`, `paginate`) operate on the **hot
|
|
53
|
+
tier only** — archived documents will not appear in their results.
|
|
54
|
+
|
|
55
|
+
To read archived history, use the timeline API, which transparently merges hot
|
|
56
|
+
and cold data for a partition (e.g. a chat room) and paginates with an opaque
|
|
57
|
+
cursor:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
const page = await spacelr.db.timeline.query({
|
|
61
|
+
collection: 'chat_messages',
|
|
62
|
+
partitionValue: 'room-123', // the cold-tier partition (e.g. room id)
|
|
63
|
+
where: { authorId: { $eq: 'user-1' } }, // optional, allow-listed operators only
|
|
64
|
+
orderBy: { field: 'createdAt', direction: 'desc' },
|
|
65
|
+
limit: 50, // 1–200, default 50
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
page.items; // merged hot + cold documents
|
|
69
|
+
page.nextCursor; // pass back as `cursor` for the next page (null = end)
|
|
70
|
+
page.sourceStats; // { hot, cold, segmentsScanned? } — where the rows came from
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Notes:
|
|
74
|
+
- Timeline paginates by partition + timestamp, not arbitrary Mongo queries;
|
|
75
|
+
`where` accepts only the allow-listed operators (`$eq`, `$ne`, `$lt`, `$lte`,
|
|
76
|
+
`$gt`, `$gte`, `$in`, `$nin`, `$and`).
|
|
77
|
+
- Enabling/configuring cold-tier on a collection is an **admin** operation and
|
|
78
|
+
is not part of this client SDK.
|
|
79
|
+
|
|
48
80
|
## Requirements
|
|
49
81
|
|
|
50
82
|
- Node.js >= 18
|
package/dist/index.d.mts
CHANGED
|
@@ -738,6 +738,98 @@ declare class StorageModule {
|
|
|
738
738
|
getPublicFileUrl(fileId: string, projectId?: string): Promise<string>;
|
|
739
739
|
}
|
|
740
740
|
|
|
741
|
+
/**
|
|
742
|
+
* Scalar values permitted inside a timeline filter. Matches the server
|
|
743
|
+
* filter allow-list (libs/shared-dtos/.../timeline-filter.dto.ts).
|
|
744
|
+
*/
|
|
745
|
+
type TimelineScalar = string | number | boolean | null;
|
|
746
|
+
/**
|
|
747
|
+
* Single-field filter expression. Either implicit equality (a scalar) or
|
|
748
|
+
* an explicit operator object. Mongo-style allow-list — the server rejects
|
|
749
|
+
* anything outside this set.
|
|
750
|
+
*/
|
|
751
|
+
type TimelineLeafFilter = TimelineScalar | {
|
|
752
|
+
$eq?: TimelineScalar;
|
|
753
|
+
$ne?: TimelineScalar;
|
|
754
|
+
$lt?: TimelineScalar;
|
|
755
|
+
$lte?: TimelineScalar;
|
|
756
|
+
$gt?: TimelineScalar;
|
|
757
|
+
$gte?: TimelineScalar;
|
|
758
|
+
$in?: TimelineScalar[];
|
|
759
|
+
$nin?: TimelineScalar[];
|
|
760
|
+
};
|
|
761
|
+
/**
|
|
762
|
+
* Filter document for a timeline query. Top-level fields apply implicit
|
|
763
|
+
* equality (or operator expression). $and supports nested filter
|
|
764
|
+
* composition; $or / $regex / etc. are intentionally NOT exposed and
|
|
765
|
+
* will be rejected server-side.
|
|
766
|
+
*
|
|
767
|
+
* Two named branches in the union so TypeScript doesn't treat `$and` as
|
|
768
|
+
* just another key under the field index signature — the array shape
|
|
769
|
+
* needs its own type or downstream usage breaks.
|
|
770
|
+
*/
|
|
771
|
+
interface TimelineAndFilter {
|
|
772
|
+
$and: TimelineFilter[];
|
|
773
|
+
}
|
|
774
|
+
type TimelineFieldFilter = Record<string, TimelineLeafFilter>;
|
|
775
|
+
type TimelineFilter = TimelineAndFilter | TimelineFieldFilter;
|
|
776
|
+
interface TimelineOrderBy {
|
|
777
|
+
field: string;
|
|
778
|
+
direction: 'asc' | 'desc';
|
|
779
|
+
}
|
|
780
|
+
interface TimelineQueryOptions {
|
|
781
|
+
/** Collection name to read from. */
|
|
782
|
+
collection: string;
|
|
783
|
+
/** Partition value (e.g. roomId, documentId — collection-configured). */
|
|
784
|
+
partitionValue: string;
|
|
785
|
+
/** Optional filter constraints (allow-listed operators only). */
|
|
786
|
+
where?: TimelineFilter;
|
|
787
|
+
/**
|
|
788
|
+
* Sort order. Defaults to DESC by the collection's configured timeline
|
|
789
|
+
* field; PR A only supports DESC. Passing direction='asc' is reserved
|
|
790
|
+
* for a future phase and currently returns BAD_REQUEST.
|
|
791
|
+
*/
|
|
792
|
+
orderBy?: TimelineOrderBy;
|
|
793
|
+
/** Page size (1..200). Default 50. */
|
|
794
|
+
limit?: number;
|
|
795
|
+
/**
|
|
796
|
+
* Opaque cursor from a previous response. The SDK does NOT decode this —
|
|
797
|
+
* pass the value of `nextCursor` from the last response verbatim.
|
|
798
|
+
*/
|
|
799
|
+
cursor?: string;
|
|
800
|
+
}
|
|
801
|
+
interface TimelineSourceStats {
|
|
802
|
+
hot: number;
|
|
803
|
+
cold: number;
|
|
804
|
+
/** Number of cold archive segments scanned (only present when cold path ran). */
|
|
805
|
+
segmentsScanned?: number;
|
|
806
|
+
}
|
|
807
|
+
interface TimelineQueryResponse {
|
|
808
|
+
items: Record<string, unknown>[];
|
|
809
|
+
/** Opaque continuation token. `null` when the page is the last one. */
|
|
810
|
+
nextCursor: string | null;
|
|
811
|
+
sourceStats: TimelineSourceStats;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Low-level timeline SDK module. One method: query(opts) → page.
|
|
816
|
+
*
|
|
817
|
+
* The cursor is opaque from the SDK's perspective — it's stored as a
|
|
818
|
+
* string, never decoded, never inspected. Callers pass the value of
|
|
819
|
+
* `nextCursor` from the previous response verbatim into the next request.
|
|
820
|
+
*
|
|
821
|
+
* Errors thrown from query() extend SpacelrError so they integrate with
|
|
822
|
+
* the SDK's existing error hierarchy. Use one of the typed subclasses
|
|
823
|
+
* (CursorInvalidError, ForbiddenError, etc.) to catch specific cases or
|
|
824
|
+
* `catch (e instanceof TimelineError)` for any timeline-related failure.
|
|
825
|
+
*/
|
|
826
|
+
declare class TimelineModule {
|
|
827
|
+
private readonly http;
|
|
828
|
+
constructor(http: HttpClient);
|
|
829
|
+
query(opts: TimelineQueryOptions): Promise<TimelineQueryResponse>;
|
|
830
|
+
private translateError;
|
|
831
|
+
}
|
|
832
|
+
|
|
741
833
|
interface PopulateOption {
|
|
742
834
|
field: string;
|
|
743
835
|
collection: string;
|
|
@@ -1106,6 +1198,16 @@ declare class CollectionRef<T = Record<string, unknown>> {
|
|
|
1106
1198
|
insertMany(documents: (Partial<T> & {
|
|
1107
1199
|
_id?: string;
|
|
1108
1200
|
})[]): Promise<InsertResult>;
|
|
1201
|
+
/**
|
|
1202
|
+
* Query the collection's **hot tier** (live MongoDB).
|
|
1203
|
+
*
|
|
1204
|
+
* **Cold-tier note:** if the collection has cold-tier archival enabled, aged
|
|
1205
|
+
* documents are moved to object storage and purged from the hot tier — they
|
|
1206
|
+
* will NOT appear in `find()` results (nor `findById`, `count`, `search`,
|
|
1207
|
+
* `paginate`, which are all hot-tier only). To read archived history, use
|
|
1208
|
+
* {@link TimelineModule.query} via `db.timeline.query(...)`, which transparently
|
|
1209
|
+
* merges hot and cold results for a partition.
|
|
1210
|
+
*/
|
|
1109
1211
|
find(filter?: Record<string, unknown>): QueryBuilder<T>;
|
|
1110
1212
|
/**
|
|
1111
1213
|
* Cursor-based scroll-back helper. Returns a `Paginator` whose `.next()`
|
|
@@ -1136,13 +1238,30 @@ declare class CollectionRef<T = Record<string, unknown>> {
|
|
|
1136
1238
|
*
|
|
1137
1239
|
* Limits: `query` 1–200 chars, `fields` 1–10 entries (each matching
|
|
1138
1240
|
* `/^[a-zA-Z0-9_.]+$/`, max 64 chars), `limit` max 100.
|
|
1241
|
+
*
|
|
1242
|
+
* **Cold-tier note:** searches the hot tier only; archived documents are not
|
|
1243
|
+
* included. See {@link CollectionRef.find} and `db.timeline.query(...)`.
|
|
1139
1244
|
*/
|
|
1140
1245
|
search(opts: SearchOptions): Promise<SearchResult<T>>;
|
|
1246
|
+
/**
|
|
1247
|
+
* Fetch a single document by `_id` from the **hot tier**.
|
|
1248
|
+
*
|
|
1249
|
+
* **Cold-tier note:** returns null/throws for documents that have been
|
|
1250
|
+
* archived and purged from the hot tier. Archived history is reachable only
|
|
1251
|
+
* via `db.timeline.query(...)`. See {@link CollectionRef.find}.
|
|
1252
|
+
*/
|
|
1141
1253
|
findById(id: string, options?: FindByIdOptions): Promise<T & {
|
|
1142
1254
|
_id: string;
|
|
1143
1255
|
}>;
|
|
1144
1256
|
update(id: string, update: Partial<T>): Promise<UpdateResult>;
|
|
1145
1257
|
delete(id: string): Promise<DeleteResult>;
|
|
1258
|
+
/**
|
|
1259
|
+
* Count documents in the **hot tier** matching `filter`.
|
|
1260
|
+
*
|
|
1261
|
+
* **Cold-tier note:** counts hot-tier documents only — archived/purged
|
|
1262
|
+
* documents are not included, so this is not a total-history count. See
|
|
1263
|
+
* {@link CollectionRef.find} and `db.timeline.query(...)`.
|
|
1264
|
+
*/
|
|
1146
1265
|
count(filter?: Record<string, unknown>): Promise<number>;
|
|
1147
1266
|
subscribe(handlers: SubscribeHandlers<T>): () => void;
|
|
1148
1267
|
subscribeEvents(handlers: SubscribeEventsHandlers<T>): StreamSubscription;
|
|
@@ -1161,6 +1280,7 @@ declare class DatabaseModule {
|
|
|
1161
1280
|
private http;
|
|
1162
1281
|
private realtime;
|
|
1163
1282
|
private projectId;
|
|
1283
|
+
readonly timeline: TimelineModule;
|
|
1164
1284
|
constructor(http: HttpClient, projectId: string, realtime?: RealtimeClient);
|
|
1165
1285
|
collection<T = Record<string, unknown>>(name: string): CollectionRef<T>;
|
|
1166
1286
|
}
|
|
@@ -1269,12 +1389,127 @@ declare class FunctionsModule {
|
|
|
1269
1389
|
invoke(projectId: string, functionId: string, options?: FunctionInvokeOptions): Promise<FunctionInvokeResult>;
|
|
1270
1390
|
}
|
|
1271
1391
|
|
|
1392
|
+
type ScheduleStatus = 'scheduled' | 'fired' | 'failed' | 'cancelled';
|
|
1393
|
+
interface Schedule {
|
|
1394
|
+
id: string;
|
|
1395
|
+
projectId: string;
|
|
1396
|
+
functionId: string;
|
|
1397
|
+
payload: Record<string, unknown>;
|
|
1398
|
+
executeAt: string;
|
|
1399
|
+
idempotencyKey: string | null;
|
|
1400
|
+
status: ScheduleStatus;
|
|
1401
|
+
bullJobId: string | null;
|
|
1402
|
+
firedAt: string | null;
|
|
1403
|
+
executionId: string | null;
|
|
1404
|
+
attemptNumber: number;
|
|
1405
|
+
maxAttempts: number;
|
|
1406
|
+
lastError: string | null;
|
|
1407
|
+
createdAt: string;
|
|
1408
|
+
updatedAt: string;
|
|
1409
|
+
}
|
|
1410
|
+
interface ScheduleInvokeOptions {
|
|
1411
|
+
/** 24-char hex function id to invoke when the schedule fires. */
|
|
1412
|
+
functionId: string;
|
|
1413
|
+
/** Arbitrary JSON payload surfaced to the function as `event.payload`. */
|
|
1414
|
+
payload?: Record<string, unknown>;
|
|
1415
|
+
/**
|
|
1416
|
+
* When to fire. Accepts a `Date`, an ISO-8601 string, or epoch ms.
|
|
1417
|
+
* Server-side applies a 5-second past-skew tolerance and rejects anything
|
|
1418
|
+
* beyond `SCHEDULE_MAX_DELAY_DAYS` (default 90 days).
|
|
1419
|
+
*/
|
|
1420
|
+
executeAt: Date | string | number;
|
|
1421
|
+
/**
|
|
1422
|
+
* Dedup key. Repeating the call with the same key in the same project for
|
|
1423
|
+
* the same function returns the existing schedule unchanged.
|
|
1424
|
+
*/
|
|
1425
|
+
idempotencyKey?: string;
|
|
1426
|
+
/**
|
|
1427
|
+
* Maximum retry attempts after a failed execution (0–10, default 3).
|
|
1428
|
+
* Counts only retries — the initial fire is always attempted.
|
|
1429
|
+
*/
|
|
1430
|
+
maxAttempts?: number;
|
|
1431
|
+
}
|
|
1432
|
+
interface ScheduleListOptions {
|
|
1433
|
+
functionId?: string;
|
|
1434
|
+
status?: ScheduleStatus;
|
|
1435
|
+
limit?: number;
|
|
1436
|
+
offset?: number;
|
|
1437
|
+
}
|
|
1438
|
+
declare class ScheduleModule {
|
|
1439
|
+
private readonly http;
|
|
1440
|
+
private readonly projectId;
|
|
1441
|
+
constructor(http: HttpClient, projectId: string);
|
|
1442
|
+
/**
|
|
1443
|
+
* Schedule a one-shot function invocation. Returns the existing handle
|
|
1444
|
+
* unchanged if `idempotencyKey` matches a prior invoke in this project
|
|
1445
|
+
* for this function.
|
|
1446
|
+
*/
|
|
1447
|
+
invoke(options: ScheduleInvokeOptions): Promise<Schedule>;
|
|
1448
|
+
get(scheduleId: string): Promise<Schedule>;
|
|
1449
|
+
list(options?: ScheduleListOptions): Promise<{
|
|
1450
|
+
items: Schedule[];
|
|
1451
|
+
total: number;
|
|
1452
|
+
}>;
|
|
1453
|
+
cancel(scheduleId: string): Promise<Schedule>;
|
|
1454
|
+
private toIsoString;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
/**
|
|
1458
|
+
* Base class for all timeline-related errors thrown by the SDK. Extends
|
|
1459
|
+
* SpacelrError so it fits the SDK's existing `catch (e instanceof
|
|
1460
|
+
* SpacelrError)` pattern. Subclasses give callers fine-grained control
|
|
1461
|
+
* (e.g. catch only `CursorInvalidError` and restart pagination).
|
|
1462
|
+
*/
|
|
1463
|
+
declare class TimelineError extends SpacelrError {
|
|
1464
|
+
constructor(message: string, opts?: {
|
|
1465
|
+
statusCode?: number;
|
|
1466
|
+
code?: string;
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
declare class CursorInvalidError extends TimelineError {
|
|
1470
|
+
constructor(message: string, opts?: {
|
|
1471
|
+
statusCode?: number;
|
|
1472
|
+
code?: string;
|
|
1473
|
+
});
|
|
1474
|
+
}
|
|
1475
|
+
declare class ValidationError extends TimelineError {
|
|
1476
|
+
constructor(message: string, opts?: {
|
|
1477
|
+
statusCode?: number;
|
|
1478
|
+
code?: string;
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
declare class ForbiddenError extends TimelineError {
|
|
1482
|
+
constructor(message: string, opts?: {
|
|
1483
|
+
statusCode?: number;
|
|
1484
|
+
code?: string;
|
|
1485
|
+
});
|
|
1486
|
+
}
|
|
1487
|
+
declare class NotFoundError extends TimelineError {
|
|
1488
|
+
constructor(message: string, opts?: {
|
|
1489
|
+
statusCode?: number;
|
|
1490
|
+
code?: string;
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
declare class ServerConfigError extends TimelineError {
|
|
1494
|
+
constructor(message: string, opts?: {
|
|
1495
|
+
statusCode?: number;
|
|
1496
|
+
code?: string;
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
declare class TimeoutError extends TimelineError {
|
|
1500
|
+
constructor(message: string, opts?: {
|
|
1501
|
+
statusCode?: number;
|
|
1502
|
+
code?: string;
|
|
1503
|
+
});
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1272
1506
|
interface SpacelrClient {
|
|
1273
1507
|
readonly auth: AuthModule;
|
|
1274
1508
|
readonly storage: StorageModule;
|
|
1275
1509
|
readonly db: DatabaseModule;
|
|
1276
1510
|
readonly notifications: NotificationsModule;
|
|
1277
1511
|
readonly functions: FunctionsModule;
|
|
1512
|
+
readonly schedule: ScheduleModule;
|
|
1278
1513
|
/**
|
|
1279
1514
|
* Store auth tokens externally (e.g. obtained via the auth-components
|
|
1280
1515
|
* library that bypasses the SDK). Makes the tokens available to HTTP +
|
|
@@ -1326,4 +1561,4 @@ interface SpacelrClient {
|
|
|
1326
1561
|
}
|
|
1327
1562
|
declare function createClient(config: SpacelrClientConfig): SpacelrClient;
|
|
1328
1563
|
|
|
1329
|
-
export { type ApiResponse, type AuthLostReason, type AuthState, type AuthStateListener, type AuthorizationUrlParams, BrowserTokenStorage, CodeChallengeMethod, type ConnectionState, type CursorStorage, type DatabaseChangeEvent, type DownloadUrlResponse, type ExchangeCodeParams, type FileInfo, type FileListResponse, FileVisibility, type FunctionInvokeOptions, type FunctionInvokeResult, type GapReason, GrantType, type InitMultipartUploadParams, type InitMultipartUploadResponse, type JWK, type JWKSResponse, type ListFilesParams, type LoginParams, type LoginResponse, MemoryTokenStorage, type OpenIDConfiguration, type PKCEChallenge, type PartEtag, type PushSubscriptionInfo, type QuotaInfo, type RegisterParams, type RegisterResponse, type SearchOptions, type ShareFileParams, SharePermission, SpacelrAuthError, type SpacelrClient, type SpacelrClientConfig, SpacelrEmailVerificationRequiredError, SpacelrError, SpacelrNetworkError, SpacelrSearchFilterRequiredError, SpacelrTimeoutError, SpacelrTwoFactorRequiredError, type StoredTokens, type StreamGapInfo, type StreamSubscription, type SubscribeEventsHandlers, type SubscribeHandlers, type SubscribeWithSnapshotOptions, type TokenResponse, type TokenStorage, type TwoFactorResponse, type TwoFactorVerifyParams, type UnshareFileParams, type UploadFileParams, type UploadLargeFileParams, type UploadProgress, type UserInfo, type UserProfile, type VapidKeyResponse, createClient, generatePKCEChallenge, localStorageCursorStorage, memoryCursorStorage };
|
|
1564
|
+
export { type ApiResponse, type AuthLostReason, type AuthState, type AuthStateListener, type AuthorizationUrlParams, BrowserTokenStorage, CodeChallengeMethod, type ConnectionState, CursorInvalidError, type CursorStorage, type DatabaseChangeEvent, type DownloadUrlResponse, type ExchangeCodeParams, type FileInfo, type FileListResponse, FileVisibility, ForbiddenError, type FunctionInvokeOptions, type FunctionInvokeResult, type GapReason, GrantType, type InitMultipartUploadParams, type InitMultipartUploadResponse, type JWK, type JWKSResponse, type ListFilesParams, type LoginParams, type LoginResponse, MemoryTokenStorage, NotFoundError, type OpenIDConfiguration, type PKCEChallenge, type PartEtag, type PushSubscriptionInfo, type QuotaInfo, type RegisterParams, type RegisterResponse, type Schedule, type ScheduleInvokeOptions, type ScheduleListOptions, type ScheduleStatus, type SearchOptions, ServerConfigError, type ShareFileParams, SharePermission, SpacelrAuthError, type SpacelrClient, type SpacelrClientConfig, SpacelrEmailVerificationRequiredError, SpacelrError, SpacelrNetworkError, SpacelrSearchFilterRequiredError, SpacelrTimeoutError, SpacelrTwoFactorRequiredError, type StoredTokens, type StreamGapInfo, type StreamSubscription, type SubscribeEventsHandlers, type SubscribeHandlers, type SubscribeWithSnapshotOptions, type TimelineAndFilter, TimelineError, type TimelineFieldFilter, type TimelineFilter, type TimelineLeafFilter, TimelineModule, type TimelineOrderBy, type TimelineQueryOptions, type TimelineQueryResponse, type TimelineScalar, type TimelineSourceStats, TimeoutError, type TokenResponse, type TokenStorage, type TwoFactorResponse, type TwoFactorVerifyParams, type UnshareFileParams, type UploadFileParams, type UploadLargeFileParams, type UploadProgress, type UserInfo, type UserProfile, ValidationError, type VapidKeyResponse, createClient, generatePKCEChallenge, localStorageCursorStorage, memoryCursorStorage };
|
package/dist/index.d.ts
CHANGED
|
@@ -738,6 +738,98 @@ declare class StorageModule {
|
|
|
738
738
|
getPublicFileUrl(fileId: string, projectId?: string): Promise<string>;
|
|
739
739
|
}
|
|
740
740
|
|
|
741
|
+
/**
|
|
742
|
+
* Scalar values permitted inside a timeline filter. Matches the server
|
|
743
|
+
* filter allow-list (libs/shared-dtos/.../timeline-filter.dto.ts).
|
|
744
|
+
*/
|
|
745
|
+
type TimelineScalar = string | number | boolean | null;
|
|
746
|
+
/**
|
|
747
|
+
* Single-field filter expression. Either implicit equality (a scalar) or
|
|
748
|
+
* an explicit operator object. Mongo-style allow-list — the server rejects
|
|
749
|
+
* anything outside this set.
|
|
750
|
+
*/
|
|
751
|
+
type TimelineLeafFilter = TimelineScalar | {
|
|
752
|
+
$eq?: TimelineScalar;
|
|
753
|
+
$ne?: TimelineScalar;
|
|
754
|
+
$lt?: TimelineScalar;
|
|
755
|
+
$lte?: TimelineScalar;
|
|
756
|
+
$gt?: TimelineScalar;
|
|
757
|
+
$gte?: TimelineScalar;
|
|
758
|
+
$in?: TimelineScalar[];
|
|
759
|
+
$nin?: TimelineScalar[];
|
|
760
|
+
};
|
|
761
|
+
/**
|
|
762
|
+
* Filter document for a timeline query. Top-level fields apply implicit
|
|
763
|
+
* equality (or operator expression). $and supports nested filter
|
|
764
|
+
* composition; $or / $regex / etc. are intentionally NOT exposed and
|
|
765
|
+
* will be rejected server-side.
|
|
766
|
+
*
|
|
767
|
+
* Two named branches in the union so TypeScript doesn't treat `$and` as
|
|
768
|
+
* just another key under the field index signature — the array shape
|
|
769
|
+
* needs its own type or downstream usage breaks.
|
|
770
|
+
*/
|
|
771
|
+
interface TimelineAndFilter {
|
|
772
|
+
$and: TimelineFilter[];
|
|
773
|
+
}
|
|
774
|
+
type TimelineFieldFilter = Record<string, TimelineLeafFilter>;
|
|
775
|
+
type TimelineFilter = TimelineAndFilter | TimelineFieldFilter;
|
|
776
|
+
interface TimelineOrderBy {
|
|
777
|
+
field: string;
|
|
778
|
+
direction: 'asc' | 'desc';
|
|
779
|
+
}
|
|
780
|
+
interface TimelineQueryOptions {
|
|
781
|
+
/** Collection name to read from. */
|
|
782
|
+
collection: string;
|
|
783
|
+
/** Partition value (e.g. roomId, documentId — collection-configured). */
|
|
784
|
+
partitionValue: string;
|
|
785
|
+
/** Optional filter constraints (allow-listed operators only). */
|
|
786
|
+
where?: TimelineFilter;
|
|
787
|
+
/**
|
|
788
|
+
* Sort order. Defaults to DESC by the collection's configured timeline
|
|
789
|
+
* field; PR A only supports DESC. Passing direction='asc' is reserved
|
|
790
|
+
* for a future phase and currently returns BAD_REQUEST.
|
|
791
|
+
*/
|
|
792
|
+
orderBy?: TimelineOrderBy;
|
|
793
|
+
/** Page size (1..200). Default 50. */
|
|
794
|
+
limit?: number;
|
|
795
|
+
/**
|
|
796
|
+
* Opaque cursor from a previous response. The SDK does NOT decode this —
|
|
797
|
+
* pass the value of `nextCursor` from the last response verbatim.
|
|
798
|
+
*/
|
|
799
|
+
cursor?: string;
|
|
800
|
+
}
|
|
801
|
+
interface TimelineSourceStats {
|
|
802
|
+
hot: number;
|
|
803
|
+
cold: number;
|
|
804
|
+
/** Number of cold archive segments scanned (only present when cold path ran). */
|
|
805
|
+
segmentsScanned?: number;
|
|
806
|
+
}
|
|
807
|
+
interface TimelineQueryResponse {
|
|
808
|
+
items: Record<string, unknown>[];
|
|
809
|
+
/** Opaque continuation token. `null` when the page is the last one. */
|
|
810
|
+
nextCursor: string | null;
|
|
811
|
+
sourceStats: TimelineSourceStats;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Low-level timeline SDK module. One method: query(opts) → page.
|
|
816
|
+
*
|
|
817
|
+
* The cursor is opaque from the SDK's perspective — it's stored as a
|
|
818
|
+
* string, never decoded, never inspected. Callers pass the value of
|
|
819
|
+
* `nextCursor` from the previous response verbatim into the next request.
|
|
820
|
+
*
|
|
821
|
+
* Errors thrown from query() extend SpacelrError so they integrate with
|
|
822
|
+
* the SDK's existing error hierarchy. Use one of the typed subclasses
|
|
823
|
+
* (CursorInvalidError, ForbiddenError, etc.) to catch specific cases or
|
|
824
|
+
* `catch (e instanceof TimelineError)` for any timeline-related failure.
|
|
825
|
+
*/
|
|
826
|
+
declare class TimelineModule {
|
|
827
|
+
private readonly http;
|
|
828
|
+
constructor(http: HttpClient);
|
|
829
|
+
query(opts: TimelineQueryOptions): Promise<TimelineQueryResponse>;
|
|
830
|
+
private translateError;
|
|
831
|
+
}
|
|
832
|
+
|
|
741
833
|
interface PopulateOption {
|
|
742
834
|
field: string;
|
|
743
835
|
collection: string;
|
|
@@ -1106,6 +1198,16 @@ declare class CollectionRef<T = Record<string, unknown>> {
|
|
|
1106
1198
|
insertMany(documents: (Partial<T> & {
|
|
1107
1199
|
_id?: string;
|
|
1108
1200
|
})[]): Promise<InsertResult>;
|
|
1201
|
+
/**
|
|
1202
|
+
* Query the collection's **hot tier** (live MongoDB).
|
|
1203
|
+
*
|
|
1204
|
+
* **Cold-tier note:** if the collection has cold-tier archival enabled, aged
|
|
1205
|
+
* documents are moved to object storage and purged from the hot tier — they
|
|
1206
|
+
* will NOT appear in `find()` results (nor `findById`, `count`, `search`,
|
|
1207
|
+
* `paginate`, which are all hot-tier only). To read archived history, use
|
|
1208
|
+
* {@link TimelineModule.query} via `db.timeline.query(...)`, which transparently
|
|
1209
|
+
* merges hot and cold results for a partition.
|
|
1210
|
+
*/
|
|
1109
1211
|
find(filter?: Record<string, unknown>): QueryBuilder<T>;
|
|
1110
1212
|
/**
|
|
1111
1213
|
* Cursor-based scroll-back helper. Returns a `Paginator` whose `.next()`
|
|
@@ -1136,13 +1238,30 @@ declare class CollectionRef<T = Record<string, unknown>> {
|
|
|
1136
1238
|
*
|
|
1137
1239
|
* Limits: `query` 1–200 chars, `fields` 1–10 entries (each matching
|
|
1138
1240
|
* `/^[a-zA-Z0-9_.]+$/`, max 64 chars), `limit` max 100.
|
|
1241
|
+
*
|
|
1242
|
+
* **Cold-tier note:** searches the hot tier only; archived documents are not
|
|
1243
|
+
* included. See {@link CollectionRef.find} and `db.timeline.query(...)`.
|
|
1139
1244
|
*/
|
|
1140
1245
|
search(opts: SearchOptions): Promise<SearchResult<T>>;
|
|
1246
|
+
/**
|
|
1247
|
+
* Fetch a single document by `_id` from the **hot tier**.
|
|
1248
|
+
*
|
|
1249
|
+
* **Cold-tier note:** returns null/throws for documents that have been
|
|
1250
|
+
* archived and purged from the hot tier. Archived history is reachable only
|
|
1251
|
+
* via `db.timeline.query(...)`. See {@link CollectionRef.find}.
|
|
1252
|
+
*/
|
|
1141
1253
|
findById(id: string, options?: FindByIdOptions): Promise<T & {
|
|
1142
1254
|
_id: string;
|
|
1143
1255
|
}>;
|
|
1144
1256
|
update(id: string, update: Partial<T>): Promise<UpdateResult>;
|
|
1145
1257
|
delete(id: string): Promise<DeleteResult>;
|
|
1258
|
+
/**
|
|
1259
|
+
* Count documents in the **hot tier** matching `filter`.
|
|
1260
|
+
*
|
|
1261
|
+
* **Cold-tier note:** counts hot-tier documents only — archived/purged
|
|
1262
|
+
* documents are not included, so this is not a total-history count. See
|
|
1263
|
+
* {@link CollectionRef.find} and `db.timeline.query(...)`.
|
|
1264
|
+
*/
|
|
1146
1265
|
count(filter?: Record<string, unknown>): Promise<number>;
|
|
1147
1266
|
subscribe(handlers: SubscribeHandlers<T>): () => void;
|
|
1148
1267
|
subscribeEvents(handlers: SubscribeEventsHandlers<T>): StreamSubscription;
|
|
@@ -1161,6 +1280,7 @@ declare class DatabaseModule {
|
|
|
1161
1280
|
private http;
|
|
1162
1281
|
private realtime;
|
|
1163
1282
|
private projectId;
|
|
1283
|
+
readonly timeline: TimelineModule;
|
|
1164
1284
|
constructor(http: HttpClient, projectId: string, realtime?: RealtimeClient);
|
|
1165
1285
|
collection<T = Record<string, unknown>>(name: string): CollectionRef<T>;
|
|
1166
1286
|
}
|
|
@@ -1269,12 +1389,127 @@ declare class FunctionsModule {
|
|
|
1269
1389
|
invoke(projectId: string, functionId: string, options?: FunctionInvokeOptions): Promise<FunctionInvokeResult>;
|
|
1270
1390
|
}
|
|
1271
1391
|
|
|
1392
|
+
type ScheduleStatus = 'scheduled' | 'fired' | 'failed' | 'cancelled';
|
|
1393
|
+
interface Schedule {
|
|
1394
|
+
id: string;
|
|
1395
|
+
projectId: string;
|
|
1396
|
+
functionId: string;
|
|
1397
|
+
payload: Record<string, unknown>;
|
|
1398
|
+
executeAt: string;
|
|
1399
|
+
idempotencyKey: string | null;
|
|
1400
|
+
status: ScheduleStatus;
|
|
1401
|
+
bullJobId: string | null;
|
|
1402
|
+
firedAt: string | null;
|
|
1403
|
+
executionId: string | null;
|
|
1404
|
+
attemptNumber: number;
|
|
1405
|
+
maxAttempts: number;
|
|
1406
|
+
lastError: string | null;
|
|
1407
|
+
createdAt: string;
|
|
1408
|
+
updatedAt: string;
|
|
1409
|
+
}
|
|
1410
|
+
interface ScheduleInvokeOptions {
|
|
1411
|
+
/** 24-char hex function id to invoke when the schedule fires. */
|
|
1412
|
+
functionId: string;
|
|
1413
|
+
/** Arbitrary JSON payload surfaced to the function as `event.payload`. */
|
|
1414
|
+
payload?: Record<string, unknown>;
|
|
1415
|
+
/**
|
|
1416
|
+
* When to fire. Accepts a `Date`, an ISO-8601 string, or epoch ms.
|
|
1417
|
+
* Server-side applies a 5-second past-skew tolerance and rejects anything
|
|
1418
|
+
* beyond `SCHEDULE_MAX_DELAY_DAYS` (default 90 days).
|
|
1419
|
+
*/
|
|
1420
|
+
executeAt: Date | string | number;
|
|
1421
|
+
/**
|
|
1422
|
+
* Dedup key. Repeating the call with the same key in the same project for
|
|
1423
|
+
* the same function returns the existing schedule unchanged.
|
|
1424
|
+
*/
|
|
1425
|
+
idempotencyKey?: string;
|
|
1426
|
+
/**
|
|
1427
|
+
* Maximum retry attempts after a failed execution (0–10, default 3).
|
|
1428
|
+
* Counts only retries — the initial fire is always attempted.
|
|
1429
|
+
*/
|
|
1430
|
+
maxAttempts?: number;
|
|
1431
|
+
}
|
|
1432
|
+
interface ScheduleListOptions {
|
|
1433
|
+
functionId?: string;
|
|
1434
|
+
status?: ScheduleStatus;
|
|
1435
|
+
limit?: number;
|
|
1436
|
+
offset?: number;
|
|
1437
|
+
}
|
|
1438
|
+
declare class ScheduleModule {
|
|
1439
|
+
private readonly http;
|
|
1440
|
+
private readonly projectId;
|
|
1441
|
+
constructor(http: HttpClient, projectId: string);
|
|
1442
|
+
/**
|
|
1443
|
+
* Schedule a one-shot function invocation. Returns the existing handle
|
|
1444
|
+
* unchanged if `idempotencyKey` matches a prior invoke in this project
|
|
1445
|
+
* for this function.
|
|
1446
|
+
*/
|
|
1447
|
+
invoke(options: ScheduleInvokeOptions): Promise<Schedule>;
|
|
1448
|
+
get(scheduleId: string): Promise<Schedule>;
|
|
1449
|
+
list(options?: ScheduleListOptions): Promise<{
|
|
1450
|
+
items: Schedule[];
|
|
1451
|
+
total: number;
|
|
1452
|
+
}>;
|
|
1453
|
+
cancel(scheduleId: string): Promise<Schedule>;
|
|
1454
|
+
private toIsoString;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
/**
|
|
1458
|
+
* Base class for all timeline-related errors thrown by the SDK. Extends
|
|
1459
|
+
* SpacelrError so it fits the SDK's existing `catch (e instanceof
|
|
1460
|
+
* SpacelrError)` pattern. Subclasses give callers fine-grained control
|
|
1461
|
+
* (e.g. catch only `CursorInvalidError` and restart pagination).
|
|
1462
|
+
*/
|
|
1463
|
+
declare class TimelineError extends SpacelrError {
|
|
1464
|
+
constructor(message: string, opts?: {
|
|
1465
|
+
statusCode?: number;
|
|
1466
|
+
code?: string;
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
declare class CursorInvalidError extends TimelineError {
|
|
1470
|
+
constructor(message: string, opts?: {
|
|
1471
|
+
statusCode?: number;
|
|
1472
|
+
code?: string;
|
|
1473
|
+
});
|
|
1474
|
+
}
|
|
1475
|
+
declare class ValidationError extends TimelineError {
|
|
1476
|
+
constructor(message: string, opts?: {
|
|
1477
|
+
statusCode?: number;
|
|
1478
|
+
code?: string;
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
declare class ForbiddenError extends TimelineError {
|
|
1482
|
+
constructor(message: string, opts?: {
|
|
1483
|
+
statusCode?: number;
|
|
1484
|
+
code?: string;
|
|
1485
|
+
});
|
|
1486
|
+
}
|
|
1487
|
+
declare class NotFoundError extends TimelineError {
|
|
1488
|
+
constructor(message: string, opts?: {
|
|
1489
|
+
statusCode?: number;
|
|
1490
|
+
code?: string;
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
declare class ServerConfigError extends TimelineError {
|
|
1494
|
+
constructor(message: string, opts?: {
|
|
1495
|
+
statusCode?: number;
|
|
1496
|
+
code?: string;
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
declare class TimeoutError extends TimelineError {
|
|
1500
|
+
constructor(message: string, opts?: {
|
|
1501
|
+
statusCode?: number;
|
|
1502
|
+
code?: string;
|
|
1503
|
+
});
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1272
1506
|
interface SpacelrClient {
|
|
1273
1507
|
readonly auth: AuthModule;
|
|
1274
1508
|
readonly storage: StorageModule;
|
|
1275
1509
|
readonly db: DatabaseModule;
|
|
1276
1510
|
readonly notifications: NotificationsModule;
|
|
1277
1511
|
readonly functions: FunctionsModule;
|
|
1512
|
+
readonly schedule: ScheduleModule;
|
|
1278
1513
|
/**
|
|
1279
1514
|
* Store auth tokens externally (e.g. obtained via the auth-components
|
|
1280
1515
|
* library that bypasses the SDK). Makes the tokens available to HTTP +
|
|
@@ -1326,4 +1561,4 @@ interface SpacelrClient {
|
|
|
1326
1561
|
}
|
|
1327
1562
|
declare function createClient(config: SpacelrClientConfig): SpacelrClient;
|
|
1328
1563
|
|
|
1329
|
-
export { type ApiResponse, type AuthLostReason, type AuthState, type AuthStateListener, type AuthorizationUrlParams, BrowserTokenStorage, CodeChallengeMethod, type ConnectionState, type CursorStorage, type DatabaseChangeEvent, type DownloadUrlResponse, type ExchangeCodeParams, type FileInfo, type FileListResponse, FileVisibility, type FunctionInvokeOptions, type FunctionInvokeResult, type GapReason, GrantType, type InitMultipartUploadParams, type InitMultipartUploadResponse, type JWK, type JWKSResponse, type ListFilesParams, type LoginParams, type LoginResponse, MemoryTokenStorage, type OpenIDConfiguration, type PKCEChallenge, type PartEtag, type PushSubscriptionInfo, type QuotaInfo, type RegisterParams, type RegisterResponse, type SearchOptions, type ShareFileParams, SharePermission, SpacelrAuthError, type SpacelrClient, type SpacelrClientConfig, SpacelrEmailVerificationRequiredError, SpacelrError, SpacelrNetworkError, SpacelrSearchFilterRequiredError, SpacelrTimeoutError, SpacelrTwoFactorRequiredError, type StoredTokens, type StreamGapInfo, type StreamSubscription, type SubscribeEventsHandlers, type SubscribeHandlers, type SubscribeWithSnapshotOptions, type TokenResponse, type TokenStorage, type TwoFactorResponse, type TwoFactorVerifyParams, type UnshareFileParams, type UploadFileParams, type UploadLargeFileParams, type UploadProgress, type UserInfo, type UserProfile, type VapidKeyResponse, createClient, generatePKCEChallenge, localStorageCursorStorage, memoryCursorStorage };
|
|
1564
|
+
export { type ApiResponse, type AuthLostReason, type AuthState, type AuthStateListener, type AuthorizationUrlParams, BrowserTokenStorage, CodeChallengeMethod, type ConnectionState, CursorInvalidError, type CursorStorage, type DatabaseChangeEvent, type DownloadUrlResponse, type ExchangeCodeParams, type FileInfo, type FileListResponse, FileVisibility, ForbiddenError, type FunctionInvokeOptions, type FunctionInvokeResult, type GapReason, GrantType, type InitMultipartUploadParams, type InitMultipartUploadResponse, type JWK, type JWKSResponse, type ListFilesParams, type LoginParams, type LoginResponse, MemoryTokenStorage, NotFoundError, type OpenIDConfiguration, type PKCEChallenge, type PartEtag, type PushSubscriptionInfo, type QuotaInfo, type RegisterParams, type RegisterResponse, type Schedule, type ScheduleInvokeOptions, type ScheduleListOptions, type ScheduleStatus, type SearchOptions, ServerConfigError, type ShareFileParams, SharePermission, SpacelrAuthError, type SpacelrClient, type SpacelrClientConfig, SpacelrEmailVerificationRequiredError, SpacelrError, SpacelrNetworkError, SpacelrSearchFilterRequiredError, SpacelrTimeoutError, SpacelrTwoFactorRequiredError, type StoredTokens, type StreamGapInfo, type StreamSubscription, type SubscribeEventsHandlers, type SubscribeHandlers, type SubscribeWithSnapshotOptions, type TimelineAndFilter, TimelineError, type TimelineFieldFilter, type TimelineFilter, type TimelineLeafFilter, TimelineModule, type TimelineOrderBy, type TimelineQueryOptions, type TimelineQueryResponse, type TimelineScalar, type TimelineSourceStats, TimeoutError, type TokenResponse, type TokenStorage, type TwoFactorResponse, type TwoFactorVerifyParams, type UnshareFileParams, type UploadFileParams, type UploadLargeFileParams, type UploadProgress, type UserInfo, type UserProfile, ValidationError, type VapidKeyResponse, createClient, generatePKCEChallenge, localStorageCursorStorage, memoryCursorStorage };
|