@xnetjs/data 0.0.2 → 0.0.3

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.
Files changed (137) hide show
  1. package/README.md +112 -0
  2. package/dist/account-BZHETMC4.js +12 -0
  3. package/dist/auth/index.d.ts +413 -0
  4. package/dist/auth/index.js +102 -0
  5. package/dist/budget-WR2Q4YH3.js +12 -0
  6. package/dist/canvas-HFMMVQLD.js +10 -0
  7. package/dist/channel-DXDYJ3ZH.js +12 -0
  8. package/dist/chat-message-QUUQGXEW.js +10 -0
  9. package/dist/chunk-2DSDH2ZH.js +52 -0
  10. package/dist/chunk-337E3ZOB.js +54 -0
  11. package/dist/chunk-37267RSF.js +41 -0
  12. package/dist/chunk-3JKW6TDE.js +66 -0
  13. package/dist/chunk-3RB2FMMO.js +148 -0
  14. package/dist/{chunk-BQBPA5HS.js → chunk-4U4KBCDN.js} +16 -2
  15. package/dist/chunk-4UQTURCD.js +722 -0
  16. package/dist/chunk-54Y7QRZN.js +109 -0
  17. package/dist/chunk-5FHJE7RC.js +46 -0
  18. package/dist/chunk-64AM6JPM.js +40 -0
  19. package/dist/chunk-6CN53PON.js +143 -0
  20. package/dist/chunk-6GB7PBCR.js +40 -0
  21. package/dist/chunk-6OPZJ7MG.js +78 -0
  22. package/dist/{chunk-IDMBCRUC.js → chunk-77UDLVQY.js} +1 -1
  23. package/dist/chunk-7GMJOAPF.js +52 -0
  24. package/dist/chunk-7PDRDSFH.js +69 -0
  25. package/dist/chunk-C5IRSEEZ.js +69 -0
  26. package/dist/chunk-CHZUSBSB.js +45 -0
  27. package/dist/chunk-DOZJXPQ6.js +232 -0
  28. package/dist/chunk-DTPSTMUD.js +105 -0
  29. package/dist/chunk-E6S557NC.js +402 -0
  30. package/dist/chunk-EIQX7INF.js +45 -0
  31. package/dist/chunk-ENTHVNOC.js +57 -0
  32. package/dist/chunk-EZA5UT4Y.js +5543 -0
  33. package/dist/chunk-GR3NDMBY.js +76 -0
  34. package/dist/chunk-GWYVY2K4.js +63 -0
  35. package/dist/chunk-IJ675GJR.js +42 -0
  36. package/dist/chunk-IP4BEVVD.js +57 -0
  37. package/dist/chunk-J4IVJA5M.js +102 -0
  38. package/dist/chunk-J6EDPPH4.js +84 -0
  39. package/dist/{chunk-SZC345Z2.js → chunk-JESSJ5CZ.js} +1015 -1110
  40. package/dist/chunk-JO6Y4E5V.js +73 -0
  41. package/dist/chunk-KPVBKKZS.js +47 -0
  42. package/dist/chunk-KTJLFJEQ.js +43 -0
  43. package/dist/chunk-L66WXPTW.js +32 -0
  44. package/dist/chunk-LGD72FVD.js +48 -0
  45. package/dist/chunk-O64EK5FK.js +887 -0
  46. package/dist/chunk-PMUQACPY.js +33 -0
  47. package/dist/chunk-PSUJEKVV.js +1722 -0
  48. package/dist/chunk-QVZXXJSP.js +6122 -0
  49. package/dist/chunk-QWFTRZQT.js +142 -0
  50. package/dist/chunk-RSSZXCLL.js +51 -0
  51. package/dist/chunk-S4B5OPZU.js +415 -0
  52. package/dist/{chunk-VYR5GPJP.js → chunk-SPFKSTPT.js} +9 -3
  53. package/dist/chunk-U6CBYDVZ.js +50 -0
  54. package/dist/chunk-UDUPQKRB.js +49 -0
  55. package/dist/chunk-V6HZ3LF3.js +380 -0
  56. package/dist/chunk-WMSCEBFH.js +64 -0
  57. package/dist/chunk-WUR3WWQM.js +65 -0
  58. package/dist/chunk-XHEA5UER.js +75 -0
  59. package/dist/chunk-XTUGZSYQ.js +75 -0
  60. package/dist/chunk-XWA3CJQ6.js +45 -0
  61. package/dist/chunk-YEQ6LLUY.js +49 -0
  62. package/dist/chunk-YWN27MLD.js +47 -0
  63. package/dist/chunk-YXZGYLKV.js +65 -0
  64. package/dist/chunk-ZICIXDEE.js +54 -0
  65. package/dist/chunk-ZMCO3O2Z.js +70 -0
  66. package/dist/clone-DpbVKLUu.d.ts +2205 -0
  67. package/dist/comment-Y2Y3QYYI.js +10 -0
  68. package/dist/crm-AAJXYIJY.js +68 -0
  69. package/dist/dashboard-3DC6B4BJ.js +10 -0
  70. package/dist/database/index.d.ts +882 -0
  71. package/dist/database/index.js +523 -0
  72. package/dist/database-DRGL5UYS.js +10 -0
  73. package/dist/database-field-F47FY3XX.js +10 -0
  74. package/dist/database-row-77OXW2NF.js +10 -0
  75. package/dist/database-select-option-6S3TTA7A.js +10 -0
  76. package/dist/database-view-YW7DQG5X.js +10 -0
  77. package/dist/experiment-TJOAL3OH.js +10 -0
  78. package/dist/external-item-D654PKLI.js +14 -0
  79. package/dist/external-reference-K5SUJIQN.js +8 -0
  80. package/dist/feed-L23XTNDI.js +12 -0
  81. package/dist/feed-item-GSO242J6.js +12 -0
  82. package/dist/folder-ONKSWHUT.js +21 -0
  83. package/dist/game-BF7DP5JU.js +50 -0
  84. package/dist/grant-NNKMWXPX.js +8 -0
  85. package/dist/grant-expiration-cleaner-DBiNTWbD.d.ts +249 -0
  86. package/dist/import-batch-JMESZ4VI.js +12 -0
  87. package/dist/inbox-state-AN6FPCIY.js +12 -0
  88. package/dist/index.d.ts +224 -4548
  89. package/dist/index.js +2206 -4754
  90. package/dist/map-AUV65YS3.js +10 -0
  91. package/dist/media-asset-4I5YPR4R.js +8 -0
  92. package/dist/memory-NV6EVJBE.js +12 -0
  93. package/dist/metric-X7W55DLC.js +10 -0
  94. package/dist/milestone-JJGOGK4R.js +12 -0
  95. package/dist/moderation-QSUVBCNS.js +30 -0
  96. package/dist/observation-UZSXXGBC.js +10 -0
  97. package/dist/page-NI7XODS6.js +10 -0
  98. package/dist/posting-FZOYVGH2.js +12 -0
  99. package/dist/profile-42A43GES.js +8 -0
  100. package/dist/project-G2CTLDXY.js +10 -0
  101. package/dist/query-ast-CWo6_30h.d.ts +226 -0
  102. package/dist/reaction-VAQBVDUD.js +10 -0
  103. package/dist/registry-CQoN_p8U.d.ts +99 -0
  104. package/dist/saved-view-AOQHGHNM.js +10 -0
  105. package/dist/schema/index.d.ts +6182 -0
  106. package/dist/schema/index.js +631 -0
  107. package/dist/schema-extension-5BUXRDPB.js +18 -0
  108. package/dist/space-PZ737CIS.js +42 -0
  109. package/dist/space-membership-N35NRX6F.js +14 -0
  110. package/dist/store/index.d.ts +391 -0
  111. package/dist/store/index.js +135 -0
  112. package/dist/store-CvgiydME.d.ts +338 -0
  113. package/dist/sync/awareness.d.ts +69 -0
  114. package/dist/sync/awareness.js +20 -0
  115. package/dist/system-Q5I6STDC.js +38 -0
  116. package/dist/tag-C677GKQW.js +16 -0
  117. package/dist/task-WQLMPN5U.js +16 -0
  118. package/dist/task-view-T5S32V4L.js +10 -0
  119. package/dist/transaction-U3ITRGJP.js +12 -0
  120. package/dist/transcription-F3T23LLO.js +12 -0
  121. package/dist/types-Def-5Nka.d.ts +1525 -0
  122. package/dist/updates.d.ts +44 -0
  123. package/dist/updates.js +16 -0
  124. package/dist/user-widget-4SJJFPG5.js +8 -0
  125. package/dist/view-types-DSde-uT_.d.ts +316 -0
  126. package/package.json +32 -9
  127. package/dist/canvas-HSIKIQFK.js +0 -7
  128. package/dist/chunk-2L5ZUGG5.js +0 -53
  129. package/dist/chunk-4MTS5KAQ.js +0 -22
  130. package/dist/chunk-GZHARFKC.js +0 -25
  131. package/dist/chunk-WKIKJTI2.js +0 -45
  132. package/dist/comment-277JD7DV.js +0 -7
  133. package/dist/database-W3KEHLI3.js +0 -7
  134. package/dist/database-row-3O2QSNZN.js +0 -7
  135. package/dist/grant-QVZ454YC.js +0 -7
  136. package/dist/page-O4WTOIEO.js +0 -7
  137. package/dist/task-SEKAYJH7.js +0 -7
