@recordtimelabel/core 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +1 -1
- package/src/index.js +40 -11
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ During local development an app can consume a sibling checkout with:
|
|
|
20
20
|
For release builds, consume a fixed npm package, git tag, or private registry version so builds do not depend on a sibling folder path. The v2 gateway contract release is:
|
|
21
21
|
|
|
22
22
|
```json
|
|
23
|
-
"@recordtimelabel/core": "0.2.
|
|
23
|
+
"@recordtimelabel/core": "0.2.1"
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
If this checkout's `package.json` is ahead of the published version, publish the new package before updating consumers to that version.
|
|
@@ -50,7 +50,7 @@ If this checkout's `package.json` is ahead of the published version, publish the
|
|
|
50
50
|
- `extendFirestoreV2OperationReadPlanWithRecords(readPlan, records)`
|
|
51
51
|
- `planFirestoreV2OperationChanges({ documents, operations, localState, now })`
|
|
52
52
|
- `estimateFirestoreV2WriteUnits(changes, overhead)`
|
|
53
|
-
- `buildOperationsFromSnapshotDiff({ previousState, nextState, now, operationIdPrefix, batchSize })`
|
|
53
|
+
- `buildOperationsFromSnapshotDiff({ previousState, nextState, now, operationIdPrefix, batchSize })`(一般操作在 `batches`,`folder.delete` 在 `bulkOperations`)
|
|
54
54
|
- `RTL_SYNC_PROTOCOL_VERSION`
|
|
55
55
|
- `hasMeaningfulRecordTimeLabelCloudState(data, options)`
|
|
56
56
|
- `buildRecordTimeLabelContentFingerprint(data)`
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -5,7 +5,7 @@ const REQUIRED_FOLDERS = [
|
|
|
5
5
|
{ id: DEFAULT_FOLDER_ID, name: 'Uncategorized' }
|
|
6
6
|
];
|
|
7
7
|
|
|
8
|
-
export const RECORD_TIMELABEL_CORE_VERSION = '0.2.
|
|
8
|
+
export const RECORD_TIMELABEL_CORE_VERSION = '0.2.1';
|
|
9
9
|
export const RTL_SYNC_PROTOCOL_VERSION = 1;
|
|
10
10
|
export const RTL_MAX_OPERATIONS_PER_REQUEST = 20;
|
|
11
11
|
export const RTL_MAX_REQUEST_BYTES = 256 * 1024;
|
|
@@ -46,9 +46,20 @@ export const RECORD_TIMELABEL_CLOUD_SCHEMAS = Object.freeze({
|
|
|
46
46
|
export const FIRESTORE_V2_SETTINGS_DOC_ID = 'main';
|
|
47
47
|
|
|
48
48
|
const toArray = (value) => (Array.isArray(value) ? value : []);
|
|
49
|
-
const clone = (value) => {
|
|
50
|
-
if (value === undefined || value === null) return value;
|
|
51
|
-
return
|
|
49
|
+
const clone = (value, seen = new WeakMap()) => {
|
|
50
|
+
if (value === undefined || value === null || typeof value !== 'object') return value;
|
|
51
|
+
if (value instanceof Date) return new Date(value.getTime());
|
|
52
|
+
const prototype = Object.getPrototypeOf(value);
|
|
53
|
+
if (prototype !== Object.prototype && prototype !== null && !Array.isArray(value)) {
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
if (seen.has(value)) return seen.get(value);
|
|
57
|
+
const copy = Array.isArray(value) ? [] : {};
|
|
58
|
+
seen.set(value, copy);
|
|
59
|
+
Reflect.ownKeys(value).forEach((key) => {
|
|
60
|
+
copy[key] = clone(value[key], seen);
|
|
61
|
+
});
|
|
62
|
+
return copy;
|
|
52
63
|
};
|
|
53
64
|
|
|
54
65
|
const toFiniteTimestamp = (value) => {
|
|
@@ -2526,21 +2537,23 @@ export const planFirestoreV2OperationChanges = ({
|
|
|
2526
2537
|
});
|
|
2527
2538
|
const recordDocument = applied.documents.records[recordId];
|
|
2528
2539
|
if (!recordDocument) { reason = 'blocked_by_tombstone'; break; }
|
|
2529
|
-
|
|
2530
|
-
|
|
2540
|
+
const candidateRoot = clone(applied.documents.root);
|
|
2541
|
+
const candidateFolders = clone(nextDocuments.folders);
|
|
2531
2542
|
const targetFolder = rtlEnsureTargetFolder({
|
|
2532
|
-
root:
|
|
2533
|
-
folders:
|
|
2543
|
+
root: candidateRoot,
|
|
2544
|
+
folders: candidateFolders,
|
|
2534
2545
|
localState: normalizedLocalState,
|
|
2535
2546
|
folderId: targetFolderId,
|
|
2536
2547
|
now: operationNow
|
|
2537
2548
|
});
|
|
2538
2549
|
if (!targetFolder) {
|
|
2539
2550
|
reason = 'folder_not_found';
|
|
2540
|
-
delete nextDocuments.records[recordId];
|
|
2541
2551
|
break;
|
|
2542
2552
|
}
|
|
2543
2553
|
targetFolder.recordOrder = rtlMergeOrder([recordId], targetFolder.recordOrder);
|
|
2554
|
+
rtlSetRoot(nextDocuments.root, candidateRoot);
|
|
2555
|
+
nextDocuments.folders = candidateFolders;
|
|
2556
|
+
nextDocuments.records[recordId] = recordDocument;
|
|
2544
2557
|
changed = true;
|
|
2545
2558
|
break;
|
|
2546
2559
|
}
|
|
@@ -2751,6 +2764,7 @@ export const buildOperationsFromSnapshotDiff = ({
|
|
|
2751
2764
|
const previousFolders = new Map(previous.folders.map((folder) => [folder.id, folder]));
|
|
2752
2765
|
const nextFolders = new Map(next.folders.map((folder) => [folder.id, folder]));
|
|
2753
2766
|
const drafts = [];
|
|
2767
|
+
const bulkDrafts = [];
|
|
2754
2768
|
|
|
2755
2769
|
nextFolders.forEach((folder, folderId) => {
|
|
2756
2770
|
if (RTL_PROTECTED_FOLDER_IDS.has(folderId)) return;
|
|
@@ -2787,7 +2801,10 @@ export const buildOperationsFromSnapshotDiff = ({
|
|
|
2787
2801
|
|
|
2788
2802
|
previousFolders.forEach((folder, folderId) => {
|
|
2789
2803
|
if (!RTL_PROTECTED_FOLDER_IDS.has(folderId) && !nextFolders.has(folderId)) {
|
|
2790
|
-
|
|
2804
|
+
bulkDrafts.push({
|
|
2805
|
+
type: OPERATION_TYPES.FOLDER_DELETE,
|
|
2806
|
+
payload: {folderId, deletedAt: now}
|
|
2807
|
+
});
|
|
2791
2808
|
}
|
|
2792
2809
|
});
|
|
2793
2810
|
|
|
@@ -2812,6 +2829,11 @@ export const buildOperationsFromSnapshotDiff = ({
|
|
|
2812
2829
|
createdAt: now + index,
|
|
2813
2830
|
...draft
|
|
2814
2831
|
}));
|
|
2832
|
+
const bulkOperations = bulkDrafts.map((draft, index) => ({
|
|
2833
|
+
id: `${operationIdPrefix}:bulk:${String(index).padStart(6, '0')}`,
|
|
2834
|
+
createdAt: now + operations.length + index,
|
|
2835
|
+
...draft
|
|
2836
|
+
}));
|
|
2815
2837
|
const boundedBatchSize = Math.max(1, Math.min(
|
|
2816
2838
|
RTL_MAX_OPERATIONS_PER_REQUEST,
|
|
2817
2839
|
Number.isSafeInteger(batchSize) ? batchSize : RTL_MAX_OPERATIONS_PER_REQUEST
|
|
@@ -2826,7 +2848,14 @@ export const buildOperationsFromSnapshotDiff = ({
|
|
|
2826
2848
|
const changes = buildFirestoreV2DocumentChangeSet(previousDocuments, nextDocuments, {
|
|
2827
2849
|
allowDeletes: true
|
|
2828
2850
|
});
|
|
2829
|
-
return {
|
|
2851
|
+
return {
|
|
2852
|
+
operations,
|
|
2853
|
+
batches,
|
|
2854
|
+
bulkOperations,
|
|
2855
|
+
changes,
|
|
2856
|
+
previousDocuments,
|
|
2857
|
+
nextDocuments
|
|
2858
|
+
};
|
|
2830
2859
|
};
|
|
2831
2860
|
|
|
2832
2861
|
export default {
|