@vrtmrz/livesync-commonlib 0.1.31 → 0.1.33
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/README.md +12 -0
- package/dist/API/DirectFileManipulatorV2.d.ts +2 -0
- package/dist/API/DirectFileManipulatorV2.js +17 -5
- package/dist/API/processSetting.d.ts +19 -0
- package/dist/API/processSetting.js +91 -6
- package/dist/common/idDerivation.d.ts +15 -0
- package/dist/common/idDerivation.js +102 -0
- package/dist/common/models/db.definition.d.ts +1 -0
- package/dist/common/models/setting.const.defaults.js +3 -0
- package/dist/common/models/setting.const.qr.js +4 -1
- package/dist/common/models/setting.type.d.ts +6 -0
- package/dist/common/models/tweak.compatibility.js +6 -2
- package/dist/common/models/tweak.definition.d.ts +8 -0
- package/dist/common/models/tweak.definition.js +4 -3
- package/dist/common/settingConstants.d.ts +3 -0
- package/dist/common/utils.js +3 -1
- package/dist/events/coreEvents.d.ts +3 -0
- package/dist/events/coreEvents.js +2 -0
- package/dist/hashing.d.ts +3 -0
- package/dist/hashing.js +4 -0
- package/dist/managers/EntryManager/EntryManagerImpls.js +10 -1
- package/dist/managers/HashManager/HashManager.d.ts +4 -0
- package/dist/managers/HashManager/HashManager.js +34 -2
- package/dist/managers/LiveSyncManagers.js +6 -0
- package/dist/pouchdb/LiveSyncDBFunctions.d.ts +1 -1
- package/dist/pouchdb/LiveSyncDBFunctions.js +33 -38
- package/dist/pouchdb/negotiation.js +7 -3
- package/dist/pouchdb/remoteFeatureCompatibility.d.ts +10 -0
- package/dist/pouchdb/remoteFeatureCompatibility.js +12 -1
- package/dist/pouchdb/remoteIdCompatibility.d.ts +5 -0
- package/dist/pouchdb/remoteIdCompatibility.js +28 -0
- package/dist/replication/CentralCompatibility.d.ts +1 -0
- package/dist/replication/CentralCompatibility.js +2 -1
- package/dist/replication/couchdb/LiveSyncReplicator.d.ts +6 -2
- package/dist/replication/couchdb/LiveSyncReplicator.js +24 -5
- package/dist/replication/journal/LiveSyncJournalReplicator.d.ts +1 -0
- package/dist/replication/journal/LiveSyncJournalReplicator.js +50 -5
- package/dist/replication/trystero/ProxiedDB.d.ts +1 -1
- package/dist/replication/trystero/TrysteroReplicator.d.ts +369 -5
- package/dist/replication/trystero/TrysteroReplicator.js +31 -4
- package/dist/services/base/AppLifecycleService.d.ts +2 -0
- package/dist/services/base/AppLifecycleService.js +5 -0
- package/dist/services/base/IService.d.ts +1 -0
- package/dist/services/base/PathService.d.ts +3 -1
- package/dist/services/base/PathService.js +9 -4
- package/dist/services/base/SettingService.js +47 -0
- package/dist/settings.d.ts +2 -1
- package/dist/settings.js +14 -0
- package/dist/setupUri.d.ts +6 -0
- package/dist/setupUri.js +14 -0
- package/dist/string_and_binary/path.d.ts +1 -1
- package/dist/string_and_binary/path.js +3 -3
- package/dist/worker/bgWorker.js +1 -1
- package/docs/proven-in-use.md +12 -0
- package/docs/releasing.md +1 -1
- package/docs/setup-uri.md +58 -0
- package/package.json +17 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type EntryDoc, type ObsidianLiveSyncSettings } from "../../common/types.js";
|
|
1
|
+
import { type EntryDoc, type ObsidianLiveSyncSettings, type P2PSyncSetting } from "../../common/types.js";
|
|
2
2
|
import { type LOG_LEVEL } from "octagonal-wheels/common/logger";
|
|
3
3
|
import { type ProgressInfo } from "../../pouchdb/ReplicatorShim.js";
|
|
4
4
|
import type { Confirm } from "../../interfaces/Confirm.js";
|
|
@@ -115,9 +115,9 @@ export declare class TrysteroReplicator {
|
|
|
115
115
|
private readonly fallbackAutomationCoordinator;
|
|
116
116
|
server?: P2PHost;
|
|
117
117
|
replicationStatus(): {};
|
|
118
|
-
get settings():
|
|
118
|
+
get settings(): P2PSyncSetting;
|
|
119
119
|
/** Latest room-local policy settings supplied by the owning host. */
|
|
120
|
-
get currentSettings():
|
|
120
|
+
get currentSettings(): P2PSyncSetting;
|
|
121
121
|
get db(): PouchDB.Database<EntryDoc>;
|
|
122
122
|
get deviceName(): string;
|
|
123
123
|
get platform(): string;
|
|
@@ -140,12 +140,376 @@ export declare class TrysteroReplicator {
|
|
|
140
140
|
_onSetup: boolean;
|
|
141
141
|
setOnSetup(): void;
|
|
142
142
|
clearOnSetup(): void;
|
|
143
|
-
getTweakSettings(fromPeerId: string): Promise<
|
|
143
|
+
getTweakSettings(fromPeerId: string): Promise<{
|
|
144
|
+
idDerivationVersion: 0 | 1;
|
|
145
|
+
idDerivationProof: string;
|
|
146
|
+
liveSync?: boolean;
|
|
147
|
+
syncOnSave?: boolean;
|
|
148
|
+
syncOnStart?: boolean;
|
|
149
|
+
syncOnFileOpen?: boolean;
|
|
150
|
+
syncOnEditorSave?: boolean;
|
|
151
|
+
keepReplicationActiveInBackground?: boolean;
|
|
152
|
+
allowSleepDuringSynchronisation?: boolean;
|
|
153
|
+
allowSleepDuringSynchronisationOnDesktop?: boolean;
|
|
154
|
+
syncMinimumInterval?: number;
|
|
155
|
+
showVerboseLog?: boolean;
|
|
156
|
+
lessInformationInLog?: boolean;
|
|
157
|
+
showLongerLogInsideEditor?: boolean;
|
|
158
|
+
showStatusOnEditor?: boolean;
|
|
159
|
+
showStatusOnStatusbar?: boolean;
|
|
160
|
+
showOnlyIconsOnEditor?: boolean;
|
|
161
|
+
hideFileWarningNotice?: boolean;
|
|
162
|
+
networkWarningStyle?: "" | "icon" | "hidden";
|
|
163
|
+
displayLanguage?: import("../../common/models/setting.type.js").I18N_LANGS;
|
|
164
|
+
trashInsteadDelete?: boolean;
|
|
165
|
+
doNotDeleteFolder?: boolean;
|
|
166
|
+
batchSave?: boolean;
|
|
167
|
+
batchSaveMinimumDelay?: number;
|
|
168
|
+
batchSaveMaximumDelay?: number;
|
|
169
|
+
syncMaxSizeInMB?: number;
|
|
170
|
+
useIgnoreFiles?: boolean;
|
|
171
|
+
ignoreFiles?: string;
|
|
172
|
+
processSizeMismatchedFiles?: boolean;
|
|
173
|
+
syncOnlyRegEx?: import("../../common/types.js").CustomRegExpSourceList<"|[]|">;
|
|
174
|
+
syncIgnoreRegEx?: import("../../common/types.js").CustomRegExpSourceList<"|[]|">;
|
|
175
|
+
syncAfterMerge?: boolean;
|
|
176
|
+
resolveConflictsByNewerFile?: boolean;
|
|
177
|
+
writeDocumentsIfConflicted?: boolean;
|
|
178
|
+
disableMarkdownAutoMerge?: boolean;
|
|
179
|
+
configPassphraseStore?: import("../../common/types.js").ConfigPassphraseStore;
|
|
180
|
+
encryptedPassphrase?: string;
|
|
181
|
+
encryptedIdDerivationKey?: string;
|
|
182
|
+
encryptedCouchDBConnection?: string;
|
|
183
|
+
periodicReplication?: boolean;
|
|
184
|
+
periodicReplicationInterval?: number;
|
|
185
|
+
syncInternalFiles?: boolean;
|
|
186
|
+
syncInternalFilesBeforeReplication?: boolean;
|
|
187
|
+
syncInternalFilesInterval?: number;
|
|
188
|
+
syncInternalFilesIgnorePatterns?: import("../../common/types.js").CustomRegExpSourceList<",">;
|
|
189
|
+
syncInternalFilesTargetPatterns?: import("../../common/types.js").CustomRegExpSourceList<",">;
|
|
190
|
+
watchInternalFileChanges?: boolean;
|
|
191
|
+
suppressNotifyHiddenFilesChange?: boolean;
|
|
192
|
+
syncInternalFileOverwritePatterns?: import("../../common/types.js").CustomRegExpSourceList<",">;
|
|
193
|
+
usePluginSync?: boolean;
|
|
194
|
+
usePluginSettings?: boolean;
|
|
195
|
+
showOwnPlugins?: boolean;
|
|
196
|
+
autoSweepPlugins?: boolean;
|
|
197
|
+
autoSweepPluginsPeriodic?: boolean;
|
|
198
|
+
notifyPluginOrSettingUpdated?: boolean;
|
|
199
|
+
deviceAndVaultName?: string;
|
|
200
|
+
usePluginSyncV2?: boolean;
|
|
201
|
+
usePluginEtc?: boolean;
|
|
202
|
+
pluginSyncExtendedSetting?: Record<import("../../common/types.js").PluginSyncSettingEntry["key"], import("../../common/types.js").PluginSyncSettingEntry>;
|
|
203
|
+
useAdvancedMode?: boolean;
|
|
204
|
+
usePowerUserMode?: boolean;
|
|
205
|
+
useEdgeCaseMode?: boolean;
|
|
206
|
+
notifyThresholdOfRemoteStorageSize?: number;
|
|
207
|
+
disableWorkerForGeneratingChunks?: boolean;
|
|
208
|
+
processSmallFilesInUIThread?: boolean;
|
|
209
|
+
savingDelay?: number;
|
|
210
|
+
gcDelay?: number;
|
|
211
|
+
skipOlderFilesOnSync?: boolean;
|
|
212
|
+
useIndexedDBAdapter?: boolean;
|
|
213
|
+
enableDebugTools?: boolean;
|
|
214
|
+
writeLogToTheFile?: boolean;
|
|
215
|
+
settingSyncFile?: string;
|
|
216
|
+
writeCredentialsForSettingSync?: boolean;
|
|
217
|
+
notifyAllSettingSyncFile?: boolean;
|
|
218
|
+
suspendFileWatching?: boolean;
|
|
219
|
+
suspendParseReplicationResult?: boolean;
|
|
220
|
+
doNotSuspendOnFetching?: boolean;
|
|
221
|
+
maxMTimeForReflectEvents?: number;
|
|
222
|
+
versionUpFlash?: string;
|
|
223
|
+
settingVersion?: number;
|
|
224
|
+
isConfigured?: boolean;
|
|
225
|
+
lastReadUpdates?: number;
|
|
226
|
+
doctorProcessedVersion?: string;
|
|
227
|
+
remoteConfigurations?: Record<string, import("../../remoteConfigurations.js").RemoteConfiguration>;
|
|
228
|
+
activeConfigurationId?: string;
|
|
229
|
+
P2P_ActiveRemoteConfigurationId?: string;
|
|
230
|
+
couchDB_URI?: string;
|
|
231
|
+
couchDB_USER?: string;
|
|
232
|
+
couchDB_PASSWORD?: string;
|
|
233
|
+
couchDB_DBNAME?: string;
|
|
234
|
+
couchDB_CustomHeaders?: string;
|
|
235
|
+
useJWT?: boolean;
|
|
236
|
+
jwtAlgorithm?: import("../../common/models/auth.type.js").JWTAlgorithm;
|
|
237
|
+
jwtKey?: string;
|
|
238
|
+
jwtKid?: string;
|
|
239
|
+
jwtSub?: string;
|
|
240
|
+
jwtExpDuration?: number;
|
|
241
|
+
useRequestAPI?: boolean;
|
|
242
|
+
accessKey?: string;
|
|
243
|
+
secretKey?: string;
|
|
244
|
+
bucket?: string;
|
|
245
|
+
region?: string;
|
|
246
|
+
endpoint?: string;
|
|
247
|
+
useCustomRequestHandler?: boolean;
|
|
248
|
+
bucketCustomHeaders?: string;
|
|
249
|
+
bucketPrefix?: string;
|
|
250
|
+
forcePathStyle?: boolean;
|
|
251
|
+
remoteType?: import("../../common/types.js").RemoteType;
|
|
252
|
+
encrypt?: boolean;
|
|
253
|
+
passphrase?: string;
|
|
254
|
+
idDerivationKey?: string;
|
|
255
|
+
usePathObfuscation?: boolean;
|
|
256
|
+
encryptInternalMetadata?: boolean;
|
|
257
|
+
E2EEAlgorithm?: import("../../common/types.js").E2EEAlgorithm;
|
|
258
|
+
hashAlg?: import("../../common/types.js").HashAlgorithm;
|
|
259
|
+
minimumChunkSize?: number;
|
|
260
|
+
customChunkSize?: number;
|
|
261
|
+
longLineThreshold?: number;
|
|
262
|
+
useSegmenter?: boolean;
|
|
263
|
+
enableChunkSplitterV2?: boolean;
|
|
264
|
+
doNotUseFixedRevisionForChunks?: boolean;
|
|
265
|
+
chunkSplitterVersion?: import("../../common/types.js").ChunkSplitterVersion;
|
|
266
|
+
useEden?: boolean;
|
|
267
|
+
maxChunksInEden?: number;
|
|
268
|
+
maxTotalLengthInEden?: number;
|
|
269
|
+
maxAgeInEden?: number;
|
|
270
|
+
tweakModified?: number | undefined;
|
|
271
|
+
checkIntegrityOnSave?: boolean;
|
|
272
|
+
useHistory?: boolean;
|
|
273
|
+
disableRequestURI?: boolean;
|
|
274
|
+
sendChunksBulk?: boolean;
|
|
275
|
+
sendChunksBulkMaxSize?: number;
|
|
276
|
+
useDynamicIterationCount?: boolean;
|
|
277
|
+
doNotPaceReplication?: boolean;
|
|
278
|
+
readChunksOnline?: boolean;
|
|
279
|
+
useOnlyLocalChunk?: boolean;
|
|
280
|
+
concurrencyOfReadChunksOnline?: number;
|
|
281
|
+
minimumIntervalOfReadChunksOnline?: number;
|
|
282
|
+
enableCompression?: boolean;
|
|
283
|
+
batch_size?: number;
|
|
284
|
+
batches_limit?: number;
|
|
285
|
+
ignoreVersionCheck?: boolean;
|
|
286
|
+
disableCheckingConfigMismatch?: boolean;
|
|
287
|
+
autoAcceptCompatibleTweak?: boolean | undefined;
|
|
288
|
+
hashCacheMaxCount?: number;
|
|
289
|
+
hashCacheMaxAmount?: number;
|
|
290
|
+
permitEmptyPassphrase?: boolean;
|
|
291
|
+
handleFilenameCaseSensitive?: boolean;
|
|
292
|
+
checkConflictOnlyOnOpen?: boolean;
|
|
293
|
+
showMergeDialogOnlyOnActive?: boolean;
|
|
294
|
+
additionalSuffixOfDatabaseName?: string | undefined;
|
|
295
|
+
useTimeouts?: boolean;
|
|
296
|
+
deleteMetadataOfDeletedFiles?: boolean;
|
|
297
|
+
automaticallyDeleteMetadataOfDeletedFiles?: number;
|
|
298
|
+
P2P_AutoAccepting?: import("../../common/types.js").AutoAccepting;
|
|
299
|
+
P2P_AutoSyncPeers?: string;
|
|
300
|
+
P2P_AutoWatchPeers?: string;
|
|
301
|
+
P2P_SyncOnReplication?: string;
|
|
302
|
+
P2P_RebuildFrom?: string;
|
|
303
|
+
P2P_AutoAcceptingPeers?: string;
|
|
304
|
+
P2P_AutoDenyingPeers?: string;
|
|
305
|
+
P2P_IsHeadless?: boolean;
|
|
306
|
+
P2P_iceServers?: readonly RTCIceServer[];
|
|
307
|
+
P2P_iceServersExpiresAt?: number;
|
|
308
|
+
P2P_Enabled?: boolean;
|
|
309
|
+
P2P_relays?: string;
|
|
310
|
+
P2P_roomID?: string;
|
|
311
|
+
P2P_passphrase?: string;
|
|
312
|
+
P2P_AppID?: string;
|
|
313
|
+
P2P_AutoStart?: boolean;
|
|
314
|
+
P2P_AutoBroadcast?: boolean;
|
|
315
|
+
P2P_DevicePeerName?: string;
|
|
316
|
+
P2P_turnServers?: string;
|
|
317
|
+
P2P_turnUsername?: string;
|
|
318
|
+
P2P_turnCredential?: string;
|
|
319
|
+
P2P_managedType?: string;
|
|
320
|
+
P2P_managedId?: string;
|
|
321
|
+
P2P_managedToken?: string;
|
|
322
|
+
P2P_maxWirePayloadBytes?: number;
|
|
323
|
+
P2P_connectionPath?: import("../../common/types.js").P2PConnectionPath;
|
|
324
|
+
P2P_useDiagRTC?: boolean;
|
|
325
|
+
}>;
|
|
144
326
|
private handleSynchronisationRequest;
|
|
145
327
|
getCommands(): {
|
|
146
328
|
reqSync: (fromPeerId: string) => Promise<P2PReplicationWireResult>;
|
|
147
329
|
"!reqAuth": (fromPeerId: string) => Promise<boolean>;
|
|
148
|
-
getTweakSettings: (fromPeerId: string) => Promise<
|
|
330
|
+
getTweakSettings: (fromPeerId: string) => Promise<{
|
|
331
|
+
idDerivationVersion: 0 | 1;
|
|
332
|
+
idDerivationProof: string;
|
|
333
|
+
liveSync?: boolean;
|
|
334
|
+
syncOnSave?: boolean;
|
|
335
|
+
syncOnStart?: boolean;
|
|
336
|
+
syncOnFileOpen?: boolean;
|
|
337
|
+
syncOnEditorSave?: boolean;
|
|
338
|
+
keepReplicationActiveInBackground?: boolean;
|
|
339
|
+
allowSleepDuringSynchronisation?: boolean;
|
|
340
|
+
allowSleepDuringSynchronisationOnDesktop?: boolean;
|
|
341
|
+
syncMinimumInterval?: number;
|
|
342
|
+
showVerboseLog?: boolean;
|
|
343
|
+
lessInformationInLog?: boolean;
|
|
344
|
+
showLongerLogInsideEditor?: boolean;
|
|
345
|
+
showStatusOnEditor?: boolean;
|
|
346
|
+
showStatusOnStatusbar?: boolean;
|
|
347
|
+
showOnlyIconsOnEditor?: boolean;
|
|
348
|
+
hideFileWarningNotice?: boolean;
|
|
349
|
+
networkWarningStyle?: "" | "icon" | "hidden";
|
|
350
|
+
displayLanguage?: import("../../common/models/setting.type.js").I18N_LANGS;
|
|
351
|
+
trashInsteadDelete?: boolean;
|
|
352
|
+
doNotDeleteFolder?: boolean;
|
|
353
|
+
batchSave?: boolean;
|
|
354
|
+
batchSaveMinimumDelay?: number;
|
|
355
|
+
batchSaveMaximumDelay?: number;
|
|
356
|
+
syncMaxSizeInMB?: number;
|
|
357
|
+
useIgnoreFiles?: boolean;
|
|
358
|
+
ignoreFiles?: string;
|
|
359
|
+
processSizeMismatchedFiles?: boolean;
|
|
360
|
+
syncOnlyRegEx?: import("../../common/types.js").CustomRegExpSourceList<"|[]|">;
|
|
361
|
+
syncIgnoreRegEx?: import("../../common/types.js").CustomRegExpSourceList<"|[]|">;
|
|
362
|
+
syncAfterMerge?: boolean;
|
|
363
|
+
resolveConflictsByNewerFile?: boolean;
|
|
364
|
+
writeDocumentsIfConflicted?: boolean;
|
|
365
|
+
disableMarkdownAutoMerge?: boolean;
|
|
366
|
+
configPassphraseStore?: import("../../common/types.js").ConfigPassphraseStore;
|
|
367
|
+
encryptedPassphrase?: string;
|
|
368
|
+
encryptedIdDerivationKey?: string;
|
|
369
|
+
encryptedCouchDBConnection?: string;
|
|
370
|
+
periodicReplication?: boolean;
|
|
371
|
+
periodicReplicationInterval?: number;
|
|
372
|
+
syncInternalFiles?: boolean;
|
|
373
|
+
syncInternalFilesBeforeReplication?: boolean;
|
|
374
|
+
syncInternalFilesInterval?: number;
|
|
375
|
+
syncInternalFilesIgnorePatterns?: import("../../common/types.js").CustomRegExpSourceList<",">;
|
|
376
|
+
syncInternalFilesTargetPatterns?: import("../../common/types.js").CustomRegExpSourceList<",">;
|
|
377
|
+
watchInternalFileChanges?: boolean;
|
|
378
|
+
suppressNotifyHiddenFilesChange?: boolean;
|
|
379
|
+
syncInternalFileOverwritePatterns?: import("../../common/types.js").CustomRegExpSourceList<",">;
|
|
380
|
+
usePluginSync?: boolean;
|
|
381
|
+
usePluginSettings?: boolean;
|
|
382
|
+
showOwnPlugins?: boolean;
|
|
383
|
+
autoSweepPlugins?: boolean;
|
|
384
|
+
autoSweepPluginsPeriodic?: boolean;
|
|
385
|
+
notifyPluginOrSettingUpdated?: boolean;
|
|
386
|
+
deviceAndVaultName?: string;
|
|
387
|
+
usePluginSyncV2?: boolean;
|
|
388
|
+
usePluginEtc?: boolean;
|
|
389
|
+
pluginSyncExtendedSetting?: Record<import("../../common/types.js").PluginSyncSettingEntry["key"], import("../../common/types.js").PluginSyncSettingEntry>;
|
|
390
|
+
useAdvancedMode?: boolean;
|
|
391
|
+
usePowerUserMode?: boolean;
|
|
392
|
+
useEdgeCaseMode?: boolean;
|
|
393
|
+
notifyThresholdOfRemoteStorageSize?: number;
|
|
394
|
+
disableWorkerForGeneratingChunks?: boolean;
|
|
395
|
+
processSmallFilesInUIThread?: boolean;
|
|
396
|
+
savingDelay?: number;
|
|
397
|
+
gcDelay?: number;
|
|
398
|
+
skipOlderFilesOnSync?: boolean;
|
|
399
|
+
useIndexedDBAdapter?: boolean;
|
|
400
|
+
enableDebugTools?: boolean;
|
|
401
|
+
writeLogToTheFile?: boolean;
|
|
402
|
+
settingSyncFile?: string;
|
|
403
|
+
writeCredentialsForSettingSync?: boolean;
|
|
404
|
+
notifyAllSettingSyncFile?: boolean;
|
|
405
|
+
suspendFileWatching?: boolean;
|
|
406
|
+
suspendParseReplicationResult?: boolean;
|
|
407
|
+
doNotSuspendOnFetching?: boolean;
|
|
408
|
+
maxMTimeForReflectEvents?: number;
|
|
409
|
+
versionUpFlash?: string;
|
|
410
|
+
settingVersion?: number;
|
|
411
|
+
isConfigured?: boolean;
|
|
412
|
+
lastReadUpdates?: number;
|
|
413
|
+
doctorProcessedVersion?: string;
|
|
414
|
+
remoteConfigurations?: Record<string, import("../../remoteConfigurations.js").RemoteConfiguration>;
|
|
415
|
+
activeConfigurationId?: string;
|
|
416
|
+
P2P_ActiveRemoteConfigurationId?: string;
|
|
417
|
+
couchDB_URI?: string;
|
|
418
|
+
couchDB_USER?: string;
|
|
419
|
+
couchDB_PASSWORD?: string;
|
|
420
|
+
couchDB_DBNAME?: string;
|
|
421
|
+
couchDB_CustomHeaders?: string;
|
|
422
|
+
useJWT?: boolean;
|
|
423
|
+
jwtAlgorithm?: import("../../common/models/auth.type.js").JWTAlgorithm;
|
|
424
|
+
jwtKey?: string;
|
|
425
|
+
jwtKid?: string;
|
|
426
|
+
jwtSub?: string;
|
|
427
|
+
jwtExpDuration?: number;
|
|
428
|
+
useRequestAPI?: boolean;
|
|
429
|
+
accessKey?: string;
|
|
430
|
+
secretKey?: string;
|
|
431
|
+
bucket?: string;
|
|
432
|
+
region?: string;
|
|
433
|
+
endpoint?: string;
|
|
434
|
+
useCustomRequestHandler?: boolean;
|
|
435
|
+
bucketCustomHeaders?: string;
|
|
436
|
+
bucketPrefix?: string;
|
|
437
|
+
forcePathStyle?: boolean;
|
|
438
|
+
remoteType?: import("../../common/types.js").RemoteType;
|
|
439
|
+
encrypt?: boolean;
|
|
440
|
+
passphrase?: string;
|
|
441
|
+
idDerivationKey?: string;
|
|
442
|
+
usePathObfuscation?: boolean;
|
|
443
|
+
encryptInternalMetadata?: boolean;
|
|
444
|
+
E2EEAlgorithm?: import("../../common/types.js").E2EEAlgorithm;
|
|
445
|
+
hashAlg?: import("../../common/types.js").HashAlgorithm;
|
|
446
|
+
minimumChunkSize?: number;
|
|
447
|
+
customChunkSize?: number;
|
|
448
|
+
longLineThreshold?: number;
|
|
449
|
+
useSegmenter?: boolean;
|
|
450
|
+
enableChunkSplitterV2?: boolean;
|
|
451
|
+
doNotUseFixedRevisionForChunks?: boolean;
|
|
452
|
+
chunkSplitterVersion?: import("../../common/types.js").ChunkSplitterVersion;
|
|
453
|
+
useEden?: boolean;
|
|
454
|
+
maxChunksInEden?: number;
|
|
455
|
+
maxTotalLengthInEden?: number;
|
|
456
|
+
maxAgeInEden?: number;
|
|
457
|
+
tweakModified?: number | undefined;
|
|
458
|
+
checkIntegrityOnSave?: boolean;
|
|
459
|
+
useHistory?: boolean;
|
|
460
|
+
disableRequestURI?: boolean;
|
|
461
|
+
sendChunksBulk?: boolean;
|
|
462
|
+
sendChunksBulkMaxSize?: number;
|
|
463
|
+
useDynamicIterationCount?: boolean;
|
|
464
|
+
doNotPaceReplication?: boolean;
|
|
465
|
+
readChunksOnline?: boolean;
|
|
466
|
+
useOnlyLocalChunk?: boolean;
|
|
467
|
+
concurrencyOfReadChunksOnline?: number;
|
|
468
|
+
minimumIntervalOfReadChunksOnline?: number;
|
|
469
|
+
enableCompression?: boolean;
|
|
470
|
+
batch_size?: number;
|
|
471
|
+
batches_limit?: number;
|
|
472
|
+
ignoreVersionCheck?: boolean;
|
|
473
|
+
disableCheckingConfigMismatch?: boolean;
|
|
474
|
+
autoAcceptCompatibleTweak?: boolean | undefined;
|
|
475
|
+
hashCacheMaxCount?: number;
|
|
476
|
+
hashCacheMaxAmount?: number;
|
|
477
|
+
permitEmptyPassphrase?: boolean;
|
|
478
|
+
handleFilenameCaseSensitive?: boolean;
|
|
479
|
+
checkConflictOnlyOnOpen?: boolean;
|
|
480
|
+
showMergeDialogOnlyOnActive?: boolean;
|
|
481
|
+
additionalSuffixOfDatabaseName?: string | undefined;
|
|
482
|
+
useTimeouts?: boolean;
|
|
483
|
+
deleteMetadataOfDeletedFiles?: boolean;
|
|
484
|
+
automaticallyDeleteMetadataOfDeletedFiles?: number;
|
|
485
|
+
P2P_AutoAccepting?: import("../../common/types.js").AutoAccepting;
|
|
486
|
+
P2P_AutoSyncPeers?: string;
|
|
487
|
+
P2P_AutoWatchPeers?: string;
|
|
488
|
+
P2P_SyncOnReplication?: string;
|
|
489
|
+
P2P_RebuildFrom?: string;
|
|
490
|
+
P2P_AutoAcceptingPeers?: string;
|
|
491
|
+
P2P_AutoDenyingPeers?: string;
|
|
492
|
+
P2P_IsHeadless?: boolean;
|
|
493
|
+
P2P_iceServers?: readonly RTCIceServer[];
|
|
494
|
+
P2P_iceServersExpiresAt?: number;
|
|
495
|
+
P2P_Enabled?: boolean;
|
|
496
|
+
P2P_relays?: string;
|
|
497
|
+
P2P_roomID?: string;
|
|
498
|
+
P2P_passphrase?: string;
|
|
499
|
+
P2P_AppID?: string;
|
|
500
|
+
P2P_AutoStart?: boolean;
|
|
501
|
+
P2P_AutoBroadcast?: boolean;
|
|
502
|
+
P2P_DevicePeerName?: string;
|
|
503
|
+
P2P_turnServers?: string;
|
|
504
|
+
P2P_turnUsername?: string;
|
|
505
|
+
P2P_turnCredential?: string;
|
|
506
|
+
P2P_managedType?: string;
|
|
507
|
+
P2P_managedId?: string;
|
|
508
|
+
P2P_managedToken?: string;
|
|
509
|
+
P2P_maxWirePayloadBytes?: number;
|
|
510
|
+
P2P_connectionPath?: import("../../common/types.js").P2PConnectionPath;
|
|
511
|
+
P2P_useDiagRTC?: boolean;
|
|
512
|
+
}>;
|
|
149
513
|
onProgress: (fromPeerId: string) => Promise<{
|
|
150
514
|
error: import("../../rpc/index.js").RpcErrorShape;
|
|
151
515
|
}>;
|
|
@@ -24,6 +24,9 @@ import { sha1 } from "octagonal-wheels/hash/purejs";
|
|
|
24
24
|
import { getRelaySockets, pauseRelayReconnection, resumeRelayReconnection } from "@trystero-p2p/nostr";
|
|
25
25
|
import { P2PAutomationCoordinator } from "./P2PAutomationCoordinator.js";
|
|
26
26
|
import { compatGlobal } from "../../common/coreEnvFunctions.js";
|
|
27
|
+
import { computeKeyedId, configuredIdKey } from "../../common/idDerivation.js";
|
|
28
|
+
import { getWebCrypto } from "../../mods.js";
|
|
29
|
+
import { uint8ArrayToHexString } from "../../string_and_binary/convert.js";
|
|
27
30
|
import {
|
|
28
31
|
fromP2PReplicationWireResult,
|
|
29
32
|
toP2PReplicationWireResult,
|
|
@@ -216,7 +219,14 @@ class TrysteroReplicator {
|
|
|
216
219
|
delete allSettings[key];
|
|
217
220
|
}
|
|
218
221
|
}
|
|
219
|
-
|
|
222
|
+
const idSettings = this.currentSettings;
|
|
223
|
+
const idDerivationVersion = idSettings.idDerivationVersion ?? 0;
|
|
224
|
+
const idKey = configuredIdKey({ idDerivationVersion, idDerivationKey: idSettings.idDerivationKey ?? "" });
|
|
225
|
+
return {
|
|
226
|
+
...allSettings,
|
|
227
|
+
idDerivationVersion,
|
|
228
|
+
idDerivationProof: idKey && idSettings.encrypt && idSettings.usePathObfuscation ? await computeKeyedId(idKey, "peer-agreement", fromPeerId) : ""
|
|
229
|
+
};
|
|
220
230
|
}
|
|
221
231
|
async handleSynchronisationRequest(fromPeerId, signal) {
|
|
222
232
|
if (this._onSetup) {
|
|
@@ -706,7 +716,13 @@ ${info.lastSeq} / ${info.maxSeqInBatch})`,
|
|
|
706
716
|
const decryptedConfig = JSON.parse(
|
|
707
717
|
await decrypt(encryptedConfig, passphrase)
|
|
708
718
|
);
|
|
709
|
-
|
|
719
|
+
const settings = {
|
|
720
|
+
...decryptedConfig,
|
|
721
|
+
idDerivationVersion: decryptedConfig.idDerivationVersion ?? 0,
|
|
722
|
+
idDerivationKey: decryptedConfig.idDerivationKey ?? ""
|
|
723
|
+
};
|
|
724
|
+
configuredIdKey(settings);
|
|
725
|
+
return omitP2PRuntimeSettings(settings);
|
|
710
726
|
} catch (e) {
|
|
711
727
|
Logger("Error while decrypting the configuration", LOG_LEVEL_NOTICE);
|
|
712
728
|
Logger(e, LOG_LEVEL_VERBOSE);
|
|
@@ -731,9 +747,12 @@ ${info.lastSeq} / ${info.maxSeqInBatch})`,
|
|
|
731
747
|
return true;
|
|
732
748
|
}
|
|
733
749
|
const connection = this.server.getConnection(peerId);
|
|
734
|
-
const
|
|
750
|
+
const challengeBytes = new Uint8Array(16);
|
|
751
|
+
(await getWebCrypto()).getRandomValues(challengeBytes);
|
|
752
|
+
const challenge = uint8ArrayToHexString(challengeBytes);
|
|
753
|
+
const tweakValues = await connection.invokeRemoteObjectFunction("getTweakSettings", [challenge], 5e3, signal);
|
|
735
754
|
if (signal?.aborted) return false;
|
|
736
|
-
const thisTweakValues = await this.getTweakSettings(
|
|
755
|
+
const thisTweakValues = await this.getTweakSettings(challenge);
|
|
737
756
|
if (thisTweakValues.passphrase !== tweakValues.passphrase) {
|
|
738
757
|
Logger(
|
|
739
758
|
"Replication cancelled: Passphrase is not matched\nCannot replicate to a remote database until the problem is resolved.",
|
|
@@ -741,6 +760,14 @@ ${info.lastSeq} / ${info.maxSeqInBatch})`,
|
|
|
741
760
|
);
|
|
742
761
|
return false;
|
|
743
762
|
}
|
|
763
|
+
if (thisTweakValues.encrypt !== tweakValues.encrypt || thisTweakValues.usePathObfuscation !== tweakValues.usePathObfuscation) {
|
|
764
|
+
Logger("Replication cancelled: The encryption or path obfuscation settings do not match this peer.", logLevel);
|
|
765
|
+
return false;
|
|
766
|
+
}
|
|
767
|
+
if (thisTweakValues.encrypt && thisTweakValues.usePathObfuscation && ((thisTweakValues.idDerivationVersion ?? 0) !== (tweakValues.idDerivationVersion ?? 0) || (thisTweakValues.idDerivationProof ?? "") !== (tweakValues.idDerivationProof ?? ""))) {
|
|
768
|
+
Logger("Replication cancelled: The ID derivation settings do not match this peer.", logLevel);
|
|
769
|
+
return false;
|
|
770
|
+
}
|
|
744
771
|
const tweakAssessment = assessTweakCompatibility(thisTweakValues, tweakValues);
|
|
745
772
|
if (!tweakAssessment.representationDiffers) return true;
|
|
746
773
|
Logger(
|
|
@@ -119,6 +119,8 @@ export declare abstract class AppLifecycleService<T extends ServiceContext = Ser
|
|
|
119
119
|
isReady(): boolean;
|
|
120
120
|
/**
|
|
121
121
|
* Mark the plug-in as ready.
|
|
122
|
+
* Establishing readiness emits `EVENT_APPLICATION_READY` on the context's event channel, so a host can
|
|
123
|
+
* continue work it held while the plug-in was not ready. Marking a plug-in which is already ready emits nothing.
|
|
122
124
|
*/
|
|
123
125
|
markIsReady(): void;
|
|
124
126
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EVENT_APPLICATION_READY } from "../../events/coreEvents.js";
|
|
1
2
|
import { handlers } from "../lib/HandlerUtils.js";
|
|
2
3
|
import { ServiceBase } from "./ServiceBase.js";
|
|
3
4
|
class AppLifecycleService extends ServiceBase {
|
|
@@ -107,9 +108,13 @@ class AppLifecycleService extends ServiceBase {
|
|
|
107
108
|
}
|
|
108
109
|
/**
|
|
109
110
|
* Mark the plug-in as ready.
|
|
111
|
+
* Establishing readiness emits `EVENT_APPLICATION_READY` on the context's event channel, so a host can
|
|
112
|
+
* continue work it held while the plug-in was not ready. Marking a plug-in which is already ready emits nothing.
|
|
110
113
|
*/
|
|
111
114
|
markIsReady() {
|
|
115
|
+
if (this._isReady) return;
|
|
112
116
|
this._isReady = true;
|
|
117
|
+
this.context.events.emitEvent(EVENT_APPLICATION_READY);
|
|
113
118
|
}
|
|
114
119
|
/**
|
|
115
120
|
* Reset the ready state of the plug-in.
|
|
@@ -60,6 +60,7 @@ export interface IAPIService {
|
|
|
60
60
|
export interface IPathService {
|
|
61
61
|
id2path(id: DocumentID, entry?: EntryHasPath, stripPrefix?: boolean): FilePathWithPrefix;
|
|
62
62
|
path2id(filename: FilePathWithPrefix | FilePath, prefix?: string): Promise<DocumentID>;
|
|
63
|
+
path2idWithSettings(filename: FilePathWithPrefix | FilePath, setting: Pick<RemoteDBSettings, "encrypt" | "usePathObfuscation" | "passphrase" | "handleFilenameCaseSensitive" | "idDerivationVersion" | "idDerivationKey">, prefix?: string): Promise<DocumentID>;
|
|
63
64
|
getPath(entry: AnyEntry): FilePathWithPrefix;
|
|
64
65
|
markChangesAreSame(old: UXFileInfo | AnyEntry | FilePathWithPrefix, newMtime: number, oldMtime: number): boolean | undefined;
|
|
65
66
|
unmarkChanges(file: AnyEntry | FilePathWithPrefix | UXFileInfoStub): void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DocumentID, EntryHasPath, FilePathWithPrefix, FilePath, AnyEntry, UXFileInfo, UXFileInfoStub } from "../../common/types.js";
|
|
1
|
+
import type { DocumentID, EntryHasPath, FilePathWithPrefix, FilePath, AnyEntry, RemoteDBSettings, UXFileInfo, UXFileInfoStub } from "../../common/types.js";
|
|
2
2
|
import type { IPathService, ISettingService } from "./IService.js";
|
|
3
3
|
import { ServiceBase, type ServiceContext } from "./ServiceBase.js";
|
|
4
4
|
import type { BASE_IS_NEW, EVEN, TARGET_IS_NEW } from "../../common/models/shared.const.symbols.js";
|
|
@@ -36,6 +36,8 @@ export declare abstract class PathService<T extends ServiceContext = ServiceCont
|
|
|
36
36
|
* @param prefix The prefix to use for the document ID.
|
|
37
37
|
*/
|
|
38
38
|
path2id(filename: FilePathWithPrefix | FilePath, prefix?: string): Promise<DocumentID>;
|
|
39
|
+
/** Convert a path using the caller's settings snapshot and this host's path normalisation. */
|
|
40
|
+
path2idWithSettings(filename: FilePathWithPrefix | FilePath, setting: Pick<RemoteDBSettings, "encrypt" | "usePathObfuscation" | "passphrase" | "handleFilenameCaseSensitive" | "idDerivationVersion" | "idDerivationKey">, prefix?: string): Promise<DocumentID>;
|
|
39
41
|
getPath(entry: AnyEntry): FilePathWithPrefix;
|
|
40
42
|
abstract markChangesAreSame(old: UXFileInfo | AnyEntry | FilePathWithPrefix, newMtime: number, oldMtime: number): boolean | undefined;
|
|
41
43
|
abstract unmarkChanges(file: AnyEntry | FilePathWithPrefix | UXFileInfoStub): void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ServiceBase } from "./ServiceBase.js";
|
|
2
2
|
import { addPrefix, expandFilePathPrefix, id2path_base, path2id_base } from "../../string_and_binary/path.js";
|
|
3
|
+
import { configuredIdKey } from "../../common/idDerivation.js";
|
|
3
4
|
import { isInternalMetadata, stripInternalMetadataPrefix } from "../../common/typeUtils.js";
|
|
4
5
|
class PathService extends ServiceBase {
|
|
5
6
|
settingService;
|
|
@@ -17,10 +18,10 @@ class PathService extends ServiceBase {
|
|
|
17
18
|
const [prefix, path] = expandFilePathPrefix(filename);
|
|
18
19
|
return prefix + this.normalizePath(path);
|
|
19
20
|
}
|
|
20
|
-
async _path2id(filename, obfuscatePassphrase, caseInsensitive) {
|
|
21
|
+
async _path2id(filename, obfuscatePassphrase, caseInsensitive, idDerivationKey) {
|
|
21
22
|
const [prefix, path] = expandFilePathPrefix(filename);
|
|
22
23
|
const fixedPath = prefix + this.normalizePath(path);
|
|
23
|
-
const out = await path2id_base(fixedPath, obfuscatePassphrase, caseInsensitive);
|
|
24
|
+
const out = await path2id_base(fixedPath, obfuscatePassphrase, caseInsensitive, idDerivationKey);
|
|
24
25
|
return out;
|
|
25
26
|
}
|
|
26
27
|
/**
|
|
@@ -44,13 +45,17 @@ class PathService extends ServiceBase {
|
|
|
44
45
|
* @param prefix The prefix to use for the document ID.
|
|
45
46
|
*/
|
|
46
47
|
async path2id(filename, prefix) {
|
|
48
|
+
return this.path2idWithSettings(filename, this.settings, prefix);
|
|
49
|
+
}
|
|
50
|
+
/** Convert a path using the caller's settings snapshot and this host's path normalisation. */
|
|
51
|
+
async path2idWithSettings(filename, setting, prefix) {
|
|
47
52
|
const destPath = addPrefix(filename, prefix ?? "");
|
|
48
|
-
const setting = this.settings;
|
|
49
53
|
const pathObfuscationPassphrase = this.getPathObfuscationPassphrase?.() ?? (setting.usePathObfuscation ? setting.passphrase : false);
|
|
50
54
|
return await this._path2id(
|
|
51
55
|
destPath,
|
|
52
56
|
pathObfuscationPassphrase,
|
|
53
|
-
!setting.handleFilenameCaseSensitive
|
|
57
|
+
!setting.handleFilenameCaseSensitive,
|
|
58
|
+
setting.encrypt && configuredIdKey(setting) || void 0
|
|
54
59
|
);
|
|
55
60
|
}
|
|
56
61
|
getPath(entry) {
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
migrateP2PActiveRemoteConfigurationIdInPlace
|
|
22
22
|
} from "../../serviceFeatures/remoteConfig.js";
|
|
23
23
|
import { ConnectionStringParser } from "../../common/ConnectionString.js";
|
|
24
|
+
import { configuredIdKey } from "../../common/idDerivation.js";
|
|
24
25
|
class SettingService extends ServiceBase {
|
|
25
26
|
deviceAndVaultName = "";
|
|
26
27
|
APIService;
|
|
@@ -152,6 +153,32 @@ class SettingService extends ServiceBase {
|
|
|
152
153
|
Object.assign(settings, patch);
|
|
153
154
|
Object.assign(this.settings, patch);
|
|
154
155
|
}
|
|
156
|
+
const idKey = configuredIdKey(settings);
|
|
157
|
+
if (settings.idDerivationVersion === 1) {
|
|
158
|
+
if (idKey === false) {
|
|
159
|
+
throw new Error("The configured ID derivation key is unavailable.");
|
|
160
|
+
}
|
|
161
|
+
let passphrase = this.usedPassphrase;
|
|
162
|
+
if (passphrase === "") {
|
|
163
|
+
passphrase = await this.getPassphrase(settings);
|
|
164
|
+
}
|
|
165
|
+
if (passphrase === false || passphrase === "") {
|
|
166
|
+
const message = "Failed to retrieve a passphrase for the ID derivation key. Settings were not saved.";
|
|
167
|
+
this._log(message, LOG_LEVEL_URGENT);
|
|
168
|
+
throw new Error(message);
|
|
169
|
+
}
|
|
170
|
+
const encryptedIdKey = await encryptString(idKey, passphrase + SALT_OF_PASSPHRASE);
|
|
171
|
+
if (encryptedIdKey === "") {
|
|
172
|
+
const message = "Failed to encrypt the ID derivation key. Settings were not saved.";
|
|
173
|
+
this._log(message, LOG_LEVEL_URGENT);
|
|
174
|
+
throw new Error(message);
|
|
175
|
+
}
|
|
176
|
+
settings.encryptedIdDerivationKey = encryptedIdKey;
|
|
177
|
+
settings.idDerivationKey = "";
|
|
178
|
+
this.usedPassphrase = passphrase;
|
|
179
|
+
} else {
|
|
180
|
+
settings.encryptedIdDerivationKey = "";
|
|
181
|
+
}
|
|
155
182
|
settings.deviceAndVaultName = "";
|
|
156
183
|
if (settings.P2P_DevicePeerName && settings.P2P_DevicePeerName.trim() !== "") {
|
|
157
184
|
this._log("Saving device peer name to small config");
|
|
@@ -435,7 +462,27 @@ class SettingService extends ServiceBase {
|
|
|
435
462
|
* @param settings The settings to decrypt.
|
|
436
463
|
*/
|
|
437
464
|
async decryptSettings(settings) {
|
|
465
|
+
if (settings.idDerivationVersion !== 1) {
|
|
466
|
+
configuredIdKey(settings);
|
|
467
|
+
} else if (!settings.encryptedIdDerivationKey) {
|
|
468
|
+
throw new Error("The configured ID derivation key is missing or unavailable.");
|
|
469
|
+
}
|
|
438
470
|
const passphrase = await this.getPassphrase(settings);
|
|
471
|
+
if (settings.idDerivationVersion === 1) {
|
|
472
|
+
if (passphrase === false || passphrase === "") {
|
|
473
|
+
throw new Error("The configured ID derivation key cannot be decrypted without a passphrase.");
|
|
474
|
+
}
|
|
475
|
+
const decryptedIdKey = await this.decryptConfigurationItem(settings.encryptedIdDerivationKey, passphrase);
|
|
476
|
+
if (decryptedIdKey === false) {
|
|
477
|
+
throw new Error("The configured ID derivation key could not be decrypted.");
|
|
478
|
+
}
|
|
479
|
+
try {
|
|
480
|
+
configuredIdKey({ ...settings, idDerivationKey: decryptedIdKey });
|
|
481
|
+
} catch {
|
|
482
|
+
throw new Error("The configured ID derivation key is invalid.");
|
|
483
|
+
}
|
|
484
|
+
settings.idDerivationKey = decryptedIdKey;
|
|
485
|
+
}
|
|
439
486
|
if (passphrase === false) {
|
|
440
487
|
this._log("No passphrase found for data.json! Verify configuration before syncing.", LOG_LEVEL_URGENT);
|
|
441
488
|
const hasEncryptedRemoteConfigurations = Object.values(settings.remoteConfigurations || {}).some(
|
package/dist/settings.d.ts
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
export { DEFAULT_SETTINGS, NEW_VAULT_SETTINGS, P2P_DEFAULT_SETTINGS, SETTINGS_SCHEMA_DEFAULTS, createNewVaultSettings, } from "./common/models/setting.const.defaults.js";
|
|
7
7
|
export { PREFERRED_BASE, PREFERRED_JOURNAL_SYNC, PREFERRED_SETTING_CLOUDANT, PREFERRED_SETTING_SELF_HOSTED, } from "./common/models/setting.const.preferred.js";
|
|
8
8
|
export { CURRENT_SETTING_VERSION } from "./common/models/setting.const.js";
|
|
9
|
+
export { deriveIdKey, deriveOrImportIdKey, formatIdRecoveryCode, configuredIdKey, ID_DERIVATION_VERSION, ID_RECOVERY_CODE_PREFIX, } from "./common/idDerivation.js";
|
|
9
10
|
export { prepareSettingsForLoad, SettingsMigrationReviewCodes, type PreparedSettings, type SettingsMigrationReviewCode, type SettingsMigrationReviewReason, type SettingsMigrationState, } from "./common/models/setting.lifecycle.js";
|
|
10
11
|
export { assessTweakCompatibility } from "./common/models/tweak.compatibility.js";
|
|
11
12
|
export type { TweakAssessment, TweakAssessmentEntry, TweakAssessmentRelation, TweakAssessmentValue, TweakTransition, TweakTransitionReason, } from "./common/models/tweak.compatibility.js";
|
|
12
13
|
export type { TweakReconstruction, TweakValues } from "./common/models/tweak.definition.js";
|
|
13
|
-
export type { ObsidianLiveSyncSettings, RemoteDBSettings, RemoteTypeSettings
|
|
14
|
+
export type { ObsidianLiveSyncSettings, RemoteDBSettings, RemoteTypeSettings } from "./common/models/setting.type.js";
|