teamplay 0.4.0 → 0.5.0-alpha.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.
Files changed (237) hide show
  1. package/babel-loader.cjs +1 -0
  2. package/babel.cjs +1 -0
  3. package/dist/connect/index.d.ts +1 -0
  4. package/dist/connect/index.js +9 -0
  5. package/dist/connect/lib/sharedb-crosstab-pubsub.d.cts +10 -0
  6. package/dist/connect/offline/index.d.ts +1 -0
  7. package/dist/connect/offline/index.js +126 -0
  8. package/dist/connect/offline/react-native.d.ts +10 -0
  9. package/dist/connect/offline/react-native.js +25 -0
  10. package/dist/connect/offline/web.d.ts +9 -0
  11. package/dist/connect/offline/web.js +12 -0
  12. package/dist/connect/sharedbConnection.d.cts +2 -0
  13. package/dist/connect/test.d.ts +1 -0
  14. package/dist/connect/test.js +12 -0
  15. package/dist/index.d.ts +66 -0
  16. package/dist/index.js +74 -0
  17. package/dist/orm/$.d.ts +9 -0
  18. package/dist/orm/$.js +34 -0
  19. package/dist/orm/Aggregation.d.ts +17 -0
  20. package/dist/orm/Aggregation.js +115 -0
  21. package/dist/orm/Cache.d.ts +9 -0
  22. package/dist/orm/Cache.js +32 -0
  23. package/dist/orm/Compat/SignalCompat.d.ts +3 -0
  24. package/dist/orm/Compat/SignalCompat.js +1542 -0
  25. package/dist/orm/Compat/eventsCompat.d.ts +3 -0
  26. package/dist/orm/Compat/eventsCompat.js +73 -0
  27. package/dist/orm/Compat/hooksCompat.d.ts +33 -0
  28. package/dist/orm/Compat/hooksCompat.js +360 -0
  29. package/dist/orm/Compat/modelEvents.d.ts +6 -0
  30. package/dist/orm/Compat/modelEvents.js +228 -0
  31. package/dist/orm/Compat/queryReadiness.d.ts +5 -0
  32. package/dist/orm/Compat/queryReadiness.js +185 -0
  33. package/dist/orm/Compat/refFallback.d.ts +13 -0
  34. package/dist/orm/Compat/refFallback.js +65 -0
  35. package/dist/orm/Compat/refRegistry.d.ts +6 -0
  36. package/dist/orm/Compat/refRegistry.js +54 -0
  37. package/dist/orm/Compat/silentContext.d.ts +5 -0
  38. package/dist/orm/Compat/silentContext.js +48 -0
  39. package/dist/orm/Compat/startStopCompat.d.ts +3 -0
  40. package/dist/orm/Compat/startStopCompat.js +217 -0
  41. package/dist/orm/Doc.d.ts +96 -0
  42. package/dist/orm/Doc.js +966 -0
  43. package/dist/orm/Query.d.ts +117 -0
  44. package/dist/orm/Query.js +1111 -0
  45. package/dist/orm/Reaction.d.ts +10 -0
  46. package/dist/orm/Reaction.js +41 -0
  47. package/dist/orm/Root.d.ts +22 -0
  48. package/dist/orm/Root.js +85 -0
  49. package/dist/orm/Signal.d.ts +12 -0
  50. package/dist/orm/Signal.js +7 -0
  51. package/dist/orm/SignalBase.d.ts +168 -0
  52. package/dist/orm/SignalBase.js +625 -0
  53. package/dist/orm/SubscriptionState.d.ts +17 -0
  54. package/dist/orm/SubscriptionState.js +123 -0
  55. package/dist/orm/Value.d.ts +9 -0
  56. package/dist/orm/Value.js +25 -0
  57. package/dist/orm/addModel.d.ts +6 -0
  58. package/dist/orm/addModel.js +39 -0
  59. package/dist/orm/associations.d.ts +18 -0
  60. package/dist/orm/associations.js +70 -0
  61. package/dist/orm/batchScheduler.d.ts +7 -0
  62. package/dist/orm/batchScheduler.js +62 -0
  63. package/dist/orm/compatEnv.d.ts +1 -0
  64. package/dist/orm/compatEnv.js +4 -0
  65. package/dist/orm/connection.d.ts +26 -0
  66. package/dist/orm/connection.js +38 -0
  67. package/dist/orm/dataTree.d.ts +34 -0
  68. package/dist/orm/dataTree.js +880 -0
  69. package/dist/orm/disposeRootContext.d.ts +4 -0
  70. package/dist/orm/disposeRootContext.js +59 -0
  71. package/dist/orm/getSignal.d.ts +16 -0
  72. package/dist/orm/getSignal.js +133 -0
  73. package/dist/orm/idFields.d.ts +14 -0
  74. package/dist/orm/idFields.js +95 -0
  75. package/dist/orm/index.d.ts +7 -0
  76. package/dist/orm/index.js +6 -0
  77. package/dist/orm/initModels.d.ts +5 -0
  78. package/dist/orm/initModels.js +74 -0
  79. package/dist/orm/missingDoc.d.ts +1 -0
  80. package/dist/orm/missingDoc.js +3 -0
  81. package/dist/orm/pluralize.d.ts +12 -0
  82. package/dist/orm/privateData.d.ts +22 -0
  83. package/dist/orm/privateData.js +170 -0
  84. package/dist/orm/rootContext.d.ts +78 -0
  85. package/dist/orm/rootContext.js +297 -0
  86. package/dist/orm/rootScope.d.ts +12 -0
  87. package/dist/orm/rootScope.js +46 -0
  88. package/dist/orm/signalArrayReaders.d.ts +22 -0
  89. package/dist/orm/signalArrayReaders.js +42 -0
  90. package/dist/orm/signalMetadata.d.ts +17 -0
  91. package/dist/orm/signalMetadata.js +56 -0
  92. package/dist/orm/signalMutationGuards.d.ts +4 -0
  93. package/dist/orm/signalMutationGuards.js +14 -0
  94. package/dist/orm/signalPathKind.d.ts +2 -0
  95. package/dist/orm/signalPathKind.js +10 -0
  96. package/dist/orm/signalPathRules.d.ts +6 -0
  97. package/dist/orm/signalPathRules.js +28 -0
  98. package/dist/orm/signalReads.d.ts +26 -0
  99. package/dist/orm/signalReads.js +64 -0
  100. package/dist/orm/signalRuntimeAccess.d.ts +16 -0
  101. package/dist/orm/signalRuntimeAccess.js +24 -0
  102. package/dist/orm/signalRuntimeDescriptor.d.ts +19 -0
  103. package/dist/orm/signalRuntimeDescriptor.js +97 -0
  104. package/dist/orm/signalStorageMutations.d.ts +18 -0
  105. package/dist/orm/signalStorageMutations.js +26 -0
  106. package/dist/orm/signalSymbols.d.ts +5 -0
  107. package/dist/orm/signalSymbols.js +5 -0
  108. package/dist/orm/signalValueMutations.d.ts +14 -0
  109. package/dist/orm/signalValueMutations.js +36 -0
  110. package/dist/orm/sub.d.ts +37 -0
  111. package/dist/orm/sub.js +187 -0
  112. package/dist/orm/subscriptionGcDelay.d.ts +4 -0
  113. package/dist/orm/subscriptionGcDelay.js +26 -0
  114. package/dist/orm/types/baseMethods.d.ts +43 -0
  115. package/dist/orm/types/baseMethods.js +1 -0
  116. package/dist/orm/types/jsonSchema.d.ts +75 -0
  117. package/dist/orm/types/jsonSchema.js +1 -0
  118. package/dist/orm/types/modelManifest.d.ts +37 -0
  119. package/dist/orm/types/modelManifest.js +1 -0
  120. package/dist/orm/types/path.d.ts +8 -0
  121. package/dist/orm/types/path.js +1 -0
  122. package/dist/orm/types/query.d.ts +29 -0
  123. package/dist/orm/types/query.js +1 -0
  124. package/dist/orm/types/signal.d.ts +132 -0
  125. package/dist/orm/types/signal.js +1 -0
  126. package/dist/react/compatComponentRegistry.d.ts +4 -0
  127. package/dist/react/compatComponentRegistry.js +19 -0
  128. package/dist/react/convertToObserver.d.ts +26 -0
  129. package/dist/react/convertToObserver.js +114 -0
  130. package/dist/react/executionContextTracker.d.ts +11 -0
  131. package/dist/react/executionContextTracker.js +28 -0
  132. package/dist/react/helpers.d.ts +34 -0
  133. package/dist/react/helpers.js +134 -0
  134. package/dist/react/observer.d.ts +22 -0
  135. package/dist/react/observer.js +8 -0
  136. package/dist/react/promiseBatcher.d.ts +13 -0
  137. package/dist/react/promiseBatcher.js +118 -0
  138. package/dist/react/renderAttemptDestroyer.d.ts +19 -0
  139. package/dist/react/renderAttemptDestroyer.js +46 -0
  140. package/dist/react/trapRender.d.ts +6 -0
  141. package/dist/react/trapRender.js +48 -0
  142. package/dist/react/universal$.d.ts +1 -0
  143. package/dist/react/universal$.js +18 -0
  144. package/dist/react/universalSub.d.ts +1 -0
  145. package/dist/react/universalSub.js +22 -0
  146. package/dist/react/useApi.d.ts +13 -0
  147. package/dist/react/useApi.js +67 -0
  148. package/dist/react/useSub.d.ts +102 -0
  149. package/dist/react/useSub.js +189 -0
  150. package/dist/react/useSuspendMemo.d.ts +3 -0
  151. package/dist/react/useSuspendMemo.js +102 -0
  152. package/dist/react/wrapIntoSuspense.d.ts +9 -0
  153. package/dist/react/wrapIntoSuspense.js +102 -0
  154. package/dist/server.d.ts +11 -0
  155. package/dist/server.js +28 -0
  156. package/dist/utils/MockFinalizationRegistry.d.ts +37 -0
  157. package/dist/utils/MockFinalizationRegistry.js +85 -0
  158. package/dist/utils/MockWeakRef.d.ts +12 -0
  159. package/dist/utils/MockWeakRef.js +23 -0
  160. package/dist/utils/isServer.d.ts +3 -0
  161. package/dist/utils/isServer.js +18 -0
  162. package/dist/utils/setDiffDeep.d.ts +1 -0
  163. package/dist/utils/setDiffDeep.js +61 -0
  164. package/dist/utils/useIsomorphicLayoutEffect.d.ts +3 -0
  165. package/dist/utils/useIsomorphicLayoutEffect.js +3 -0
  166. package/file-based-models.js +3 -0
  167. package/file-based-models.node.js +6 -0
  168. package/package.json +77 -32
  169. package/teamplay.models.auto-init.virtual.js +1 -0
  170. package/teamplay.models.virtual.js +1 -0
  171. package/connect/index.js +0 -9
  172. package/connect/offline/index.js +0 -124
  173. package/connect/offline/react-native.js +0 -28
  174. package/connect/offline/web.js +0 -15
  175. package/connect/test.js +0 -12
  176. package/index.d.ts +0 -106
  177. package/index.js +0 -125
  178. package/orm/$.js +0 -38
  179. package/orm/Aggregation.js +0 -117
  180. package/orm/Cache.js +0 -46
  181. package/orm/Compat/README.md +0 -1064
  182. package/orm/Compat/SignalCompat.js +0 -1479
  183. package/orm/Compat/eventsCompat.js +0 -79
  184. package/orm/Compat/hooksCompat.js +0 -374
  185. package/orm/Compat/modelEvents.js +0 -225
  186. package/orm/Compat/queryReadiness.js +0 -191
  187. package/orm/Compat/refFallback.js +0 -62
  188. package/orm/Compat/refRegistry.js +0 -61
  189. package/orm/Compat/silentContext.js +0 -51
  190. package/orm/Compat/startStopCompat.js +0 -207
  191. package/orm/Doc.js +0 -969
  192. package/orm/Query.js +0 -1127
  193. package/orm/Reaction.js +0 -48
  194. package/orm/Root.js +0 -88
  195. package/orm/Signal.js +0 -22
  196. package/orm/SignalBase.js +0 -696
  197. package/orm/SubscriptionState.js +0 -138
  198. package/orm/Value.js +0 -30
  199. package/orm/addModel.js +0 -31
  200. package/orm/associations.js +0 -97
  201. package/orm/batchScheduler.js +0 -62
  202. package/orm/compatEnv.js +0 -4
  203. package/orm/connection.js +0 -46
  204. package/orm/dataTree.js +0 -869
  205. package/orm/disposeRootContext.js +0 -68
  206. package/orm/getSignal.js +0 -130
  207. package/orm/idFields.js +0 -88
  208. package/orm/index.d.ts +0 -6
  209. package/orm/index.js +0 -5
  210. package/orm/missingDoc.js +0 -3
  211. package/orm/privateData.js +0 -181
  212. package/orm/rootContext.js +0 -313
  213. package/orm/rootScope.js +0 -51
  214. package/orm/sub.js +0 -151
  215. package/orm/subscriptionGcDelay.js +0 -32
  216. package/react/compatComponentRegistry.js +0 -20
  217. package/react/convertToObserver.js +0 -117
  218. package/react/executionContextTracker.js +0 -32
  219. package/react/helpers.js +0 -141
  220. package/react/observer.js +0 -9
  221. package/react/promiseBatcher.js +0 -115
  222. package/react/renderAttemptDestroyer.js +0 -47
  223. package/react/trapRender.js +0 -50
  224. package/react/universal$.js +0 -18
  225. package/react/universalSub.js +0 -21
  226. package/react/useApi.js +0 -63
  227. package/react/useSub.js +0 -169
  228. package/react/useSuspendMemo.js +0 -96
  229. package/react/wrapIntoSuspense.js +0 -119
  230. package/server.js +0 -31
  231. package/utils/MockFinalizationRegistry.js +0 -94
  232. package/utils/MockWeakRef.js +0 -25
  233. package/utils/isServer.js +0 -17
  234. package/utils/setDiffDeep.js +0 -58
  235. package/utils/useIsomorphicLayoutEffect.js +0 -4
  236. /package/{connect → dist/connect}/lib/sharedb-crosstab-pubsub.cjs +0 -0
  237. /package/{connect → dist/connect}/sharedbConnection.cjs +0 -0