@@ -0,0 +1,142 @@
1
+ // src/database/fractional-index.ts
2
+ var ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
3
+ var BASE = ALPHABET.length;
4
+ var START_KEY = "a0";
5
+ var MIDPOINT_CHAR = ALPHABET[Math.floor(BASE / 2)];
6
+ function generateSortKey(before, after) {
7
+ if (!before && !after) {
8
+ return START_KEY;
9
+ }
10
+ if (before && !after) {
11
+ return incrementKey(before);
12
+ }
13
+ if (!before && after) {
14
+ return prependKey(after);
15
+ }
16
+ return midpointKey(before, after);
17
+ }
18
+ function generateSortKeyWithJitter(before, after) {
19
+ const base = generateSortKey(before, after);
20
+ const jitter = ALPHABET[randomInt(BASE)] + ALPHABET[randomInt(BASE)];
21
+ return base + jitter;
22
+ }
23
+ function incrementKey(key) {
24
+ const chars = key.split("");
25
+ let i = chars.length - 1;
26
+ while (i >= 0) {
27
+ const idx = ALPHABET.indexOf(chars[i]);
28
+ if (idx < BASE - 1) {
29
+ chars[i] = ALPHABET[idx + 1];
30
+ return chars.join("");
31
+ }
32
+ chars[i] = ALPHABET[0];
33
+ i--;
34
+ }
35
+ return key + ALPHABET[0];
36
+ }
37
+ function prependKey(key) {
38
+ const chars = key.split("");
39
+ for (let i = 0; i < chars.length; i++) {
40
+ const idx = ALPHABET.indexOf(chars[i]);
41
+ if (idx > 0) {
42
+ chars[i] = ALPHABET[idx - 1];
43
+ return chars.slice(0, i + 1).join("") + ALPHABET[BASE - 1];
44
+ }
45
+ }
46
+ return ALPHABET[0] + key.slice(1) + MIDPOINT_CHAR;
47
+ }
48
+ function midpointKey(before, after) {
49
+ if (before >= after) {
50
+ throw new Error(`Invalid key order: "${before}" >= "${after}"`);
51
+ }
52
+ const maxLen = Math.max(before.length, after.length) + 1;
53
+ const paddedBefore = before.padEnd(maxLen, ALPHABET[0]);
54
+ const paddedAfter = after.padEnd(maxLen, ALPHABET[0]);
55
+ for (let i = 0; i < maxLen; i++) {
56
+ const beforeIdx = ALPHABET.indexOf(paddedBefore[i]);
57
+ const afterIdx = ALPHABET.indexOf(paddedAfter[i]);
58
+ if (beforeIdx === afterIdx) {
59
+ continue;
60
+ }
61
+ if (afterIdx - beforeIdx > 1) {
62
+ const midIdx = Math.floor((beforeIdx + afterIdx) / 2);
63
+ return paddedBefore.slice(0, i) + ALPHABET[midIdx];
64
+ }
65
+ for (let j = i + 1; j < maxLen; j++) {
66
+ const bIdx = ALPHABET.indexOf(paddedBefore[j]);
67
+ const aIdx = ALPHABET.indexOf(paddedAfter[j]);
68
+ if (aIdx > bIdx + 1) {
69
+ const midIdx = Math.floor((bIdx + aIdx) / 2);
70
+ return paddedBefore.slice(0, j) + ALPHABET[midIdx];
71
+ } else if (aIdx > bIdx) {
72
+ continue;
73
+ } else {
74
+ const midIdx = Math.floor((bIdx + BASE) / 2);
75
+ return paddedBefore.slice(0, j) + ALPHABET[midIdx];
76
+ }
77
+ }
78
+ return before + MIDPOINT_CHAR;
79
+ }
80
+ for (let i = before.length; i < after.length; i++) {
81
+ const afterIdx = ALPHABET.indexOf(after[i]);
82
+ if (afterIdx > 0) {
83
+ const midIdx = Math.floor(afterIdx / 2);
84
+ return before + ALPHABET[0].repeat(i - before.length) + ALPHABET[midIdx];
85
+ }
86
+ }
87
+ return before + MIDPOINT_CHAR;
88
+ }
89
+ function isValidSortKey(key) {
90
+ if (!key || key.length === 0) return false;
91
+ return key.split("").every((c) => ALPHABET.includes(c));
92
+ }
93
+ function compareSortKeys(a, b) {
94
+ if (a < b) return -1;
95
+ if (a > b) return 1;
96
+ return 0;
97
+ }
98
+ function rebalanceSortKeys(rowIds) {
99
+ const result = /* @__PURE__ */ new Map();
100
+ if (rowIds.length === 0) {
101
+ return result;
102
+ }
103
+ for (let i = 0; i < rowIds.length; i++) {
104
+ const key = indexToKey(i, rowIds.length);
105
+ result.set(rowIds[i], key);
106
+ }
107
+ return result;
108
+ }
109
+ function indexToKey(index, total) {
110
+ const charCount = total <= BASE * BASE ? 2 : 3;
111
+ const range = Math.pow(BASE, charCount);
112
+ const step = Math.floor(range / (total + 1));
113
+ const value = step * (index + 1);
114
+ return valueToKey(value, charCount);
115
+ }
116
+ function valueToKey(value, length) {
117
+ let result = "";
118
+ let remaining = value;
119
+ for (let i = 0; i < length; i++) {
120
+ const idx = remaining % BASE;
121
+ result = ALPHABET[idx] + result;
122
+ remaining = Math.floor(remaining / BASE);
123
+ }
124
+ return result;
125
+ }
126
+ function randomInt(max) {
127
+ return Math.floor(Math.random() * max);
128
+ }
129
+ var MAX_KEY_LENGTH = 10;
130
+ function needsRebalancing(sortKeys) {
131
+ return sortKeys.some((key) => key.length > MAX_KEY_LENGTH);
132
+ }
133
+
134
+ export {
135
+ generateSortKey,
136
+ generateSortKeyWithJitter,
137
+ isValidSortKey,
138
+ compareSortKeys,
139
+ rebalanceSortKeys,
140
+ MAX_KEY_LENGTH,
141
+ needsRebalancing
142
+ };
@@ -0,0 +1,51 @@
1
+ import {
2
+ spaceCascadeAuthorization
3
+ } from "./chunk-6OPZJ7MG.js";
4
+ import {
5
+ checkbox,
6
+ created,
7
+ createdBy,
8
+ date,
9
+ defineSchema,
10
+ file,
11
+ json,
12
+ relation,
13
+ text
14
+ } from "./chunk-O64EK5FK.js";
15
+
16
+ // src/schema/schemas/chat-message.ts
17
+ var ChatMessageSchema = defineSchema({
18
+ name: "ChatMessage",
19
+ namespace: "xnet://xnet.fyi/",
20
+ properties: {
21
+ /** The channel this message belongs to */
22
+ channel: relation({ target: "xnet://xnet.fyi/Channel@1.0.0", required: true }),
23
+ /** Message body in GitHub-flavored markdown */
24
+ content: text({ required: true, maxLength: 1e4 }),
25
+ /** Thread root message (flat threading, like Comment.inReplyTo) */
26
+ inReplyTo: relation({ target: "xnet://xnet.fyi/ChatMessage@1.0.0" }),
27
+ /** Optional file attachments */
28
+ attachments: file({ multiple: true }),
29
+ /** Structured mentions ({ dids, room? }) — populated by the composer */
30
+ mentions: json({}),
31
+ /** Whether the message has been edited */
32
+ edited: checkbox({ default: false }),
33
+ /** When the message was last edited */
34
+ editedAt: date({}),
35
+ /** Soft tombstone: content removed, message shell kept for thread shape */
36
+ redacted: checkbox({ default: false }),
37
+ /** Workspace-wide labels from inline #hashtag pills (exploration 0169) */
38
+ tags: relation({ target: "xnet://xnet.fyi/Tag@1.0.0", multiple: true }),
39
+ /** Node ids from the composer's [[ link picks (exploration 0170) */
40
+ links: relation({ multiple: true }),
41
+ createdAt: created(),
42
+ createdBy: createdBy()
43
+ },
44
+ document: void 0,
45
+ // Inherits access from its home Space (exploration 0181/0192).
46
+ authorization: spaceCascadeAuthorization("channel")
47
+ });
48
+
49
+ export {
50
+ ChatMessageSchema
51
+ };
@@ -0,0 +1,415 @@
1
+ // src/store/query.ts
2
+ function sortRecord(record) {
3
+ if (!record) return void 0;
4
+ const entries = Object.entries(record).sort(([left], [right]) => left.localeCompare(right));
5
+ if (entries.length === 0) return void 0;
6
+ return Object.fromEntries(entries);
7
+ }
8
+ function normalizeSpatialPoint(point) {
9
+ return {
10
+ x: point.x,
11
+ y: point.y
12
+ };
13
+ }
14
+ function normalizeSpatialRect(rect) {
15
+ return {
16
+ x: rect.x,
17
+ y: rect.y,
18
+ width: rect.width,
19
+ height: rect.height
20
+ };
21
+ }
22
+ function normalizeSpatialFilter(spatial) {
23
+ if (!spatial) {
24
+ return void 0;
25
+ }
26
+ if (spatial.kind === "window") {
27
+ const overscan = spatial.overscan ?? 0;
28
+ return {
29
+ kind: "window",
30
+ rect: normalizeSpatialRect(spatial.rect),
31
+ fields: {
32
+ x: spatial.fields.x,
33
+ y: spatial.fields.y,
34
+ width: spatial.fields.width,
35
+ height: spatial.fields.height
36
+ },
37
+ ...overscan !== 0 ? { overscan } : {}
38
+ };
39
+ }
40
+ return {
41
+ kind: "radius",
42
+ center: normalizeSpatialPoint(spatial.center),
43
+ radius: spatial.radius,
44
+ fields: {
45
+ x: spatial.fields.x,
46
+ y: spatial.fields.y
47
+ }
48
+ };
49
+ }
50
+ function normalizeSearchFilter(search) {
51
+ if (typeof search === "string") {
52
+ const text2 = search.trim();
53
+ return text2.length > 0 ? { text: text2 } : void 0;
54
+ }
55
+ if (!search) {
56
+ return void 0;
57
+ }
58
+ const text = search.text.trim();
59
+ if (text.length === 0) {
60
+ return void 0;
61
+ }
62
+ const fields = search.fields ? [...new Set(search.fields)].filter((field) => field === "title" || field === "content").sort() : void 0;
63
+ return {
64
+ text,
65
+ ...fields && fields.length > 0 ? { fields } : {}
66
+ };
67
+ }
68
+ function normalizeMaterializedViewOptions(materializedView) {
69
+ if (typeof materializedView === "string") {
70
+ const viewId2 = materializedView.trim();
71
+ return viewId2.length > 0 ? { viewId: viewId2 } : void 0;
72
+ }
73
+ if (!materializedView) {
74
+ return void 0;
75
+ }
76
+ const viewId = materializedView.viewId.trim();
77
+ if (viewId.length === 0) {
78
+ return void 0;
79
+ }
80
+ const maxAgeMs = materializedView.maxAgeMs !== void 0 && Number.isFinite(materializedView.maxAgeMs) && materializedView.maxAgeMs >= 0 ? materializedView.maxAgeMs : void 0;
81
+ return {
82
+ viewId,
83
+ ...maxAgeMs !== void 0 ? { maxAgeMs } : {},
84
+ ...materializedView.forceRefresh ? { forceRefresh: true } : {}
85
+ };
86
+ }
87
+ var NODE_QUERY_CURSOR_PREFIX = "xnet-query-cursor:";
88
+ function encodeBase64Url(value) {
89
+ const bytes = new TextEncoder().encode(value);
90
+ let binary = "";
91
+ bytes.forEach((byte) => {
92
+ binary += String.fromCharCode(byte);
93
+ });
94
+ return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
95
+ }
96
+ function decodeBase64Url(value) {
97
+ const base64 = value.replaceAll("-", "+").replaceAll("_", "/");
98
+ const padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, "=");
99
+ const binary = atob(padded);
100
+ const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));
101
+ return new TextDecoder().decode(bytes);
102
+ }
103
+ function isSortDirection(value) {
104
+ return value === "asc" || value === "desc";
105
+ }
106
+ function isNodeQueryCursor(value) {
107
+ if (!value || typeof value !== "object") return false;
108
+ const cursor = value;
109
+ return cursor.version === 1 && typeof cursor.schemaId === "string" && typeof cursor.nodeId === "string" && Array.isArray(cursor.order) && cursor.order.every(
110
+ (entry) => entry && typeof entry === "object" && typeof entry.field === "string" && isSortDirection(entry.direction)
111
+ );
112
+ }
113
+ function getExplicitOrderEntries(descriptor) {
114
+ return Object.entries(descriptor.orderBy ?? {}).filter((entry) => isSortDirection(entry[1])).map(([field, direction]) => ({ field, direction }));
115
+ }
116
+ function getCursorOrderEntries(descriptor) {
117
+ const entries = getExplicitOrderEntries(descriptor);
118
+ return entries.length > 0 ? entries : [{ field: "updatedAt", direction: "desc" }];
119
+ }
120
+ function getSortOrderEntries(descriptor) {
121
+ const entries = getExplicitOrderEntries(descriptor);
122
+ if (entries.length === 0) {
123
+ return descriptor.after ? [...getCursorOrderEntries(descriptor), { field: "nodeId", direction: "asc" }] : [];
124
+ }
125
+ return [...entries, { field: "nodeId", direction: "asc" }];
126
+ }
127
+ function getOrderValue(node, field) {
128
+ if (field === "nodeId") return node.id;
129
+ if (field === "createdAt" || field === "updatedAt") return node[field];
130
+ return node.properties[field];
131
+ }
132
+ function compareOrderValues(leftValue, rightValue, direction) {
133
+ if (leftValue === rightValue) return 0;
134
+ if (leftValue == null) return direction === "asc" ? 1 : -1;
135
+ if (rightValue == null) return direction === "asc" ? -1 : 1;
136
+ const comparison = leftValue < rightValue ? -1 : 1;
137
+ return direction === "asc" ? comparison : -comparison;
138
+ }
139
+ function compareNodeToCursor(node, cursor) {
140
+ for (const entry of cursor.order) {
141
+ const comparison = compareOrderValues(
142
+ getOrderValue(node, entry.field),
143
+ entry.value,
144
+ entry.direction
145
+ );
146
+ if (comparison !== 0) return comparison;
147
+ }
148
+ return compareOrderValues(node.id, cursor.nodeId, "asc");
149
+ }
150
+ function filterAfterCursor(nodes, descriptor) {
151
+ if (!descriptor.after) return nodes;
152
+ const cursor = decodeNodeQueryCursor(descriptor.after);
153
+ if (!cursor || cursor.schemaId !== descriptor.schemaId) return nodes;
154
+ return nodes.filter((node) => compareNodeToCursor(node, cursor) > 0);
155
+ }
156
+ function encodeNodeQueryCursor(descriptor, node) {
157
+ const cursor = {
158
+ version: 1,
159
+ schemaId: descriptor.schemaId,
160
+ order: getCursorOrderEntries(descriptor).map((entry) => ({
161
+ field: entry.field,
162
+ direction: entry.direction,
163
+ value: getOrderValue(node, entry.field)
164
+ })),
165
+ nodeId: node.id
166
+ };
167
+ return `${NODE_QUERY_CURSOR_PREFIX}${encodeBase64Url(JSON.stringify(cursor))}`;
168
+ }
169
+ function decodeNodeQueryCursor(cursor) {
170
+ if (!cursor.startsWith(NODE_QUERY_CURSOR_PREFIX)) return null;
171
+ try {
172
+ const payload = JSON.parse(decodeBase64Url(cursor.slice(NODE_QUERY_CURSOR_PREFIX.length)));
173
+ return isNodeQueryCursor(payload) ? payload : null;
174
+ } catch {
175
+ return null;
176
+ }
177
+ }
178
+ function getNodeQuerySearchTokens(search) {
179
+ return tokenizeSearchText(search.text);
180
+ }
181
+ function tokenizeSearchText(text) {
182
+ const tokens = text.toLocaleLowerCase().match(/[\p{L}\p{N}_]+/gu);
183
+ return [...new Set(tokens ?? [])];
184
+ }
185
+ function extractTipTapText(value) {
186
+ if (!value || typeof value !== "object") {
187
+ return "";
188
+ }
189
+ const node = value;
190
+ const parts = [];
191
+ if (typeof node.text === "string") {
192
+ parts.push(node.text);
193
+ }
194
+ if (Array.isArray(node.content)) {
195
+ parts.push(...node.content.map(extractTipTapText));
196
+ }
197
+ return parts.join(" ").trim();
198
+ }
199
+ function getSearchableText(node, fields = ["title", "content"]) {
200
+ const parts = [];
201
+ if (fields.includes("title") && typeof node.properties.title === "string") {
202
+ parts.push(node.properties.title);
203
+ }
204
+ if (fields.includes("content")) {
205
+ const content = node.properties.content;
206
+ if (typeof content === "string") {
207
+ parts.push(content);
208
+ } else {
209
+ const richText = extractTipTapText(content);
210
+ if (richText.length > 0) {
211
+ parts.push(richText);
212
+ }
213
+ }
214
+ const description = node.properties.description;
215
+ if (typeof description === "string") {
216
+ parts.push(description);
217
+ }
218
+ const body = node.properties.body;
219
+ if (typeof body === "string") {
220
+ parts.push(body);
221
+ }
222
+ }
223
+ return parts.join(" ");
224
+ }
225
+ function getNumericProperty(properties, key) {
226
+ if (!key) {
227
+ return null;
228
+ }
229
+ const value = properties[key];
230
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
231
+ }
232
+ function matchesSpatialFilter(descriptor, node) {
233
+ const spatial = descriptor.spatial;
234
+ if (!spatial) {
235
+ return true;
236
+ }
237
+ const x = getNumericProperty(node.properties, spatial.fields.x);
238
+ const y = getNumericProperty(node.properties, spatial.fields.y);
239
+ if (x === null || y === null) {
240
+ return false;
241
+ }
242
+ if (spatial.kind === "radius") {
243
+ const dx = x - spatial.center.x;
244
+ const dy = y - spatial.center.y;
245
+ return dx * dx + dy * dy <= spatial.radius * spatial.radius;
246
+ }
247
+ const overscan = spatial.overscan ?? 0;
248
+ const left = spatial.rect.x - overscan;
249
+ const top = spatial.rect.y - overscan;
250
+ const right = spatial.rect.x + spatial.rect.width + overscan;
251
+ const bottom = spatial.rect.y + spatial.rect.height + overscan;
252
+ const width = getNumericProperty(node.properties, spatial.fields.width) ?? 0;
253
+ const height = getNumericProperty(node.properties, spatial.fields.height) ?? 0;
254
+ const nodeLeft = Math.min(x, x + width);
255
+ const nodeTop = Math.min(y, y + height);
256
+ const nodeRight = Math.max(x, x + width);
257
+ const nodeBottom = Math.max(y, y + height);
258
+ const isPointLike = width === 0 && height === 0;
259
+ if (isPointLike) {
260
+ return x >= left && x <= right && y >= top && y <= bottom;
261
+ }
262
+ return nodeRight >= left && nodeLeft <= right && nodeBottom >= top && nodeTop <= bottom;
263
+ }
264
+ function matchesSearchFilter(descriptor, node) {
265
+ const search = descriptor.search;
266
+ if (!search) {
267
+ return true;
268
+ }
269
+ const queryTokens = getNodeQuerySearchTokens(search);
270
+ if (queryTokens.length === 0) {
271
+ return false;
272
+ }
273
+ const searchableTokens = tokenizeSearchText(
274
+ getSearchableText(node, search.fields ?? ["title", "content"])
275
+ );
276
+ if (searchableTokens.length === 0) {
277
+ return false;
278
+ }
279
+ return queryTokens.every(
280
+ (queryToken) => searchableTokens.some((searchableToken) => searchableToken.startsWith(queryToken))
281
+ );
282
+ }
283
+ function createNodeQueryDescriptor(schemaId, options) {
284
+ return {
285
+ schemaId,
286
+ nodeId: options?.nodeId,
287
+ where: sortRecord(options?.where),
288
+ includeDeleted: options?.includeDeleted ?? false,
289
+ orderBy: sortRecord(options?.orderBy),
290
+ limit: options?.limit ?? options?.page?.first,
291
+ offset: options?.offset,
292
+ after: options?.page?.after,
293
+ count: options?.page?.count,
294
+ spatial: normalizeSpatialFilter(options?.spatial),
295
+ search: normalizeSearchFilter(options?.search),
296
+ materializedView: normalizeMaterializedViewOptions(options?.materializedView)
297
+ };
298
+ }
299
+ function nodeQueryDescriptorToOptions(descriptor) {
300
+ const options = {};
301
+ if (descriptor.nodeId) {
302
+ options.nodeId = descriptor.nodeId;
303
+ }
304
+ if (descriptor.where) {
305
+ options.where = descriptor.where;
306
+ }
307
+ if (descriptor.includeDeleted) {
308
+ options.includeDeleted = true;
309
+ }
310
+ if (descriptor.orderBy) {
311
+ options.orderBy = descriptor.orderBy;
312
+ }
313
+ if (descriptor.limit !== void 0) {
314
+ options.limit = descriptor.limit;
315
+ }
316
+ if (descriptor.offset !== void 0) {
317
+ options.offset = descriptor.offset;
318
+ }
319
+ if (descriptor.after || descriptor.count) {
320
+ options.page = {
321
+ first: descriptor.limit ?? 0,
322
+ ...descriptor.after ? { after: descriptor.after } : {},
323
+ ...descriptor.count ? { count: descriptor.count } : {}
324
+ };
325
+ }
326
+ if (descriptor.spatial) {
327
+ options.spatial = descriptor.spatial;
328
+ }
329
+ if (descriptor.search) {
330
+ options.search = descriptor.search;
331
+ }
332
+ if (descriptor.materializedView) {
333
+ options.materializedView = descriptor.materializedView;
334
+ }
335
+ return options;
336
+ }
337
+ function serializeNodeQueryDescriptor(descriptor) {
338
+ return JSON.stringify(descriptor);
339
+ }
340
+ function matchesNodeQueryDescriptor(descriptor, node) {
341
+ if (!node) return false;
342
+ if (node.schemaId !== descriptor.schemaId) return false;
343
+ if (descriptor.nodeId && node.id !== descriptor.nodeId) return false;
344
+ if (!descriptor.includeDeleted && node.deleted) return false;
345
+ if (descriptor.where) {
346
+ for (const [key, value] of Object.entries(descriptor.where)) {
347
+ if (node.properties[key] !== value) {
348
+ return false;
349
+ }
350
+ }
351
+ }
352
+ return matchesSpatialFilter(descriptor, node) && matchesSearchFilter(descriptor, node);
353
+ }
354
+ function filterNodeQueryResults(nodes, descriptor) {
355
+ return nodes.filter((node) => matchesNodeQueryDescriptor(descriptor, node));
356
+ }
357
+ function sortNodeQueryResults(nodes, descriptor) {
358
+ const entries = getSortOrderEntries(descriptor);
359
+ if (entries.length === 0) return nodes;
360
+ return [...nodes].sort((left, right) => {
361
+ for (const entry of entries) {
362
+ const comparison = compareOrderValues(
363
+ getOrderValue(left, entry.field),
364
+ getOrderValue(right, entry.field),
365
+ entry.direction
366
+ );
367
+ if (comparison !== 0) {
368
+ return comparison;
369
+ }
370
+ }
371
+ return 0;
372
+ });
373
+ }
374
+ function applyNodeQueryDescriptor(nodes, descriptor) {
375
+ const filtered = filterNodeQueryResults(nodes, descriptor);
376
+ const sorted = sortNodeQueryResults(filtered, descriptor);
377
+ const afterCursor = filterAfterCursor(sorted, descriptor);
378
+ const offset = descriptor.offset ?? 0;
379
+ if (descriptor.limit === void 0) {
380
+ return afterCursor.slice(offset);
381
+ }
382
+ return afterCursor.slice(offset, offset + descriptor.limit);
383
+ }
384
+ function nodeQueryDescriptorNeedsBoundedReload(descriptor) {
385
+ return descriptor.limit !== void 0 || (descriptor.offset ?? 0) > 0 || descriptor.after !== void 0;
386
+ }
387
+ function withoutNodeQueryPagination(descriptor) {
388
+ const next = { ...descriptor };
389
+ delete next.limit;
390
+ delete next.offset;
391
+ delete next.after;
392
+ delete next.count;
393
+ return next;
394
+ }
395
+ function withoutNodeQueryMaterializedView(descriptor) {
396
+ const next = { ...descriptor };
397
+ delete next.materializedView;
398
+ return next;
399
+ }
400
+
401
+ export {
402
+ encodeNodeQueryCursor,
403
+ decodeNodeQueryCursor,
404
+ getNodeQuerySearchTokens,
405
+ createNodeQueryDescriptor,
406
+ nodeQueryDescriptorToOptions,
407
+ serializeNodeQueryDescriptor,
408
+ matchesNodeQueryDescriptor,
409
+ filterNodeQueryResults,
410
+ sortNodeQueryResults,
411
+ applyNodeQueryDescriptor,
412
+ nodeQueryDescriptorNeedsBoundedReload,
413
+ withoutNodeQueryPagination,
414
+ withoutNodeQueryMaterializedView
415
+ };
@@ -1,20 +1,24 @@
1
+ import {
2
+ spaceCascadeAuthorization
3
+ } from "./chunk-6OPZJ7MG.js";
1
4
  import {
2
5
  defineSchema,
3
6
  relation,
4
7
  text
5
- } from "./chunk-SZC345Z2.js";
8
+ } from "./chunk-O64EK5FK.js";
6
9
 
