@comapeo/core-react 2.0.0 → 3.0.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.
- package/dist/commonjs/contexts/ClientApi.d.ts +5 -5
- package/dist/commonjs/contexts/ClientApi.js +3 -3
- package/dist/commonjs/hooks/documents.d.ts +8 -8
- package/dist/commonjs/hooks/projects.d.ts +50 -0
- package/dist/commonjs/hooks/projects.js +62 -0
- package/dist/commonjs/index.d.ts +3 -7
- package/dist/commonjs/index.js +5 -29
- package/dist/commonjs/lib/react-query/documents.d.ts +1 -8
- package/dist/commonjs/lib/react-query/projects.d.ts +16 -0
- package/dist/commonjs/lib/react-query/projects.js +20 -0
- package/dist/commonjs/lib/sync.d.ts +10 -0
- package/dist/commonjs/lib/sync.js +119 -0
- package/dist/commonjs/lib/types.d.ts +9 -0
- package/dist/commonjs/lib/types.js +2 -0
- package/dist/esm/contexts/ClientApi.d.ts +5 -5
- package/dist/esm/contexts/ClientApi.js +3 -3
- package/dist/esm/hooks/documents.d.ts +8 -8
- package/dist/esm/hooks/projects.d.ts +50 -0
- package/dist/esm/hooks/projects.js +59 -1
- package/dist/esm/index.d.ts +3 -7
- package/dist/esm/index.js +1 -7
- package/dist/esm/lib/react-query/documents.d.ts +1 -8
- package/dist/esm/lib/react-query/projects.d.ts +16 -0
- package/dist/esm/lib/react-query/projects.js +18 -0
- package/dist/esm/lib/sync.d.ts +10 -0
- package/dist/esm/lib/sync.js +114 -0
- package/dist/esm/lib/types.d.ts +9 -0
- package/dist/esm/lib/types.js +1 -0
- package/docs/API.md +84 -3
- package/package.json +26 -26
- package/CHANGELOG.md +0 -23
|
@@ -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
|
|
9
|
-
*
|
|
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
|
-
}):
|
|
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
|
|
12
|
-
*
|
|
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 {
|
|
2
|
+
import type { WriteableDocumentType } from '../lib/types.js';
|
|
3
3
|
type ReadHookResult<D> = {
|
|
4
4
|
data: D;
|
|
5
5
|
error: Error | null;
|
|
@@ -106,9 +106,9 @@ export declare function useManyDocs<D extends WriteableDocumentType>({ projectId
|
|
|
106
106
|
docType: D;
|
|
107
107
|
includeDeleted?: boolean;
|
|
108
108
|
lang?: string;
|
|
109
|
-
}): ReadHookResult<Extract<MapeoDoc, {
|
|
109
|
+
}): ReadHookResult<Array<Extract<MapeoDoc, {
|
|
110
110
|
schemaName: D;
|
|
111
|
-
}
|
|
111
|
+
}>>>;
|
|
112
112
|
/**
|
|
113
113
|
* Create a document for a project.
|
|
114
114
|
*
|
|
@@ -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/
|
|
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/
|
|
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/
|
|
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/
|
|
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/
|
|
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
|
*
|
|
@@ -332,3 +333,52 @@ export declare function useCreateBlob({ projectId }: {
|
|
|
332
333
|
reset: () => void;
|
|
333
334
|
status: "pending" | "error" | "success" | "idle";
|
|
334
335
|
};
|
|
336
|
+
/**
|
|
337
|
+
* Hook to subscribe to the current sync state.
|
|
338
|
+
*
|
|
339
|
+
* Creates a global singleton for each project, to minimize traffic over IPC -
|
|
340
|
+
* this hook can safely be used in more than one place without attaching
|
|
341
|
+
* additional listeners across the IPC channel.
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* ```ts
|
|
345
|
+
* function Example() {
|
|
346
|
+
* const syncState = useSyncState({ projectId });
|
|
347
|
+
*
|
|
348
|
+
* if (!syncState) {
|
|
349
|
+
* // Sync information hasn't been loaded yet
|
|
350
|
+
* }
|
|
351
|
+
*
|
|
352
|
+
* // Actual info about sync state is available...
|
|
353
|
+
* }
|
|
354
|
+
* ```
|
|
355
|
+
*
|
|
356
|
+
* @param opts.projectId Project public ID
|
|
357
|
+
*/
|
|
358
|
+
export declare function useSyncState({ projectId, }: {
|
|
359
|
+
projectId: string;
|
|
360
|
+
}): SyncState | null;
|
|
361
|
+
/**
|
|
362
|
+
* Provides the progress of data sync for sync-enabled connected peers
|
|
363
|
+
*
|
|
364
|
+
* @returns `null` if no sync state events have been received. Otherwise returns a value between 0 and 1 (inclusive)
|
|
365
|
+
*/
|
|
366
|
+
export declare function useDataSyncProgress({ projectId, }: {
|
|
367
|
+
projectId: string;
|
|
368
|
+
}): number | null;
|
|
369
|
+
export declare function useStartSync({ projectId }: {
|
|
370
|
+
projectId: string;
|
|
371
|
+
}): {
|
|
372
|
+
mutate: import("@tanstack/react-query").UseMutateFunction<void, Error, {
|
|
373
|
+
autostopDataSyncAfter: number | null;
|
|
374
|
+
} | undefined, unknown>;
|
|
375
|
+
reset: () => void;
|
|
376
|
+
status: "pending" | "error" | "success" | "idle";
|
|
377
|
+
};
|
|
378
|
+
export declare function useStopSync({ projectId }: {
|
|
379
|
+
projectId: string;
|
|
380
|
+
}): {
|
|
381
|
+
mutate: import("@tanstack/react-query").UseMutateFunction<void, Error, void, unknown>;
|
|
382
|
+
reset: () => void;
|
|
383
|
+
status: "pending" | "error" | "success" | "idle";
|
|
384
|
+
};
|
|
@@ -14,8 +14,14 @@ exports.useLeaveProject = useLeaveProject;
|
|
|
14
14
|
exports.useImportProjectConfig = useImportProjectConfig;
|
|
15
15
|
exports.useUpdateProjectSettings = useUpdateProjectSettings;
|
|
16
16
|
exports.useCreateBlob = useCreateBlob;
|
|
17
|
+
exports.useSyncState = useSyncState;
|
|
18
|
+
exports.useDataSyncProgress = useDataSyncProgress;
|
|
19
|
+
exports.useStartSync = useStartSync;
|
|
20
|
+
exports.useStopSync = useStopSync;
|
|
17
21
|
const react_query_1 = require("@tanstack/react-query");
|
|
22
|
+
const react_1 = require("react");
|
|
18
23
|
const projects_js_1 = require("../lib/react-query/projects.js");
|
|
24
|
+
const sync_js_1 = require("../lib/sync.js");
|
|
19
25
|
const client_js_1 = require("./client.js");
|
|
20
26
|
/**
|
|
21
27
|
* Retrieve the project settings for a project.
|
|
@@ -318,3 +324,59 @@ function useCreateBlob({ projectId }) {
|
|
|
318
324
|
const { mutate, reset, status } = (0, react_query_1.useMutation)((0, projects_js_1.createBlobMutationOptions)({ projectApi }));
|
|
319
325
|
return { mutate, reset, status };
|
|
320
326
|
}
|
|
327
|
+
const PROJECT_SYNC_STORE_MAP = new WeakMap();
|
|
328
|
+
function useSyncStore({ projectId }) {
|
|
329
|
+
const { data: projectApi } = useSingleProject({ projectId });
|
|
330
|
+
let syncStore = PROJECT_SYNC_STORE_MAP.get(projectApi);
|
|
331
|
+
if (!syncStore) {
|
|
332
|
+
syncStore = new sync_js_1.SyncStore(projectApi);
|
|
333
|
+
PROJECT_SYNC_STORE_MAP.set(projectApi, syncStore);
|
|
334
|
+
}
|
|
335
|
+
return syncStore;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Hook to subscribe to the current sync state.
|
|
339
|
+
*
|
|
340
|
+
* Creates a global singleton for each project, to minimize traffic over IPC -
|
|
341
|
+
* this hook can safely be used in more than one place without attaching
|
|
342
|
+
* additional listeners across the IPC channel.
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```ts
|
|
346
|
+
* function Example() {
|
|
347
|
+
* const syncState = useSyncState({ projectId });
|
|
348
|
+
*
|
|
349
|
+
* if (!syncState) {
|
|
350
|
+
* // Sync information hasn't been loaded yet
|
|
351
|
+
* }
|
|
352
|
+
*
|
|
353
|
+
* // Actual info about sync state is available...
|
|
354
|
+
* }
|
|
355
|
+
* ```
|
|
356
|
+
*
|
|
357
|
+
* @param opts.projectId Project public ID
|
|
358
|
+
*/
|
|
359
|
+
function useSyncState({ projectId, }) {
|
|
360
|
+
const syncStore = useSyncStore({ projectId });
|
|
361
|
+
const { subscribe, getStateSnapshot } = syncStore;
|
|
362
|
+
return (0, react_1.useSyncExternalStore)(subscribe, getStateSnapshot);
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Provides the progress of data sync for sync-enabled connected peers
|
|
366
|
+
*
|
|
367
|
+
* @returns `null` if no sync state events have been received. Otherwise returns a value between 0 and 1 (inclusive)
|
|
368
|
+
*/
|
|
369
|
+
function useDataSyncProgress({ projectId, }) {
|
|
370
|
+
const { subscribe, getDataProgressSnapshot } = useSyncStore({ projectId });
|
|
371
|
+
return (0, react_1.useSyncExternalStore)(subscribe, getDataProgressSnapshot);
|
|
372
|
+
}
|
|
373
|
+
function useStartSync({ projectId }) {
|
|
374
|
+
const { data: projectApi } = useSingleProject({ projectId });
|
|
375
|
+
const { mutate, reset, status } = (0, react_query_1.useMutation)((0, projects_js_1.startSyncMutationOptions)({ projectApi }));
|
|
376
|
+
return { mutate, reset, status };
|
|
377
|
+
}
|
|
378
|
+
function useStopSync({ projectId }) {
|
|
379
|
+
const { data: projectApi } = useSingleProject({ projectId });
|
|
380
|
+
const { mutate, reset, status } = (0, react_query_1.useMutation)((0, projects_js_1.stopSyncMutationOptions)({ projectApi }));
|
|
381
|
+
return { mutate, reset, status };
|
|
382
|
+
}
|
package/dist/commonjs/index.d.ts
CHANGED
|
@@ -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 {
|
|
8
|
-
export {
|
|
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, 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';
|
package/dist/commonjs/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
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.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,6 +29,7 @@ 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; } });
|
|
@@ -39,31 +39,7 @@ Object.defineProperty(exports, "useManyProjects", { enumerable: true, get: funct
|
|
|
39
39
|
Object.defineProperty(exports, "useProjectSettings", { enumerable: true, get: function () { return projects_js_1.useProjectSettings; } });
|
|
40
40
|
Object.defineProperty(exports, "useSingleMember", { enumerable: true, get: function () { return projects_js_1.useSingleMember; } });
|
|
41
41
|
Object.defineProperty(exports, "useSingleProject", { enumerable: true, get: function () { return projects_js_1.useSingleProject; } });
|
|
42
|
+
Object.defineProperty(exports, "useStartSync", { enumerable: true, get: function () { return projects_js_1.useStartSync; } });
|
|
43
|
+
Object.defineProperty(exports, "useStopSync", { enumerable: true, get: function () { return projects_js_1.useStopSync; } });
|
|
44
|
+
Object.defineProperty(exports, "useSyncState", { enumerable: true, get: function () { return projects_js_1.useSyncState; } });
|
|
42
45
|
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
|
-
|
|
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 {};
|
|
@@ -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
|
|
9
|
-
*
|
|
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
|
-
}):
|
|
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
|
|
8
|
-
*
|
|
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 {
|
|
2
|
+
import type { WriteableDocumentType } from '../lib/types.js';
|
|
3
3
|
type ReadHookResult<D> = {
|
|
4
4
|
data: D;
|
|
5
5
|
error: Error | null;
|
|
@@ -106,9 +106,9 @@ export declare function useManyDocs<D extends WriteableDocumentType>({ projectId
|
|
|
106
106
|
docType: D;
|
|
107
107
|
includeDeleted?: boolean;
|
|
108
108
|
lang?: string;
|
|
109
|
-
}): ReadHookResult<Extract<MapeoDoc, {
|
|
109
|
+
}): ReadHookResult<Array<Extract<MapeoDoc, {
|
|
110
110
|
schemaName: D;
|
|
111
|
-
}
|
|
111
|
+
}>>>;
|
|
112
112
|
/**
|
|
113
113
|
* Create a document for a project.
|
|
114
114
|
*
|
|
@@ -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/
|
|
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/
|
|
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/
|
|
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/
|
|
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/
|
|
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
|
*
|
|
@@ -332,3 +333,52 @@ export declare function useCreateBlob({ projectId }: {
|
|
|
332
333
|
reset: () => void;
|
|
333
334
|
status: "pending" | "error" | "success" | "idle";
|
|
334
335
|
};
|
|
336
|
+
/**
|
|
337
|
+
* Hook to subscribe to the current sync state.
|
|
338
|
+
*
|
|
339
|
+
* Creates a global singleton for each project, to minimize traffic over IPC -
|
|
340
|
+
* this hook can safely be used in more than one place without attaching
|
|
341
|
+
* additional listeners across the IPC channel.
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* ```ts
|
|
345
|
+
* function Example() {
|
|
346
|
+
* const syncState = useSyncState({ projectId });
|
|
347
|
+
*
|
|
348
|
+
* if (!syncState) {
|
|
349
|
+
* // Sync information hasn't been loaded yet
|
|
350
|
+
* }
|
|
351
|
+
*
|
|
352
|
+
* // Actual info about sync state is available...
|
|
353
|
+
* }
|
|
354
|
+
* ```
|
|
355
|
+
*
|
|
356
|
+
* @param opts.projectId Project public ID
|
|
357
|
+
*/
|
|
358
|
+
export declare function useSyncState({ projectId, }: {
|
|
359
|
+
projectId: string;
|
|
360
|
+
}): SyncState | null;
|
|
361
|
+
/**
|
|
362
|
+
* Provides the progress of data sync for sync-enabled connected peers
|
|
363
|
+
*
|
|
364
|
+
* @returns `null` if no sync state events have been received. Otherwise returns a value between 0 and 1 (inclusive)
|
|
365
|
+
*/
|
|
366
|
+
export declare function useDataSyncProgress({ projectId, }: {
|
|
367
|
+
projectId: string;
|
|
368
|
+
}): number | null;
|
|
369
|
+
export declare function useStartSync({ projectId }: {
|
|
370
|
+
projectId: string;
|
|
371
|
+
}): {
|
|
372
|
+
mutate: import("@tanstack/react-query").UseMutateFunction<void, Error, {
|
|
373
|
+
autostopDataSyncAfter: number | null;
|
|
374
|
+
} | undefined, unknown>;
|
|
375
|
+
reset: () => void;
|
|
376
|
+
status: "pending" | "error" | "success" | "idle";
|
|
377
|
+
};
|
|
378
|
+
export declare function useStopSync({ projectId }: {
|
|
379
|
+
projectId: string;
|
|
380
|
+
}): {
|
|
381
|
+
mutate: import("@tanstack/react-query").UseMutateFunction<void, Error, void, unknown>;
|
|
382
|
+
reset: () => void;
|
|
383
|
+
status: "pending" | "error" | "success" | "idle";
|
|
384
|
+
};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { useMutation, useQueryClient, useSuspenseQuery, } from '@tanstack/react-query';
|
|
2
|
-
import {
|
|
2
|
+
import { useSyncExternalStore } from 'react';
|
|
3
|
+
import { addServerPeerMutationOptions, attachmentUrlQueryOptions, createBlobMutationOptions, createProjectMutationOptions, documentCreatedByQueryOptions, iconUrlQueryOptions, importProjectConfigMutationOptions, leaveProjectMutationOptions, projectByIdQueryOptions, projectMemberByIdQueryOptions, projectMembersQueryOptions, projectSettingsQueryOptions, projectsQueryOptions, startSyncMutationOptions, stopSyncMutationOptions, updateProjectSettingsMutationOptions, } from '../lib/react-query/projects.js';
|
|
4
|
+
import { SyncStore } from '../lib/sync.js';
|
|
3
5
|
import { useClientApi } from './client.js';
|
|
4
6
|
/**
|
|
5
7
|
* Retrieve the project settings for a project.
|
|
@@ -302,3 +304,59 @@ export function useCreateBlob({ projectId }) {
|
|
|
302
304
|
const { mutate, reset, status } = useMutation(createBlobMutationOptions({ projectApi }));
|
|
303
305
|
return { mutate, reset, status };
|
|
304
306
|
}
|
|
307
|
+
const PROJECT_SYNC_STORE_MAP = new WeakMap();
|
|
308
|
+
function useSyncStore({ projectId }) {
|
|
309
|
+
const { data: projectApi } = useSingleProject({ projectId });
|
|
310
|
+
let syncStore = PROJECT_SYNC_STORE_MAP.get(projectApi);
|
|
311
|
+
if (!syncStore) {
|
|
312
|
+
syncStore = new SyncStore(projectApi);
|
|
313
|
+
PROJECT_SYNC_STORE_MAP.set(projectApi, syncStore);
|
|
314
|
+
}
|
|
315
|
+
return syncStore;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Hook to subscribe to the current sync state.
|
|
319
|
+
*
|
|
320
|
+
* Creates a global singleton for each project, to minimize traffic over IPC -
|
|
321
|
+
* this hook can safely be used in more than one place without attaching
|
|
322
|
+
* additional listeners across the IPC channel.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* ```ts
|
|
326
|
+
* function Example() {
|
|
327
|
+
* const syncState = useSyncState({ projectId });
|
|
328
|
+
*
|
|
329
|
+
* if (!syncState) {
|
|
330
|
+
* // Sync information hasn't been loaded yet
|
|
331
|
+
* }
|
|
332
|
+
*
|
|
333
|
+
* // Actual info about sync state is available...
|
|
334
|
+
* }
|
|
335
|
+
* ```
|
|
336
|
+
*
|
|
337
|
+
* @param opts.projectId Project public ID
|
|
338
|
+
*/
|
|
339
|
+
export function useSyncState({ projectId, }) {
|
|
340
|
+
const syncStore = useSyncStore({ projectId });
|
|
341
|
+
const { subscribe, getStateSnapshot } = syncStore;
|
|
342
|
+
return useSyncExternalStore(subscribe, getStateSnapshot);
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Provides the progress of data sync for sync-enabled connected peers
|
|
346
|
+
*
|
|
347
|
+
* @returns `null` if no sync state events have been received. Otherwise returns a value between 0 and 1 (inclusive)
|
|
348
|
+
*/
|
|
349
|
+
export function useDataSyncProgress({ projectId, }) {
|
|
350
|
+
const { subscribe, getDataProgressSnapshot } = useSyncStore({ projectId });
|
|
351
|
+
return useSyncExternalStore(subscribe, getDataProgressSnapshot);
|
|
352
|
+
}
|
|
353
|
+
export function useStartSync({ projectId }) {
|
|
354
|
+
const { data: projectApi } = useSingleProject({ projectId });
|
|
355
|
+
const { mutate, reset, status } = useMutation(startSyncMutationOptions({ projectApi }));
|
|
356
|
+
return { mutate, reset, status };
|
|
357
|
+
}
|
|
358
|
+
export function useStopSync({ projectId }) {
|
|
359
|
+
const { data: projectApi } = useSingleProject({ projectId });
|
|
360
|
+
const { mutate, reset, status } = useMutation(stopSyncMutationOptions({ projectApi }));
|
|
361
|
+
return { mutate, reset, status };
|
|
362
|
+
}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -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 {
|
|
8
|
-
export {
|
|
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, 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';
|
package/dist/esm/index.js
CHANGED
|
@@ -3,10 +3,4 @@ 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, } 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, useProjectSettings, useSingleMember, useSingleProject, useStartSync, useStopSync, useSyncState, useUpdateProjectSettings, } from './hooks/projects.js';
|
|
@@ -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
|
-
|
|
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
|
+
};
|
|
@@ -207,3 +207,21 @@ export function createBlobMutationOptions({ projectApi, }) {
|
|
|
207
207
|
},
|
|
208
208
|
};
|
|
209
209
|
}
|
|
210
|
+
export function startSyncMutationOptions({ projectApi, }) {
|
|
211
|
+
return {
|
|
212
|
+
...baseMutationOptions(),
|
|
213
|
+
mutationFn: async (opts) => {
|
|
214
|
+
// Have to avoid passing `undefined` explicitly
|
|
215
|
+
// See https://github.com/digidem/rpc-reflector/issues/21
|
|
216
|
+
return opts ? projectApi.$sync.start(opts) : projectApi.$sync.start();
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
export function stopSyncMutationOptions({ projectApi, }) {
|
|
221
|
+
return {
|
|
222
|
+
...baseMutationOptions(),
|
|
223
|
+
mutationFn: async () => {
|
|
224
|
+
return projectApi.$sync.stop();
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|
|
@@ -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").State | null;
|
|
9
|
+
getDataProgressSnapshot: () => number | null;
|
|
10
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export function getDataSyncCountForDevice(syncStateForDevice) {
|
|
2
|
+
const { data } = syncStateForDevice;
|
|
3
|
+
return data.want + data.wanted;
|
|
4
|
+
}
|
|
5
|
+
export class SyncStore {
|
|
6
|
+
#project;
|
|
7
|
+
#listeners = new Set();
|
|
8
|
+
#isSubscribedInternal = false;
|
|
9
|
+
#error = null;
|
|
10
|
+
#state = null;
|
|
11
|
+
// Used for calculating sync progress
|
|
12
|
+
#perDeviceMaxSyncCount = new Map();
|
|
13
|
+
constructor(project) {
|
|
14
|
+
this.#project = project;
|
|
15
|
+
}
|
|
16
|
+
subscribe = (listener) => {
|
|
17
|
+
this.#listeners.add(listener);
|
|
18
|
+
if (!this.#isSubscribedInternal)
|
|
19
|
+
this.#startSubscription();
|
|
20
|
+
return () => {
|
|
21
|
+
this.#listeners.delete(listener);
|
|
22
|
+
if (this.#listeners.size === 0)
|
|
23
|
+
this.#stopSubscription();
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
getStateSnapshot = () => {
|
|
27
|
+
if (this.#error)
|
|
28
|
+
throw this.#error;
|
|
29
|
+
return this.#state;
|
|
30
|
+
};
|
|
31
|
+
getDataProgressSnapshot = () => {
|
|
32
|
+
if (this.#state === null) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
let currentSyncCount = 0;
|
|
36
|
+
let totalMaxSyncCount = 0;
|
|
37
|
+
let otherEnabledDevicesExist = false;
|
|
38
|
+
for (const [deviceId, deviceSyncState] of Object.entries(this.#state.remoteDeviceSyncState)) {
|
|
39
|
+
if (deviceSyncState.data.isSyncEnabled) {
|
|
40
|
+
otherEnabledDevicesExist = true;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const existingMaxCount = this.#perDeviceMaxSyncCount.get(deviceId);
|
|
46
|
+
if (typeof existingMaxCount === 'number' && existingMaxCount > 0) {
|
|
47
|
+
currentSyncCount = getDataSyncCountForDevice(deviceSyncState);
|
|
48
|
+
totalMaxSyncCount += existingMaxCount;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (!otherEnabledDevicesExist) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
if (totalMaxSyncCount === 0) {
|
|
55
|
+
return 1;
|
|
56
|
+
}
|
|
57
|
+
const ratio = (totalMaxSyncCount - currentSyncCount) / totalMaxSyncCount;
|
|
58
|
+
if (ratio <= 0)
|
|
59
|
+
return 0;
|
|
60
|
+
if (ratio >= 1)
|
|
61
|
+
return 1;
|
|
62
|
+
return clamp(ratio, 0.01, 0.99);
|
|
63
|
+
};
|
|
64
|
+
#notifyListeners() {
|
|
65
|
+
for (const listener of this.#listeners) {
|
|
66
|
+
listener();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
#onSyncState = (state) => {
|
|
70
|
+
const dataSyncWasEnabled = this.#state
|
|
71
|
+
? this.#state.data.isSyncEnabled
|
|
72
|
+
: false;
|
|
73
|
+
// Reset map keeping track of counts used for progress if data sync is toggled
|
|
74
|
+
if (dataSyncWasEnabled !== state.data.isSyncEnabled) {
|
|
75
|
+
this.#perDeviceMaxSyncCount.clear();
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// Remove devices from #perDeviceMaxSyncCount that are no longer found in the new sync state
|
|
79
|
+
for (const deviceId of this.#perDeviceMaxSyncCount.keys()) {
|
|
80
|
+
if (!Object.hasOwn(state.remoteDeviceSyncState, deviceId)) {
|
|
81
|
+
this.#perDeviceMaxSyncCount.delete(deviceId);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
for (const [deviceId, stateForDevice] of Object.entries(state.remoteDeviceSyncState)) {
|
|
86
|
+
const existingCount = this.#perDeviceMaxSyncCount.get(deviceId);
|
|
87
|
+
const newCount = getDataSyncCountForDevice(stateForDevice);
|
|
88
|
+
if (existingCount === undefined || existingCount < newCount) {
|
|
89
|
+
this.#perDeviceMaxSyncCount.set(deviceId, newCount);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
this.#state = state;
|
|
93
|
+
this.#error = null;
|
|
94
|
+
this.#notifyListeners();
|
|
95
|
+
};
|
|
96
|
+
#startSubscription = () => {
|
|
97
|
+
this.#project.$sync.on('sync-state', this.#onSyncState);
|
|
98
|
+
this.#isSubscribedInternal = true;
|
|
99
|
+
this.#project.$sync
|
|
100
|
+
.getState()
|
|
101
|
+
.then(this.#onSyncState)
|
|
102
|
+
.catch((e) => {
|
|
103
|
+
this.#error = e;
|
|
104
|
+
this.#notifyListeners();
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
#stopSubscription = () => {
|
|
108
|
+
this.#isSubscribedInternal = false;
|
|
109
|
+
this.#project.$sync.off('sync-state', this.#onSyncState);
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function clamp(value, min, max) {
|
|
113
|
+
return Math.max(min, Math.min(value, max));
|
|
114
|
+
}
|
|
@@ -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 @@
|
|
|
1
|
+
export {};
|
package/docs/API.md
CHANGED
|
@@ -20,6 +20,10 @@
|
|
|
20
20
|
- [useImportProjectConfig](#useimportprojectconfig)
|
|
21
21
|
- [useUpdateProjectSettings](#useupdateprojectsettings)
|
|
22
22
|
- [useCreateBlob](#usecreateblob)
|
|
23
|
+
- [useSyncState](#usesyncstate)
|
|
24
|
+
- [useDataSyncProgress](#usedatasyncprogress)
|
|
25
|
+
- [useStartSync](#usestartsync)
|
|
26
|
+
- [useStopSync](#usestopsync)
|
|
23
27
|
- [useSingleDocByDocId](#usesingledocbydocid)
|
|
24
28
|
- [useSingleDocByVersionId](#usesingledocbyversionid)
|
|
25
29
|
- [useManyDocs](#usemanydocs)
|
|
@@ -38,7 +42,7 @@ Create a context provider that holds a CoMapeo API client instance.
|
|
|
38
42
|
|
|
39
43
|
| Function | Type |
|
|
40
44
|
| ---------- | ---------- |
|
|
41
|
-
| `ClientApiProvider` | `({ children, clientApi, }: { children: ReactNode; clientApi: MapeoClientApi; }) =>
|
|
45
|
+
| `ClientApiProvider` | `({ children, clientApi, }: { children: ReactNode; clientApi: MapeoClientApi; }) => Element` |
|
|
42
46
|
|
|
43
47
|
Parameters:
|
|
44
48
|
|
|
@@ -427,13 +431,65 @@ Create a blob for a project.
|
|
|
427
431
|
|
|
428
432
|
| Function | Type |
|
|
429
433
|
| ---------- | ---------- |
|
|
430
|
-
| `useCreateBlob` | `({ projectId }: { projectId: string; }) => { mutate: UseMutateFunction<{ driveId: string; name: string; type: "
|
|
434
|
+
| `useCreateBlob` | `({ projectId }: { projectId: string; }) => { mutate: UseMutateFunction<{ driveId: string; name: string; type: "photo" or "audio" or "video"; hash: string; }, Error, { original: string; preview?: string or undefined; thumbnail?: string or undefined; metadata: Metadata; }, unknown>; reset: () => void; status: "pending" or ...` |
|
|
431
435
|
|
|
432
436
|
Parameters:
|
|
433
437
|
|
|
434
438
|
* `opts.projectId`: Public project ID of project to apply to changes to.
|
|
435
439
|
|
|
436
440
|
|
|
441
|
+
### useSyncState
|
|
442
|
+
|
|
443
|
+
Hook to subscribe to the current sync state.
|
|
444
|
+
|
|
445
|
+
Creates a global singleton for each project, to minimize traffic over IPC -
|
|
446
|
+
this hook can safely be used in more than one place without attaching
|
|
447
|
+
additional listeners across the IPC channel.
|
|
448
|
+
|
|
449
|
+
| Function | Type |
|
|
450
|
+
| ---------- | ---------- |
|
|
451
|
+
| `useSyncState` | `({ projectId, }: { projectId: string; }) => State or null` |
|
|
452
|
+
|
|
453
|
+
Parameters:
|
|
454
|
+
|
|
455
|
+
* `opts.projectId`: Project public ID
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
Examples:
|
|
459
|
+
|
|
460
|
+
```ts
|
|
461
|
+
function Example() {
|
|
462
|
+
const syncState = useSyncState({ projectId });
|
|
463
|
+
|
|
464
|
+
if (!syncState) {
|
|
465
|
+
// Sync information hasn't been loaded yet
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Actual info about sync state is available...
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
### useDataSyncProgress
|
|
474
|
+
|
|
475
|
+
Provides the progress of data sync for sync-enabled connected peers
|
|
476
|
+
|
|
477
|
+
| Function | Type |
|
|
478
|
+
| ---------- | ---------- |
|
|
479
|
+
| `useDataSyncProgress` | `({ projectId, }: { projectId: string; }) => number or null` |
|
|
480
|
+
|
|
481
|
+
### useStartSync
|
|
482
|
+
|
|
483
|
+
| Function | Type |
|
|
484
|
+
| ---------- | ---------- |
|
|
485
|
+
| `useStartSync` | `({ projectId }: { projectId: string; }) => { mutate: UseMutateFunction<void, Error, { autostopDataSyncAfter: number or null; } or undefined, unknown>; reset: () => void; status: "pending" or ... 2 more ... or "idle"; }` |
|
|
486
|
+
|
|
487
|
+
### useStopSync
|
|
488
|
+
|
|
489
|
+
| Function | Type |
|
|
490
|
+
| ---------- | ---------- |
|
|
491
|
+
| `useStopSync` | `({ projectId }: { projectId: string; }) => { mutate: UseMutateFunction<void, Error, void, unknown>; reset: () => void; status: "pending" or "error" or "success" or "idle"; }` |
|
|
492
|
+
|
|
437
493
|
### useSingleDocByDocId
|
|
438
494
|
|
|
439
495
|
Retrieve a single document from the database based on the document's document ID.
|
|
@@ -508,7 +564,7 @@ Retrieve all documents of a specific `docType`.
|
|
|
508
564
|
|
|
509
565
|
| Function | Type |
|
|
510
566
|
| ---------- | ---------- |
|
|
511
|
-
| `useManyDocs` | `<D extends WriteableDocumentType>({ projectId, docType, includeDeleted, lang, }: { projectId: string; docType: D; includeDeleted?: boolean or undefined; lang?: string or undefined; }) => ReadHookResult<Extract<{ schemaName: "deviceInfo"; name: string; deviceType: "device_type_unspecified" or ... 4 more ... or "
|
|
567
|
+
| `useManyDocs` | `<D extends WriteableDocumentType>({ projectId, docType, includeDeleted, lang, }: { projectId: string; docType: D; includeDeleted?: boolean or undefined; lang?: string or undefined; }) => ReadHookResult<(Extract<{ schemaName: "deviceInfo"; name: string; deviceType: "device_type_unspecified" or ... 4 more ... or "UNRECOGN...` |
|
|
512
568
|
|
|
513
569
|
Parameters:
|
|
514
570
|
|
|
@@ -678,3 +734,28 @@ function ExampleWithRefreshToken() {
|
|
|
678
734
|
| `ClientApiContext` | `Context<MapeoClientApi or null>` |
|
|
679
735
|
|
|
680
736
|
|
|
737
|
+
|
|
738
|
+
## Types
|
|
739
|
+
|
|
740
|
+
- [WriteableDocumentType](#writeabledocumenttype)
|
|
741
|
+
- [WriteableValue](#writeablevalue)
|
|
742
|
+
- [WriteableDocument](#writeabledocument)
|
|
743
|
+
|
|
744
|
+
### WriteableDocumentType
|
|
745
|
+
|
|
746
|
+
| Type | Type |
|
|
747
|
+
| ---------- | ---------- |
|
|
748
|
+
| `WriteableDocumentType` | `Extract< MapeoDoc['schemaName'], 'field' or 'observation' or 'preset' or 'track' or 'remoteDetectionAlert' >` |
|
|
749
|
+
|
|
750
|
+
### WriteableValue
|
|
751
|
+
|
|
752
|
+
| Type | Type |
|
|
753
|
+
| ---------- | ---------- |
|
|
754
|
+
| `WriteableValue` | `Extract< MapeoValue, { schemaName: D } >` |
|
|
755
|
+
|
|
756
|
+
### WriteableDocument
|
|
757
|
+
|
|
758
|
+
| Type | Type |
|
|
759
|
+
| ---------- | ---------- |
|
|
760
|
+
| `WriteableDocument` | `Extract< MapeoDoc, { schemaName: D } >` |
|
|
761
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@comapeo/core-react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "React wrapper for working with @comapeo/core",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,7 +35,6 @@
|
|
|
35
35
|
"types": "./dist/commonjs/index.d.ts",
|
|
36
36
|
"module": "./dist/esm/index.js",
|
|
37
37
|
"files": [
|
|
38
|
-
"CHANGELOG.md",
|
|
39
38
|
"dist/",
|
|
40
39
|
"docs/API.md"
|
|
41
40
|
],
|
|
@@ -48,16 +47,14 @@
|
|
|
48
47
|
}
|
|
49
48
|
},
|
|
50
49
|
"scripts": {
|
|
51
|
-
"
|
|
52
|
-
"prepare:tshy": "tshy",
|
|
53
|
-
"prepare": "npm-run-all --parallel prepare:*",
|
|
50
|
+
"docs:generate": "tsdoc --src=src/contexts/*,src/hooks/*,src/lib/types.ts --dest=docs/API.md --noemoji --types",
|
|
54
51
|
"lint:eslint": "eslint --cache .",
|
|
55
52
|
"lint:format": "prettier --cache --check .",
|
|
56
53
|
"lint": "npm-run-all --parallel --continue-on-error --print-label --aggregate-output lint:*",
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"test": "
|
|
60
|
-
"
|
|
54
|
+
"prepack": "tshy",
|
|
55
|
+
"prepare": "husky",
|
|
56
|
+
"test": "vitest run",
|
|
57
|
+
"types": "tsc"
|
|
61
58
|
},
|
|
62
59
|
"peerDependencies": {
|
|
63
60
|
"@comapeo/core": "*",
|
|
@@ -67,30 +64,33 @@
|
|
|
67
64
|
"react": "^18 || ^19"
|
|
68
65
|
},
|
|
69
66
|
"devDependencies": {
|
|
70
|
-
"@
|
|
71
|
-
"@
|
|
67
|
+
"@comapeo/core": "2.3.1",
|
|
68
|
+
"@comapeo/ipc": "2.1.0",
|
|
69
|
+
"@comapeo/schema": "1.4.1",
|
|
70
|
+
"@eslint/compat": "1.2.7",
|
|
71
|
+
"@eslint/js": "9.23.0",
|
|
72
72
|
"@ianvs/prettier-plugin-sort-imports": "4.4.1",
|
|
73
73
|
"@mapeo/crypto": "1.0.0-alpha.10",
|
|
74
|
-
"@tanstack/eslint-plugin-query": "5.
|
|
74
|
+
"@tanstack/eslint-plugin-query": "5.68.0",
|
|
75
|
+
"@tanstack/react-query": "5.69.0",
|
|
75
76
|
"@testing-library/dom": "10.4.0",
|
|
76
|
-
"@testing-library/react": "16.
|
|
77
|
-
"@types/
|
|
78
|
-
"@types/
|
|
79
|
-
"@types/react": "19.0.
|
|
80
|
-
"
|
|
81
|
-
"commit-and-tag-version": "12.5.0",
|
|
82
|
-
"eslint": "9.18.0",
|
|
77
|
+
"@testing-library/react": "16.2.0",
|
|
78
|
+
"@types/node": "22.13.13",
|
|
79
|
+
"@types/react": "19.0.12",
|
|
80
|
+
"@types/react-dom": "19.0.4",
|
|
81
|
+
"eslint": "9.23.0",
|
|
83
82
|
"fastify": "4.29.0",
|
|
84
|
-
"globals": "
|
|
83
|
+
"globals": "16.0.0",
|
|
85
84
|
"husky": "9.1.7",
|
|
86
|
-
"lint-staged": "15.
|
|
85
|
+
"lint-staged": "15.5.0",
|
|
87
86
|
"npm-run-all2": "7.0.2",
|
|
88
|
-
"prettier": "3.
|
|
87
|
+
"prettier": "3.5.3",
|
|
89
88
|
"random-access-memory": "6.2.1",
|
|
90
|
-
"
|
|
89
|
+
"react": "19.0.0",
|
|
90
|
+
"tsdoc-markdown": "1.2.0",
|
|
91
91
|
"tshy": "3.0.2",
|
|
92
|
-
"typescript": "5.
|
|
93
|
-
"typescript-eslint": "8.
|
|
94
|
-
"vitest": "
|
|
92
|
+
"typescript": "5.8.2",
|
|
93
|
+
"typescript-eslint": "8.27.0",
|
|
94
|
+
"vitest": "3.0.9"
|
|
95
95
|
}
|
|
96
96
|
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
|
|
4
|
-
|
|
5
|
-
## [0.1.2](https://github.com/digidem/comapeo-core-react/compare/v0.1.1...v0.1.2) (2024-12-12)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
### Bug Fixes
|
|
9
|
-
|
|
10
|
-
* fix return value of getIsArchiveDeviceQueryKey() ([8742fc2](https://github.com/digidem/comapeo-core-react/commit/8742fc24379564f64f9ec25c4c2e9179083d659d))
|
|
11
|
-
|
|
12
|
-
## [0.1.1](https://github.com/digidem/comapeo-core-react/compare/v0.1.0...v0.1.1) (2024-12-12)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
### Bug Fixes
|
|
16
|
-
|
|
17
|
-
* adjust peer dep specification for react query ([df090c3](https://github.com/digidem/comapeo-core-react/commit/df090c3b57032cf51d25b77afaa0e562163297c5))
|
|
18
|
-
|
|
19
|
-
## 0.1.0 (2024-12-12)
|
|
20
|
-
|
|
21
|
-
### Features
|
|
22
|
-
|
|
23
|
-
- initial implementation of many tanstack-query queries ([8a6aed7](https://github.com/digidem/comapeo-core-react/commit/8a6aed78f646c0f536551ac4a0423ff5d7780b33))
|