@serve.zone/interfaces 27.2.0 → 27.3.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.
@@ -23,6 +23,7 @@ import { validatePlatformObjectStorageBucketName } from './platform/objectstorag
23
23
  import {
24
24
  canonicalizeStrictJson,
25
25
  createCanonicalJsonSha256Hex,
26
+ deepFreezeValue,
26
27
  } from './private/canonicaljson.js';
27
28
 
28
29
  export type TCorestoreCredentialCapability = 'database' | 'objectstorage';
@@ -1266,3 +1267,610 @@ export const getCorestoreCredentialPublicationErrorMetadata = (
1266
1267
  code: codeArg,
1267
1268
  retryable: corestoreCredentialPublicationErrorMetadata[codeArg].retryable,
1268
1269
  });
1270
+
1271
+ const corestoreDatabaseBackupMaximumSnapshotPayloadBytes = 96 * 1024 * 1024;
1272
+
1273
+ export const corestoreDatabaseBackupRuntimeLimits = Object.freeze({
1274
+ maximumControlBytes: 16 * 1024,
1275
+ maximumClosureBytes: 256 * 1024 * 1024,
1276
+ maximumVerifiedPlaintextBytes: 128 * 1024 * 1024,
1277
+ maximumSnapshotPayloadBytes: corestoreDatabaseBackupMaximumSnapshotPayloadBytes,
1278
+ maximumSnapshotOriginalBytes: corestoreDatabaseBackupMaximumSnapshotPayloadBytes + 1,
1279
+ maximumClosureObjects: 4096,
1280
+ maximumClosureChunks: 1_000_000,
1281
+ maximumServiceNameBytes: 1024,
1282
+ });
1283
+
1284
+ export interface ICorestoreDatabaseAllocationReference {
1285
+ purpose: 'scratch-rehearsal';
1286
+ rehearsalId: string;
1287
+ allocationId: string;
1288
+ generation: number;
1289
+ bindingSha256: string;
1290
+ receiptSha256: string;
1291
+ }
1292
+
1293
+ export interface ICorestoreDatabaseBackupSnapshotTags {
1294
+ corestore: 'resource';
1295
+ serviceId: string;
1296
+ serviceName: string;
1297
+ capability: 'database';
1298
+ resourceName: string;
1299
+ snapshotName: string;
1300
+ backupId: string;
1301
+ }
1302
+
1303
+ export interface ICorestoreDatabaseBackupSnapshot {
1304
+ capability: 'database';
1305
+ resourceName: string;
1306
+ snapshotId: string;
1307
+ snapshotName: string;
1308
+ originalSize: number;
1309
+ storedSize: number;
1310
+ createdAt: number;
1311
+ tags: ICorestoreDatabaseBackupSnapshotTags;
1312
+ databaseName: string;
1313
+ databaseAllocation?: ICorestoreDatabaseAllocationReference;
1314
+ }
1315
+
1316
+ export interface ICorestoreDatabaseBackupClosureReceipt {
1317
+ formatVersion: 1;
1318
+ snapshotIds: [string];
1319
+ objectCount: number;
1320
+ packCount: number;
1321
+ chunkCount: number;
1322
+ payloadBytes: number;
1323
+ archiveBytes: number;
1324
+ sha256: string;
1325
+ }
1326
+
1327
+ export interface ICorestoreDatabaseBackupReceipt {
1328
+ schemaVersion: 1;
1329
+ format: 'corestore.database.backup.v1';
1330
+ backupId: string;
1331
+ sourceServiceId: string;
1332
+ createdAt: number;
1333
+ snapshot: ICorestoreDatabaseBackupSnapshot;
1334
+ closure: ICorestoreDatabaseBackupClosureReceipt;
1335
+ }
1336
+
1337
+ export interface ICorestoreDatabaseBackupRestoreRequest {
1338
+ schemaVersion: 1;
1339
+ targetServiceId: string;
1340
+ receipt: ICorestoreDatabaseBackupReceipt;
1341
+ expectedDatabaseAllocation?: ICorestoreDatabaseAllocationReference;
1342
+ /** Caller-owned idempotency identity. A new value forces a new fenced restore attempt. */
1343
+ restoreAttemptId?: string;
1344
+ }
1345
+
1346
+ export interface ICorestoreDatabaseBackupRestoreResponse {
1347
+ schemaVersion: 1;
1348
+ ok: true;
1349
+ backupId: string;
1350
+ sourceServiceId: string;
1351
+ targetServiceId: string;
1352
+ snapshotId: string;
1353
+ restoreId: string;
1354
+ requestSha256: string;
1355
+ replayed: boolean;
1356
+ }
1357
+
1358
+ const corestoreDatabaseBackupIdentifierPattern =
1359
+ /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,255}$/;
1360
+ const corestoreDatabaseAllocationRehearsalIdPattern =
1361
+ /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,191}$/;
1362
+
1363
+ const failCorestoreDatabaseBackup = (reasonArg: string): never => {
1364
+ throw new Error(reasonArg);
1365
+ };
1366
+
1367
+ const readCorestoreDatabaseBackupRecord = (
1368
+ valueArg: unknown,
1369
+ pathArg: string,
1370
+ ): Record<string, unknown> => {
1371
+ if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
1372
+ return failCorestoreDatabaseBackup(`${pathArg} must be a plain object`);
1373
+ }
1374
+ const prototype = Object.getPrototypeOf(valueArg);
1375
+ if (prototype !== Object.prototype && prototype !== null) {
1376
+ return failCorestoreDatabaseBackup(`${pathArg} must be a plain object`);
1377
+ }
1378
+ const value = valueArg as Record<string, unknown>;
1379
+ for (const key of Reflect.ownKeys(value)) {
1380
+ if (typeof key !== 'string') {
1381
+ return failCorestoreDatabaseBackup(`${pathArg} must contain string keys only`);
1382
+ }
1383
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
1384
+ if (!descriptor || !descriptor.enumerable || !Object.hasOwn(descriptor, 'value')) {
1385
+ return failCorestoreDatabaseBackup(`${pathArg} must contain data properties only`);
1386
+ }
1387
+ }
1388
+ return value;
1389
+ };
1390
+
1391
+ const assertCorestoreDatabaseBackupExactKeys = (
1392
+ valueArg: Record<string, unknown>,
1393
+ keysArg: readonly string[],
1394
+ pathArg: string,
1395
+ ): void => {
1396
+ if (!hasExactKeys(valueArg, keysArg)) {
1397
+ failCorestoreDatabaseBackup(`${pathArg} must use its exact schema`);
1398
+ }
1399
+ };
1400
+
1401
+ const readCorestoreDatabaseBackupIdentifier = (
1402
+ valueArg: unknown,
1403
+ pathArg: string,
1404
+ ): string => {
1405
+ if (typeof valueArg !== 'string' || !corestoreDatabaseBackupIdentifierPattern.test(valueArg)) {
1406
+ return failCorestoreDatabaseBackup(`${pathArg} must be a canonical identifier`);
1407
+ }
1408
+ return valueArg;
1409
+ };
1410
+
1411
+ const readCorestoreDatabaseBackupSha256 = (
1412
+ valueArg: unknown,
1413
+ pathArg: string,
1414
+ ): string => {
1415
+ if (typeof valueArg !== 'string' || !bareSha256Pattern.test(valueArg)) {
1416
+ return failCorestoreDatabaseBackup(`${pathArg} must be bare lowercase SHA-256`);
1417
+ }
1418
+ return valueArg;
1419
+ };
1420
+
1421
+ const readCorestoreDatabaseBackupInteger = (
1422
+ valueArg: unknown,
1423
+ pathArg: string,
1424
+ minimumArg: number,
1425
+ maximumArg = Number.MAX_SAFE_INTEGER,
1426
+ ): number => {
1427
+ if (!Number.isSafeInteger(valueArg)
1428
+ || Object.is(valueArg, -0)
1429
+ || (valueArg as number) < minimumArg
1430
+ || (valueArg as number) > maximumArg) {
1431
+ return failCorestoreDatabaseBackup(`${pathArg} must be a bounded safe integer`);
1432
+ }
1433
+ return valueArg as number;
1434
+ };
1435
+
1436
+ const finalizeCorestoreDatabaseBackup = <T>(
1437
+ valueArg: T,
1438
+ pathArg: string,
1439
+ ): Readonly<T> => {
1440
+ const canonical = canonicalizeStrictJson(valueArg, failCorestoreDatabaseBackup, pathArg);
1441
+ if (utf8ByteLength(canonical) > corestoreDatabaseBackupRuntimeLimits.maximumControlBytes) {
1442
+ failCorestoreDatabaseBackup(`${pathArg} exceeds its canonical byte limit`);
1443
+ }
1444
+ return deepFreezeValue(valueArg);
1445
+ };
1446
+
1447
+ const normalizeCorestoreDatabaseAllocationReferenceInternal = (
1448
+ valueArg: unknown,
1449
+ pathArg: string,
1450
+ ): ICorestoreDatabaseAllocationReference => {
1451
+ const value = readCorestoreDatabaseBackupRecord(valueArg, pathArg);
1452
+ assertCorestoreDatabaseBackupExactKeys(value, [
1453
+ 'purpose',
1454
+ 'rehearsalId',
1455
+ 'allocationId',
1456
+ 'generation',
1457
+ 'bindingSha256',
1458
+ 'receiptSha256',
1459
+ ], pathArg);
1460
+ if (value.purpose !== 'scratch-rehearsal'
1461
+ || typeof value.rehearsalId !== 'string'
1462
+ || !corestoreDatabaseAllocationRehearsalIdPattern.test(value.rehearsalId)) {
1463
+ failCorestoreDatabaseBackup(`${pathArg} rehearsal authority must be canonical`);
1464
+ }
1465
+ const rehearsalId = value.rehearsalId as string;
1466
+ return {
1467
+ purpose: 'scratch-rehearsal',
1468
+ rehearsalId,
1469
+ allocationId: readCorestoreDatabaseBackupSha256(
1470
+ value.allocationId,
1471
+ `${pathArg}.allocationId`,
1472
+ ),
1473
+ generation: readCorestoreDatabaseBackupInteger(
1474
+ value.generation,
1475
+ `${pathArg}.generation`,
1476
+ 1,
1477
+ ),
1478
+ bindingSha256: readCorestoreDatabaseBackupSha256(
1479
+ value.bindingSha256,
1480
+ `${pathArg}.bindingSha256`,
1481
+ ),
1482
+ receiptSha256: readCorestoreDatabaseBackupSha256(
1483
+ value.receiptSha256,
1484
+ `${pathArg}.receiptSha256`,
1485
+ ),
1486
+ };
1487
+ };
1488
+
1489
+ export const normalizeCorestoreDatabaseAllocationReference = (
1490
+ valueArg: unknown,
1491
+ ): Readonly<ICorestoreDatabaseAllocationReference> => finalizeCorestoreDatabaseBackup(
1492
+ normalizeCorestoreDatabaseAllocationReferenceInternal(valueArg, 'databaseAllocation'),
1493
+ 'databaseAllocation',
1494
+ );
1495
+
1496
+ const normalizeCorestoreDatabaseBackupReceiptInternal = (
1497
+ valueArg: unknown,
1498
+ pathArg: string,
1499
+ ): ICorestoreDatabaseBackupReceipt => {
1500
+ const value = readCorestoreDatabaseBackupRecord(valueArg, pathArg);
1501
+ assertCorestoreDatabaseBackupExactKeys(value, [
1502
+ 'schemaVersion',
1503
+ 'format',
1504
+ 'backupId',
1505
+ 'sourceServiceId',
1506
+ 'createdAt',
1507
+ 'snapshot',
1508
+ 'closure',
1509
+ ], pathArg);
1510
+ if (value.schemaVersion !== 1 || value.format !== 'corestore.database.backup.v1') {
1511
+ failCorestoreDatabaseBackup(`${pathArg} version must be canonical`);
1512
+ }
1513
+ const backupId = readCorestoreDatabaseBackupIdentifier(value.backupId, `${pathArg}.backupId`);
1514
+ const sourceServiceId = readCorestoreDatabaseBackupIdentifier(
1515
+ value.sourceServiceId,
1516
+ `${pathArg}.sourceServiceId`,
1517
+ );
1518
+ const createdAt = readCorestoreDatabaseBackupInteger(value.createdAt, `${pathArg}.createdAt`, 1);
1519
+ const snapshotValue = readCorestoreDatabaseBackupRecord(value.snapshot, `${pathArg}.snapshot`);
1520
+ const hasDatabaseAllocation = Object.hasOwn(snapshotValue, 'databaseAllocation');
1521
+ assertCorestoreDatabaseBackupExactKeys(snapshotValue, [
1522
+ 'capability',
1523
+ 'resourceName',
1524
+ 'snapshotId',
1525
+ 'snapshotName',
1526
+ 'originalSize',
1527
+ 'storedSize',
1528
+ 'createdAt',
1529
+ 'tags',
1530
+ 'databaseName',
1531
+ ...(hasDatabaseAllocation ? ['databaseAllocation'] : []),
1532
+ ], `${pathArg}.snapshot`);
1533
+ if (snapshotValue.capability !== 'database') {
1534
+ failCorestoreDatabaseBackup(`${pathArg}.snapshot capability must be database`);
1535
+ }
1536
+ const resourceName = readCorestoreDatabaseBackupIdentifier(
1537
+ snapshotValue.resourceName,
1538
+ `${pathArg}.snapshot.resourceName`,
1539
+ );
1540
+ const snapshotId = readCorestoreDatabaseBackupIdentifier(
1541
+ snapshotValue.snapshotId,
1542
+ `${pathArg}.snapshot.snapshotId`,
1543
+ );
1544
+ const snapshotName = readCorestoreDatabaseBackupIdentifier(
1545
+ snapshotValue.snapshotName,
1546
+ `${pathArg}.snapshot.snapshotName`,
1547
+ );
1548
+ const databaseName = readCorestoreDatabaseBackupIdentifier(
1549
+ snapshotValue.databaseName,
1550
+ `${pathArg}.snapshot.databaseName`,
1551
+ );
1552
+ const snapshotCreatedAt = readCorestoreDatabaseBackupInteger(
1553
+ snapshotValue.createdAt,
1554
+ `${pathArg}.snapshot.createdAt`,
1555
+ 1,
1556
+ );
1557
+ if (snapshotName !== backupId || snapshotCreatedAt !== createdAt) {
1558
+ failCorestoreDatabaseBackup(`${pathArg}.snapshot identity must match its receipt`);
1559
+ }
1560
+ const tagsValue = readCorestoreDatabaseBackupRecord(
1561
+ snapshotValue.tags,
1562
+ `${pathArg}.snapshot.tags`,
1563
+ );
1564
+ assertCorestoreDatabaseBackupExactKeys(tagsValue, [
1565
+ 'corestore',
1566
+ 'serviceId',
1567
+ 'serviceName',
1568
+ 'capability',
1569
+ 'resourceName',
1570
+ 'snapshotName',
1571
+ 'backupId',
1572
+ ], `${pathArg}.snapshot.tags`);
1573
+ if (tagsValue.corestore !== 'resource'
1574
+ || tagsValue.serviceId !== sourceServiceId
1575
+ || tagsValue.capability !== 'database'
1576
+ || tagsValue.resourceName !== resourceName
1577
+ || tagsValue.snapshotName !== backupId
1578
+ || tagsValue.backupId !== backupId
1579
+ || typeof tagsValue.serviceName !== 'string'
1580
+ || tagsValue.serviceName.length > 256
1581
+ || utf8ByteLength(tagsValue.serviceName)
1582
+ > corestoreDatabaseBackupRuntimeLimits.maximumServiceNameBytes) {
1583
+ failCorestoreDatabaseBackup(`${pathArg}.snapshot.tags ownership must be canonical`);
1584
+ }
1585
+ const serviceName = tagsValue.serviceName as string;
1586
+ const closureValue = readCorestoreDatabaseBackupRecord(value.closure, `${pathArg}.closure`);
1587
+ assertCorestoreDatabaseBackupExactKeys(closureValue, [
1588
+ 'formatVersion',
1589
+ 'snapshotIds',
1590
+ 'objectCount',
1591
+ 'packCount',
1592
+ 'chunkCount',
1593
+ 'payloadBytes',
1594
+ 'archiveBytes',
1595
+ 'sha256',
1596
+ ], `${pathArg}.closure`);
1597
+ if (!Array.isArray(closureValue.snapshotIds)
1598
+ || Object.getPrototypeOf(closureValue.snapshotIds) !== Array.prototype
1599
+ || closureValue.snapshotIds.length !== 1
1600
+ || !Object.hasOwn(closureValue.snapshotIds, 0)
1601
+ || Reflect.ownKeys(closureValue.snapshotIds).some((keyArg) => keyArg !== 'length' && keyArg !== '0')) {
1602
+ failCorestoreDatabaseBackup(`${pathArg}.closure snapshot coverage must be exact`);
1603
+ }
1604
+ const snapshotIdDescriptor = Object.getOwnPropertyDescriptor(closureValue.snapshotIds, '0');
1605
+ if (!snapshotIdDescriptor
1606
+ || !snapshotIdDescriptor.enumerable
1607
+ || !Object.hasOwn(snapshotIdDescriptor, 'value')
1608
+ || snapshotIdDescriptor.value !== snapshotId) {
1609
+ failCorestoreDatabaseBackup(`${pathArg}.closure snapshot coverage must use data entries`);
1610
+ }
1611
+ const objectCount = readCorestoreDatabaseBackupInteger(
1612
+ closureValue.objectCount,
1613
+ `${pathArg}.closure.objectCount`,
1614
+ 1,
1615
+ corestoreDatabaseBackupRuntimeLimits.maximumClosureObjects,
1616
+ );
1617
+ const packCount = readCorestoreDatabaseBackupInteger(
1618
+ closureValue.packCount,
1619
+ `${pathArg}.closure.packCount`,
1620
+ 1,
1621
+ corestoreDatabaseBackupRuntimeLimits.maximumClosureObjects,
1622
+ );
1623
+ const chunkCount = readCorestoreDatabaseBackupInteger(
1624
+ closureValue.chunkCount,
1625
+ `${pathArg}.closure.chunkCount`,
1626
+ 1,
1627
+ corestoreDatabaseBackupRuntimeLimits.maximumClosureChunks,
1628
+ );
1629
+ if (packCount > objectCount) {
1630
+ failCorestoreDatabaseBackup(`${pathArg}.closure pack coverage must be canonical`);
1631
+ }
1632
+ const originalSize = readCorestoreDatabaseBackupInteger(
1633
+ snapshotValue.originalSize,
1634
+ `${pathArg}.snapshot.originalSize`,
1635
+ 1,
1636
+ corestoreDatabaseBackupRuntimeLimits.maximumSnapshotOriginalBytes,
1637
+ );
1638
+ const storedSize = readCorestoreDatabaseBackupInteger(
1639
+ snapshotValue.storedSize,
1640
+ `${pathArg}.snapshot.storedSize`,
1641
+ 1,
1642
+ corestoreDatabaseBackupRuntimeLimits.maximumClosureBytes,
1643
+ );
1644
+ const databaseAllocation = hasDatabaseAllocation
1645
+ ? normalizeCorestoreDatabaseAllocationReferenceInternal(
1646
+ snapshotValue.databaseAllocation,
1647
+ `${pathArg}.snapshot.databaseAllocation`,
1648
+ )
1649
+ : undefined;
1650
+ return {
1651
+ schemaVersion: 1,
1652
+ format: 'corestore.database.backup.v1',
1653
+ backupId,
1654
+ sourceServiceId,
1655
+ createdAt,
1656
+ snapshot: {
1657
+ capability: 'database',
1658
+ resourceName,
1659
+ snapshotId,
1660
+ snapshotName,
1661
+ originalSize,
1662
+ storedSize,
1663
+ createdAt: snapshotCreatedAt,
1664
+ tags: {
1665
+ corestore: 'resource',
1666
+ serviceId: sourceServiceId,
1667
+ serviceName,
1668
+ capability: 'database',
1669
+ resourceName,
1670
+ snapshotName,
1671
+ backupId,
1672
+ },
1673
+ databaseName,
1674
+ ...(databaseAllocation ? { databaseAllocation } : {}),
1675
+ },
1676
+ closure: {
1677
+ formatVersion: closureValue.formatVersion === 1
1678
+ ? 1
1679
+ : failCorestoreDatabaseBackup(`${pathArg}.closure formatVersion must be 1`),
1680
+ snapshotIds: [snapshotId],
1681
+ objectCount,
1682
+ packCount,
1683
+ chunkCount,
1684
+ payloadBytes: readCorestoreDatabaseBackupInteger(
1685
+ closureValue.payloadBytes,
1686
+ `${pathArg}.closure.payloadBytes`,
1687
+ 1,
1688
+ corestoreDatabaseBackupRuntimeLimits.maximumClosureBytes,
1689
+ ),
1690
+ archiveBytes: readCorestoreDatabaseBackupInteger(
1691
+ closureValue.archiveBytes,
1692
+ `${pathArg}.closure.archiveBytes`,
1693
+ 1,
1694
+ corestoreDatabaseBackupRuntimeLimits.maximumClosureBytes,
1695
+ ),
1696
+ sha256: readCorestoreDatabaseBackupSha256(
1697
+ closureValue.sha256,
1698
+ `${pathArg}.closure.sha256`,
1699
+ ),
1700
+ },
1701
+ };
1702
+ };
1703
+
1704
+ export const normalizeCorestoreDatabaseBackupReceipt = (
1705
+ valueArg: unknown,
1706
+ ): Readonly<ICorestoreDatabaseBackupReceipt> => finalizeCorestoreDatabaseBackup(
1707
+ normalizeCorestoreDatabaseBackupReceiptInternal(valueArg, 'databaseBackupReceipt'),
1708
+ 'databaseBackupReceipt',
1709
+ );
1710
+
1711
+ export const normalizeCorestoreDatabaseBackupRestoreRequest = (
1712
+ valueArg: unknown,
1713
+ ): Readonly<ICorestoreDatabaseBackupRestoreRequest> => {
1714
+ const value = readCorestoreDatabaseBackupRecord(valueArg, 'databaseBackupRestoreRequest');
1715
+ const hasAllocation = Object.hasOwn(value, 'expectedDatabaseAllocation');
1716
+ const hasRestoreAttemptId = Object.hasOwn(value, 'restoreAttemptId');
1717
+ assertCorestoreDatabaseBackupExactKeys(value, [
1718
+ 'schemaVersion',
1719
+ 'targetServiceId',
1720
+ 'receipt',
1721
+ ...(hasAllocation ? ['expectedDatabaseAllocation'] : []),
1722
+ ...(hasRestoreAttemptId ? ['restoreAttemptId'] : []),
1723
+ ], 'databaseBackupRestoreRequest');
1724
+ if (value.schemaVersion !== 1) {
1725
+ failCorestoreDatabaseBackup('databaseBackupRestoreRequest schemaVersion must be 1');
1726
+ }
1727
+ const receipt = normalizeCorestoreDatabaseBackupReceiptInternal(
1728
+ value.receipt,
1729
+ 'databaseBackupRestoreRequest.receipt',
1730
+ );
1731
+ const expectedDatabaseAllocation = hasAllocation
1732
+ ? normalizeCorestoreDatabaseAllocationReferenceInternal(
1733
+ value.expectedDatabaseAllocation,
1734
+ 'databaseBackupRestoreRequest.expectedDatabaseAllocation',
1735
+ )
1736
+ : undefined;
1737
+ const restoreAttemptId = hasRestoreAttemptId
1738
+ ? readCorestoreDatabaseBackupIdentifier(
1739
+ value.restoreAttemptId,
1740
+ 'databaseBackupRestoreRequest.restoreAttemptId',
1741
+ )
1742
+ : undefined;
1743
+ return finalizeCorestoreDatabaseBackup({
1744
+ schemaVersion: 1,
1745
+ targetServiceId: readCorestoreDatabaseBackupIdentifier(
1746
+ value.targetServiceId,
1747
+ 'databaseBackupRestoreRequest.targetServiceId',
1748
+ ),
1749
+ receipt,
1750
+ ...(expectedDatabaseAllocation ? { expectedDatabaseAllocation } : {}),
1751
+ ...(restoreAttemptId ? { restoreAttemptId } : {}),
1752
+ }, 'databaseBackupRestoreRequest');
1753
+ };
1754
+
1755
+ export const normalizeCorestoreDatabaseBackupRestoreResponse = (
1756
+ valueArg: unknown,
1757
+ ): Readonly<ICorestoreDatabaseBackupRestoreResponse> => {
1758
+ const value = readCorestoreDatabaseBackupRecord(valueArg, 'databaseBackupRestoreResponse');
1759
+ assertCorestoreDatabaseBackupExactKeys(value, [
1760
+ 'schemaVersion',
1761
+ 'ok',
1762
+ 'backupId',
1763
+ 'sourceServiceId',
1764
+ 'targetServiceId',
1765
+ 'snapshotId',
1766
+ 'restoreId',
1767
+ 'requestSha256',
1768
+ 'replayed',
1769
+ ], 'databaseBackupRestoreResponse');
1770
+ if (value.schemaVersion !== 1 || value.ok !== true || typeof value.replayed !== 'boolean') {
1771
+ failCorestoreDatabaseBackup('databaseBackupRestoreResponse constants must be canonical');
1772
+ }
1773
+ const replayed = value.replayed as boolean;
1774
+ return finalizeCorestoreDatabaseBackup({
1775
+ schemaVersion: 1,
1776
+ ok: true,
1777
+ backupId: readCorestoreDatabaseBackupIdentifier(
1778
+ value.backupId,
1779
+ 'databaseBackupRestoreResponse.backupId',
1780
+ ),
1781
+ sourceServiceId: readCorestoreDatabaseBackupIdentifier(
1782
+ value.sourceServiceId,
1783
+ 'databaseBackupRestoreResponse.sourceServiceId',
1784
+ ),
1785
+ targetServiceId: readCorestoreDatabaseBackupIdentifier(
1786
+ value.targetServiceId,
1787
+ 'databaseBackupRestoreResponse.targetServiceId',
1788
+ ),
1789
+ snapshotId: readCorestoreDatabaseBackupIdentifier(
1790
+ value.snapshotId,
1791
+ 'databaseBackupRestoreResponse.snapshotId',
1792
+ ),
1793
+ restoreId: readCorestoreDatabaseBackupIdentifier(
1794
+ value.restoreId,
1795
+ 'databaseBackupRestoreResponse.restoreId',
1796
+ ),
1797
+ requestSha256: readCorestoreDatabaseBackupSha256(
1798
+ value.requestSha256,
1799
+ 'databaseBackupRestoreResponse.requestSha256',
1800
+ ),
1801
+ replayed,
1802
+ }, 'databaseBackupRestoreResponse');
1803
+ };
1804
+
1805
+ const createCorestoreDatabaseBackupCanonicalJson = (
1806
+ valueArg: unknown,
1807
+ pathArg: string,
1808
+ ): string => canonicalizeStrictJson(valueArg, failCorestoreDatabaseBackup, pathArg);
1809
+
1810
+ export const encodeCorestoreDatabaseAllocationReference = (
1811
+ valueArg: unknown,
1812
+ ): Uint8Array => new TextEncoder().encode(createCorestoreDatabaseBackupCanonicalJson(
1813
+ normalizeCorestoreDatabaseAllocationReference(valueArg),
1814
+ 'databaseAllocation',
1815
+ ));
1816
+
1817
+ export const encodeCorestoreDatabaseBackupReceipt = (
1818
+ valueArg: unknown,
1819
+ ): Uint8Array => new TextEncoder().encode(createCorestoreDatabaseBackupCanonicalJson(
1820
+ normalizeCorestoreDatabaseBackupReceipt(valueArg),
1821
+ 'databaseBackupReceipt',
1822
+ ));
1823
+
1824
+ export const encodeCorestoreDatabaseBackupRestoreRequest = (
1825
+ valueArg: unknown,
1826
+ ): Uint8Array => new TextEncoder().encode(createCorestoreDatabaseBackupCanonicalJson(
1827
+ normalizeCorestoreDatabaseBackupRestoreRequest(valueArg),
1828
+ 'databaseBackupRestoreRequest',
1829
+ ));
1830
+
1831
+ export const encodeCorestoreDatabaseBackupRestoreResponse = (
1832
+ valueArg: unknown,
1833
+ ): Uint8Array => new TextEncoder().encode(createCorestoreDatabaseBackupCanonicalJson(
1834
+ normalizeCorestoreDatabaseBackupRestoreResponse(valueArg),
1835
+ 'databaseBackupRestoreResponse',
1836
+ ));
1837
+
1838
+ export const computeCorestoreDatabaseAllocationReferenceSha256 = async (
1839
+ valueArg: unknown,
1840
+ ): Promise<string> => createCanonicalJsonSha256Hex(
1841
+ createCorestoreDatabaseBackupCanonicalJson(
1842
+ normalizeCorestoreDatabaseAllocationReference(valueArg),
1843
+ 'databaseAllocation',
1844
+ ),
1845
+ failCorestoreDatabaseBackup,
1846
+ );
1847
+
1848
+ export const computeCorestoreDatabaseBackupReceiptSha256 = async (
1849
+ valueArg: unknown,
1850
+ ): Promise<string> => createCanonicalJsonSha256Hex(
1851
+ createCorestoreDatabaseBackupCanonicalJson(
1852
+ normalizeCorestoreDatabaseBackupReceipt(valueArg),
1853
+ 'databaseBackupReceipt',
1854
+ ),
1855
+ failCorestoreDatabaseBackup,
1856
+ );
1857
+
1858
+ export const computeCorestoreDatabaseBackupRestoreRequestSha256 = async (
1859
+ valueArg: unknown,
1860
+ ): Promise<string> => createCanonicalJsonSha256Hex(
1861
+ createCorestoreDatabaseBackupCanonicalJson(
1862
+ normalizeCorestoreDatabaseBackupRestoreRequest(valueArg),
1863
+ 'databaseBackupRestoreRequest',
1864
+ ),
1865
+ failCorestoreDatabaseBackup,
1866
+ );
1867
+
1868
+ export const computeCorestoreDatabaseBackupRestoreResponseSha256 = async (
1869
+ valueArg: unknown,
1870
+ ): Promise<string> => createCanonicalJsonSha256Hex(
1871
+ createCorestoreDatabaseBackupCanonicalJson(
1872
+ normalizeCorestoreDatabaseBackupRestoreResponse(valueArg),
1873
+ 'databaseBackupRestoreResponse',
1874
+ ),
1875
+ failCorestoreDatabaseBackup,
1876
+ );