@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 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] !== expected) {
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
- return stableStringify(a ?? null) === stableStringify(b ?? null);
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 resolvedScopes = resolveSessionScopes(this.store.getSchema(), {
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