@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.
- package/changelog.md +10 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.d.ts +513 -5
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.js +1931 -8
- package/dist_ts/runtime.corestore.d.ts +89 -0
- package/dist_ts/runtime.corestore.js +306 -2
- package/package.json +1 -1
- package/readme.md +78 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/runtime.cloudlylegacydeploymentsettlement.ts +3751 -17
- package/ts/runtime.corestore.ts +608 -0
package/ts/runtime.corestore.ts
CHANGED
|
@@ -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
|
+
);
|