7
10
  // src/schema/schemas/database-row.ts
8
11
  var DatabaseRowSchema = defineSchema({
9
12
  name: "DatabaseRow",
10
13
  namespace: "xnet://xnet.fyi/",
14
+ version: "2.0.0",
11
15
  properties: {
12
16
  /**
13
17
  * Reference to the parent database.
14
18
  * This is a typed relation that only accepts Database node IDs.
15
19
  */
16
20
  database: relation({
17
- target: "xnet://xnet.fyi/Database@1.0.0",
21
+ target: "xnet://xnet.fyi/Database@2.0.0",
18
22
  required: true
19
23
  }),
20
24
  /**
@@ -31,7 +35,9 @@ var DatabaseRowSchema = defineSchema({
31
35
  * Only created when the row has rich text columns.
32
36
  * Each rich text column gets its own Y.XmlFragment in the doc.
33
37
  */
34
- document: "yjs"
38
+ document: "yjs",
39
+ // Inherits access from its home Space (exploration 0181/0192).
40
+ authorization: spaceCascadeAuthorization("database")
35
41
  });
36
42
 
37
43
  export {
@@ -0,0 +1,50 @@
1
+ import {
2
+ spaceCascadeAuthorization
3
+ } from "./chunk-6OPZJ7MG.js";
4
+ import {
5
+ defineSchema,
6
+ file,
7
+ relation,
8
+ select,
9
+ text
10
+ } from "./chunk-O64EK5FK.js";
11
+
12
+ // src/schema/schemas/page.ts
13
+ var PageSchema = defineSchema({
14
+ name: "Page",
15
+ namespace: "xnet://xnet.fyi/",
16
+ properties: {
17
+ /** Page title */
18
+ title: text({ required: true, maxLength: 500 }),
19
+ /** Emoji or icon URL */
20
+ icon: text({}),
21
+ /** Cover image */
22
+ cover: file({ accept: ["image/*"] }),
23
+ /** Canonical home; empty = Unfiled (exploration 0169) */
24
+ folder: relation({ target: "xnet://xnet.fyi/Folder@1.0.0" }),
25
+ /** Order among folder siblings — fractional index */
26
+ sortKey: text({ maxLength: 500 }),
27
+ /** Workspace-wide labels, referenced by id (exploration 0169) */
28
+ tags: relation({ target: "xnet://xnet.fyi/Tag@1.0.0", multiple: true }),
29
+ /** Canonical SECURITY home; empty = personal/private (exploration 0179) */
30
+ space: relation({ target: "xnet://xnet.fyi/Space@1.0.0" }),
31
+ /** Per-node visibility; `inherit` defers to the Space (exploration 0179) */
32
+ visibility: select({
33
+ options: [
34
+ { id: "inherit", name: "Inherit", color: "gray" },
35
+ { id: "private", name: "Private", color: "gray" },
36
+ { id: "unlisted", name: "Unlisted", color: "yellow" },
37
+ { id: "public", name: "Public", color: "green" }
38
+ ],
39
+ default: "inherit"
40
+ })
41
+ },
42
+ document: "yjs",
43
+ // Collaborative Y.Doc for rich text
44
+ // Inherits access from its home Space (exploration 0181/0192).
45
+ authorization: spaceCascadeAuthorization()
46
+ });
47
+
48
+ export {
49
+ PageSchema
50
+ };