@recordtimelabel/core 0.1.8 → 0.1.10
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 -1
- package/package.json +1 -1
- package/src/index.js +102 -1
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 current published release is:
|
|
21
21
|
|
|
22
22
|
```json
|
|
23
|
-
"@recordtimelabel/core": "0.1.
|
|
23
|
+
"@recordtimelabel/core": "0.1.10"
|
|
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.
|
|
@@ -43,6 +43,7 @@ If this checkout's `package.json` is ahead of the published version, publish the
|
|
|
43
43
|
- `buildFirestoreV1UserPatch(state, options)`
|
|
44
44
|
- `buildFirestoreV2LogicalPaths(userId)`
|
|
45
45
|
- `buildFirestoreV2DocumentsFromState(state, options)`
|
|
46
|
+
- `buildFirestoreV2DocumentChangeSet(previousDocuments, nextDocuments, options)`
|
|
46
47
|
- `buildStateFromFirestoreV2Documents(documents, options)`
|
|
47
48
|
- `hasMeaningfulRecordTimeLabelCloudState(data, options)`
|
|
48
49
|
- `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.1.
|
|
8
|
+
export const RECORD_TIMELABEL_CORE_VERSION = '0.1.10';
|
|
9
9
|
|
|
10
10
|
export const OPERATION_TYPES = Object.freeze({
|
|
11
11
|
RECORD_CREATE: 'record.create',
|
|
@@ -1274,6 +1274,106 @@ export const buildFirestoreV2DocumentsFromState = (state = {}, options = {}) =>
|
|
|
1274
1274
|
};
|
|
1275
1275
|
};
|
|
1276
1276
|
|
|
1277
|
+
const canonicalizeFirestoreV2DocumentValue = (value) => {
|
|
1278
|
+
if (value === null) {
|
|
1279
|
+
return ['null'];
|
|
1280
|
+
}
|
|
1281
|
+
if (Array.isArray(value)) {
|
|
1282
|
+
return ['array', value.map((entry) => canonicalizeFirestoreV2DocumentValue(entry))];
|
|
1283
|
+
}
|
|
1284
|
+
if (value instanceof Date) {
|
|
1285
|
+
const timestamp = value.getTime();
|
|
1286
|
+
return ['date', Number.isNaN(timestamp) ? 'invalid' : value.toISOString()];
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
const valueType = typeof value;
|
|
1290
|
+
if (valueType === 'number') {
|
|
1291
|
+
if (Number.isNaN(value)) return ['number', 'NaN'];
|
|
1292
|
+
if (value === Infinity) return ['number', 'Infinity'];
|
|
1293
|
+
if (value === -Infinity) return ['number', '-Infinity'];
|
|
1294
|
+
return ['number', value];
|
|
1295
|
+
}
|
|
1296
|
+
if (valueType !== 'object') {
|
|
1297
|
+
return [valueType, valueType === 'bigint' ? value.toString() : value];
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
return [
|
|
1301
|
+
'object',
|
|
1302
|
+
Object.keys(value)
|
|
1303
|
+
.sort()
|
|
1304
|
+
.map((key) => [key, canonicalizeFirestoreV2DocumentValue(value[key])])
|
|
1305
|
+
];
|
|
1306
|
+
};
|
|
1307
|
+
|
|
1308
|
+
const areFirestoreV2DocumentValuesEqual = (left, right) => (
|
|
1309
|
+
JSON.stringify(canonicalizeFirestoreV2DocumentValue(left)) ===
|
|
1310
|
+
JSON.stringify(canonicalizeFirestoreV2DocumentValue(right))
|
|
1311
|
+
);
|
|
1312
|
+
|
|
1313
|
+
const buildFirestoreV2CollectionChangeSet = (previousCollection, nextCollection, allowDeletes) => {
|
|
1314
|
+
const previous = previousCollection && typeof previousCollection === 'object'
|
|
1315
|
+
? previousCollection
|
|
1316
|
+
: {};
|
|
1317
|
+
const next = nextCollection && typeof nextCollection === 'object'
|
|
1318
|
+
? nextCollection
|
|
1319
|
+
: {};
|
|
1320
|
+
const upserts = {};
|
|
1321
|
+
|
|
1322
|
+
Object.keys(next).sort().forEach((documentId) => {
|
|
1323
|
+
if (!Object.prototype.hasOwnProperty.call(previous, documentId) ||
|
|
1324
|
+
!areFirestoreV2DocumentValuesEqual(previous[documentId], next[documentId])) {
|
|
1325
|
+
upserts[documentId] = next[documentId];
|
|
1326
|
+
}
|
|
1327
|
+
});
|
|
1328
|
+
|
|
1329
|
+
const deleteIds = allowDeletes
|
|
1330
|
+
? Object.keys(previous).filter((documentId) => (
|
|
1331
|
+
!Object.prototype.hasOwnProperty.call(next, documentId)
|
|
1332
|
+
)).sort()
|
|
1333
|
+
: [];
|
|
1334
|
+
|
|
1335
|
+
return { upserts, deleteIds };
|
|
1336
|
+
};
|
|
1337
|
+
|
|
1338
|
+
export const buildFirestoreV2DocumentChangeSet = (
|
|
1339
|
+
previousDocuments = {},
|
|
1340
|
+
nextDocuments = {},
|
|
1341
|
+
options = {}
|
|
1342
|
+
) => {
|
|
1343
|
+
const allowDeletes = options.allowDeletes === true;
|
|
1344
|
+
const previousRoot = previousDocuments?.root;
|
|
1345
|
+
const nextRoot = nextDocuments?.root;
|
|
1346
|
+
const rootUpsert = nextRoot && !areFirestoreV2DocumentValuesEqual(previousRoot, nextRoot)
|
|
1347
|
+
? nextRoot
|
|
1348
|
+
: null;
|
|
1349
|
+
const records = buildFirestoreV2CollectionChangeSet(
|
|
1350
|
+
previousDocuments?.records,
|
|
1351
|
+
nextDocuments?.records,
|
|
1352
|
+
allowDeletes
|
|
1353
|
+
);
|
|
1354
|
+
const folders = buildFirestoreV2CollectionChangeSet(
|
|
1355
|
+
previousDocuments?.folders,
|
|
1356
|
+
nextDocuments?.folders,
|
|
1357
|
+
allowDeletes
|
|
1358
|
+
);
|
|
1359
|
+
const ops = buildFirestoreV2CollectionChangeSet(
|
|
1360
|
+
previousDocuments?.ops,
|
|
1361
|
+
nextDocuments?.ops,
|
|
1362
|
+
allowDeletes
|
|
1363
|
+
);
|
|
1364
|
+
const hasCollectionChanges = [records, folders, ops].some((changeSet) => (
|
|
1365
|
+
Object.keys(changeSet.upserts).length > 0 || changeSet.deleteIds.length > 0
|
|
1366
|
+
));
|
|
1367
|
+
|
|
1368
|
+
return {
|
|
1369
|
+
hasChanges: Boolean(rootUpsert) || hasCollectionChanges,
|
|
1370
|
+
root: { upsert: rootUpsert },
|
|
1371
|
+
records,
|
|
1372
|
+
folders,
|
|
1373
|
+
ops
|
|
1374
|
+
};
|
|
1375
|
+
};
|
|
1376
|
+
|
|
1277
1377
|
const removeV2Metadata = (data = {}) => {
|
|
1278
1378
|
const { schemaVersion, folderId, ...rest } = data || {};
|
|
1279
1379
|
return rest;
|
|
@@ -2125,6 +2225,7 @@ export default {
|
|
|
2125
2225
|
buildFirestoreV1UserPatch,
|
|
2126
2226
|
buildFirestoreV2LogicalPaths,
|
|
2127
2227
|
buildFirestoreV2DocumentsFromState,
|
|
2228
|
+
buildFirestoreV2DocumentChangeSet,
|
|
2128
2229
|
buildStateFromFirestoreV2Documents,
|
|
2129
2230
|
flushPendingOperations,
|
|
2130
2231
|
mergeRemoteStateIntoLocal,
|