@korajs/server 1.0.0-beta.10 → 1.0.0-beta.11
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.cjs +66 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +62 -4
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -169,6 +169,7 @@ var index_exports = {};
|
|
|
169
169
|
__export(index_exports, {
|
|
170
170
|
AwarenessRelay: () => AwarenessRelay,
|
|
171
171
|
ClientSession: () => ClientSession,
|
|
172
|
+
DEFAULT_MAX_SCOPE_PREDICATE_VALUES: () => DEFAULT_MAX_SCOPE_PREDICATE_VALUES,
|
|
172
173
|
HttpServerTransport: () => HttpServerTransport,
|
|
173
174
|
KoraAuthProvider: () => KoraAuthProvider,
|
|
174
175
|
KoraSyncServer: () => KoraSyncServer,
|
|
@@ -188,7 +189,9 @@ __export(index_exports, {
|
|
|
188
189
|
createProductionServer: () => createProductionServer,
|
|
189
190
|
createSilentLogger: () => createSilentLogger,
|
|
190
191
|
createSqliteServerStore: () => createSqliteServerStore,
|
|
191
|
-
isRetriableRejection: () => isRetriableRejection
|
|
192
|
+
isRetriableRejection: () => isRetriableRejection,
|
|
193
|
+
normalizeScopeMap: () => normalizeScopeMap,
|
|
194
|
+
operationMatchesScopes: () => operationMatchesScopes
|
|
192
195
|
});
|
|
193
196
|
module.exports = __toCommonJS(index_exports);
|
|
194
197
|
init_cjs_shims();
|
|
@@ -2725,6 +2728,39 @@ function mergeScopeMaps(base, overlay, source) {
|
|
|
2725
2728
|
|
|
2726
2729
|
// src/scopes/server-scope-filter.ts
|
|
2727
2730
|
init_cjs_shims();
|
|
2731
|
+
var DEFAULT_MAX_SCOPE_PREDICATE_VALUES = 100;
|
|
2732
|
+
function normalizeScopeMap(scopes, maxValues = DEFAULT_MAX_SCOPE_PREDICATE_VALUES) {
|
|
2733
|
+
const normalized = {};
|
|
2734
|
+
for (const collection of Object.keys(scopes).sort()) {
|
|
2735
|
+
const predicate = {};
|
|
2736
|
+
for (const field of Object.keys(scopes[collection] ?? {}).sort()) {
|
|
2737
|
+
const expected = scopes[collection]?.[field];
|
|
2738
|
+
if (expected && typeof expected === "object" && !Array.isArray(expected) && "$in" in expected) {
|
|
2739
|
+
const values = expected.$in;
|
|
2740
|
+
if (!Array.isArray(values))
|
|
2741
|
+
throw new Error(`Invalid $in predicate for ${collection}.${field}`);
|
|
2742
|
+
const unique = [...new Map(values.map((value) => [stableValueKey(value), value])).values()];
|
|
2743
|
+
if (unique.length > maxValues)
|
|
2744
|
+
throw new Error(
|
|
2745
|
+
`Scope predicate for ${collection}.${field} exceeds the ${maxValues}-value limit`
|
|
2746
|
+
);
|
|
2747
|
+
predicate[field] = {
|
|
2748
|
+
$in: unique.sort((a, b) => stableValueKey(a).localeCompare(stableValueKey(b)))
|
|
2749
|
+
};
|
|
2750
|
+
} else predicate[field] = expected;
|
|
2751
|
+
}
|
|
2752
|
+
normalized[collection] = predicate;
|
|
2753
|
+
}
|
|
2754
|
+
return normalized;
|
|
2755
|
+
}
|
|
2756
|
+
function stableValueKey(value) {
|
|
2757
|
+
if (Array.isArray(value)) return `[${value.map(stableValueKey).join(",")}]`;
|
|
2758
|
+
if (value && typeof value === "object")
|
|
2759
|
+
return `{${Object.keys(value).sort().map(
|
|
2760
|
+
(key) => `${JSON.stringify(key)}:${stableValueKey(value[key])}`
|
|
2761
|
+
).join(",")}}`;
|
|
2762
|
+
return JSON.stringify(value);
|
|
2763
|
+
}
|
|
2728
2764
|
function operationMatchesScopes(op, scopes, fullRecord) {
|
|
2729
2765
|
if (!scopes) return true;
|
|
2730
2766
|
const collectionScope = scopes[op.collection];
|
|
@@ -2733,12 +2769,19 @@ function operationMatchesScopes(op, scopes, fullRecord) {
|
|
|
2733
2769
|
const snapshot = buildSnapshot(op, fullRecord);
|
|
2734
2770
|
if (!snapshot) return false;
|
|
2735
2771
|
for (const [field, expected] of Object.entries(collectionScope)) {
|
|
2736
|
-
if (snapshot[field]
|
|
2772
|
+
if (!matchesPredicate(snapshot[field], expected)) {
|
|
2737
2773
|
return false;
|
|
2738
2774
|
}
|
|
2739
2775
|
}
|
|
2740
2776
|
return true;
|
|
2741
2777
|
}
|
|
2778
|
+
function matchesPredicate(actual, expected) {
|
|
2779
|
+
if (expected && typeof expected === "object" && !Array.isArray(expected) && "$in" in expected) {
|
|
2780
|
+
const values = expected.$in;
|
|
2781
|
+
return Array.isArray(values) && values.some((value) => Object.is(actual, value));
|
|
2782
|
+
}
|
|
2783
|
+
return Object.is(actual, expected);
|
|
2784
|
+
}
|
|
2742
2785
|
function missingScopeFields(op, scopes) {
|
|
2743
2786
|
if (!scopes) return [];
|
|
2744
2787
|
const collectionScope = scopes[op.collection];
|
|
@@ -2857,7 +2900,8 @@ function stableStringify(value) {
|
|
|
2857
2900
|
return JSON.stringify(value);
|
|
2858
2901
|
}
|
|
2859
2902
|
function sameScopeMap(a, b) {
|
|
2860
|
-
|
|
2903
|
+
const normalize = (value) => value && typeof value === "object" ? normalizeScopeMap(value) : value;
|
|
2904
|
+
return stableStringify(normalize(a) ?? null) === stableStringify(normalize(b) ?? null);
|
|
2861
2905
|
}
|
|
2862
2906
|
var ClientSession = class _ClientSession {
|
|
2863
2907
|
state = "connected";
|
|
@@ -3227,10 +3271,24 @@ var ClientSession = class _ClientSession {
|
|
|
3227
3271
|
this.authContext = context;
|
|
3228
3272
|
this.state = "authenticated";
|
|
3229
3273
|
}
|
|
3230
|
-
const
|
|
3274
|
+
const rawResolvedScopes = resolveSessionScopes(this.store.getSchema(), {
|
|
3231
3275
|
handshakeScope: msg.syncScope,
|
|
3232
3276
|
authScopes: this.authContext?.scopes
|
|
3233
3277
|
});
|
|
3278
|
+
let resolvedScopes;
|
|
3279
|
+
try {
|
|
3280
|
+
resolvedScopes = rawResolvedScopes ? normalizeScopeMap(rawResolvedScopes) : void 0;
|
|
3281
|
+
} catch (error) {
|
|
3282
|
+
this.sendToClient({
|
|
3283
|
+
type: "error",
|
|
3284
|
+
messageId: (0, import_core11.generateUUIDv7)(),
|
|
3285
|
+
code: "SCOPE_PREDICATE_LIMIT",
|
|
3286
|
+
message: error instanceof Error ? error.message : "Invalid scope predicate",
|
|
3287
|
+
retriable: false
|
|
3288
|
+
});
|
|
3289
|
+
this.close("invalid scope predicate");
|
|
3290
|
+
return;
|
|
3291
|
+
}
|
|
3234
3292
|
if (resolvedScopes) {
|
|
3235
3293
|
if (this.authContext) {
|
|
3236
3294
|
this.authContext = { ...this.authContext, scopes: resolvedScopes };
|
|
@@ -5727,6 +5785,7 @@ function formatUptime(ms) {
|
|
|
5727
5785
|
0 && (module.exports = {
|
|
5728
5786
|
AwarenessRelay,
|
|
5729
5787
|
ClientSession,
|
|
5788
|
+
DEFAULT_MAX_SCOPE_PREDICATE_VALUES,
|
|
5730
5789
|
HttpServerTransport,
|
|
5731
5790
|
KoraAuthProvider,
|
|
5732
5791
|
KoraSyncServer,
|
|
@@ -5746,6 +5805,8 @@ function formatUptime(ms) {
|
|
|
5746
5805
|
createProductionServer,
|
|
5747
5806
|
createSilentLogger,
|
|
5748
5807
|
createSqliteServerStore,
|
|
5749
|
-
isRetriableRejection
|
|
5808
|
+
isRetriableRejection,
|
|
5809
|
+
normalizeScopeMap,
|
|
5810
|
+
operationMatchesScopes
|
|
5750
5811
|
});
|
|
5751
5812
|
//# sourceMappingURL=index.cjs.map
|