@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/dist/index.js
CHANGED
|
@@ -22,9 +22,13 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
BrowserTokenStorage: () => BrowserTokenStorage,
|
|
24
24
|
CodeChallengeMethod: () => CodeChallengeMethod,
|
|
25
|
+
CursorInvalidError: () => CursorInvalidError,
|
|
25
26
|
FileVisibility: () => FileVisibility,
|
|
27
|
+
ForbiddenError: () => ForbiddenError,
|
|
26
28
|
GrantType: () => GrantType,
|
|
27
29
|
MemoryTokenStorage: () => MemoryTokenStorage,
|
|
30
|
+
NotFoundError: () => NotFoundError,
|
|
31
|
+
ServerConfigError: () => ServerConfigError,
|
|
28
32
|
SharePermission: () => SharePermission,
|
|
29
33
|
SpacelrAuthError: () => SpacelrAuthError,
|
|
30
34
|
SpacelrEmailVerificationRequiredError: () => SpacelrEmailVerificationRequiredError,
|
|
@@ -33,6 +37,10 @@ __export(index_exports, {
|
|
|
33
37
|
SpacelrSearchFilterRequiredError: () => SpacelrSearchFilterRequiredError,
|
|
34
38
|
SpacelrTimeoutError: () => SpacelrTimeoutError,
|
|
35
39
|
SpacelrTwoFactorRequiredError: () => SpacelrTwoFactorRequiredError,
|
|
40
|
+
TimelineError: () => TimelineError,
|
|
41
|
+
TimelineModule: () => TimelineModule,
|
|
42
|
+
TimeoutError: () => TimeoutError,
|
|
43
|
+
ValidationError: () => ValidationError,
|
|
36
44
|
createClient: () => createClient,
|
|
37
45
|
generatePKCEChallenge: () => generatePKCEChallenge,
|
|
38
46
|
localStorageCursorStorage: () => localStorageCursorStorage,
|
|
@@ -860,7 +868,7 @@ var RealtimeClient = class {
|
|
|
860
868
|
if (!where || Object.keys(where).length === 0) {
|
|
861
869
|
return base;
|
|
862
870
|
}
|
|
863
|
-
const filterStr = Object.keys(where).sort().map((k) => `${k}=${
|
|
871
|
+
const filterStr = Object.keys(where).sort().map((k) => `${k}=${JSON.stringify(where[k])}`).join("&");
|
|
864
872
|
return `${base}?${filterStr}`;
|
|
865
873
|
}
|
|
866
874
|
async ensureConnected() {
|
|
@@ -1008,15 +1016,15 @@ var RealtimeClient = class {
|
|
|
1008
1016
|
if (room === base) return true;
|
|
1009
1017
|
if (!room.startsWith(`${base}?`)) return false;
|
|
1010
1018
|
const where = this.roomWhereMap.get(room);
|
|
1011
|
-
if (!where) return
|
|
1019
|
+
if (!where) return false;
|
|
1012
1020
|
if (!event.document) return false;
|
|
1013
1021
|
for (const [key, value] of Object.entries(where)) {
|
|
1014
1022
|
const docValue = event.document[key];
|
|
1015
1023
|
if (Array.isArray(docValue)) {
|
|
1016
|
-
if (!docValue.
|
|
1024
|
+
if (!docValue.includes(value)) {
|
|
1017
1025
|
return false;
|
|
1018
1026
|
}
|
|
1019
|
-
} else if (
|
|
1027
|
+
} else if (docValue !== value) {
|
|
1020
1028
|
return false;
|
|
1021
1029
|
}
|
|
1022
1030
|
}
|
|
@@ -1819,6 +1827,144 @@ var StorageModule = class {
|
|
|
1819
1827
|
}
|
|
1820
1828
|
};
|
|
1821
1829
|
|
|
1830
|
+
// libs/sdk/src/modules/timeline.errors.ts
|
|
1831
|
+
var TimelineError = class extends SpacelrError {
|
|
1832
|
+
constructor(message, opts = {}) {
|
|
1833
|
+
super(message, opts.code ?? "TIMELINE_ERROR", opts.statusCode);
|
|
1834
|
+
this.name = "TimelineError";
|
|
1835
|
+
}
|
|
1836
|
+
};
|
|
1837
|
+
var CursorInvalidError = class extends TimelineError {
|
|
1838
|
+
constructor(message, opts = {}) {
|
|
1839
|
+
super(message, { statusCode: opts.statusCode ?? 400, code: opts.code ?? "CURSOR_INVALID" });
|
|
1840
|
+
this.name = "CursorInvalidError";
|
|
1841
|
+
}
|
|
1842
|
+
};
|
|
1843
|
+
var ValidationError = class extends TimelineError {
|
|
1844
|
+
constructor(message, opts = {}) {
|
|
1845
|
+
super(message, { statusCode: opts.statusCode ?? 400, code: opts.code ?? "BAD_REQUEST" });
|
|
1846
|
+
this.name = "ValidationError";
|
|
1847
|
+
}
|
|
1848
|
+
};
|
|
1849
|
+
var ForbiddenError = class extends TimelineError {
|
|
1850
|
+
constructor(message, opts = {}) {
|
|
1851
|
+
super(message, { statusCode: opts.statusCode ?? 403, code: opts.code ?? "FORBIDDEN" });
|
|
1852
|
+
this.name = "ForbiddenError";
|
|
1853
|
+
}
|
|
1854
|
+
};
|
|
1855
|
+
var NotFoundError = class extends TimelineError {
|
|
1856
|
+
constructor(message, opts = {}) {
|
|
1857
|
+
super(message, { statusCode: opts.statusCode ?? 404, code: opts.code ?? "NOT_FOUND" });
|
|
1858
|
+
this.name = "NotFoundError";
|
|
1859
|
+
}
|
|
1860
|
+
};
|
|
1861
|
+
var ServerConfigError = class extends TimelineError {
|
|
1862
|
+
constructor(message, opts = {}) {
|
|
1863
|
+
super(message, { statusCode: opts.statusCode ?? 500, code: opts.code ?? "CONFIG_INVALID" });
|
|
1864
|
+
this.name = "ServerConfigError";
|
|
1865
|
+
}
|
|
1866
|
+
};
|
|
1867
|
+
var TimeoutError = class extends TimelineError {
|
|
1868
|
+
constructor(message, opts = {}) {
|
|
1869
|
+
super(message, { statusCode: opts.statusCode ?? 504, code: opts.code ?? "TIMEOUT" });
|
|
1870
|
+
this.name = "TimeoutError";
|
|
1871
|
+
}
|
|
1872
|
+
};
|
|
1873
|
+
function mapTimelineError(statusCode, body) {
|
|
1874
|
+
const code = body?.code;
|
|
1875
|
+
const message = body?.message ?? `Timeline request failed with HTTP ${statusCode}`;
|
|
1876
|
+
if (statusCode === 400) {
|
|
1877
|
+
if (code === "CURSOR_INVALID") {
|
|
1878
|
+
return new CursorInvalidError(message, { statusCode, code });
|
|
1879
|
+
}
|
|
1880
|
+
return new ValidationError(message, { statusCode, code });
|
|
1881
|
+
}
|
|
1882
|
+
if (statusCode === 403) {
|
|
1883
|
+
return new ForbiddenError(message, { statusCode, code });
|
|
1884
|
+
}
|
|
1885
|
+
if (statusCode === 404) {
|
|
1886
|
+
return new NotFoundError(message, { statusCode, code });
|
|
1887
|
+
}
|
|
1888
|
+
if (statusCode === 500) {
|
|
1889
|
+
return new ServerConfigError(message, { statusCode, code });
|
|
1890
|
+
}
|
|
1891
|
+
if (statusCode === 504) {
|
|
1892
|
+
return new TimeoutError(message, { statusCode, code });
|
|
1893
|
+
}
|
|
1894
|
+
return new TimelineError(message, { statusCode, code });
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
// libs/sdk/src/modules/timeline.module.ts
|
|
1898
|
+
var TimelineModule = class {
|
|
1899
|
+
constructor(http) {
|
|
1900
|
+
this.http = http;
|
|
1901
|
+
}
|
|
1902
|
+
async query(opts) {
|
|
1903
|
+
const body = {
|
|
1904
|
+
collection: opts.collection,
|
|
1905
|
+
partitionValue: opts.partitionValue
|
|
1906
|
+
};
|
|
1907
|
+
if (opts.where !== void 0) body["where"] = opts.where;
|
|
1908
|
+
if (opts.orderBy !== void 0) body["orderBy"] = opts.orderBy;
|
|
1909
|
+
if (opts.limit !== void 0) body["limit"] = opts.limit;
|
|
1910
|
+
if (opts.cursor !== void 0) body["cursor"] = opts.cursor;
|
|
1911
|
+
let raw;
|
|
1912
|
+
try {
|
|
1913
|
+
raw = await this.http.request({
|
|
1914
|
+
method: "POST",
|
|
1915
|
+
path: "/db/timeline",
|
|
1916
|
+
body,
|
|
1917
|
+
authenticated: true
|
|
1918
|
+
});
|
|
1919
|
+
} catch (err) {
|
|
1920
|
+
throw this.translateError(err);
|
|
1921
|
+
}
|
|
1922
|
+
if (!isTimelineQueryResponse(raw)) {
|
|
1923
|
+
throw new TimelineError(
|
|
1924
|
+
"Timeline gateway returned a response shape the SDK does not recognise",
|
|
1925
|
+
{ statusCode: 500, code: "INVALID_RESPONSE_SHAPE" }
|
|
1926
|
+
);
|
|
1927
|
+
}
|
|
1928
|
+
return raw;
|
|
1929
|
+
}
|
|
1930
|
+
translateError(err) {
|
|
1931
|
+
if (err instanceof SpacelrTimeoutError) {
|
|
1932
|
+
return new TimeoutError(err.message, { statusCode: 504, code: "TIMEOUT" });
|
|
1933
|
+
}
|
|
1934
|
+
if (err instanceof SpacelrAuthError) {
|
|
1935
|
+
if (err.statusCode === 403) {
|
|
1936
|
+
return new ForbiddenError(err.message, { statusCode: 403, code: err.code ?? "FORBIDDEN" });
|
|
1937
|
+
}
|
|
1938
|
+
return err;
|
|
1939
|
+
}
|
|
1940
|
+
if (err instanceof SpacelrNetworkError) {
|
|
1941
|
+
return err;
|
|
1942
|
+
}
|
|
1943
|
+
if (err instanceof SpacelrError) {
|
|
1944
|
+
return mapTimelineError(err.statusCode ?? 0, { code: err.code, message: err.message });
|
|
1945
|
+
}
|
|
1946
|
+
return err;
|
|
1947
|
+
}
|
|
1948
|
+
};
|
|
1949
|
+
function isTimelineQueryResponse(value) {
|
|
1950
|
+
if (typeof value !== "object" || value === null) return false;
|
|
1951
|
+
const v = value;
|
|
1952
|
+
if (!Array.isArray(v["items"])) return false;
|
|
1953
|
+
if (v["nextCursor"] !== null && typeof v["nextCursor"] !== "string") return false;
|
|
1954
|
+
if (!isTimelineSourceStats(v["sourceStats"])) return false;
|
|
1955
|
+
return true;
|
|
1956
|
+
}
|
|
1957
|
+
function isTimelineSourceStats(value) {
|
|
1958
|
+
if (typeof value !== "object" || value === null) return false;
|
|
1959
|
+
const v = value;
|
|
1960
|
+
if (typeof v["hot"] !== "number") return false;
|
|
1961
|
+
if (typeof v["cold"] !== "number") return false;
|
|
1962
|
+
if (v["segmentsScanned"] !== void 0 && typeof v["segmentsScanned"] !== "number") {
|
|
1963
|
+
return false;
|
|
1964
|
+
}
|
|
1965
|
+
return true;
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1822
1968
|
// libs/sdk/src/modules/database.module.ts
|
|
1823
1969
|
var Paginator = class {
|
|
1824
1970
|
constructor(http, basePath, opts) {
|
|
@@ -2002,6 +2148,16 @@ var CollectionRef = class {
|
|
|
2002
2148
|
authenticated: true
|
|
2003
2149
|
});
|
|
2004
2150
|
}
|
|
2151
|
+
/**
|
|
2152
|
+
* Query the collection's **hot tier** (live MongoDB).
|
|
2153
|
+
*
|
|
2154
|
+
* **Cold-tier note:** if the collection has cold-tier archival enabled, aged
|
|
2155
|
+
* documents are moved to object storage and purged from the hot tier — they
|
|
2156
|
+
* will NOT appear in `find()` results (nor `findById`, `count`, `search`,
|
|
2157
|
+
* `paginate`, which are all hot-tier only). To read archived history, use
|
|
2158
|
+
* {@link TimelineModule.query} via `db.timeline.query(...)`, which transparently
|
|
2159
|
+
* merges hot and cold results for a partition.
|
|
2160
|
+
*/
|
|
2005
2161
|
find(filter) {
|
|
2006
2162
|
return new QueryBuilder(this.http, this.basePath, filter);
|
|
2007
2163
|
}
|
|
@@ -2036,6 +2192,9 @@ var CollectionRef = class {
|
|
|
2036
2192
|
*
|
|
2037
2193
|
* Limits: `query` 1–200 chars, `fields` 1–10 entries (each matching
|
|
2038
2194
|
* `/^[a-zA-Z0-9_.]+$/`, max 64 chars), `limit` max 100.
|
|
2195
|
+
*
|
|
2196
|
+
* **Cold-tier note:** searches the hot tier only; archived documents are not
|
|
2197
|
+
* included. See {@link CollectionRef.find} and `db.timeline.query(...)`.
|
|
2039
2198
|
*/
|
|
2040
2199
|
async search(opts) {
|
|
2041
2200
|
return this.http.request({
|
|
@@ -2045,6 +2204,13 @@ var CollectionRef = class {
|
|
|
2045
2204
|
authenticated: true
|
|
2046
2205
|
});
|
|
2047
2206
|
}
|
|
2207
|
+
/**
|
|
2208
|
+
* Fetch a single document by `_id` from the **hot tier**.
|
|
2209
|
+
*
|
|
2210
|
+
* **Cold-tier note:** returns null/throws for documents that have been
|
|
2211
|
+
* archived and purged from the hot tier. Archived history is reachable only
|
|
2212
|
+
* via `db.timeline.query(...)`. See {@link CollectionRef.find}.
|
|
2213
|
+
*/
|
|
2048
2214
|
async findById(id, options) {
|
|
2049
2215
|
const query = {};
|
|
2050
2216
|
if (options?.populate?.length) {
|
|
@@ -2074,6 +2240,13 @@ var CollectionRef = class {
|
|
|
2074
2240
|
authenticated: true
|
|
2075
2241
|
});
|
|
2076
2242
|
}
|
|
2243
|
+
/**
|
|
2244
|
+
* Count documents in the **hot tier** matching `filter`.
|
|
2245
|
+
*
|
|
2246
|
+
* **Cold-tier note:** counts hot-tier documents only — archived/purged
|
|
2247
|
+
* documents are not included, so this is not a total-history count. See
|
|
2248
|
+
* {@link CollectionRef.find} and `db.timeline.query(...)`.
|
|
2249
|
+
*/
|
|
2077
2250
|
async count(filter) {
|
|
2078
2251
|
const result = await this.http.request({
|
|
2079
2252
|
method: "POST",
|
|
@@ -2509,6 +2682,7 @@ var DatabaseModule = class {
|
|
|
2509
2682
|
this.http = http;
|
|
2510
2683
|
this.projectId = projectId;
|
|
2511
2684
|
this.realtime = realtime ?? null;
|
|
2685
|
+
this.timeline = new TimelineModule(http);
|
|
2512
2686
|
}
|
|
2513
2687
|
collection(name) {
|
|
2514
2688
|
return new CollectionRef(this.http, this.realtime, this.projectId, name);
|
|
@@ -2707,6 +2881,65 @@ var FunctionsModule = class {
|
|
|
2707
2881
|
}
|
|
2708
2882
|
};
|
|
2709
2883
|
|
|
2884
|
+
// libs/sdk/src/modules/schedule.module.ts
|
|
2885
|
+
var ScheduleModule = class {
|
|
2886
|
+
constructor(http, projectId) {
|
|
2887
|
+
this.http = http;
|
|
2888
|
+
this.projectId = projectId;
|
|
2889
|
+
}
|
|
2890
|
+
/**
|
|
2891
|
+
* Schedule a one-shot function invocation. Returns the existing handle
|
|
2892
|
+
* unchanged if `idempotencyKey` matches a prior invoke in this project
|
|
2893
|
+
* for this function.
|
|
2894
|
+
*/
|
|
2895
|
+
async invoke(options) {
|
|
2896
|
+
return this.http.request({
|
|
2897
|
+
method: "POST",
|
|
2898
|
+
path: `/schedules/${encodeURIComponent(this.projectId)}`,
|
|
2899
|
+
body: {
|
|
2900
|
+
functionId: options.functionId,
|
|
2901
|
+
executeAt: this.toIsoString(options.executeAt),
|
|
2902
|
+
...options.payload !== void 0 ? { payload: options.payload } : {},
|
|
2903
|
+
...options.idempotencyKey !== void 0 ? { idempotencyKey: options.idempotencyKey } : {},
|
|
2904
|
+
...options.maxAttempts !== void 0 ? { maxAttempts: options.maxAttempts } : {}
|
|
2905
|
+
},
|
|
2906
|
+
authenticated: true
|
|
2907
|
+
});
|
|
2908
|
+
}
|
|
2909
|
+
async get(scheduleId) {
|
|
2910
|
+
return this.http.request({
|
|
2911
|
+
method: "GET",
|
|
2912
|
+
path: `/schedules/${encodeURIComponent(this.projectId)}/${encodeURIComponent(scheduleId)}`,
|
|
2913
|
+
authenticated: true
|
|
2914
|
+
});
|
|
2915
|
+
}
|
|
2916
|
+
async list(options = {}) {
|
|
2917
|
+
return this.http.request({
|
|
2918
|
+
method: "GET",
|
|
2919
|
+
path: `/schedules/${encodeURIComponent(this.projectId)}`,
|
|
2920
|
+
query: {
|
|
2921
|
+
functionId: options.functionId,
|
|
2922
|
+
status: options.status,
|
|
2923
|
+
limit: options.limit,
|
|
2924
|
+
offset: options.offset
|
|
2925
|
+
},
|
|
2926
|
+
authenticated: true
|
|
2927
|
+
});
|
|
2928
|
+
}
|
|
2929
|
+
async cancel(scheduleId) {
|
|
2930
|
+
return this.http.request({
|
|
2931
|
+
method: "DELETE",
|
|
2932
|
+
path: `/schedules/${encodeURIComponent(this.projectId)}/${encodeURIComponent(scheduleId)}`,
|
|
2933
|
+
authenticated: true
|
|
2934
|
+
});
|
|
2935
|
+
}
|
|
2936
|
+
toIsoString(input) {
|
|
2937
|
+
if (input instanceof Date) return input.toISOString();
|
|
2938
|
+
if (typeof input === "number") return new Date(input).toISOString();
|
|
2939
|
+
return input;
|
|
2940
|
+
}
|
|
2941
|
+
};
|
|
2942
|
+
|
|
2710
2943
|
// libs/sdk/src/client.ts
|
|
2711
2944
|
function createClient(config) {
|
|
2712
2945
|
const tokenStorage = config.tokenStorage ?? (typeof window !== "undefined" && typeof window.localStorage !== "undefined" ? new BrowserTokenStorage() : new MemoryTokenStorage());
|
|
@@ -2725,12 +2958,14 @@ function createClient(config) {
|
|
|
2725
2958
|
const db = new DatabaseModule(httpClient, config.projectId, realtime);
|
|
2726
2959
|
const notifications = new NotificationsModule(httpClient);
|
|
2727
2960
|
const functions = new FunctionsModule(httpClient);
|
|
2961
|
+
const schedule = new ScheduleModule(httpClient, config.projectId);
|
|
2728
2962
|
return {
|
|
2729
2963
|
auth,
|
|
2730
2964
|
storage,
|
|
2731
2965
|
db,
|
|
2732
2966
|
notifications,
|
|
2733
2967
|
functions,
|
|
2968
|
+
schedule,
|
|
2734
2969
|
setTokens(tokens) {
|
|
2735
2970
|
return tokenManager.setTokens(tokens);
|
|
2736
2971
|
},
|
|
@@ -2758,9 +2993,13 @@ function createClient(config) {
|
|
|
2758
2993
|
0 && (module.exports = {
|
|
2759
2994
|
BrowserTokenStorage,
|
|
2760
2995
|
CodeChallengeMethod,
|
|
2996
|
+
CursorInvalidError,
|
|
2761
2997
|
FileVisibility,
|
|
2998
|
+
ForbiddenError,
|
|
2762
2999
|
GrantType,
|
|
2763
3000
|
MemoryTokenStorage,
|
|
3001
|
+
NotFoundError,
|
|
3002
|
+
ServerConfigError,
|
|
2764
3003
|
SharePermission,
|
|
2765
3004
|
SpacelrAuthError,
|
|
2766
3005
|
SpacelrEmailVerificationRequiredError,
|
|
@@ -2769,6 +3008,10 @@ function createClient(config) {
|
|
|
2769
3008
|
SpacelrSearchFilterRequiredError,
|
|
2770
3009
|
SpacelrTimeoutError,
|
|
2771
3010
|
SpacelrTwoFactorRequiredError,
|
|
3011
|
+
TimelineError,
|
|
3012
|
+
TimelineModule,
|
|
3013
|
+
TimeoutError,
|
|
3014
|
+
ValidationError,
|
|
2772
3015
|
createClient,
|
|
2773
3016
|
generatePKCEChallenge,
|
|
2774
3017
|
localStorageCursorStorage,
|