lazypock 0.9.0 → 0.10.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/README.md +12 -4
- package/dist/{chunk-CGQVJ7TT.js → chunk-JYKRCEC3.js} +17 -16
- package/dist/{chunk-CGQVJ7TT.js.map → chunk-JYKRCEC3.js.map} +1 -1
- package/dist/cli.cjs +16 -15
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.global.js +16 -15
- package/dist/cli.global.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +48 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -10
- package/dist/index.d.ts +43 -10
- package/dist/index.global.js +48 -17
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +33 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/codegen.ts +16 -15
- package/src/http.ts +20 -1
- package/src/lazypock.ts +30 -1
- package/src/realtime.ts +25 -0
- package/src/types.ts +37 -10
package/dist/index.cjs
CHANGED
|
@@ -61,8 +61,10 @@ var HttpClient = class {
|
|
|
61
61
|
/**
|
|
62
62
|
* @param baseUrl The API base URL (e.g. `http://localhost:4000/api`). Trailing slash stripped.
|
|
63
63
|
* @param authStore The auth store providing the token for Authorization headers.
|
|
64
|
+
* @param connectionId Optional per-client connection id, sent as the
|
|
65
|
+
* `X-Connection-Id` header on every request (realtime origin-exclusion).
|
|
64
66
|
*/
|
|
65
|
-
constructor(baseUrl, authStore) {
|
|
67
|
+
constructor(baseUrl, authStore, connectionId) {
|
|
66
68
|
/**
|
|
67
69
|
* Abort controllers for in-flight requests, keyed by their cancellation key
|
|
68
70
|
* (default `METHOD path`). A new request with the same key aborts the
|
|
@@ -80,6 +82,7 @@ var HttpClient = class {
|
|
|
80
82
|
this.enableAutoCancellation = true;
|
|
81
83
|
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
82
84
|
this.authStore = authStore;
|
|
85
|
+
this.connectionId = connectionId;
|
|
83
86
|
this.defaultFetch = globalThis.fetch.bind(globalThis);
|
|
84
87
|
}
|
|
85
88
|
async refreshAuth() {
|
|
@@ -232,6 +235,9 @@ var HttpClient = class {
|
|
|
232
235
|
if (this.authStore.token) {
|
|
233
236
|
headers["Authorization"] = "Bearer " + this.authStore.token;
|
|
234
237
|
}
|
|
238
|
+
if (this.connectionId && !headers["X-Connection-Id"] && !headers["x-connection-id"]) {
|
|
239
|
+
headers["X-Connection-Id"] = this.connectionId;
|
|
240
|
+
}
|
|
235
241
|
const init = {
|
|
236
242
|
method,
|
|
237
243
|
headers,
|
|
@@ -947,6 +953,16 @@ var RealtimeService = class {
|
|
|
947
953
|
get lastToken() {
|
|
948
954
|
return this.token;
|
|
949
955
|
}
|
|
956
|
+
/**
|
|
957
|
+
* Set the per-client connection id (browser tab / device). The SDK
|
|
958
|
+
* appends it as the `connectionId` socket query param at connect time
|
|
959
|
+
* (unless the URL already carries one), matching the `X-Connection-Id`
|
|
960
|
+
* header the HTTP client sends — together they let the server exclude
|
|
961
|
+
* the originating connection from its own realtime broadcasts.
|
|
962
|
+
*/
|
|
963
|
+
setConnectionId(id) {
|
|
964
|
+
this.connectionId = id;
|
|
965
|
+
}
|
|
950
966
|
/**
|
|
951
967
|
* Set the socket URL. Useful before subscribing so the SDK can
|
|
952
968
|
* auto-connect on the first {@link subscribe}.
|
|
@@ -1068,6 +1084,9 @@ var RealtimeService = class {
|
|
|
1068
1084
|
if (token) {
|
|
1069
1085
|
url += (url.includes("?") ? "&" : "?") + "token=" + encodeURIComponent(token);
|
|
1070
1086
|
}
|
|
1087
|
+
if (this.connectionId && !url.includes("connectionId=")) {
|
|
1088
|
+
url += (url.includes("?") ? "&" : "?") + "connectionId=" + encodeURIComponent(this.connectionId);
|
|
1089
|
+
}
|
|
1071
1090
|
this.ws = new WebSocket(url);
|
|
1072
1091
|
this.ws.onopen = () => {
|
|
1073
1092
|
this.reconnectAttempt = 0;
|
|
@@ -1614,26 +1633,27 @@ export function createClient(options: LazypockClientOptions): TypedClient {
|
|
|
1614
1633
|
}
|
|
1615
1634
|
|
|
1616
1635
|
export class TypedClient extends LazypockClient {
|
|
1617
|
-
//
|
|
1618
|
-
//
|
|
1619
|
-
//
|
|
1620
|
-
//
|
|
1621
|
-
//
|
|
1636
|
+
// The constraint is "keyof LazypockCollections | (string & {})" rather than a
|
|
1637
|
+
// bare generic string or a strict keyof:
|
|
1638
|
+
// - the keyof LazypockCollections member is what makes the IDE suggest
|
|
1639
|
+
// collection names, and known literals resolve to the typed service:
|
|
1640
|
+
// client.collection("posts") // suggested + typed
|
|
1641
|
+
// - the string & {} member keeps unknown/dynamic names compiling \u2014 they
|
|
1642
|
+
// resolve to the untyped service, so a studio that manages
|
|
1643
|
+
// user-created collections can still call collection(someString).
|
|
1622
1644
|
//
|
|
1623
|
-
//
|
|
1624
|
-
//
|
|
1625
|
-
// T extends string (rather than keyof LazypockCollections) with a conditional
|
|
1626
|
-
// return type, so the IDE suggests collection names AND unknown/dynamic names
|
|
1627
|
-
// still resolve to the untyped service \u2014 a studio that manages
|
|
1628
|
-
// user-created collections must be able to call collection(someString).
|
|
1645
|
+
// The (string & {}) intersection keeps the union from collapsing to plain
|
|
1646
|
+
// string (which would silently kill the suggestions).
|
|
1629
1647
|
//
|
|
1630
1648
|
// create()/update() take the collection's *CreateData \u2014 the read model
|
|
1631
1649
|
// omits password/hidden fields, but the write model carries them.
|
|
1632
|
-
override collection<
|
|
1633
|
-
|
|
1650
|
+
override collection<K extends keyof LazypockCollections | (string & {})>(
|
|
1651
|
+
name: K,
|
|
1652
|
+
): K extends keyof LazypockCollections
|
|
1653
|
+
? CollectionService<LazypockCollections[K], LazypockCreateData[K]>
|
|
1634
1654
|
: CollectionService<unknown> {
|
|
1635
|
-
return super.collection(name) as
|
|
1636
|
-
? CollectionService<LazypockCollections[
|
|
1655
|
+
return super.collection(name) as K extends keyof LazypockCollections
|
|
1656
|
+
? CollectionService<LazypockCollections[K], LazypockCreateData[K]>
|
|
1637
1657
|
: CollectionService<unknown>;
|
|
1638
1658
|
}
|
|
1639
1659
|
}
|
|
@@ -1675,6 +1695,15 @@ function createDataMemberLines(f) {
|
|
|
1675
1695
|
}
|
|
1676
1696
|
|
|
1677
1697
|
// src/lazypock.ts
|
|
1698
|
+
function createConnectionId() {
|
|
1699
|
+
try {
|
|
1700
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
1701
|
+
return crypto.randomUUID();
|
|
1702
|
+
}
|
|
1703
|
+
} catch {
|
|
1704
|
+
}
|
|
1705
|
+
return "conn-" + Math.random().toString(36).slice(2) + Date.now().toString(36);
|
|
1706
|
+
}
|
|
1678
1707
|
var LazypockClient = class {
|
|
1679
1708
|
/**
|
|
1680
1709
|
* Create a new Lazypock client.
|
|
@@ -1685,11 +1714,13 @@ var LazypockClient = class {
|
|
|
1685
1714
|
const baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
1686
1715
|
this.authStore = options.authStore ?? new AuthStore(options.storage ?? memoryStorage);
|
|
1687
1716
|
this.authReady = options.authStore ? Promise.resolve() : this.authStore.init();
|
|
1688
|
-
|
|
1717
|
+
const connectionId = createConnectionId();
|
|
1718
|
+
this.http = new HttpClient(baseUrl, this.authStore, connectionId);
|
|
1689
1719
|
this.realtime = options.realtime ?? new RealtimeService();
|
|
1690
1720
|
if (!options.realtime) {
|
|
1691
1721
|
this.realtime.setUrl(wsUrlFromBaseUrl(baseUrl));
|
|
1692
1722
|
}
|
|
1723
|
+
this.realtime.setConnectionId(connectionId);
|
|
1693
1724
|
this.realtime.setTokenProvider(() => this.authStore.token);
|
|
1694
1725
|
this.authStore.onChange(() => this.realtime.refresh());
|
|
1695
1726
|
this.authReady.then(() => this.realtime.refresh());
|