@comapeo/core-react 2.0.1 → 3.1.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.
@@ -1,14 +1,14 @@
1
1
  import type { MapeoClientApi } from '@comapeo/ipc' with { 'resolution-mode': 'import' };
2
- import { type ReactNode } from 'react';
2
+ import { type JSX, type ReactNode } from 'react';
3
3
  export declare const ClientApiContext: import("react").Context<import("@comapeo/ipc/dist/client.js", { with: { "resolution-mode": "import" } }).MapeoClientApi | null>;
4
4
  /**
5
5
  * Create a context provider that holds a CoMapeo API client instance.
6
6
  *
7
- * @param opts
8
- * @param {ReactNode} opts.children React children node
9
- * @param {MapeoClientApi} opts.clientApi Client API instance
7
+ * @param opts.children React children node
8
+ * @param opts.clientApi Client API instance
9
+ *
10
10
  */
11
11
  export declare function ClientApiProvider({ children, clientApi, }: {
12
12
  children: ReactNode;
13
13
  clientApi: MapeoClientApi;
14
- }): import("react").FunctionComponentElement<import("react").ProviderProps<import("@comapeo/ipc/dist/client.js", { with: { "resolution-mode": "import" } }).MapeoClientApi | null>>;
14
+ }): JSX.Element;
@@ -7,9 +7,9 @@ exports.ClientApiContext = (0, react_1.createContext)(null);
7
7
  /**
8
8
  * Create a context provider that holds a CoMapeo API client instance.
9
9
  *
10
- * @param opts
11
- * @param {ReactNode} opts.children React children node
12
- * @param {MapeoClientApi} opts.clientApi Client API instance
10
+ * @param opts.children React children node
11
+ * @param opts.clientApi Client API instance
12
+ *
13
13
  */
