@dabble/patches 0.5.5 → 0.5.7
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/algorithms/server/createVersion.js +4 -4
- package/dist/algorithms/server/getSnapshotAtRevision.js +2 -2
- package/dist/algorithms/server/handleOfflineSessionsAndBatches.js +2 -2
- package/dist/algorithms/shared/changeBatching.js +4 -1
- package/dist/client/PatchesDoc.js +7 -1
- package/dist/net/PatchesSync.d.ts +6 -6
- package/dist/server/PatchesBranchManager.js +9 -9
- package/dist/server/types.d.ts +8 -2
- package/dist/solid/context.d.ts +67 -0
- package/dist/solid/context.js +20 -0
- package/dist/solid/doc-manager.d.ts +88 -0
- package/dist/solid/doc-manager.js +125 -0
- package/dist/solid/index.d.ts +19 -0
- package/dist/solid/index.js +17 -0
- package/dist/solid/primitives.d.ts +235 -0
- package/dist/solid/primitives.js +226 -0
- package/dist/types.d.ts +10 -10
- package/dist/vue/composables.d.ts +207 -0
- package/dist/vue/composables.js +216 -0
- package/dist/vue/doc-manager.d.ts +88 -0
- package/dist/vue/doc-manager.js +125 -0
- package/dist/vue/index.d.ts +19 -0
- package/dist/vue/index.js +28 -0
- package/dist/vue/provider.d.ts +89 -0
- package/dist/vue/provider.js +27 -0
- package/package.json +29 -5
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { Accessor } from 'solid-js';
|
|
2
|
+
import { PatchesDoc } from '../client/PatchesDoc.js';
|
|
3
|
+
import { ChangeMutator } from '../types.js';
|
|
4
|
+
import '../event-signal.js';
|
|
5
|
+
import '../algorithms/shared/changeBatching.js';
|
|
6
|
+
import '../json-patch/JSONPatch.js';
|
|
7
|
+
import '@dabble/delta';
|
|
8
|
+
import '../json-patch/types.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Options for usePatchesDoc primitive.
|
|
12
|
+
*/
|
|
13
|
+
interface UsePatchesDocOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Whether to automatically open/close the document based on component lifecycle.
|
|
16
|
+
*
|
|
17
|
+
* - `false` (default): Assumes doc is already open. Throws if not.
|
|
18
|
+
* - `true`: Opens doc on mount with ref counting, closes on cleanup.
|
|
19
|
+
*
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
autoClose?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Return type for usePatchesDoc primitive.
|
|
26
|
+
*/
|
|
27
|
+
interface UsePatchesDocReturn<T extends object> {
|
|
28
|
+
/**
|
|
29
|
+
* Accessor for the document state.
|
|
30
|
+
* Updated whenever the document changes (local or remote).
|
|
31
|
+
*/
|
|
32
|
+
data: Accessor<T | undefined>;
|
|
33
|
+
/**
|
|
34
|
+
* Whether the document is currently loading/syncing.
|
|
35
|
+
* - `true` during initial load or updates
|
|
36
|
+
* - `false` when fully synced
|
|
37
|
+
*/
|
|
38
|
+
loading: Accessor<boolean>;
|
|
39
|
+
/**
|
|
40
|
+
* Error that occurred during sync, if any.
|
|
41
|
+
*/
|
|
42
|
+
error: Accessor<Error | null>;
|
|
43
|
+
/**
|
|
44
|
+
* The committed revision number.
|
|
45
|
+
* Increments each time the server confirms changes.
|
|
46
|
+
*/
|
|
47
|
+
rev: Accessor<number>;
|
|
48
|
+
/**
|
|
49
|
+
* Whether there are pending local changes not yet committed by server.
|
|
50
|
+
*/
|
|
51
|
+
hasPending: Accessor<boolean>;
|
|
52
|
+
/**
|
|
53
|
+
* Make changes to the document.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* change((patch, root) => {
|
|
58
|
+
* patch.replace(root.title!, 'New Title')
|
|
59
|
+
* })
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
change: (mutator: ChangeMutator<T>) => void;
|
|
63
|
+
/**
|
|
64
|
+
* The underlying PatchesDoc instance.
|
|
65
|
+
* Useful for advanced operations.
|
|
66
|
+
*/
|
|
67
|
+
doc: Accessor<PatchesDoc<T> | undefined>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Solid primitive for reactive Patches document state.
|
|
71
|
+
*
|
|
72
|
+
* Provides reactive access to a Patches document with automatic lifecycle management.
|
|
73
|
+
*
|
|
74
|
+
* ## Explicit Lifecycle (default)
|
|
75
|
+
*
|
|
76
|
+
* By default, assumes the document is already open and just adds Solid reactivity.
|
|
77
|
+
* You control when documents are opened and closed.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```tsx
|
|
81
|
+
* import { onMount, onCleanup } from 'solid-js';
|
|
82
|
+
* import { usePatchesContext, usePatchesDoc } from '@dabble/patches/solid';
|
|
83
|
+
*
|
|
84
|
+
* function MyComponent(props) {
|
|
85
|
+
* const { patches } = usePatchesContext();
|
|
86
|
+
*
|
|
87
|
+
* // You control lifecycle
|
|
88
|
+
* onMount(() => patches.openDoc(props.docId));
|
|
89
|
+
* onCleanup(() => patches.closeDoc(props.docId));
|
|
90
|
+
*
|
|
91
|
+
* // Just adds reactivity
|
|
92
|
+
* // For static: usePatchesDoc('doc-123')
|
|
93
|
+
* // For reactive: usePatchesDoc(() => props.docId)
|
|
94
|
+
* const { data, loading, change } = usePatchesDoc(() => props.docId);
|
|
95
|
+
*
|
|
96
|
+
* return <div>{data()?.title}</div>;
|
|
97
|
+
* }
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
100
|
+
* ## Auto Lifecycle
|
|
101
|
+
*
|
|
102
|
+
* With `autoClose: true`, the primitive manages the document lifecycle with
|
|
103
|
+
* reference counting. Safe to use in multiple components with the same docId.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```tsx
|
|
107
|
+
* // Opens on mount, closes on cleanup (ref-counted)
|
|
108
|
+
* const { data, loading, change } = usePatchesDoc('doc-123', {
|
|
109
|
+
* autoClose: true
|
|
110
|
+
* });
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @param docId - Document ID (static string or accessor function)
|
|
114
|
+
* @param options - Configuration options
|
|
115
|
+
* @returns Reactive document state and utilities
|
|
116
|
+
* @throws Error if Patches context not provided
|
|
117
|
+
* @throws Error if doc not open in explicit mode
|
|
118
|
+
*/
|
|
119
|
+
declare function usePatchesDoc<T extends object>(docId: MaybeAccessor<string>, options?: UsePatchesDocOptions): UsePatchesDocReturn<T>;
|
|
120
|
+
/**
|
|
121
|
+
* Return type for usePatchesSync primitive.
|
|
122
|
+
*/
|
|
123
|
+
interface UsePatchesSyncReturn {
|
|
124
|
+
/**
|
|
125
|
+
* Whether the WebSocket connection is established.
|
|
126
|
+
*/
|
|
127
|
+
connected: Accessor<boolean>;
|
|
128
|
+
/**
|
|
129
|
+
* Whether documents are currently syncing with the server.
|
|
130
|
+
*/
|
|
131
|
+
syncing: Accessor<boolean>;
|
|
132
|
+
/**
|
|
133
|
+
* Whether the client believes it has network connectivity.
|
|
134
|
+
*/
|
|
135
|
+
online: Accessor<boolean>;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Solid primitive for reactive Patches sync state.
|
|
139
|
+
*
|
|
140
|
+
* Provides reactive access to PatchesSync connection and sync status.
|
|
141
|
+
* Useful for showing "Offline" banners, global loading indicators, etc.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```tsx
|
|
145
|
+
* const { connected, syncing, online } = usePatchesSync();
|
|
146
|
+
*
|
|
147
|
+
* return (
|
|
148
|
+
* <Show when={!connected()}>
|
|
149
|
+
* <div>You are offline</div>
|
|
150
|
+
* </Show>
|
|
151
|
+
* );
|
|
152
|
+
* ```
|
|
153
|
+
*
|
|
154
|
+
* @returns Reactive sync state
|
|
155
|
+
* @throws Error if Patches context not provided
|
|
156
|
+
* @throws Error if PatchesSync was not provided to context
|
|
157
|
+
*/
|
|
158
|
+
declare function usePatchesSync(): UsePatchesSyncReturn;
|
|
159
|
+
/**
|
|
160
|
+
* Type for document ID - can be static string or accessor function.
|
|
161
|
+
*/
|
|
162
|
+
type MaybeAccessor<T> = T | Accessor<T>;
|
|
163
|
+
/**
|
|
164
|
+
* Creates a named document context that can be provided to child components.
|
|
165
|
+
*
|
|
166
|
+
* This enables child components to access the document using the returned `useDoc` hook
|
|
167
|
+
* without needing to pass the docId down through props. Supports both static and
|
|
168
|
+
* reactive docIds.
|
|
169
|
+
*
|
|
170
|
+
* ## Use Cases
|
|
171
|
+
*
|
|
172
|
+
* **Static document (user settings):**
|
|
173
|
+
* ```tsx
|
|
174
|
+
* const { Provider, useDoc } = createPatchesDoc<User>('user');
|
|
175
|
+
*
|
|
176
|
+
* <Provider docId="user-123">
|
|
177
|
+
* <UserProfile />
|
|
178
|
+
* </Provider>
|
|
179
|
+
* ```
|
|
180
|
+
*
|
|
181
|
+
* **Reactive document (multi-tab):**
|
|
182
|
+
* ```tsx
|
|
183
|
+
* const { Provider, useDoc } = createPatchesDoc<Whiteboard>('whiteboard');
|
|
184
|
+
* const [activeTabId, setActiveTabId] = createSignal('design-1');
|
|
185
|
+
*
|
|
186
|
+
* <Provider docId={activeTabId}>
|
|
187
|
+
* <WhiteboardCanvas />
|
|
188
|
+
* </Provider>
|
|
189
|
+
* ```
|
|
190
|
+
*
|
|
191
|
+
* **With autoClose:**
|
|
192
|
+
* ```tsx
|
|
193
|
+
* const { Provider, useDoc } = createPatchesDoc<Doc>('document');
|
|
194
|
+
* const [currentDocId, setCurrentDocId] = createSignal('doc-1');
|
|
195
|
+
*
|
|
196
|
+
* <Provider docId={currentDocId} autoClose>
|
|
197
|
+
* <DocumentEditor />
|
|
198
|
+
* </Provider>
|
|
199
|
+
* ```
|
|
200
|
+
*
|
|
201
|
+
* @param name - Unique identifier for this document context (e.g., 'whiteboard', 'user')
|
|
202
|
+
* @returns Object with Provider component and useDoc hook
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* ```tsx
|
|
206
|
+
* // Create the context
|
|
207
|
+
* const { Provider: WhiteboardProvider, useDoc: useWhiteboard } =
|
|
208
|
+
* createPatchesDoc<WhiteboardDoc>('whiteboard');
|
|
209
|
+
*
|
|
210
|
+
* // Use in parent
|
|
211
|
+
* <WhiteboardProvider docId="whiteboard-123">
|
|
212
|
+
* <Canvas />
|
|
213
|
+
* </WhiteboardProvider>
|
|
214
|
+
*
|
|
215
|
+
* // Use in child
|
|
216
|
+
* function Canvas() {
|
|
217
|
+
* const { data, change } = useWhiteboard();
|
|
218
|
+
* return <div>{data()?.title}</div>;
|
|
219
|
+
* }
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
222
|
+
/**
|
|
223
|
+
* Props for the Provider component returned by createPatchesDoc.
|
|
224
|
+
*/
|
|
225
|
+
interface PatchesDocProviderProps {
|
|
226
|
+
docId: MaybeAccessor<string>;
|
|
227
|
+
autoClose?: boolean;
|
|
228
|
+
children: any;
|
|
229
|
+
}
|
|
230
|
+
declare function createPatchesDoc<T extends object>(name: string): {
|
|
231
|
+
Provider: (props: PatchesDocProviderProps) => any;
|
|
232
|
+
useDoc: () => UsePatchesDocReturn<T>;
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
export { type MaybeAccessor, type PatchesDocProviderProps, type UsePatchesDocOptions, type UsePatchesDocReturn, type UsePatchesSyncReturn, createPatchesDoc, usePatchesDoc, usePatchesSync };
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import "../chunk-IZ2YBCUP.js";
|
|
2
|
+
import {
|
|
3
|
+
createSignal,
|
|
4
|
+
createContext,
|
|
5
|
+
useContext,
|
|
6
|
+
createResource,
|
|
7
|
+
createEffect,
|
|
8
|
+
onCleanup
|
|
9
|
+
} from "solid-js";
|
|
10
|
+
import { usePatchesContext } from "./context.js";
|
|
11
|
+
import { getDocManager } from "./doc-manager.js";
|
|
12
|
+
function usePatchesDoc(docId, options = {}) {
|
|
13
|
+
const { patches } = usePatchesContext();
|
|
14
|
+
const autoClose = options.autoClose ?? false;
|
|
15
|
+
const [doc, setDoc] = createSignal(void 0);
|
|
16
|
+
const [data, setData] = createSignal(void 0);
|
|
17
|
+
const [loading, setLoading] = createSignal(true);
|
|
18
|
+
const [error, setError] = createSignal(null);
|
|
19
|
+
const [rev, setRev] = createSignal(0);
|
|
20
|
+
const [hasPending, setHasPending] = createSignal(false);
|
|
21
|
+
const manager = getDocManager(patches);
|
|
22
|
+
const docIdAccessor = toAccessor(docId);
|
|
23
|
+
function setupDoc(patchesDoc) {
|
|
24
|
+
setDoc(patchesDoc);
|
|
25
|
+
const unsubState = patchesDoc.subscribe((state) => {
|
|
26
|
+
setData(() => state);
|
|
27
|
+
setRev(patchesDoc.committedRev);
|
|
28
|
+
setHasPending(patchesDoc.hasPending);
|
|
29
|
+
});
|
|
30
|
+
onCleanup(() => unsubState());
|
|
31
|
+
const unsubSync = patchesDoc.onSyncing((syncState) => {
|
|
32
|
+
setLoading(syncState === "initial" || syncState === "updating");
|
|
33
|
+
setError(syncState instanceof Error ? syncState : null);
|
|
34
|
+
});
|
|
35
|
+
onCleanup(() => unsubSync());
|
|
36
|
+
setLoading(patchesDoc.syncing !== null);
|
|
37
|
+
}
|
|
38
|
+
if (autoClose) {
|
|
39
|
+
const [docResource] = createResource(docIdAccessor, async (id) => {
|
|
40
|
+
return await manager.openDoc(patches, id);
|
|
41
|
+
});
|
|
42
|
+
createEffect(() => {
|
|
43
|
+
const loadedDoc = docResource();
|
|
44
|
+
if (loadedDoc) {
|
|
45
|
+
setupDoc(loadedDoc);
|
|
46
|
+
}
|
|
47
|
+
const resourceError = docResource.error;
|
|
48
|
+
if (resourceError) {
|
|
49
|
+
setError(resourceError);
|
|
50
|
+
setLoading(false);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
onCleanup(() => {
|
|
54
|
+
const id = docIdAccessor();
|
|
55
|
+
manager.closeDoc(patches, id);
|
|
56
|
+
});
|
|
57
|
+
} else {
|
|
58
|
+
createEffect(() => {
|
|
59
|
+
const id = docIdAccessor();
|
|
60
|
+
const patchesDoc = patches.getOpenDoc(id);
|
|
61
|
+
if (!patchesDoc) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`Document "${id}" is not open. Either open it with patches.openDoc() first, or use { autoClose: true } option.`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
manager.incrementRefCount(id);
|
|
67
|
+
setupDoc(patchesDoc);
|
|
68
|
+
onCleanup(() => {
|
|
69
|
+
manager.decrementRefCount(id);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function change(mutator) {
|
|
74
|
+
const currentDoc = doc();
|
|
75
|
+
if (!currentDoc) {
|
|
76
|
+
throw new Error("Cannot make changes: document not loaded yet");
|
|
77
|
+
}
|
|
78
|
+
currentDoc.change(mutator);
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
data,
|
|
82
|
+
loading,
|
|
83
|
+
error,
|
|
84
|
+
rev,
|
|
85
|
+
hasPending,
|
|
86
|
+
change,
|
|
87
|
+
doc
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function usePatchesSync() {
|
|
91
|
+
const { sync } = usePatchesContext();
|
|
92
|
+
if (!sync) {
|
|
93
|
+
throw new Error("PatchesSync not found in context. Did you forget to pass sync to PatchesProvider?");
|
|
94
|
+
}
|
|
95
|
+
const [connected, setConnected] = createSignal(sync.state.connected);
|
|
96
|
+
const [syncing, setSyncing] = createSignal(sync.state.syncing === "updating");
|
|
97
|
+
const [online, setOnline] = createSignal(sync.state.online);
|
|
98
|
+
const unsubscribe = sync.onStateChange((state) => {
|
|
99
|
+
setConnected(state.connected);
|
|
100
|
+
setSyncing(state.syncing === "updating");
|
|
101
|
+
setOnline(state.online);
|
|
102
|
+
});
|
|
103
|
+
onCleanup(() => {
|
|
104
|
+
unsubscribe();
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
connected,
|
|
108
|
+
syncing,
|
|
109
|
+
online
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function toAccessor(value) {
|
|
113
|
+
return typeof value === "function" ? value : () => value;
|
|
114
|
+
}
|
|
115
|
+
function createPatchesDoc(name) {
|
|
116
|
+
const Context = createContext();
|
|
117
|
+
function Provider(props) {
|
|
118
|
+
const { patches } = usePatchesContext();
|
|
119
|
+
const manager = getDocManager(patches);
|
|
120
|
+
const autoClose = props.autoClose ?? false;
|
|
121
|
+
const [doc, setDoc] = createSignal(void 0);
|
|
122
|
+
const [data, setData] = createSignal(void 0);
|
|
123
|
+
const [loading, setLoading] = createSignal(true);
|
|
124
|
+
const [error, setError] = createSignal(null);
|
|
125
|
+
const [rev, setRev] = createSignal(0);
|
|
126
|
+
const [hasPending, setHasPending] = createSignal(false);
|
|
127
|
+
function setupDoc(patchesDoc) {
|
|
128
|
+
setDoc(patchesDoc);
|
|
129
|
+
const unsubState = patchesDoc.subscribe((state) => {
|
|
130
|
+
setData(() => state);
|
|
131
|
+
setRev(patchesDoc.committedRev);
|
|
132
|
+
setHasPending(patchesDoc.hasPending);
|
|
133
|
+
});
|
|
134
|
+
onCleanup(() => unsubState());
|
|
135
|
+
const unsubSync = patchesDoc.onSyncing((syncState) => {
|
|
136
|
+
setLoading(syncState === "initial" || syncState === "updating");
|
|
137
|
+
setError(syncState instanceof Error ? syncState : null);
|
|
138
|
+
});
|
|
139
|
+
onCleanup(() => unsubSync());
|
|
140
|
+
setLoading(patchesDoc.syncing !== null);
|
|
141
|
+
}
|
|
142
|
+
const docIdAccessor = toAccessor(props.docId);
|
|
143
|
+
if (autoClose) {
|
|
144
|
+
const [docResource] = createResource(docIdAccessor, async (id) => {
|
|
145
|
+
return await manager.openDoc(patches, id);
|
|
146
|
+
});
|
|
147
|
+
createEffect(() => {
|
|
148
|
+
const loadedDoc = docResource();
|
|
149
|
+
if (loadedDoc) {
|
|
150
|
+
setupDoc(loadedDoc);
|
|
151
|
+
}
|
|
152
|
+
const resourceError = docResource.error;
|
|
153
|
+
if (resourceError) {
|
|
154
|
+
setError(resourceError);
|
|
155
|
+
setLoading(false);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
createEffect((prevId) => {
|
|
159
|
+
const currentId = docIdAccessor();
|
|
160
|
+
if (prevId && prevId !== currentId) {
|
|
161
|
+
manager.closeDoc(patches, prevId);
|
|
162
|
+
}
|
|
163
|
+
return currentId;
|
|
164
|
+
});
|
|
165
|
+
onCleanup(() => {
|
|
166
|
+
const id = docIdAccessor();
|
|
167
|
+
manager.closeDoc(patches, id);
|
|
168
|
+
});
|
|
169
|
+
} else {
|
|
170
|
+
createEffect((prevId) => {
|
|
171
|
+
const id = docIdAccessor();
|
|
172
|
+
if (prevId && prevId !== id) {
|
|
173
|
+
manager.decrementRefCount(prevId);
|
|
174
|
+
}
|
|
175
|
+
const patchesDoc = patches.getOpenDoc(id);
|
|
176
|
+
if (!patchesDoc) {
|
|
177
|
+
throw new Error(
|
|
178
|
+
`Document "${id}" is not open. Either open it with patches.openDoc() first, or use autoClose option.`
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
manager.incrementRefCount(id);
|
|
182
|
+
setupDoc(patchesDoc);
|
|
183
|
+
return id;
|
|
184
|
+
});
|
|
185
|
+
onCleanup(() => {
|
|
186
|
+
const id = docIdAccessor();
|
|
187
|
+
manager.decrementRefCount(id);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
function change(mutator) {
|
|
191
|
+
const currentDoc = doc();
|
|
192
|
+
if (!currentDoc) {
|
|
193
|
+
throw new Error("Cannot make changes: document not loaded yet");
|
|
194
|
+
}
|
|
195
|
+
currentDoc.change(mutator);
|
|
196
|
+
}
|
|
197
|
+
const value = {
|
|
198
|
+
data,
|
|
199
|
+
loading,
|
|
200
|
+
error,
|
|
201
|
+
rev,
|
|
202
|
+
hasPending,
|
|
203
|
+
change,
|
|
204
|
+
doc
|
|
205
|
+
};
|
|
206
|
+
return /* @__PURE__ */ React.createElement(Context.Provider, { value, children: props.children });
|
|
207
|
+
}
|
|
208
|
+
function useDoc() {
|
|
209
|
+
const context = useContext(Context);
|
|
210
|
+
if (!context) {
|
|
211
|
+
throw new Error(
|
|
212
|
+
`useDoc('${name}') must be called within the corresponding Provider. Did you forget to wrap your component with the Provider from createPatchesDoc('${name}')?`
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
return context;
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
Provider,
|
|
219
|
+
useDoc
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
export {
|
|
223
|
+
createPatchesDoc,
|
|
224
|
+
usePatchesDoc,
|
|
225
|
+
usePatchesSync
|
|
226
|
+
};
|
package/dist/types.d.ts
CHANGED
|
@@ -68,9 +68,9 @@ interface Branch {
|
|
|
68
68
|
/** The ID of the branch document. */
|
|
69
69
|
id: string;
|
|
70
70
|
/** The ID of the document this document was branched from. */
|
|
71
|
-
|
|
71
|
+
docId: string;
|
|
72
72
|
/** The revision number on the source document where the branch occurred. */
|
|
73
|
-
|
|
73
|
+
branchedAtRev: number;
|
|
74
74
|
/** Server-side ISO timestamp when the branch was created (UTC with Z). */
|
|
75
75
|
createdAt: string;
|
|
76
76
|
/** Optional user-friendly name for the branch. */
|
|
@@ -80,7 +80,7 @@ interface Branch {
|
|
|
80
80
|
/** Optional arbitrary metadata associated with the branch record. */
|
|
81
81
|
[metadata: string]: any;
|
|
82
82
|
}
|
|
83
|
-
type EditableBranchMetadata = Disallowed<Branch, 'id' | '
|
|
83
|
+
type EditableBranchMetadata = Disallowed<Branch, 'id' | 'docId' | 'branchedAtRev' | 'createdAt' | 'status'>;
|
|
84
84
|
/**
|
|
85
85
|
* Metadata, state snapshot, and included changes for a specific version.
|
|
86
86
|
*/
|
|
@@ -102,17 +102,17 @@ interface VersionMetadata {
|
|
|
102
102
|
startedAt: string;
|
|
103
103
|
/** Server-side ISO timestamp of version end (UTC with Z). */
|
|
104
104
|
endedAt: string;
|
|
105
|
-
/** The revision number this version
|
|
106
|
-
|
|
107
|
-
/** The revision number
|
|
108
|
-
|
|
105
|
+
/** The ending revision number of this version (the last change's rev). */
|
|
106
|
+
endRev: number;
|
|
107
|
+
/** The starting revision number of this version (the first change's baseRev). If this is an offline/branch version, this is the revision number of the source document where the branch was created. */
|
|
108
|
+
startRev: number;
|
|
109
109
|
/** Optional arbitrary metadata associated with the version. */
|
|
110
110
|
[metadata: string]: any;
|
|
111
111
|
}
|
|
112
112
|
type Disallowed<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>> & {
|
|
113
113
|
[P in K]?: never;
|
|
114
114
|
};
|
|
115
|
-
type EditableVersionMetadata = Disallowed<VersionMetadata, 'id' | 'parentId' | 'groupId' | 'origin' | 'branchName' | 'startedAt' | 'endedAt' | '
|
|
115
|
+
type EditableVersionMetadata = Disallowed<VersionMetadata, 'id' | 'parentId' | 'groupId' | 'origin' | 'branchName' | 'startedAt' | 'endedAt' | 'endRev' | 'startRev'>;
|
|
116
116
|
/**
|
|
117
117
|
* Options for committing changes.
|
|
118
118
|
*/
|
|
@@ -155,8 +155,8 @@ interface ListVersionsOptions {
|
|
|
155
155
|
endBefore?: number | string;
|
|
156
156
|
/** Maximum number of versions to return. */
|
|
157
157
|
limit?: number;
|
|
158
|
-
/** Sort by startedAt,
|
|
159
|
-
orderBy?: 'startedAt' | '
|
|
158
|
+
/** Sort by startedAt, endRev, or startRev. Defaults to 'endRev'. */
|
|
159
|
+
orderBy?: 'startedAt' | 'endRev' | 'startRev';
|
|
160
160
|
/** Return versions in descending order. Defaults to false (ascending). When reversed, startAfter and endBefore apply to the *reversed* list. */
|
|
161
161
|
reverse?: boolean;
|
|
162
162
|
/** Filter by the origin type. */
|