@@ -0,0 +1 @@
1
+ module.exports = require('babel-plugin-teamplay/loader')
package/babel.cjs ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('babel-plugin-teamplay')
@@ -0,0 +1 @@
1
+ export default function connect(options: any): void;
@@ -0,0 +1,9 @@
1
+ import Socket from '@teamplay/channel';
2
+ import Connection from './sharedbConnection.cjs';
3
+ import { connection, setConnection } from "../orm/connection.js";
4
+ export default function connect(options) {
5
+ if (connection)
6
+ return;
7
+ const socket = new Socket(options);
8
+ setConnection(new Connection(socket));
9
+ }
@@ -0,0 +1,10 @@
1
+ export = CrossTabPubSub;
2
+ declare function CrossTabPubSub({ onMessage, ...options }?: {}): CrossTabPubSub;
3
+ declare class CrossTabPubSub {
4
+ constructor({ onMessage, ...options }?: {});
5
+ _onMessage: any;
6
+ close(callback: any): void;
7
+ _subscribe(channel: any, callback: any): any;
8
+ _unsubscribe(channel: any, callback: any): any;
9
+ _publish(channels: any, data: any, callback: any): any;
10
+ }
@@ -0,0 +1 @@
1
+ export default function createConnectWithPersistence({ storage, createPubsub }?: {}): () => Promise<void>;
@@ -0,0 +1,126 @@
1
+ // Offline 'connect' implementation with persistence to local storage.
2
+ // This creates a full sharedb server with mingo database in the browser or react-native app.
3
+ import ShareDbMingo from '@startupjs/sharedb-mingo-memory';
4
+ import ShareBackend from 'sharedb';
5
+ import { connection, setConnection } from "../../orm/connection.js";
6
+ const STORAGE_NAMESPACE = 'teamplay-offline';
7
+ const DOCS_PREFIX = `${STORAGE_NAMESPACE}:docs:`;
8
+ const LAST_OP_PREFIX = `${STORAGE_NAMESPACE}:last-op:`;
9
+ export default function createConnectWithPersistence({ storage, createPubsub } = {}) {
10
+ if (!storage)
11
+ throw new Error('[connect-offline] storage is required');
12
+ return async function connect() {
13
+ if (connection)
14
+ return;
15
+ const db = new ShareDbMingo();
16
+ const options = { db };
17
+ const { pubsub } = (await init(db, storage, createPubsub)) || {};
18
+ if (pubsub)
19
+ options.pubsub = pubsub;
20
+ const backend = new ShareBackend(options);
21
+ setConnection(backend.connect());
22
+ };
23
+ }
24
+ async function init(db, storage, createPubsub) {
25
+ await loadData(db, storage);
26
+ addPersistence(db, storage);
27
+ globalThis.db = db;
28
+ const pubsub = createPubsub
29
+ ? createPubsub((channel, data) => {
30
+ if (!(data?.c && data?.d))
31
+ return;
32
+ updateDocInDb(db, storage, data.c, data.d);
33
+ })
34
+ : null;
35
+ return { pubsub };
36
+ }
37
+ // do same thing as in loadData but for a single doc
38
+ async function updateDocInDb(db, storage, collection, docId) {
39
+ try {
40
+ const snapshot = await storage.getItem(getDocsKey(collection, docId));
41
+ if (!snapshot)
42
+ return;
43
+ if (!db.docs[collection]) {
44
+ db.docs[collection] = {};
45
+ db.ops[collection] = {};
46
+ }
47
+ if (snapshot && typeof snapshot === 'object' && snapshot.v == null)
48
+ snapshot.v = 0;
49
+ db.docs[collection][docId] = snapshot;
50
+ if (!db.ops[collection])
51
+ db.ops[collection] = {};
52
+ const lastOp = await storage.getItem(getLastOpKey(collection, docId));
53
+ db.ops[collection][docId] = buildOpsArray(lastOp);
54
+ }
55
+ catch (err) {
56
+ console.error('Error updating doc from storage:', err);
57
+ }
58
+ }
59
+ async function loadData(db, storage) {
60
+ const docsToLoad = [];
61
+ await storage.iterate((value, key) => {
62
+ const parsedKey = parseStorageKey(key);
63
+ if (!parsedKey || parsedKey.type !== 'docs')
64
+ return;
65
+ const { collection, docId } = parsedKey;
66
+ if (!db.docs[collection]) {
67
+ db.docs[collection] = {};
68
+ db.ops[collection] = {};
69
+ }
70
+ // We don't support multiplayer in offline-only mode.
71
+ // Note: if you have multiple tabs open in browser then the last operation wins.
72
+ if (value && typeof value === 'object' && value.v == null)
73
+ value.v = 0;
74
+ db.docs[collection][docId] = value;
75
+ if (!db.ops[collection][docId])
76
+ db.ops[collection][docId] = [];
77
+ docsToLoad.push({ collection, docId });
78
+ });
79
+ for (const { collection, docId } of docsToLoad) {
80
+ const lastOp = await storage.getItem(getLastOpKey(collection, docId));
81
+ if (!db.ops[collection])
82
+ db.ops[collection] = {};
83
+ db.ops[collection][docId] = buildOpsArray(lastOp);
84
+ }
85
+ console.log('DB data was loaded from storage to shareDbMingo');
86
+ }
87
+ function addPersistence(db, storage) {
88
+ const originalCommit = db.commit;
89
+ db.commit = function (collection, docId, op, snapshot, options, callback) {
90
+ originalCommit.call(this, collection, docId, op, snapshot, options, async (err) => {
91
+ if (err)
92
+ return callback(err);
93
+ try {
94
+ await storage.setItem(getDocsKey(collection, docId), snapshot);
95
+ await storage.setItem(getLastOpKey(collection, docId), op);
96
+ }
97
+ catch (err) {
98
+ throw Error('Error saving to storage:\n', err.message);
99
+ }
100
+ callback(null, true);
101
+ });
102
+ };
103
+ }
104
+ function parseStorageKey(key) {
105
+ const [namespace, type, collection, ...docSegments] = key.split(':');
106
+ if (namespace !== STORAGE_NAMESPACE)
107
+ return null;
108
+ return { type, collection, docId: docSegments.join(':') };
109
+ }
110
+ function getDocsKey(collection, docId) {
111
+ return `${DOCS_PREFIX}${collection}:${docId}`;
112
+ }
113
+ function getLastOpKey(collection, docId) {
114
+ return `${LAST_OP_PREFIX}${collection}:${docId}`;
115
+ }
116
+ function buildOpsArray(lastOp) {
117
+ if (!lastOp)
118
+ return [];
119
+ const version = lastOp.v;
120
+ if (Number.isFinite(version) && version > 0) {
121
+ const ops = new Array(version + 1);
122
+ ops[version] = lastOp;
123
+ return ops;
124
+ }
125
+ return [lastOp];
126
+ }
@@ -0,0 +1,10 @@
1
+ export namespace storage {
2
+ export { getItem };
3
+ export { setItem };
4
+ export { iterate };
5
+ }
6
+ declare const _default: () => Promise<void>;
7
+ export default _default;
8
+ declare function getItem(key: any): Promise<any>;
9
+ declare function setItem(key: any, value: any): Promise<any>;
10
+ declare function iterate(iterator: any): Promise<void>;
@@ -0,0 +1,25 @@
1
+ import AsyncStorage from '@react-native-async-storage/async-storage';
2
+ import createConnectWithPersistence from './index.js';
3
+ async function getItem(key) {
4
+ const value = await AsyncStorage.getItem(key);
5
+ if (value == null)
6
+ return null;
7
+ try {
8
+ return JSON.parse(value);
9
+ }
10
+ catch {
11
+ return value;
12
+ }
13
+ }
14
+ async function setItem(key, value) {
15
+ return AsyncStorage.setItem(key, JSON.stringify(value));
16
+ }
17
+ async function iterate(iterator) {
18
+ const keys = await AsyncStorage.getAllKeys();
19
+ for (const key of keys) {
20
+ const value = await getItem(key);
21
+ await iterator(value, key);
22
+ }
23
+ }
24
+ export const storage = { getItem, setItem, iterate };
25
+ export default createConnectWithPersistence({ storage });
@@ -0,0 +1,9 @@
1
+ export function createPubsub(onMessage: any): SharedbCrosstabPubsub;
2
+ export namespace storage {
3
+ function getItem(key: any): Promise<any>;
4
+ function setItem(key: any, value: any): Promise<any>;
5
+ function iterate(iterator: any): Promise<any>;
6
+ }
7
+ declare const _default: () => Promise<void>;
8
+ export default _default;
9
+ import SharedbCrosstabPubsub from '../lib/sharedb-crosstab-pubsub.cjs';
@@ -0,0 +1,12 @@
1
+ import localforage from 'localforage';
2
+ import SharedbCrosstabPubsub from '../lib/sharedb-crosstab-pubsub.cjs';
3
+ import createConnectWithPersistence from './index.js';
4
+ export const storage = {
5
+ getItem: key => localforage.getItem(key),
6
+ setItem: (key, value) => localforage.setItem(key, value),
7
+ iterate: iterator => localforage.iterate(iterator)
8
+ };
9
+ export function createPubsub(onMessage) {
10
+ return new SharedbCrosstabPubsub({ onMessage });
11
+ }
12
+ export default createConnectWithPersistence({ storage, createPubsub });
@@ -0,0 +1,2 @@
1
+ declare const _exports: any;
2
+ export = _exports;
@@ -0,0 +1 @@
1
+ export default function connect(): void;
@@ -0,0 +1,12 @@
1
+ // mock of client connection to sharedb to use inside tests.
2
+ // This just creates a sharedb server with in-memory database
3
+ // and creates a server connection to it.
4
+ import ShareDbMingo from '@startupjs/sharedb-mingo-memory';
5
+ import ShareBackend from 'sharedb';
6
+ import { connection, setConnection } from "../orm/connection.js";
7
+ export default function connect() {
8
+ if (connection)
9
+ return;
10
+ const backend = new ShareBackend({ db: new ShareDbMingo() });
11
+ setConnection(backend.connect());
12
+ }
@@ -0,0 +1,66 @@
1
+ import type * as React from 'react';
2
+ import { SEGMENTS } from './orm/Signal.js';
3
+ import useApi from './react/useApi.js';
4
+ import type { AnySignal, ArraySignal, CollectionDocument, CollectionDocumentModel, CollectionSignal, CollectionSignalFromSpec, CollectionAggregationSignal, CollectionQuerySignal, CollectionSpec, CollectionsFromManifest, DocumentSignal, FromJsonSchema, JsonSchema, JsonSchemaSpec, MaybePromise, MaybePromiseSubResult, ModelEntry, ModelManifest, PathModelsFromManifest, PublicSignal, LocalSignalFactory, RuntimeSignalConstructor, RuntimeSignalInstance, RootCollections, RootSignal, WildcardPathSegment, WildcardSignalPath, AppendPath, JoinPath, QueryParams, QuerySignal, RegisteredAggregationInput, SignalChild, SignalBaseInstance, SignalArrayMutatorMethods, SignalArrayReaderMethods, SignalClass, SignalCollectionMethods, SignalConstructor, SignalForKind, SignalKind, SignalMetadataMethods, SignalModelConstructor, SignalStringMutatorMethods, SignalValueMethods, SubResult, TypedAggregationInput, TypedAggregationSignal, TypedSignal, ZodLikeSchema, ZodSchemaSpec } from './orm/Signal.js';
5
+ export interface TeamplayCollections {
6
+ }
7
+ export interface TeamplayModels {
8
+ }
9
+ export interface TeamplaySignalFields {
10
+ }
11
+ export type Signal<TValue = unknown> = PublicSignal<TValue>;
12
+ export type { AnySignal, ArraySignal, CollectionDocument, CollectionDocumentModel, CollectionSignal, CollectionSpec, CollectionSignalFromSpec, CollectionAggregationSignal, CollectionQuerySignal, DocumentSignal, FromJsonSchema, JsonSchema, JsonSchemaSpec, MaybePromise, MaybePromiseSubResult, ModelEntry, ModelManifest, CollectionsFromManifest, LocalSignalFactory, PathModelsFromManifest, PublicSignal, RuntimeSignalConstructor, RuntimeSignalInstance, RootCollections, RootSignal, WildcardPathSegment, WildcardSignalPath, AppendPath, JoinPath, QueryParams, QuerySignal, RegisteredAggregationInput, SignalArrayMutatorMethods, SignalArrayReaderMethods, SignalBaseInstance, SignalClass, SignalChild, SignalConstructor, SignalCollectionMethods, SignalForKind, SignalKind, SignalMetadataMethods, SignalModelConstructor, SignalStringMutatorMethods, SignalValueMethods, SubResult, TypedAggregationInput, TypedAggregationSignal, TypedSignal, ZodLikeSchema, ZodSchemaSpec };
13
+ export interface ObserverOptions {
14
+ forwardRef?: boolean;
15
+ cache?: boolean;
16
+ throttle?: number | boolean;
17
+ defer?: boolean | number;
18
+ suspenseProps?: React.ComponentProps<typeof React.Suspense>;
19
+ }
20
+ export type ObserverComponent<TProps extends object> = (props: TProps) => React.ReactNode;
21
+ export type ObserverForwardRefComponent<TProps extends object, TRef> = (props: TProps, ref: React.ForwardedRef<TRef>) => React.ReactNode;
22
+ export type ObserverForwardRefOptions = Omit<ObserverOptions, 'forwardRef'> & {
23
+ forwardRef: true;
24
+ };
25
+ export interface ObserverFunction {
26
+ <TProps extends object, TRef = unknown>(Component: ObserverForwardRefComponent<TProps, TRef>, options: ObserverForwardRefOptions): React.NamedExoticComponent<React.PropsWithoutRef<TProps> & React.RefAttributes<TRef>>;
27
+ <TProps extends object>(Component: ObserverComponent<TProps>, options?: ObserverOptions): React.NamedExoticComponent<TProps>;
28
+ __wrapObserverMeta: unknown;
29
+ __makeObserver: unknown;
30
+ }
31
+ export declare const Signal: SignalConstructor;
32
+ export { SEGMENTS };
33
+ export { __DEBUG_SIGNALS_CACHE__, rawSignal, getSignalClass } from './orm/getSignal.js';
34
+ export { default as addModel } from './orm/addModel.js';
35
+ export { defineModels, default as initModels, getModels, resetModelsForTests } from './orm/initModels.js';
36
+ export { default as signal } from './orm/getSignal.js';
37
+ export { GLOBAL_ROOT_ID } from './orm/Root.js';
38
+ export declare const $: RootSignal;
39
+ export declare const $root: RootSignal;
40
+ export declare const model: RootSignal;
41
+ export default $;
42
+ export { default as sub } from './orm/sub.js';
43
+ export { default as useSub, useAsyncSub, setUseDeferredValue as __setUseDeferredValue, setDefaultDefer as __setDefaultDefer } from './react/useSub.js';
44
+ export { default as useSuspendMemo, useSuspendMemoByKey } from './react/useSuspendMemo.js';
45
+ export declare const observer: ObserverFunction;
46
+ export { useValue, useValue$, useModel, useLocal, useLocal$, useLocalDoc, useLocalDoc$, useSession, useSession$, usePage, usePage$, useBatch, useDoc, useDoc$, useBatchDoc, useBatchDoc$, useAsyncDoc, useAsyncDoc$, useQuery, useQuery$, useAsyncQuery, useAsyncQuery$, useBatchQuery, useBatchQuery$, useQueryIds, useBatchQueryIds, useAsyncQueryIds, useQueryDoc, useQueryDoc$, useBatchQueryDoc, useBatchQueryDoc$, useAsyncQueryDoc, useAsyncQueryDoc$ } from './orm/Compat/hooksCompat.js';
47
+ export { emit, useOn, useEmit } from './orm/Compat/eventsCompat.js';
48
+ export { useDidUpdate, useOnce, useSyncEffect } from './react/helpers.js';
49
+ export { connection, setConnection, getConnection, getDefaultFetchOnly, setDefaultFetchOnly, publicOnly, setPublicOnly } from './orm/connection.js';
50
+ export type { TeamplayConnection, TeamplayShareDoc } from './orm/connection.js';
51
+ export { getSubscriptionGcDelay, setSubscriptionGcDelay } from './orm/subscriptionGcDelay.js';
52
+ export { useId, useNow, useScheduleUpdate, useTriggerUpdate } from './react/helpers.js';
53
+ export { GUID_PATTERN, defineSchema, hasMany, hasOne, hasManyFlags, belongsTo, pickFormFields } from '@teamplay/schema';
54
+ export { aggregation, aggregationHeader as __aggregationHeader } from '@teamplay/utils/aggregation';
55
+ export { accessControl } from '@teamplay/utils/accessControl';
56
+ export type { AggregationCallback, AggregationContext, AggregationFunction, AggregationMeta, AggregationParams, AggregationQuery, ClientAggregationFunction, DefaultAggregationSession } from '@teamplay/utils/aggregation';
57
+ export type { AccessControl, AccessControlRules, AccessCreateContext, AccessDecision, AccessDeleteContext, AccessOperation, AccessReadContext, AccessRule, AccessUpdateContext, AccessValidator, AccessValidatorObject, DefaultAccessSession } from '@teamplay/utils/accessControl';
58
+ export declare function batch(): undefined;
59
+ export declare function batch<TResult>(fn: () => TResult): TResult;
60
+ export declare function batchModel(): undefined;
61
+ export declare function batchModel<TResult>(fn: () => TResult): TResult;
62
+ export declare function serverOnly<TValue>(value: TValue): TValue;
63
+ export declare function clone<TValue>(value: TValue): TValue;
64
+ export declare function initLocalCollection(name: string): any;
65
+ export { useApi };
66
+ export declare function getRootSignal<TCollections extends Record<string, any> = TeamplayCollections>(options?: Record<string, any>): RootSignal<TCollections>;
package/dist/index.js ADDED
@@ -0,0 +1,74 @@
1
+ import RuntimeSignal, { SEGMENTS } from "./orm/Signal.js";
2
+ import { getRootSignal as _getRootSignal, GLOBAL_ROOT_ID } from "./orm/Root.js";
3
+ import universal$ from "./react/universal$.js";
4
+ import useApi from "./react/useApi.js";
5
+ import runtimeObserver from "./react/observer.js";
6
+ // eslint-disable-next-line @typescript-eslint/no-redeclare
7
+ export const Signal = RuntimeSignal;
8
+ export { SEGMENTS };
9
+ export { __DEBUG_SIGNALS_CACHE__, rawSignal, getSignalClass } from "./orm/getSignal.js";
10
+ export { default as addModel } from "./orm/addModel.js";
11
+ export { defineModels, default as initModels, getModels, resetModelsForTests } from "./orm/initModels.js";
12
+ export { default as signal } from "./orm/getSignal.js";
13
+ export { GLOBAL_ROOT_ID } from "./orm/Root.js";
14
+ const getRuntimeRootSignal = _getRootSignal;
15
+ export const $ = getRuntimeRootSignal({ rootId: GLOBAL_ROOT_ID, rootFunction: universal$ });
16
+ export const $root = $;
17
+ export const model = $;
18
+ export default $;
19
+ export { default as sub } from "./orm/sub.js";
20
+ export { default as useSub, useAsyncSub, setUseDeferredValue as __setUseDeferredValue, setDefaultDefer as __setDefaultDefer } from "./react/useSub.js";
21
+ export { default as useSuspendMemo, useSuspendMemoByKey } from "./react/useSuspendMemo.js";
22
+ export const observer = runtimeObserver;
23
+ export { useValue, useValue$, useModel, useLocal, useLocal$, useLocalDoc, useLocalDoc$, useSession, useSession$, usePage, usePage$, useBatch, useDoc, useDoc$, useBatchDoc, useBatchDoc$, useAsyncDoc, useAsyncDoc$, useQuery, useQuery$, useAsyncQuery, useAsyncQuery$, useBatchQuery, useBatchQuery$, useQueryIds, useBatchQueryIds, useAsyncQueryIds, useQueryDoc, useQueryDoc$, useBatchQueryDoc, useBatchQueryDoc$, useAsyncQueryDoc, useAsyncQueryDoc$ } from './orm/Compat/hooksCompat.js';
24
+ export { emit, useOn, useEmit } from './orm/Compat/eventsCompat.js';
25
+ export { useDidUpdate, useOnce, useSyncEffect } from "./react/helpers.js";
26
+ export { connection, setConnection, getConnection, getDefaultFetchOnly, setDefaultFetchOnly, publicOnly, setPublicOnly } from "./orm/connection.js";
27
+ export { getSubscriptionGcDelay, setSubscriptionGcDelay } from "./orm/subscriptionGcDelay.js";
28
+ export { useId, useNow, useScheduleUpdate, useTriggerUpdate } from "./react/helpers.js";
29
+ export { GUID_PATTERN, defineSchema, hasMany, hasOne, hasManyFlags, belongsTo, pickFormFields } from '@teamplay/schema';
30
+ export { aggregation, aggregationHeader as __aggregationHeader } from '@teamplay/utils/aggregation';
31
+ export { accessControl } from '@teamplay/utils/accessControl';
32
+ export function batch(fn) {
33
+ return fn == null ? $.batch() : $.batch(fn);
34
+ }
35
+ export function batchModel(fn) {
36
+ return fn == null ? $.batch() : $.batch(fn);
37
+ }
38
+ export function serverOnly(value) {
39
+ return value;
40
+ }
41
+ export function clone(value) {
42
+ if (typeof globalThis.structuredClone === 'function') {
43
+ try {
44
+ return globalThis.structuredClone(value);
45
+ }
46
+ catch { }
47
+ }
48
+ if (value == null)
49
+ return value;
50
+ return JSON.parse(JSON.stringify(value));
51
+ }
52
+ export function initLocalCollection(name) {
53
+ if (typeof name !== 'string')
54
+ throw Error('initLocalCollection() expects a collection name');
55
+ if (!name)
56
+ return;
57
+ const segments = name.split('.').filter(Boolean);
58
+ if (!segments.length)
59
+ return;
60
+ let $cursor = $;
61
+ for (const segment of segments) {
62
+ $cursor = $cursor[segment];
63
+ }
64
+ if ($cursor.get() == null)
65
+ $cursor.set({});
66
+ return $cursor;
67
+ }
68
+ export { useApi };
69
+ export function getRootSignal(options) {
70
+ return getRuntimeRootSignal({
71
+ rootFunction: universal$,
72
+ ...options
73
+ });
74
+ }
@@ -0,0 +1,9 @@
1
+ import type Signal from './Signal.js'
2
+
3
+ export const LOCAL: string
4
+
5
+ export default function $ (
6
+ $root: Signal,
7
+ value?: unknown,
8
+ id?: string
9
+ ): Signal
package/dist/orm/$.js ADDED
@@ -0,0 +1,34 @@
1
+ // this is just the $() function implementation.
2
+ // The actual $ exported from this package is a Proxy targeting the dataTree root,
3
+ // and this function is an implementation of the `apply` handler for that Proxy.
4
+ import getSignal from "./getSignal.js";
5
+ import Signal from "./Signal.js";
6
+ import { LOCAL, valueSubscriptions } from './Value.js';
7
+ import { reactionSubscriptions } from './Reaction.js';
8
+ export { LOCAL } from './Value.js';
9
+ let counter = 0;
10
+ function newIncrementalId() {
11
+ const id = `_${counter}`;
12
+ counter += 1;
13
+ return id;
14
+ }
15
+ export default function $($root, value, id) {
16
+ if (!($root instanceof Signal))
17
+ throw Error('First argument of $() should be a Root Signal');
18
+ if (typeof value === 'function') {
19
+ return reaction$($root, value, id);
20
+ }
21
+ else {
22
+ return value$($root, value, id);
23
+ }
24
+ }
25
+ function value$($root, value, id = newIncrementalId()) {
26
+ const $value = getSignal($root, [LOCAL, id]);
27
+ valueSubscriptions.init($value, value);
28
+ return $value;
29
+ }
30
+ function reaction$($root, fn, id = newIncrementalId()) {
31
+ const $value = getSignal($root, [LOCAL, id]);
32
+ reactionSubscriptions.init($value, fn);
33
+ return $value;
34
+ }
@@ -0,0 +1,17 @@
1
+ import type Signal from './Signal.js'
2
+ import type {
3
+ QuerySubscriptions,
4
+ QuerySignalOptions
5
+ } from './Query.js'
6
+
7
+ export const IS_AGGREGATION: unique symbol
8
+ export const AGGREGATIONS: '$aggregations'
9
+ export const aggregationSubscriptions: QuerySubscriptions
10
+ export function getAggregationSignal (collectionName: string, params: unknown, options?: QuerySignalOptions): Signal
11
+ export function isAggregationSignal ($signal: unknown): boolean | undefined
12
+ export function getAggregationDocId (
13
+ segments: readonly unknown[],
14
+ rootId?: string,
15
+ method?: (path: unknown[]) => unknown
16
+ ): string | number | undefined
17
+ export function getAggregationCollectionName (segments: readonly unknown[]): string | undefined
@@ -0,0 +1,115 @@
1
+ import { raw } from '@nx-js/observer-util';
2
+ import { getRaw } from './dataTree.js';
3
+ import getSignal from "./getSignal.js";
4
+ import { QuerySubscriptions, hashQuery, Query, HASH, PARAMS, COLLECTION_NAME, parseQueryHash } from './Query.js';
5
+ import Signal, { SEGMENTS } from "./Signal.js";
6
+ import { getIdFieldsForSegments, isPlainObject } from "./idFields.js";
7
+ import { delPrivateData, getPrivateData, setPrivateData } from './privateData.js';
8
+ import { setSignalRuntimeDescriptor } from "./signalRuntimeDescriptor.js";
9
+ export const IS_AGGREGATION = Symbol('is aggregation signal');
10
+ export const AGGREGATIONS = '$aggregations';
11
+ class Aggregation extends Query {
12
+ _initData() {
13
+ this._syncAllRootsData();
14
+ this.shareQuery.on('extra', extra => {
15
+ extra = raw(extra);
16
+ injectAggregationIds(extra, this.collectionName);
17
+ this._forEachRoot(rootId => {
18
+ setPrivateData(rootId, [AGGREGATIONS, this.hash], extra);
19
+ });
20
+ });
21
+ }
22
+ _syncRootData(rootId) {
23
+ if (!this.shareQuery)
24
+ return;
25
+ const extra = raw(this.shareQuery.extra);
26
+ injectAggregationIds(extra, this.collectionName);
27
+ setPrivateData(rootId, [AGGREGATIONS, this.hash], extra);
28
+ }
29
+ _removeRootData(rootId) {
30
+ delPrivateData(rootId, [AGGREGATIONS, this.hash]);
31
+ }
32
+ _removeData() {
33
+ this._forEachRoot(rootId => this._removeRootData(rootId));
34
+ this.rootIds.clear();
35
+ }
36
+ }
37
+ export const aggregationSubscriptions = new QuerySubscriptions(Aggregation);
38
+ aggregationSubscriptions.runtimeKind = 'aggregation';
39
+ function injectAggregationIds(extra, collectionName) {
40
+ if (!Array.isArray(extra))
41
+ return;
42
+ const idFields = getIdFieldsForSegments([collectionName, '']);
43
+ for (const doc of extra) {
44
+ if (!isPlainObject(doc))
45
+ continue;
46
+ const docId = doc._id ?? doc.id;
47
+ if (docId == null)
48
+ continue;
49
+ if (idFields.includes('_id') && doc._id !== docId)
50
+ doc._id = docId;
51
+ if (idFields.includes('id') && doc.id !== docId)
52
+ doc.id = docId;
53
+ }
54
+ }
55
+ export function getAggregationSignal(collectionName, params, options) {
56
+ params = JSON.parse(JSON.stringify(params));
57
+ const transportHash = hashQuery(collectionName, params);
58
+ const { root, signalOptions } = parseAggregationSignalOptions(options);
59
+ const $aggregation = getSignal(root, [AGGREGATIONS, transportHash], signalOptions);
60
+ $aggregation[IS_AGGREGATION] ??= true;
61
+ $aggregation[COLLECTION_NAME] ??= collectionName;
62
+ $aggregation[PARAMS] ??= params;
63
+ $aggregation[HASH] ??= transportHash;
64
+ setSignalRuntimeDescriptor($aggregation, {
65
+ kind: 'aggregation',
66
+ collectionName,
67
+ itemPattern: [collectionName, '*']
68
+ });
69
+ return $aggregation;
70
+ }
71
+ // example: ['$aggregations', '{"active":true}']
72
+ export function isAggregationSignal($signal) {
73
+ if (!($signal instanceof Signal))
74
+ return;
75
+ const segments = $signal[SEGMENTS];
76
+ if (!(segments.length === 2))
77
+ return;
78
+ if (!(segments[0] === AGGREGATIONS))
79
+ return;
80
+ return true;
81
+ }
82
+ // example: ['$aggregations', '{"active":true}', 42]
83
+ // AND only if it also has either '_id' or 'id' field inside
84
+ export function getAggregationDocId(segments, rootId, method) {
85
+ if (!(segments.length >= 3))
86
+ return;
87
+ if (!(segments[0] === AGGREGATIONS))
88
+ return;
89
+ if (!(typeof segments[2] === 'number'))
90
+ return;
91
+ if (typeof method !== 'function') {
92
+ method = path => rootId == null ? getRaw(path) : getPrivateData(rootId, path);
93
+ }
94
+ const docId = method([...segments.slice(0, 3), '_id']) || method([...segments.slice(0, 3), 'id']);
95
+ return docId;
96
+ }
97
+ export function getAggregationCollectionName(segments) {
98
+ if (!(segments.length >= 2))
99
+ return;
100
+ if (!(segments[0] === AGGREGATIONS))
101
+ return;
102
+ const hash = segments[1];
103
+ const { collectionName } = parseQueryHash(hash);
104
+ return collectionName;
105
+ }
106
+ function parseAggregationSignalOptions(options) {
107
+ if (!options || typeof options !== 'object') {
108
+ return {
109
+ root: undefined,
110
+ signalOptions: {}
111
+ };
112
+ }
113
+ const { root, ...signalOptions } = options;
114
+ return { root, signalOptions };
115
+ }
@@ -0,0 +1,9 @@
1
+ export default class Cache<TValue extends object = object> {
2
+ private readonly cache;
3
+ private readonly fr;
4
+ _getKeys(): string[];
5
+ get(key: string): TValue | undefined;
6
+ set(key: string, value: TValue, inputs?: readonly object[]): void;
7
+ delete(key: string): void;
8
+ get size(): number;
9
+ }
@@ -0,0 +1,32 @@
1
+ import FinalizationRegistry from "../utils/MockFinalizationRegistry.js";
2
+ import WeakRef, { destroyMockWeakRef } from "../utils/MockWeakRef.js";
3
+ export default class Cache {
4
+ cache = new Map();
5
+ fr = new FinalizationRegistry(([key]) => {
6
+ // FinalizationRegistry can trigger long after the WeakRef was already
7
+ // collected and a fresh value was stored for the same key.
8
+ if (this.get(key))
9
+ return;
10
+ this.delete(key);
11
+ });
12
+ // For testing purposes.
13
+ _getKeys() {
14
+ return Array.from(this.cache.keys()).sort();
15
+ }
16
+ get(key) {
17
+ return this.cache.get(key)?.deref();
18
+ }
19
+ set(key, value, inputs = []) {
20
+ if (typeof key !== 'string')
21
+ throw Error('Cache key should be a string');
22
+ this.cache.set(key, new WeakRef(value));
23
+ this.fr.register(value, [key, ...inputs]);
24
+ }
25
+ delete(key) {
26
+ destroyMockWeakRef(this.cache.get(key));
27
+ this.cache.delete(key);
28
+ }
29
+ get size() {
30
+ return this.cache.size;
31
+ }
32
+ }
@@ -0,0 +1,3 @@
1
+ import { Signal } from '../SignalBase.js'
2
+
3
+ export default class SignalCompat<TValue = unknown> extends Signal<TValue> {}