14
14
  function ClientApiProvider({ children, clientApi, }) {
15
15
  return (0, react_1.createElement)(exports.ClientApiContext.Provider, { value: clientApi }, children);
@@ -1,5 +1,5 @@
1
1
  import type { MapeoDoc } from '@comapeo/schema' with { 'resolution-mode': 'import' };
2
- import { type WriteableDocumentType } from '../lib/react-query/documents.js';
2
+ import type { WriteableDocumentType } from '../lib/types.js';
3
3
  type ReadHookResult<D> = {
4
4
  data: D;
5
5
  error: Error | null;
@@ -119,10 +119,10 @@ export declare function useCreateDocument<D extends WriteableDocumentType>({ doc
119
119
  docType: D;
120
120
  projectId: string;
121
121
  }): {
122
- mutate: import("@tanstack/react-query").UseMutateFunction<import("../lib/react-query/documents.js").WriteableDocument<D> & {
122
+ mutate: import("@tanstack/react-query").UseMutateFunction<import("../lib/types.js").WriteableDocument<D> & {
123
123
  forks: Array<string>;
124
124
  }, Error, {
125
- value: Omit<import("../lib/react-query/documents.js").WriteableValue<D>, "schemaName">;
125
+ value: Omit<import("../lib/types.js").WriteableValue<D>, "schemaName">;
126
126
  }, unknown>;
127
127
  reset: () => void;
128
128
  status: "pending" | "error" | "success" | "idle";
@@ -137,11 +137,11 @@ export declare function useUpdateDocument<D extends WriteableDocumentType>({ doc
137
137
  docType: D;
138
138
  projectId: string;
139
139
  }): {
140
- mutate: import("@tanstack/react-query").UseMutateFunction<import("../lib/react-query/documents.js").WriteableDocument<D> & {
140
+ mutate: import("@tanstack/react-query").UseMutateFunction<import("../lib/types.js").WriteableDocument<D> & {
141
141
  forks: Array<string>;
142
142
  }, Error, {
143
143
  versionId: string;
144
- value: Omit<import("../lib/react-query/documents.js").WriteableValue<D>, "schemaName">;
144
+ value: Omit<import("../lib/types.js").WriteableValue<D>, "schemaName">;
145
145
  }, unknown>;
146
146
  reset: () => void;
147
147
  status: "pending" | "error" | "success" | "idle";
@@ -156,7 +156,7 @@ export declare function useDeleteDocument<D extends WriteableDocumentType>({ doc
156
156
  docType: D;
157
157
  projectId: string;
158
158
  }): {
159
- mutate: import("@tanstack/react-query").UseMutateFunction<import("../lib/react-query/documents.js").WriteableDocument<D> & {
159
+ mutate: import("@tanstack/react-query").UseMutateFunction<import("../lib/types.js").WriteableDocument<D> & {
160
160
  forks: Array<string>;
161
161
  }, Error, {
162
162
  docId: string;
@@ -1,5 +1,6 @@
1
1
  import type { BitmapOpts, SvgOpts } from '@comapeo/core/dist/icon-api.js' with { 'resolution-mode': 'import' };
2
2
  import type { BlobId } from '@comapeo/core/dist/types.js' with { 'resolution-mode': 'import' };
3
+ import { type SyncState } from '../lib/sync.js';
3
4
  /**
4
5
  * Retrieve the project settings for a project.
5
6
  *
@@ -249,6 +250,28 @@ export declare function useDocumentCreatedBy({ projectId, originalVersionId, }:
249
250
  error: Error | null;
250
251
  isRefetching: boolean;
251
252
  };
253
+ /**
254
+ * Get the role for the current device in a specified project.
255
+ * This is a more convenient alternative to using the `useOwnDeviceInfo` and `useManyMembers` hooks.
256
+ *
257
+ * @param opts.projectId Project public ID
258
+ *
259
+ * @example
260
+ * ```tsx
261
+ * function BasicExample() {
262
+ * const { data } = useOwnRoleInProject({
263
+ * projectId: '...',
264
+ * })
265
+ * }
266
+ * ```
267
+ */
268
+ export declare function useOwnRoleInProject({ projectId }: {
269
+ projectId: string;
270
+ }): {
271
+ data: import("@comapeo/core/dist/roles.js", { with: { "resolution-mode": "import" } }).Role<"a12a6702b93bd7ff" | "f7c150f5a3a9a855" | "012fd2d431c0bf60" | "9e6d29263cba36c9" | "8ced989b1904606b" | "08e4251e36f6e7ed">;
272
+ error: Error | null;
273
+ isRefetching: boolean;
274
+ };
252
275
  export declare function useAddServerPeer({ projectId }: {
253
276
  projectId: string;
254
277
  }): {
@@ -332,3 +355,52 @@ export declare function useCreateBlob({ projectId }: {
332
355
  reset: () => void;
333
356
  status: "pending" | "error" | "success" | "idle";
334
357
  };
358
+ /**
359
+ * Hook to subscribe to the current sync state.
360
+ *
361
+ * Creates a global singleton for each project, to minimize traffic over IPC -
362
+ * this hook can safely be used in more than one place without attaching
363
+ * additional listeners across the IPC channel.
364
+ *
365
+ * @example
366
+ * ```ts
367
+ * function Example() {
368
+ * const syncState = useSyncState({ projectId });
369
+ *
370
+ * if (!syncState) {
371
+ * // Sync information hasn't been loaded yet
372
+ * }
373
+ *
374
+ * // Actual info about sync state is available...
375
+ * }
376
+ * ```
377
+ *
378
+ * @param opts.projectId Project public ID
379
+ */
380
+ export declare function useSyncState({ projectId, }: {
381
+ projectId: string;
382
+ }): SyncState | null;
383
+ /**
384
+ * Provides the progress of data sync for sync-enabled connected peers
385
+ *
386
+ * @returns `null` if no sync state events have been received. Otherwise returns a value between 0 and 1 (inclusive)
387
+ */
388
+ export declare function useDataSyncProgress({ projectId, }: {
389
+ projectId: string;
390
+ }): number | null;
391
+ export declare function useStartSync({ projectId }: {
392
+ projectId: string;
393
+ }): {
394
+ mutate: import("@tanstack/react-query").UseMutateFunction<void, Error, {
395
+ autostopDataSyncAfter: number | null;
396
+ } | undefined, unknown>;
397
+ reset: () => void;
398
+ status: "pending" | "error" | "success" | "idle";
399
+ };
400
+ export declare function useStopSync({ projectId }: {
401
+ projectId: string;
402
+ }): {
403
+ mutate: import("@tanstack/react-query").UseMutateFunction<void, Error, void, unknown>;
404
+ reset: () => void;
405
+ status: "pending" | "error" | "success" | "idle";
406
+ };
@@ -8,14 +8,21 @@ exports.useManyMembers = useManyMembers;
8
8
  exports.useIconUrl = useIconUrl;
9
9
  exports.useAttachmentUrl = useAttachmentUrl;
10
10
  exports.useDocumentCreatedBy = useDocumentCreatedBy;
11
+ exports.useOwnRoleInProject = useOwnRoleInProject;
11
12
  exports.useAddServerPeer = useAddServerPeer;
12
13
  exports.useCreateProject = useCreateProject;
13
14
  exports.useLeaveProject = useLeaveProject;
14
15
  exports.useImportProjectConfig = useImportProjectConfig;
15
16
  exports.useUpdateProjectSettings = useUpdateProjectSettings;
16
17
  exports.useCreateBlob = useCreateBlob;
18
+ exports.useSyncState = useSyncState;
19
+ exports.useDataSyncProgress = useDataSyncProgress;
20
+ exports.useStartSync = useStartSync;
21
+ exports.useStopSync = useStopSync;
17
22
  const react_query_1 = require("@tanstack/react-query");
23
+ const react_1 = require("react");
18
24
  const projects_js_1 = require("../lib/react-query/projects.js");
25
+ const sync_js_1 = require("../lib/sync.js");
19
26
  const client_js_1 = require("./client.js");
20
27
  /**
21
28
  * Retrieve the project settings for a project.
@@ -262,6 +269,26 @@ function useDocumentCreatedBy({ projectId, originalVersionId, }) {
262
269
  const { data, error, isRefetching } = (0, react_query_1.useSuspenseQuery)((0, projects_js_1.documentCreatedByQueryOptions)({ projectApi, projectId, originalVersionId }));
263
270
  return { data, error, isRefetching };
264
271
  }
272
+ /**
273
+ * Get the role for the current device in a specified project.
274
+ * This is a more convenient alternative to using the `useOwnDeviceInfo` and `useManyMembers` hooks.
275
+ *
276
+ * @param opts.projectId Project public ID
277
+ *
278
+ * @example
279
+ * ```tsx
280
+ * function BasicExample() {
281
+ * const { data } = useOwnRoleInProject({
282
+ * projectId: '...',
283
+ * })
284
+ * }
285
+ * ```
286
+ */
287
+ function useOwnRoleInProject({ projectId }) {
288
+ const { data: projectApi } = useSingleProject({ projectId });
289
+ const { data, error, isRefetching } = (0, react_query_1.useSuspenseQuery)((0, projects_js_1.projectOwnRoleQueryOptions)({ projectApi, projectId }));
290
+ return { data, error, isRefetching };
291
+ }
265
292
  function useAddServerPeer({ projectId }) {
266
293
  const queryClient = (0, react_query_1.useQueryClient)();
267
294
  const { data: projectApi } = useSingleProject({ projectId });
@@ -318,3 +345,59 @@ function useCreateBlob({ projectId }) {
318
345
  const { mutate, reset, status } = (0, react_query_1.useMutation)((0, projects_js_1.createBlobMutationOptions)({ projectApi }));
319
346
  return { mutate, reset, status };
320
347
  }
348
+ const PROJECT_SYNC_STORE_MAP = new WeakMap();
349
+ function useSyncStore({ projectId }) {
350
+ const { data: projectApi } = useSingleProject({ projectId });
351
+ let syncStore = PROJECT_SYNC_STORE_MAP.get(projectApi);
352
+ if (!syncStore) {
353
+ syncStore = new sync_js_1.SyncStore(projectApi);
354
+ PROJECT_SYNC_STORE_MAP.set(projectApi, syncStore);
355
+ }
356
+ return syncStore;
357
+ }
358
+ /**
359
+ * Hook to subscribe to the current sync state.
360
+ *
361
+ * Creates a global singleton for each project, to minimize traffic over IPC -
362
+ * this hook can safely be used in more than one place without attaching
363
+ * additional listeners across the IPC channel.
364
+ *
365
+ * @example
366
+ * ```ts
367
+ * function Example() {
368
+ * const syncState = useSyncState({ projectId });
369
+ *
370
+ * if (!syncState) {
371
+ * // Sync information hasn't been loaded yet
372
+ * }
373
+ *
374
+ * // Actual info about sync state is available...
375
+ * }
376
+ * ```
377
+ *
378
+ * @param opts.projectId Project public ID
379
+ */
380
+ function useSyncState({ projectId, }) {
381
+ const syncStore = useSyncStore({ projectId });
382
+ const { subscribe, getStateSnapshot } = syncStore;
383
+ return (0, react_1.useSyncExternalStore)(subscribe, getStateSnapshot);
384
+ }
385
+ /**
386
+ * Provides the progress of data sync for sync-enabled connected peers
387
+ *
388
+ * @returns `null` if no sync state events have been received. Otherwise returns a value between 0 and 1 (inclusive)
389
+ */
390
+ function useDataSyncProgress({ projectId, }) {
391
+ const { subscribe, getDataProgressSnapshot } = useSyncStore({ projectId });
392
+ return (0, react_1.useSyncExternalStore)(subscribe, getDataProgressSnapshot);
393
+ }
394
+ function useStartSync({ projectId }) {
395
+ const { data: projectApi } = useSingleProject({ projectId });
396
+ const { mutate, reset, status } = (0, react_query_1.useMutation)((0, projects_js_1.startSyncMutationOptions)({ projectApi }));
397
+ return { mutate, reset, status };
398
+ }
399
+ function useStopSync({ projectId }) {
400
+ const { data: projectApi } = useSingleProject({ projectId });
401
+ const { mutate, reset, status } = (0, react_query_1.useMutation)((0, projects_js_1.stopSyncMutationOptions)({ projectApi }));
402
+ return { mutate, reset, status };
403
+ }
@@ -3,10 +3,6 @@ export { useClientApi, useIsArchiveDevice, useOwnDeviceInfo, useSetIsArchiveDevi
3
3
  export { useCreateDocument, useDeleteDocument, useManyDocs, useSingleDocByDocId, useSingleDocByVersionId, useUpdateDocument, } from './hooks/documents.js';
4
4
  export { useAcceptInvite, useRejectInvite, useRequestCancelInvite, useSendInvite, } from './hooks/invites.js';
5
5
  export { useMapStyleUrl } from './hooks/maps.js';
6
- export { useAddServerPeer, useAttachmentUrl, useCreateBlob, useCreateProject, useDocumentCreatedBy, useIconUrl, useImportProjectConfig, useLeaveProject, useManyMembers, useManyProjects, useProjectSettings, useSingleMember, useSingleProject, useUpdateProjectSettings, } from './hooks/projects.js';
7
- export { getClientQueryKey, getDeviceInfoQueryKey, getIsArchiveDeviceQueryKey, } from './lib/react-query/client.js';
8
- export { getDocumentByDocIdQueryKey, getDocumentByVersionIdQueryKey, getDocumentsQueryKey, getManyDocumentsQueryKey, type WriteableDocument, type WriteableDocumentType, type WriteableValue, } from './lib/react-query/documents.js';
9
- export { getInvitesQueryKey, getPendingInvitesQueryKey, } from './lib/react-query/invites.js';
10
- export { getMapsQueryKey, getStyleJsonUrlQueryKey, } from './lib/react-query/maps.js';
11
- export { getAttachmentUrlQueryKey, getDocumentCreatedByQueryKey, getIconUrlQueryKey, getMemberByIdQueryKey, getMembersQueryKey, getProjectByIdQueryKey, getProjectRoleQueryKey, getProjectSettingsQueryKey, getProjectsQueryKey, } from './lib/react-query/projects.js';
12
- export { ROOT_QUERY_KEY } from './lib/react-query/shared.js';
6
+ export { useAddServerPeer, useAttachmentUrl, useCreateBlob, useCreateProject, useDataSyncProgress, useDocumentCreatedBy, useIconUrl, useImportProjectConfig, useLeaveProject, useManyMembers, useManyProjects, useOwnRoleInProject, useProjectSettings, useSingleMember, useSingleProject, useStartSync, useStopSync, useSyncState, useUpdateProjectSettings, } from './hooks/projects.js';
7
+ export { type SyncState } from './lib/sync.js';
8
+ export { type WriteableDocument, type WriteableDocumentType, type WriteableValue, } from './lib/types.js';
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getProjectRoleQueryKey = exports.getProjectByIdQueryKey = exports.getMembersQueryKey = exports.getMemberByIdQueryKey = exports.getIconUrlQueryKey = exports.getDocumentCreatedByQueryKey = exports.getAttachmentUrlQueryKey = exports.getStyleJsonUrlQueryKey = exports.getMapsQueryKey = exports.getPendingInvitesQueryKey = exports.getInvitesQueryKey = exports.getManyDocumentsQueryKey = exports.getDocumentsQueryKey = exports.getDocumentByVersionIdQueryKey = exports.getDocumentByDocIdQueryKey = exports.getIsArchiveDeviceQueryKey = exports.getDeviceInfoQueryKey = exports.getClientQueryKey = exports.useUpdateProjectSettings = exports.useSingleProject = exports.useSingleMember = exports.useProjectSettings = exports.useManyProjects = exports.useManyMembers = exports.useLeaveProject = exports.useImportProjectConfig = exports.useIconUrl = exports.useDocumentCreatedBy = exports.useCreateProject = exports.useCreateBlob = exports.useAttachmentUrl = exports.useAddServerPeer = exports.useMapStyleUrl = exports.useSendInvite = exports.useRequestCancelInvite = exports.useRejectInvite = exports.useAcceptInvite = exports.useUpdateDocument = exports.useSingleDocByVersionId = exports.useSingleDocByDocId = exports.useManyDocs = exports.useDeleteDocument = exports.useCreateDocument = exports.useSetOwnDeviceInfo = exports.useSetIsArchiveDevice = exports.useOwnDeviceInfo = exports.useIsArchiveDevice = exports.useClientApi = exports.ClientApiProvider = exports.ClientApiContext = void 0;
4
- exports.ROOT_QUERY_KEY = exports.getProjectsQueryKey = exports.getProjectSettingsQueryKey = void 0;
3
+ exports.useUpdateProjectSettings = exports.useSyncState = exports.useStopSync = exports.useStartSync = exports.useSingleProject = exports.useSingleMember = exports.useProjectSettings = exports.useOwnRoleInProject = exports.useManyProjects = exports.useManyMembers = exports.useLeaveProject = exports.useImportProjectConfig = exports.useIconUrl = exports.useDocumentCreatedBy = exports.useDataSyncProgress = exports.useCreateProject = exports.useCreateBlob = exports.useAttachmentUrl = exports.useAddServerPeer = exports.useMapStyleUrl = exports.useSendInvite = exports.useRequestCancelInvite = exports.useRejectInvite = exports.useAcceptInvite = exports.useUpdateDocument = exports.useSingleDocByVersionId = exports.useSingleDocByDocId = exports.useManyDocs = exports.useDeleteDocument = exports.useCreateDocument = exports.useSetOwnDeviceInfo = exports.useSetIsArchiveDevice = exports.useOwnDeviceInfo = exports.useIsArchiveDevice = exports.useClientApi = exports.ClientApiProvider = exports.ClientApiContext = void 0;
5
4
  var ClientApi_js_1 = require("./contexts/ClientApi.js");
6
5
  Object.defineProperty(exports, "ClientApiContext", { enumerable: true, get: function () { return ClientApi_js_1.ClientApiContext; } });
7
6
  Object.defineProperty(exports, "ClientApiProvider", { enumerable: true, get: function () { return ClientApi_js_1.ClientApiProvider; } });
@@ -30,40 +29,18 @@ Object.defineProperty(exports, "useAddServerPeer", { enumerable: true, get: func
30
29
  Object.defineProperty(exports, "useAttachmentUrl", { enumerable: true, get: function () { return projects_js_1.useAttachmentUrl; } });
31
30
  Object.defineProperty(exports, "useCreateBlob", { enumerable: true, get: function () { return projects_js_1.useCreateBlob; } });
32
31
  Object.defineProperty(exports, "useCreateProject", { enumerable: true, get: function () { return projects_js_1.useCreateProject; } });
32
+ Object.defineProperty(exports, "useDataSyncProgress", { enumerable: true, get: function () { return projects_js_1.useDataSyncProgress; } });
33
33
  Object.defineProperty(exports, "useDocumentCreatedBy", { enumerable: true, get: function () { return projects_js_1.useDocumentCreatedBy; } });
34
34
  Object.defineProperty(exports, "useIconUrl", { enumerable: true, get: function () { return projects_js_1.useIconUrl; } });
35
35
  Object.defineProperty(exports, "useImportProjectConfig", { enumerable: true, get: function () { return projects_js_1.useImportProjectConfig; } });
36
36
  Object.defineProperty(exports, "useLeaveProject", { enumerable: true, get: function () { return projects_js_1.useLeaveProject; } });
37
37
  Object.defineProperty(exports, "useManyMembers", { enumerable: true, get: function () { return projects_js_1.useManyMembers; } });
38
38
  Object.defineProperty(exports, "useManyProjects", { enumerable: true, get: function () { return projects_js_1.useManyProjects; } });
39
+ Object.defineProperty(exports, "useOwnRoleInProject", { enumerable: true, get: function () { return projects_js_1.useOwnRoleInProject; } });
39
40
  Object.defineProperty(exports, "useProjectSettings", { enumerable: true, get: function () { return projects_js_1.useProjectSettings; } });
40
41
  Object.defineProperty(exports, "useSingleMember", { enumerable: true, get: function () { return projects_js_1.useSingleMember; } });
41
42
  Object.defineProperty(exports, "useSingleProject", { enumerable: true, get: function () { return projects_js_1.useSingleProject; } });
43
+ Object.defineProperty(exports, "useStartSync", { enumerable: true, get: function () { return projects_js_1.useStartSync; } });
44
+ Object.defineProperty(exports, "useStopSync", { enumerable: true, get: function () { return projects_js_1.useStopSync; } });
45
+ Object.defineProperty(exports, "useSyncState", { enumerable: true, get: function () { return projects_js_1.useSyncState; } });
42
46
  Object.defineProperty(exports, "useUpdateProjectSettings", { enumerable: true, get: function () { return projects_js_1.useUpdateProjectSettings; } });
43
- var client_js_2 = require("./lib/react-query/client.js");
44
- Object.defineProperty(exports, "getClientQueryKey", { enumerable: true, get: function () { return client_js_2.getClientQueryKey; } });
45
- Object.defineProperty(exports, "getDeviceInfoQueryKey", { enumerable: true, get: function () { return client_js_2.getDeviceInfoQueryKey; } });
46
- Object.defineProperty(exports, "getIsArchiveDeviceQueryKey", { enumerable: true, get: function () { return client_js_2.getIsArchiveDeviceQueryKey; } });
47
- var documents_js_2 = require("./lib/react-query/documents.js");
48
- Object.defineProperty(exports, "getDocumentByDocIdQueryKey", { enumerable: true, get: function () { return documents_js_2.getDocumentByDocIdQueryKey; } });
49
- Object.defineProperty(exports, "getDocumentByVersionIdQueryKey", { enumerable: true, get: function () { return documents_js_2.getDocumentByVersionIdQueryKey; } });
50
- Object.defineProperty(exports, "getDocumentsQueryKey", { enumerable: true, get: function () { return documents_js_2.getDocumentsQueryKey; } });
51
- Object.defineProperty(exports, "getManyDocumentsQueryKey", { enumerable: true, get: function () { return documents_js_2.getManyDocumentsQueryKey; } });
52
- var invites_js_2 = require("./lib/react-query/invites.js");
53
- Object.defineProperty(exports, "getInvitesQueryKey", { enumerable: true, get: function () { return invites_js_2.getInvitesQueryKey; } });
54
- Object.defineProperty(exports, "getPendingInvitesQueryKey", { enumerable: true, get: function () { return invites_js_2.getPendingInvitesQueryKey; } });
55
- var maps_js_2 = require("./lib/react-query/maps.js");
56
- Object.defineProperty(exports, "getMapsQueryKey", { enumerable: true, get: function () { return maps_js_2.getMapsQueryKey; } });
57
- Object.defineProperty(exports, "getStyleJsonUrlQueryKey", { enumerable: true, get: function () { return maps_js_2.getStyleJsonUrlQueryKey; } });
58
- var projects_js_2 = require("./lib/react-query/projects.js");
59
- Object.defineProperty(exports, "getAttachmentUrlQueryKey", { enumerable: true, get: function () { return projects_js_2.getAttachmentUrlQueryKey; } });
60
- Object.defineProperty(exports, "getDocumentCreatedByQueryKey", { enumerable: true, get: function () { return projects_js_2.getDocumentCreatedByQueryKey; } });
61
- Object.defineProperty(exports, "getIconUrlQueryKey", { enumerable: true, get: function () { return projects_js_2.getIconUrlQueryKey; } });
62
- Object.defineProperty(exports, "getMemberByIdQueryKey", { enumerable: true, get: function () { return projects_js_2.getMemberByIdQueryKey; } });
63
- Object.defineProperty(exports, "getMembersQueryKey", { enumerable: true, get: function () { return projects_js_2.getMembersQueryKey; } });
64
- Object.defineProperty(exports, "getProjectByIdQueryKey", { enumerable: true, get: function () { return projects_js_2.getProjectByIdQueryKey; } });
65
- Object.defineProperty(exports, "getProjectRoleQueryKey", { enumerable: true, get: function () { return projects_js_2.getProjectRoleQueryKey; } });
66
- Object.defineProperty(exports, "getProjectSettingsQueryKey", { enumerable: true, get: function () { return projects_js_2.getProjectSettingsQueryKey; } });
67
- Object.defineProperty(exports, "getProjectsQueryKey", { enumerable: true, get: function () { return projects_js_2.getProjectsQueryKey; } });
68
- var shared_js_1 = require("./lib/react-query/shared.js");
69
- Object.defineProperty(exports, "ROOT_QUERY_KEY", { enumerable: true, get: function () { return shared_js_1.ROOT_QUERY_KEY; } });
@@ -1,13 +1,6 @@
1
1
  import type { MapeoProjectApi } from '@comapeo/ipc' with { 'resolution-mode': 'import' };
2
- import type { MapeoDoc, MapeoValue } from '@comapeo/schema' with { 'resolution-mode': 'import' };
3
2
  import { type QueryClient } from '@tanstack/react-query';
4
- export type WriteableDocumentType = Extract<MapeoDoc['schemaName'], 'field' | 'observation' | 'preset' | 'track' | 'remoteDetectionAlert'>;
5
- export type WriteableValue<D extends WriteableDocumentType> = Extract<MapeoValue, {
6
- schemaName: D;
7
- }>;
8
- export type WriteableDocument<D extends WriteableDocumentType> = Extract<MapeoDoc, {
9
- schemaName: D;
10
- }>;
3
+ import { WriteableDocument, WriteableDocumentType, WriteableValue } from '../types.js';
11
4
  export declare function getDocumentsQueryKey<D extends WriteableDocumentType>({ projectId, docType, }: {
12
5
  projectId: string;
13
6
  docType: D;
@@ -330,3 +330,19 @@ export declare function createBlobMutationOptions({ projectApi, }: {
330
330
  networkMode: "always";
331
331
  retry: false;
332
332
  };
333
+ export declare function startSyncMutationOptions({ projectApi, }: {
334
+ projectApi: MapeoProjectApi;
335
+ }): {
336
+ mutationFn: (opts: {
337
+ autostopDataSyncAfter: number | null;
338
+ } | undefined) => Promise<void>;
339
+ networkMode: "always";
340
+ retry: false;
341
+ };
342
+ export declare function stopSyncMutationOptions({ projectApi, }: {
343
+ projectApi: MapeoProjectApi;
344
+ }): {
345
+ mutationFn: () => Promise<void>;
346
+ networkMode: "always";
347
+ retry: false;
348
+ };
@@ -24,6 +24,8 @@ exports.leaveProjectMutationOptions = leaveProjectMutationOptions;
24
24
  exports.importProjectConfigMutationOptions = importProjectConfigMutationOptions;
25
25
  exports.updateProjectSettingsMutationOptions = updateProjectSettingsMutationOptions;
26
26
  exports.createBlobMutationOptions = createBlobMutationOptions;
27
+ exports.startSyncMutationOptions = startSyncMutationOptions;
28
+ exports.stopSyncMutationOptions = stopSyncMutationOptions;
27
29
  const react_query_1 = require("@tanstack/react-query");
28
30
  const shared_js_1 = require("./shared.js");
29
31
  function getProjectsQueryKey() {
@@ -233,3 +235,21 @@ function createBlobMutationOptions({ projectApi, }) {
233
235
  },
234
236
  };
235
237
  }
238
+ function startSyncMutationOptions({ projectApi, }) {
239
+ return {
240
+ ...(0, shared_js_1.baseMutationOptions)(),
241
+ mutationFn: async (opts) => {
242
+ // Have to avoid passing `undefined` explicitly
243
+ // See https://github.com/digidem/rpc-reflector/issues/21
244
+ return opts ? projectApi.$sync.start(opts) : projectApi.$sync.start();
245
+ },
246
+ };
247
+ }
248
+ function stopSyncMutationOptions({ projectApi, }) {
249
+ return {
250
+ ...(0, shared_js_1.baseMutationOptions)(),
251
+ mutationFn: async () => {
252
+ return projectApi.$sync.stop();
253
+ },
254
+ };
255
+ }
@@ -0,0 +1,10 @@
1
+ import type { MapeoProjectApi } from '@comapeo/ipc' with { 'resolution-mode': 'import' };
2
+ export type SyncState = Awaited<ReturnType<MapeoProjectApi['$sync']['getState']>>;
3
+ export declare function getDataSyncCountForDevice(syncStateForDevice: SyncState['remoteDeviceSyncState'][string]): number;
4
+ export declare class SyncStore {
5
+ #private;
6
+ constructor(project: MapeoProjectApi);
7
+ subscribe: (listener: () => void) => () => void;
8
+ getStateSnapshot: () => import("@comapeo/core/dist/sync/sync-api.js", { with: { "resolution-mode": "import" } }).State | null;
9
+ getDataProgressSnapshot: () => number | null;
10
+ }
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SyncStore = void 0;
4
+ exports.getDataSyncCountForDevice = getDataSyncCountForDevice;
5
+ function getDataSyncCountForDevice(syncStateForDevice) {
6
+ const { data } = syncStateForDevice;
7
+ return data.want + data.wanted;
8
+ }
9
+ class SyncStore {
10
+ #project;
11
+ #listeners = new Set();
12
+ #isSubscribedInternal = false;
13
+ #error = null;
14
+ #state = null;
15
+ // Used for calculating sync progress
16
+ #perDeviceMaxSyncCount = new Map();
17
+ constructor(project) {
18
+ this.#project = project;
19
+ }
20
+ subscribe = (listener) => {
21
+ this.#listeners.add(listener);
22
+ if (!this.#isSubscribedInternal)
23
+ this.#startSubscription();
24
+ return () => {
25
+ this.#listeners.delete(listener);
26
+ if (this.#listeners.size === 0)
27
+ this.#stopSubscription();
28
+ };
29
+ };
30
+ getStateSnapshot = () => {
31
+ if (this.#error)
32
+ throw this.#error;
33
+ return this.#state;
34
+ };
35
+ getDataProgressSnapshot = () => {
36
+ if (this.#state === null) {
37
+ return null;
38
+ }
39
+ let currentSyncCount = 0;
40
+ let totalMaxSyncCount = 0;
41
+ let otherEnabledDevicesExist = false;
42
+ for (const [deviceId, deviceSyncState] of Object.entries(this.#state.remoteDeviceSyncState)) {
43
+ if (deviceSyncState.data.isSyncEnabled) {
44
+ otherEnabledDevicesExist = true;
45
+ }
46
+ else {
47
+ continue;
48
+ }
49
+ const existingMaxCount = this.#perDeviceMaxSyncCount.get(deviceId);
50
+ if (typeof existingMaxCount === 'number' && existingMaxCount > 0) {
51
+ currentSyncCount = getDataSyncCountForDevice(deviceSyncState);
52
+ totalMaxSyncCount += existingMaxCount;
53
+ }
54
+ }
55
+ if (!otherEnabledDevicesExist) {
56
+ return null;
57
+ }
58
+ if (totalMaxSyncCount === 0) {
59
+ return 1;
60
+ }
61
+ const ratio = (totalMaxSyncCount - currentSyncCount) / totalMaxSyncCount;
62
+ if (ratio <= 0)
63
+ return 0;
64
+ if (ratio >= 1)
65
+ return 1;
66
+ return clamp(ratio, 0.01, 0.99);
67
+ };
68
+ #notifyListeners() {
69
+ for (const listener of this.#listeners) {
70
+ listener();
71
+ }
72
+ }
73
+ #onSyncState = (state) => {
74
+ const dataSyncWasEnabled = this.#state
75
+ ? this.#state.data.isSyncEnabled
76
+ : false;
77
+ // Reset map keeping track of counts used for progress if data sync is toggled
78
+ if (dataSyncWasEnabled !== state.data.isSyncEnabled) {
79
+ this.#perDeviceMaxSyncCount.clear();
80
+ }
81
+ else {
82
+ // Remove devices from #perDeviceMaxSyncCount that are no longer found in the new sync state
83
+ for (const deviceId of this.#perDeviceMaxSyncCount.keys()) {
84
+ if (!Object.hasOwn(state.remoteDeviceSyncState, deviceId)) {
85
+ this.#perDeviceMaxSyncCount.delete(deviceId);
86
+ }
87
+ }
88
+ }
89
+ for (const [deviceId, stateForDevice] of Object.entries(state.remoteDeviceSyncState)) {
90
+ const existingCount = this.#perDeviceMaxSyncCount.get(deviceId);
91
+ const newCount = getDataSyncCountForDevice(stateForDevice);
92
+ if (existingCount === undefined || existingCount < newCount) {
93
+ this.#perDeviceMaxSyncCount.set(deviceId, newCount);
94
+ }
95
+ }
96
+ this.#state = state;
97
+ this.#error = null;
98
+ this.#notifyListeners();
99
+ };
100
+ #startSubscription = () => {
101
+ this.#project.$sync.on('sync-state', this.#onSyncState);
102
+ this.#isSubscribedInternal = true;
103
+ this.#project.$sync
104
+ .getState()
105
+ .then(this.#onSyncState)
106
+ .catch((e) => {
107
+ this.#error = e;
108
+ this.#notifyListeners();
109
+ });
110
+ };
111
+ #stopSubscription = () => {
112
+ this.#isSubscribedInternal = false;
113
+ this.#project.$sync.off('sync-state', this.#onSyncState);
114
+ };
115
+ }
116
+ exports.SyncStore = SyncStore;
117
+ function clamp(value, min, max) {
118
+ return Math.max(min, Math.min(value, max));
119
+ }
@@ -0,0 +1,9 @@
1
+ import type { MapeoDoc, MapeoValue } from '@comapeo/schema' with { 'resolution-mode': 'import' };
2
+ export type WriteableDocumentType = Extract<MapeoDoc['schemaName'], 'field' | 'observation' | 'preset' | 'track' | 'remoteDetectionAlert'>;
3
+ export type WriteableValue<D extends WriteableDocumentType> = Extract<MapeoValue, {
4
+ schemaName: D;
5
+ }>;
6
+ export type WriteableDocument<D extends WriteableDocumentType> = Extract<MapeoDoc, {
7
+ schemaName: D;
8
+ }>;
9
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,14 +1,14 @@
1
1
  import type { MapeoClientApi } from '@comapeo/ipc' with { 'resolution-mode': 'import' };
2
- import { type ReactNode } from 'react';
2
+ import { type JSX, type ReactNode } from 'react';
3
3
  export declare const ClientApiContext: import("react").Context<import("@comapeo/ipc/dist/client.js").MapeoClientApi | null>;
4
4
  /**
5
5
  * Create a context provider that holds a CoMapeo API client instance.
6
6
  *
7
- * @param opts
8
- * @param {ReactNode} opts.children React children node
9
- * @param {MapeoClientApi} opts.clientApi Client API instance
7
+ * @param opts.children React children node
8
+ * @param opts.clientApi Client API instance
9
+ *
10
10
  */
11
11
  export declare function ClientApiProvider({ children, clientApi, }: {
12
12
  children: ReactNode;
13
13
  clientApi: MapeoClientApi;
14
- }): import("react").FunctionComponentElement<import("react").ProviderProps<import("@comapeo/ipc/dist/client.js").MapeoClientApi | null>>;
14
+ }): JSX.Element;
@@ -3,9 +3,9 @@ export const ClientApiContext = createContext(null);
3
3
  /**
4
4
  * Create a context provider that holds a CoMapeo API client instance.
5
5
  *
6
- * @param opts
7
- * @param {ReactNode} opts.children React children node
8
- * @param {MapeoClientApi} opts.clientApi Client API instance
6
+ * @param opts.children React children node
7
+ * @param opts.clientApi Client API instance
8
+ *
9
9
  */
10
10
  export function ClientApiProvider({ children, clientApi, }) {
11
11
  return createElement(ClientApiContext.Provider, { value: clientApi }, children);
@@ -1,5 +1,5 @@
1
1
  import type { MapeoDoc } from '@comapeo/schema' with { 'resolution-mode': 'import' };
2
- import { type WriteableDocumentType } from '../lib/react-query/documents.js';
2
+ import type { WriteableDocumentType } from '../lib/types.js';
3
3
  type ReadHookResult<D> = {
4
4
  data: D;
5
5
  error: Error | null;
@@ -119,10 +119,10 @@ export declare function useCreateDocument<D extends WriteableDocumentType>({ doc
119
119
  docType: D;
120
120
  projectId: string;
121
121
  }): {
122
- mutate: import("@tanstack/react-query").UseMutateFunction<import("../lib/react-query/documents.js").WriteableDocument<D> & {
122
+ mutate: import("@tanstack/react-query").UseMutateFunction<import("../lib/types.js").WriteableDocument<D> & {
123
123
  forks: Array<string>;
124
124
  }, Error, {
125
- value: Omit<import("../lib/react-query/documents.js").WriteableValue<D>, "schemaName">;
125
+ value: Omit<import("../lib/types.js").WriteableValue<D>, "schemaName">;
126
126
  }, unknown>;
127
127
  reset: () => void;
128
128
  status: "pending" | "error" | "success" | "idle";
@@ -137,11 +137,11 @@ export declare function useUpdateDocument<D extends WriteableDocumentType>({ doc
137
137
  docType: D;
138
138
  projectId: string;
139
139
  }): {
140
- mutate: import("@tanstack/react-query").UseMutateFunction<import("../lib/react-query/documents.js").WriteableDocument<D> & {
140
+ mutate: import("@tanstack/react-query").UseMutateFunction<import("../lib/types.js").WriteableDocument<D> & {
141
141
  forks: Array<string>;
142
142
  }, Error, {
143
143
  versionId: string;
144
- value: Omit<import("../lib/react-query/documents.js").WriteableValue<D>, "schemaName">;
144
+ value: Omit<import("../lib/types.js").WriteableValue<D>, "schemaName">;
145
145
  }, unknown>;
146
146
  reset: () => void;
147
147
  status: "pending" | "error" | "success" | "idle";
@@ -156,7 +156,7 @@ export declare function useDeleteDocument<D extends WriteableDocumentType>({ doc
156
156
  docType: D;
157
157
  projectId: string;
158
158
  }): {
159
- mutate: import("@tanstack/react-query").UseMutateFunction<import("../lib/react-query/documents.js").WriteableDocument<D> & {
159
+ mutate: import("@tanstack/react-query").UseMutateFunction<import("../lib/types.js").WriteableDocument<D> & {
160
160
  forks: Array<string>;
161
161
  }, Error, {
162
162
  docId: string;