@valbuild/shared 0.120.0 → 0.122.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 +184 -0
- package/dist/declarations/src/internal/ApiRoutes.d.ts +485 -43
- package/dist/declarations/src/internal/index.d.ts +3 -0
- package/dist/declarations/src/internal/newestCommitSha.d.ts +20 -0
- package/dist/declarations/src/internal/schema/compatibility.d.ts +62 -0
- package/dist/declarations/src/internal/zod/History.d.ts +257 -0
- package/dist/declarations/src/internal/zod/Patch.d.ts +7 -0
- package/dist/declarations/src/internal/zod/SerializedSchema.d.ts +2 -1
- package/internal/dist/valbuild-shared-internal.cjs.dev.js +1025 -60
- package/internal/dist/valbuild-shared-internal.cjs.prod.js +1025 -60
- package/internal/dist/valbuild-shared-internal.esm.js +1013 -61
- package/package.json +2 -2
|
@@ -901,6 +901,12 @@ function _asyncToGenerator(n) {
|
|
|
901
901
|
};
|
|
902
902
|
}
|
|
903
903
|
|
|
904
|
+
/**
|
|
905
|
+
* JSON, recursively — the shape of a Source over the wire.
|
|
906
|
+
*
|
|
907
|
+
* Exported because history reads stored Sources back and needs the same
|
|
908
|
+
* definition; a second copy is a second thing to keep in step.
|
|
909
|
+
*/
|
|
904
910
|
var JSONValue = zod.z.lazy(function () {
|
|
905
911
|
return zod.z.union([zod.z.string(), zod.z.number(), zod.z["boolean"](), zod.z["null"](), zod.z.array(JSONValue), zod.z.record(zod.z.string(), JSONValue)]);
|
|
906
912
|
});
|
|
@@ -1279,7 +1285,26 @@ var SerializedRouteSchema = zod.z.object({
|
|
|
1279
1285
|
readonly: zod.z["boolean"]().optional(),
|
|
1280
1286
|
hidden: zod.z["boolean"]().optional()
|
|
1281
1287
|
});
|
|
1282
|
-
|
|
1288
|
+
|
|
1289
|
+
// A settings module, and each section inside one, serialize as this - the
|
|
1290
|
+
// shape is recursive because `items` holds sections which are themselves
|
|
1291
|
+
// settings schemas. `s.settings()` never writes render/preview/customValidate
|
|
1292
|
+
// (see core/src/schema/settings.ts), but they are accepted here because they
|
|
1293
|
+
// are part of the declared type.
|
|
1294
|
+
var SerializedSettingsSchema = zod.z.lazy(function () {
|
|
1295
|
+
return zod.z.object({
|
|
1296
|
+
type: zod.z.literal("settings"),
|
|
1297
|
+
render: FieldRender,
|
|
1298
|
+
preview: zod.z.literal(true).optional(),
|
|
1299
|
+
items: zod.z.record(zod.z.string(), SerializedSchema),
|
|
1300
|
+
opt: zod.z["boolean"](),
|
|
1301
|
+
customValidate: zod.z["boolean"]().optional(),
|
|
1302
|
+
readonly: zod.z["boolean"]().optional(),
|
|
1303
|
+
hidden: zod.z["boolean"]().optional(),
|
|
1304
|
+
description: zod.z.string().optional()
|
|
1305
|
+
});
|
|
1306
|
+
});
|
|
1307
|
+
var SerializedSchema = zod.z.union([SerializedStringSchema, SerializedLiteralSchema, SerializedBooleanSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedArraySchema, SerializedUnionSchema, SerializedRichTextSchema, SerializedRecordSchema, SerializedKeyOfSchema, SerializedRouteSchema, SerializedFileSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedColorSchema, SerializedCodeSchema, SerializedSettingsSchema, SerializedImageSchema]);
|
|
1283
1308
|
|
|
1284
1309
|
var ValCommit = zod.z.object({
|
|
1285
1310
|
commitSha: zod.z.string(),
|
|
@@ -1291,6 +1316,125 @@ var ValCommit = zod.z.object({
|
|
|
1291
1316
|
commitMessage: zod.z.string().nullable()
|
|
1292
1317
|
});
|
|
1293
1318
|
|
|
1319
|
+
/**
|
|
1320
|
+
* The wire shapes for reading history.
|
|
1321
|
+
*
|
|
1322
|
+
* Here rather than in `@valbuild/server` because both sides of `/api/val` need
|
|
1323
|
+
* them: the server builds these and the Studio parses them, and a second
|
|
1324
|
+
* hand-written copy in the client is how the two drift.
|
|
1325
|
+
*
|
|
1326
|
+
* `HistoryError` is a closed union of everything that can go wrong
|
|
1327
|
+
* reconstructing a commit - see `packages/server/src/history/HistoryError.ts`
|
|
1328
|
+
* for what each one means. It travels as data rather than as a message because
|
|
1329
|
+
* the Studio decides what to OFFER from it: a schema mismatch means "cannot
|
|
1330
|
+
* restore this field", a missing source means "cannot restore this module at
|
|
1331
|
+
* all", and a rendered string cannot be told apart.
|
|
1332
|
+
*/
|
|
1333
|
+
var HistoryError = zod.z.discriminatedUnion("kind", [zod.z.object({
|
|
1334
|
+
kind: zod.z.literal("commit-not-found"),
|
|
1335
|
+
commitSha: zod.z.string()
|
|
1336
|
+
}), zod.z.object({
|
|
1337
|
+
kind: zod.z.literal("archive-unreadable"),
|
|
1338
|
+
commitSha: zod.z.string(),
|
|
1339
|
+
message: zod.z.string()
|
|
1340
|
+
}), zod.z.object({
|
|
1341
|
+
kind: zod.z.literal("source-unavailable"),
|
|
1342
|
+
moduleFilePath: zod.z.string()
|
|
1343
|
+
}), zod.z.object({
|
|
1344
|
+
kind: zod.z.literal("schema-unreadable"),
|
|
1345
|
+
moduleFilePath: zod.z.string(),
|
|
1346
|
+
message: zod.z.string()
|
|
1347
|
+
}), zod.z.object({
|
|
1348
|
+
kind: zod.z.literal("file-unavailable"),
|
|
1349
|
+
gitPath: zod.z.string(),
|
|
1350
|
+
message: zod.z.string()
|
|
1351
|
+
}), zod.z.object({
|
|
1352
|
+
kind: zod.z.literal("not-supported-in-fs-mode")
|
|
1353
|
+
}), zod.z.object({
|
|
1354
|
+
kind: zod.z.literal("transport"),
|
|
1355
|
+
message: zod.z.string()
|
|
1356
|
+
})]);
|
|
1357
|
+
var HistoricalCommit = zod.z.object({
|
|
1358
|
+
commitSha: zod.z.string(),
|
|
1359
|
+
parentCommitSha: zod.z.string(),
|
|
1360
|
+
clientCommitSha: zod.z.string(),
|
|
1361
|
+
branch: zod.z.string(),
|
|
1362
|
+
createdBranch: zod.z.string().nullable(),
|
|
1363
|
+
creator: zod.z.string().nullable(),
|
|
1364
|
+
message: zod.z.string().nullable(),
|
|
1365
|
+
createdAt: zod.z.string(),
|
|
1366
|
+
seqNum: zod.z.string(),
|
|
1367
|
+
patchCount: zod.z.number(),
|
|
1368
|
+
/** False for commits made before history was recorded. */
|
|
1369
|
+
hasArchive: zod.z["boolean"]()
|
|
1370
|
+
});
|
|
1371
|
+
var FileChange = zod.z.union([zod.z.literal("added"), zod.z.literal("modified"), zod.z.literal("deleted")]);
|
|
1372
|
+
|
|
1373
|
+
/**
|
|
1374
|
+
* A binary file the commit touched - named, with a URL, and nothing fetched.
|
|
1375
|
+
* Only an `<img src>` that mounts pays for the bytes.
|
|
1376
|
+
*/
|
|
1377
|
+
var BinaryFileRef = zod.z.object({
|
|
1378
|
+
gitPath: zod.z.string(),
|
|
1379
|
+
change: FileChange,
|
|
1380
|
+
remote: zod.z["boolean"](),
|
|
1381
|
+
url: zod.z.string()
|
|
1382
|
+
});
|
|
1383
|
+
var HistoricalModule = zod.z.object({
|
|
1384
|
+
/** The module's data at this commit. Null if deleted, or unreadable. */
|
|
1385
|
+
source: JSONValue.nullable(),
|
|
1386
|
+
/**
|
|
1387
|
+
* The schema at this commit, already validated against THIS Val.
|
|
1388
|
+
*
|
|
1389
|
+
* Null with a `schema-unreadable` failure means the stored schema came from a
|
|
1390
|
+
* Val whose schema format this one does not know — expected, not damage.
|
|
1391
|
+
*/
|
|
1392
|
+
schema: SerializedSchema.nullable(),
|
|
1393
|
+
patchIds: zod.z.array(PatchId),
|
|
1394
|
+
changedPaths: zod.z.array(zod.z.string()),
|
|
1395
|
+
failures: zod.z.array(HistoryError)
|
|
1396
|
+
});
|
|
1397
|
+
var HistoricalPatchSet = zod.z.object({
|
|
1398
|
+
commit: HistoricalCommit,
|
|
1399
|
+
modules: zod.z.record(zod.z.string(), HistoricalModule),
|
|
1400
|
+
patches: zod.z.array(zod.z.object({
|
|
1401
|
+
patchId: PatchId,
|
|
1402
|
+
moduleFilePath: zod.z.string(),
|
|
1403
|
+
patch: zod.z.unknown(),
|
|
1404
|
+
authorId: zod.z.string().nullable(),
|
|
1405
|
+
createdAt: zod.z.string(),
|
|
1406
|
+
baseSha: zod.z.string(),
|
|
1407
|
+
coreVersion: zod.z.string()
|
|
1408
|
+
})),
|
|
1409
|
+
jsonEntries: zod.z.record(zod.z.string(), zod.z.unknown()),
|
|
1410
|
+
binaryFiles: zod.z.array(BinaryFileRef),
|
|
1411
|
+
warnings: zod.z.array(HistoryError)
|
|
1412
|
+
});
|
|
1413
|
+
/**
|
|
1414
|
+
* Whether the historical value can be written back as the project stands.
|
|
1415
|
+
*
|
|
1416
|
+
* Computed in the Studio, not on the server: the verdict depends on the current
|
|
1417
|
+
* source and the current schema, both of which the client already holds, and it
|
|
1418
|
+
* runs against the same worker-thread validator that validates ordinary edits.
|
|
1419
|
+
* The types stay here because they are what a restore preview hands to the UI.
|
|
1420
|
+
*
|
|
1421
|
+
* `blocked` carries its reasons so a refusal can name the field and say why,
|
|
1422
|
+
* rather than being an unexplained disabled button.
|
|
1423
|
+
*/
|
|
1424
|
+
var RestoreVerdict = zod.z.union([zod.z.object({
|
|
1425
|
+
status: zod.z.literal("restorable")
|
|
1426
|
+
}), zod.z.object({
|
|
1427
|
+
status: zod.z.literal("blocked"),
|
|
1428
|
+
reasons: zod.z.array(HistoryError)
|
|
1429
|
+
})]);
|
|
1430
|
+
var ModuleComparison = zod.z.object({
|
|
1431
|
+
current: zod.z.unknown().nullable(),
|
|
1432
|
+
/** Paths where the commit's result and the current source differ: what a
|
|
1433
|
+
* restore would undo. */
|
|
1434
|
+
changedVsCurrent: zod.z.array(zod.z.string()),
|
|
1435
|
+
verdict: RestoreVerdict
|
|
1436
|
+
});
|
|
1437
|
+
|
|
1294
1438
|
var ModuleFilePath = zod.z.string().refine(function (_path) {
|
|
1295
1439
|
return true;
|
|
1296
1440
|
} // TODO: validation
|
|
@@ -1333,6 +1477,21 @@ var notFoundResponse = zod.z.object({
|
|
|
1333
1477
|
var GenericError = zod.z.object({
|
|
1334
1478
|
message: zod.z.string()
|
|
1335
1479
|
});
|
|
1480
|
+
|
|
1481
|
+
/**
|
|
1482
|
+
* A patch group: the set of patches one user has chosen to publish.
|
|
1483
|
+
*
|
|
1484
|
+
* Not a patch *set* — a patch set is computed from the schema and says which
|
|
1485
|
+
* patches must move together; a patch group is curated and says which ones this
|
|
1486
|
+
* user wants live. See `docs/independent-publish/PLAN.md`.
|
|
1487
|
+
*/
|
|
1488
|
+
var PatchGroup = zod.z.object({
|
|
1489
|
+
patchGroupId: zod.z.string(),
|
|
1490
|
+
authorId: zod.z.string().nullable(),
|
|
1491
|
+
createdAt: zod.z.string(),
|
|
1492
|
+
publishedAt: zod.z.string().nullable(),
|
|
1493
|
+
patchIds: zod.z.array(PatchId)
|
|
1494
|
+
});
|
|
1336
1495
|
var GenericPatchError = zod.z.union([zod.z.object({
|
|
1337
1496
|
patchId: PatchId,
|
|
1338
1497
|
message: zod.z.string()
|
|
@@ -1545,48 +1704,6 @@ var Api = {
|
|
|
1545
1704
|
})
|
|
1546
1705
|
}
|
|
1547
1706
|
},
|
|
1548
|
-
"/session": {
|
|
1549
|
-
GET: {
|
|
1550
|
-
req: {
|
|
1551
|
-
cookies: {
|
|
1552
|
-
val_session: zod.z.string().optional()
|
|
1553
|
-
}
|
|
1554
|
-
},
|
|
1555
|
-
res: zod.z.union([zod.z.object({
|
|
1556
|
-
status: zod.z.literal(200),
|
|
1557
|
-
json: zod.z.object({
|
|
1558
|
-
mode: zod.z.union([zod.z.literal("local"), zod.z.literal("proxy")]),
|
|
1559
|
-
enabled: zod.z["boolean"]()
|
|
1560
|
-
})
|
|
1561
|
-
}), zod.z.object({
|
|
1562
|
-
status: zod.z.union([
|
|
1563
|
-
// TODO: Remove the ones we don't need.
|
|
1564
|
-
zod.z.literal(400), zod.z.literal(401), zod.z.literal(403), zod.z.literal(404), zod.z.literal(500), zod.z.literal(501)]),
|
|
1565
|
-
json: zod.z.object({
|
|
1566
|
-
message: zod.z.string()
|
|
1567
|
-
})
|
|
1568
|
-
}), zod.z.object({
|
|
1569
|
-
status: zod.z.literal(401),
|
|
1570
|
-
json: zod.z.object({
|
|
1571
|
-
message: zod.z.string(),
|
|
1572
|
-
details: zod.z.union([zod.z.string(), zod.z.object({
|
|
1573
|
-
reason: zod.z.string()
|
|
1574
|
-
}), zod.z.object({
|
|
1575
|
-
sub: zod.z.string(),
|
|
1576
|
-
exp: zod.z.number(),
|
|
1577
|
-
token: zod.z.string(),
|
|
1578
|
-
org: zod.z.string(),
|
|
1579
|
-
project: zod.z.string()
|
|
1580
|
-
})])
|
|
1581
|
-
})
|
|
1582
|
-
}), zod.z.object({
|
|
1583
|
-
status: zod.z.literal(500),
|
|
1584
|
-
json: zod.z.object({
|
|
1585
|
-
message: zod.z.string()
|
|
1586
|
-
})
|
|
1587
|
-
})])
|
|
1588
|
-
}
|
|
1589
|
-
},
|
|
1590
1707
|
"/logout": {
|
|
1591
1708
|
GET: {
|
|
1592
1709
|
req: {
|
|
@@ -1714,6 +1831,30 @@ var Api = {
|
|
|
1714
1831
|
schemaSha: zod.z.string(),
|
|
1715
1832
|
sourcesSha: zod.z.string(),
|
|
1716
1833
|
patches: zod.z.array(PatchId),
|
|
1834
|
+
/**
|
|
1835
|
+
* Of `patches`, the ones that have already SHIPPED.
|
|
1836
|
+
*
|
|
1837
|
+
* A published patch stays in the chain with `appliedAt` set until
|
|
1838
|
+
* the next deployment moves the base, so the id list alone cannot
|
|
1839
|
+
* say which is which — and a client never re-fetches a record it
|
|
1840
|
+
* already holds, so it never finds out on its own. Another
|
|
1841
|
+
* author's publish then left that patch pending in your scope,
|
|
1842
|
+
* your prefix gate read a hole in front of it, and Publish
|
|
1843
|
+
* refused for a reason that had stopped being true.
|
|
1844
|
+
*
|
|
1845
|
+
* Optional: `fs` mode forgets published patches outright, and a
|
|
1846
|
+
* client that ignores this behaves exactly as it did before.
|
|
1847
|
+
*/
|
|
1848
|
+
appliedPatches: zod.z.array(PatchId).optional(),
|
|
1849
|
+
/**
|
|
1850
|
+
* The newest commit, which is the PUBLISH head.
|
|
1851
|
+
*
|
|
1852
|
+
* Not `commitSha`: that is the commit this deployment serves and
|
|
1853
|
+
* moves only when a new build lands. This moves the instant
|
|
1854
|
+
* somebody publishes, which is what makes it the thing a client
|
|
1855
|
+
* carries back to `/save` to say which world it decided against.
|
|
1856
|
+
*/
|
|
1857
|
+
headCommitSha: zod.z.string().optional(),
|
|
1717
1858
|
/**
|
|
1718
1859
|
* Unpublished changes the store threw away because it could not
|
|
1719
1860
|
* read them.
|
|
@@ -1742,6 +1883,30 @@ var Api = {
|
|
|
1742
1883
|
sourcesSha: zod.z.string(),
|
|
1743
1884
|
commitSha: zod.z.string(),
|
|
1744
1885
|
patches: zod.z.array(PatchId),
|
|
1886
|
+
/**
|
|
1887
|
+
* Of `patches`, the ones that have already SHIPPED.
|
|
1888
|
+
*
|
|
1889
|
+
* A published patch stays in the chain with `appliedAt` set until
|
|
1890
|
+
* the next deployment moves the base, so the id list alone cannot
|
|
1891
|
+
* say which is which — and a client never re-fetches a record it
|
|
1892
|
+
* already holds, so it never finds out on its own. Another
|
|
1893
|
+
* author's publish then left that patch pending in your scope,
|
|
1894
|
+
* your prefix gate read a hole in front of it, and Publish
|
|
1895
|
+
* refused for a reason that had stopped being true.
|
|
1896
|
+
*
|
|
1897
|
+
* Optional: `fs` mode forgets published patches outright, and a
|
|
1898
|
+
* client that ignores this behaves exactly as it did before.
|
|
1899
|
+
*/
|
|
1900
|
+
appliedPatches: zod.z.array(PatchId).optional(),
|
|
1901
|
+
/**
|
|
1902
|
+
* The newest commit, which is the PUBLISH head.
|
|
1903
|
+
*
|
|
1904
|
+
* Not `commitSha`: that is the commit this deployment serves and
|
|
1905
|
+
* moves only when a new build lands. This moves the instant
|
|
1906
|
+
* somebody publishes, which is what makes it the thing a client
|
|
1907
|
+
* carries back to `/save` to say which world it decided against.
|
|
1908
|
+
*/
|
|
1909
|
+
headCommitSha: zod.z.string().optional(),
|
|
1745
1910
|
commits: zod.z.array(ValCommit),
|
|
1746
1911
|
config: ValConfig,
|
|
1747
1912
|
profileId: zod.z.string().nullable(),
|
|
@@ -1811,6 +1976,26 @@ var Api = {
|
|
|
1811
1976
|
query: {
|
|
1812
1977
|
id: zod.z.array(PatchId).min(1, "At least one patch id is required")
|
|
1813
1978
|
},
|
|
1979
|
+
body: zod.z.object({
|
|
1980
|
+
/*
|
|
1981
|
+
* Patches that are NOT being deleted but must lose their patch
|
|
1982
|
+
* group membership because these are.
|
|
1983
|
+
*
|
|
1984
|
+
* Deleting a patch out of the middle of a patch set leaves every
|
|
1985
|
+
* group holding the rest with a non-prefix intersection, and a
|
|
1986
|
+
* prefix is the one invariant a group has. Which patches those are
|
|
1987
|
+
* needs the content schema, so the client computes the forward
|
|
1988
|
+
* closure and sends it; the content API drops the memberships
|
|
1989
|
+
* without touching the patches.
|
|
1990
|
+
*
|
|
1991
|
+
* In the BODY while the ids to delete are in the query, because
|
|
1992
|
+
* this list is unbounded in the same way and the query string is
|
|
1993
|
+
* already chunked to fit. Optional throughout: `fs` mode has no
|
|
1994
|
+
* groups, and a client that predates this is deleting correctly,
|
|
1995
|
+
* just not repairing.
|
|
1996
|
+
*/
|
|
1997
|
+
unstagePatchIds: zod.z.array(PatchId).optional()
|
|
1998
|
+
}).optional(),
|
|
1814
1999
|
cookies: {
|
|
1815
2000
|
val_session: zod.z.string().optional()
|
|
1816
2001
|
}
|
|
@@ -1835,7 +2020,16 @@ var Api = {
|
|
|
1835
2020
|
path: ModuleFilePath,
|
|
1836
2021
|
patchId: PatchId,
|
|
1837
2022
|
patch: zod.z.any() // TODO: this should be Patch instead - we got a weird validation error: although input looks good, it still does not accept objects as values... Which it should do via the z.record(JSONValue) type
|
|
1838
|
-
}))
|
|
2023
|
+
})),
|
|
2024
|
+
// Patch group membership. Sent with the patch itself, in one request, so
|
|
2025
|
+
// there is no window in which a patch exists but belongs to no group.
|
|
2026
|
+
// Absent means "the caller does not know about groups" - the server then
|
|
2027
|
+
// behaves exactly as before.
|
|
2028
|
+
patchGroupId: zod.z.string().nullish(),
|
|
2029
|
+
// What has to come with the patch: other patch ids that must join the
|
|
2030
|
+
// same group for it to stay applicable. Computed on the client, which
|
|
2031
|
+
// is the only side that has the schema needed to derive patch sets.
|
|
2032
|
+
withPatchIds: zod.z.array(PatchId).optional()
|
|
1839
2033
|
}),
|
|
1840
2034
|
cookies: {
|
|
1841
2035
|
val_session: zod.z.string().optional()
|
|
@@ -1861,7 +2055,8 @@ var Api = {
|
|
|
1861
2055
|
status: zod.z.literal(200),
|
|
1862
2056
|
json: zod.z.object({
|
|
1863
2057
|
newPatchIds: zod.z.array(PatchId),
|
|
1864
|
-
parentRef: ParentRef
|
|
2058
|
+
parentRef: ParentRef,
|
|
2059
|
+
patchGroupId: zod.z.string().optional()
|
|
1865
2060
|
})
|
|
1866
2061
|
})])
|
|
1867
2062
|
},
|
|
@@ -1869,7 +2064,16 @@ var Api = {
|
|
|
1869
2064
|
req: {
|
|
1870
2065
|
query: {
|
|
1871
2066
|
patch_id: zod.z.array(PatchId).optional(),
|
|
1872
|
-
exclude_patch_ops: onlyOneBooleanQueryParam.optional()
|
|
2067
|
+
exclude_patch_ops: onlyOneBooleanQueryParam.optional(),
|
|
2068
|
+
/**
|
|
2069
|
+
* Include the patch group annotation in the answer.
|
|
2070
|
+
*
|
|
2071
|
+
* Off by default because the client CHUNKS this request — a long
|
|
2072
|
+
* chain is several round trips — and the groups are a property of the
|
|
2073
|
+
* branch, identical in every chunk. Asking on each one is N identical
|
|
2074
|
+
* lookups against the content API to learn the same thing.
|
|
2075
|
+
*/
|
|
2076
|
+
include_patch_groups: onlyOneBooleanQueryParam.optional()
|
|
1873
2077
|
},
|
|
1874
2078
|
cookies: {
|
|
1875
2079
|
val_session: zod.z.string().optional()
|
|
@@ -1898,8 +2102,12 @@ var Api = {
|
|
|
1898
2102
|
authorId: zod.z.string().nullable(),
|
|
1899
2103
|
appliedAt: zod.z.object({
|
|
1900
2104
|
commitSha: zod.z.string()
|
|
1901
|
-
}).nullable()
|
|
2105
|
+
}).nullable(),
|
|
2106
|
+
// Which patch groups hold this patch. Optional so that FS mode, and
|
|
2107
|
+
// any server that predates patch groups, can leave it out.
|
|
2108
|
+
patchGroupIds: zod.z.array(zod.z.string()).optional()
|
|
1902
2109
|
})),
|
|
2110
|
+
patchGroups: zod.z.array(PatchGroup).optional(),
|
|
1903
2111
|
baseSha: zod.z.string(),
|
|
1904
2112
|
error: GenericError.optional(),
|
|
1905
2113
|
errors: zod.z.record(PatchId, GenericError).optional()
|
|
@@ -1907,6 +2115,91 @@ var Api = {
|
|
|
1907
2115
|
})])
|
|
1908
2116
|
}
|
|
1909
2117
|
},
|
|
2118
|
+
// Patch group membership. Both are idempotent set operations, and both take an
|
|
2119
|
+
// already-closed set: the client computes the prefix closure (staging) or the
|
|
2120
|
+
// forward closure (unstaging) because only the client has the schema needed to
|
|
2121
|
+
// derive patch sets. See `docs/independent-publish/PLAN.md`.
|
|
2122
|
+
"/patch-groups/~/patches": {
|
|
2123
|
+
PUT: {
|
|
2124
|
+
req: {
|
|
2125
|
+
body: zod.z.object({
|
|
2126
|
+
patchGroupId: zod.z.string(),
|
|
2127
|
+
/** What the user asked to stage. */
|
|
2128
|
+
patchIds: zod.z.array(PatchId),
|
|
2129
|
+
/*
|
|
2130
|
+
* What has to come with it, because the staged patches are written on
|
|
2131
|
+
* top of it.
|
|
2132
|
+
*
|
|
2133
|
+
* The content API records membership as `explicit` or `dependency`
|
|
2134
|
+
* and reads what it is not told about as a dependency — so folding
|
|
2135
|
+
* the two halves into `patchIds` files the patch someone clicked as
|
|
2136
|
+
* something the closure dragged in.
|
|
2137
|
+
*/
|
|
2138
|
+
withPatchIds: zod.z.array(PatchId).optional()
|
|
2139
|
+
}).refine(function (body) {
|
|
2140
|
+
var _body$withPatchIds$le, _body$withPatchIds;
|
|
2141
|
+
return body.patchIds.length > 0 || ((_body$withPatchIds$le = (_body$withPatchIds = body.withPatchIds) === null || _body$withPatchIds === void 0 ? void 0 : _body$withPatchIds.length) !== null && _body$withPatchIds$le !== void 0 ? _body$withPatchIds$le : 0) > 0;
|
|
2142
|
+
},
|
|
2143
|
+
// Either half alone is a real request: a stage of only what came with
|
|
2144
|
+
// it happens when the deferred queue's scope filter drops everything
|
|
2145
|
+
// the user originally clicked.
|
|
2146
|
+
"At least one patch id is required"),
|
|
2147
|
+
cookies: {
|
|
2148
|
+
val_session: zod.z.string().optional()
|
|
2149
|
+
}
|
|
2150
|
+
},
|
|
2151
|
+
res: zod.z.union([unauthorizedResponse, zod.z.object({
|
|
2152
|
+
status: zod.z.literal(403),
|
|
2153
|
+
json: GenericError
|
|
2154
|
+
}), zod.z.object({
|
|
2155
|
+
// The group has already been published, so its membership is frozen.
|
|
2156
|
+
status: zod.z.literal(409),
|
|
2157
|
+
json: GenericError
|
|
2158
|
+
}), zod.z.object({
|
|
2159
|
+
status: zod.z.literal(500),
|
|
2160
|
+
json: GenericError
|
|
2161
|
+
}), zod.z.object({
|
|
2162
|
+
status: zod.z.literal(200),
|
|
2163
|
+
json: zod.z.object({
|
|
2164
|
+
patchGroupId: zod.z.string(),
|
|
2165
|
+
patchIds: zod.z.array(PatchId)
|
|
2166
|
+
})
|
|
2167
|
+
})])
|
|
2168
|
+
},
|
|
2169
|
+
DELETE: {
|
|
2170
|
+
req: {
|
|
2171
|
+
body: zod.z.object({
|
|
2172
|
+
patchGroupId: zod.z.string(),
|
|
2173
|
+
/** What the user asked to unstage. */
|
|
2174
|
+
patchIds: zod.z.array(PatchId),
|
|
2175
|
+
/** What has to go with it: everything built on top of it. */
|
|
2176
|
+
withPatchIds: zod.z.array(PatchId).optional()
|
|
2177
|
+
}).refine(function (body) {
|
|
2178
|
+
var _body$withPatchIds$le2, _body$withPatchIds2;
|
|
2179
|
+
return body.patchIds.length > 0 || ((_body$withPatchIds$le2 = (_body$withPatchIds2 = body.withPatchIds) === null || _body$withPatchIds2 === void 0 ? void 0 : _body$withPatchIds2.length) !== null && _body$withPatchIds$le2 !== void 0 ? _body$withPatchIds$le2 : 0) > 0;
|
|
2180
|
+
}, "At least one patch id is required"),
|
|
2181
|
+
cookies: {
|
|
2182
|
+
val_session: zod.z.string().optional()
|
|
2183
|
+
}
|
|
2184
|
+
},
|
|
2185
|
+
res: zod.z.union([unauthorizedResponse, zod.z.object({
|
|
2186
|
+
status: zod.z.literal(403),
|
|
2187
|
+
json: GenericError
|
|
2188
|
+
}), zod.z.object({
|
|
2189
|
+
status: zod.z.literal(409),
|
|
2190
|
+
json: GenericError
|
|
2191
|
+
}), zod.z.object({
|
|
2192
|
+
status: zod.z.literal(500),
|
|
2193
|
+
json: GenericError
|
|
2194
|
+
}), zod.z.object({
|
|
2195
|
+
status: zod.z.literal(200),
|
|
2196
|
+
json: zod.z.object({
|
|
2197
|
+
patchGroupId: zod.z.string(),
|
|
2198
|
+
patchIds: zod.z.array(PatchId)
|
|
2199
|
+
})
|
|
2200
|
+
})])
|
|
2201
|
+
}
|
|
2202
|
+
},
|
|
1910
2203
|
"/schema": {
|
|
1911
2204
|
GET: {
|
|
1912
2205
|
req: {
|
|
@@ -1943,7 +2236,34 @@ var Api = {
|
|
|
1943
2236
|
validate_sources: onlyOneBooleanQueryParam.optional(),
|
|
1944
2237
|
validate_binary_files: onlyOneBooleanQueryParam.optional(),
|
|
1945
2238
|
exclude_patches: onlyOneBooleanQueryParam.optional(),
|
|
1946
|
-
apply_patches: onlyOneBooleanQueryParam.optional()
|
|
2239
|
+
apply_patches: onlyOneBooleanQueryParam.optional(),
|
|
2240
|
+
/**
|
|
2241
|
+
* Apply ONLY these patches, rather than everything pending.
|
|
2242
|
+
*
|
|
2243
|
+
* This is what makes a draft-mode render match the caller's staged
|
|
2244
|
+
* view. Without it `/sources/~` replays every pending patch on the
|
|
2245
|
+
* branch, so a server-rendered preview shows other people's
|
|
2246
|
+
* unpublished work — the one thing independent publish is for.
|
|
2247
|
+
*
|
|
2248
|
+
* Omitted means everything pending, which is the behaviour every
|
|
2249
|
+
* existing caller has and must keep. An EMPTY array is a different
|
|
2250
|
+
* answer and is honoured as one: a group holding nothing renders
|
|
2251
|
+
* base.
|
|
2252
|
+
*/
|
|
2253
|
+
patch_id: zod.z.array(PatchId).optional(),
|
|
2254
|
+
/**
|
|
2255
|
+
* Apply only the patches in the CALLER'S OWN patch groups.
|
|
2256
|
+
*
|
|
2257
|
+
* The server resolves them from the session, so a draft render does
|
|
2258
|
+
* not have to know its own group ids — which it cannot, since it has
|
|
2259
|
+
* no client state. This is what makes `fetchVal` in draft mode show
|
|
2260
|
+
* the person their own staged work rather than everybody's.
|
|
2261
|
+
*
|
|
2262
|
+
* Ignored when `patch_id` is given: an explicit list is a caller that
|
|
2263
|
+
* already knows what it wants, and silently intersecting the two
|
|
2264
|
+
* would make the narrower one invisible.
|
|
2265
|
+
*/
|
|
2266
|
+
own_patch_groups_only: onlyOneBooleanQueryParam.optional()
|
|
1947
2267
|
},
|
|
1948
2268
|
cookies: {
|
|
1949
2269
|
val_session: zod.z.string().optional()
|
|
@@ -2022,7 +2342,35 @@ var Api = {
|
|
|
2022
2342
|
req: {
|
|
2023
2343
|
body: zod.z.object({
|
|
2024
2344
|
message: zod.z.string().optional(),
|
|
2025
|
-
patchIds: zod.z.array(PatchId)
|
|
2345
|
+
patchIds: zod.z.array(PatchId),
|
|
2346
|
+
/*
|
|
2347
|
+
* The patch group this commit EMPTIES, if it empties one.
|
|
2348
|
+
*
|
|
2349
|
+
* Forwarded to the content API, which closes the group it names —
|
|
2350
|
+
* and closes it unconditionally, without checking that the commit
|
|
2351
|
+
* shipped all of it. So the client sends it only when the publish
|
|
2352
|
+
* accounts for every patch the group still holds; a partial publish
|
|
2353
|
+
* omits it and the group stays open with the rest in it.
|
|
2354
|
+
*
|
|
2355
|
+
* Optional, and absent in `fs` mode, which has no groups.
|
|
2356
|
+
*/
|
|
2357
|
+
patchGroupId: zod.z.string().optional(),
|
|
2358
|
+
/*
|
|
2359
|
+
* The newest commit this client knew about when it decided.
|
|
2360
|
+
*
|
|
2361
|
+
* Answered with 409 when the server sees a newer one, because then
|
|
2362
|
+
* somebody else published between the review screen being read and
|
|
2363
|
+
* Save being clicked, and what is about to ship was decided against a
|
|
2364
|
+
* world that no longer exists.
|
|
2365
|
+
*
|
|
2366
|
+
* Git's own not-fast-forward guard does not cover this: `ValServer`
|
|
2367
|
+
* fetches the chain and commits fresh at publish time, so the parent
|
|
2368
|
+
* commit it sends is always the server's current one.
|
|
2369
|
+
*
|
|
2370
|
+
* Optional, so a client that does not track it publishes exactly as
|
|
2371
|
+
* it did before.
|
|
2372
|
+
*/
|
|
2373
|
+
expectedHeadCommitSha: zod.z.string().optional()
|
|
2026
2374
|
}),
|
|
2027
2375
|
cookies: {
|
|
2028
2376
|
val_session: zod.z.string().optional()
|
|
@@ -2031,6 +2379,24 @@ var Api = {
|
|
|
2031
2379
|
res: zod.z.union([unauthorizedResponse, zod.z.object({
|
|
2032
2380
|
status: zod.z.literal(200),
|
|
2033
2381
|
json: zod.z.object({
|
|
2382
|
+
/**
|
|
2383
|
+
* The commit this publish just made, which becomes the new publish
|
|
2384
|
+
* head.
|
|
2385
|
+
*
|
|
2386
|
+
* Sent back because nothing else tells this client about its own
|
|
2387
|
+
* commit in time. `headCommitSha` moves on a `/stat` response, and
|
|
2388
|
+
* until the next poll lands the client still believes the
|
|
2389
|
+
* PRE-publish head — so a second publish inside that window carried
|
|
2390
|
+
* a stale `expectedHeadCommitSha`, the server compared it against
|
|
2391
|
+
* the commit this same client had just made, and answered 409
|
|
2392
|
+
* "someone else published". With auto-publish, which publishes on
|
|
2393
|
+
* every pause in typing, that window is hit routinely and the
|
|
2394
|
+
* message blames a colleague for the user's own commit.
|
|
2395
|
+
*
|
|
2396
|
+
* Optional: `fs` mode has no publish head, and neither does a
|
|
2397
|
+
* server that predates this.
|
|
2398
|
+
*/
|
|
2399
|
+
commitSha: zod.z.string().optional(),
|
|
2034
2400
|
/**
|
|
2035
2401
|
* Unpublished changes the save threw away because they could not be
|
|
2036
2402
|
* applied.
|
|
@@ -2047,12 +2413,61 @@ var Api = {
|
|
|
2047
2413
|
message: zod.z.string()
|
|
2048
2414
|
})).optional()
|
|
2049
2415
|
})
|
|
2416
|
+
}),
|
|
2417
|
+
/*
|
|
2418
|
+
* The named patch group is not this caller's, or the lookup that would
|
|
2419
|
+
* say so failed.
|
|
2420
|
+
*
|
|
2421
|
+
* Publishing may CLOSE a group, and closing somebody else's leaves
|
|
2422
|
+
* their pending work in a closed group and in no open one. So `/save`
|
|
2423
|
+
* runs the same ownership check stage and unstage do, and refuses the
|
|
2424
|
+
* same way — see `refuseUnlessOwn`.
|
|
2425
|
+
*/
|
|
2426
|
+
zod.z.object({
|
|
2427
|
+
status: zod.z.literal(403),
|
|
2428
|
+
json: GenericError
|
|
2429
|
+
}), zod.z.object({
|
|
2430
|
+
status: zod.z.literal(500),
|
|
2431
|
+
json: GenericError
|
|
2050
2432
|
}), zod.z.object({
|
|
2051
2433
|
status: zod.z.literal(409),
|
|
2052
|
-
json: zod.z.
|
|
2434
|
+
json: zod.z.union([/** A group that has already shipped. See the 403 above. */
|
|
2435
|
+
zod.z.object({
|
|
2436
|
+
message: zod.z.string()
|
|
2437
|
+
}), zod.z.object({
|
|
2053
2438
|
message: zod.z.string(),
|
|
2054
2439
|
isNotFastForward: zod.z.literal(true)
|
|
2055
|
-
})
|
|
2440
|
+
}),
|
|
2441
|
+
/*
|
|
2442
|
+
* Somebody else published between this being decided and Save.
|
|
2443
|
+
*
|
|
2444
|
+
* Its own shape rather than another `isNotFastForward`, because
|
|
2445
|
+
* they happen at different moments and mean different things to the
|
|
2446
|
+
* user: that one is git refusing a commit, this one is refused
|
|
2447
|
+
* BEFORE a commit is attempted, on a head the client named. Nothing
|
|
2448
|
+
* was written either way, but only this one is answered by looking
|
|
2449
|
+
* at the review screen again.
|
|
2450
|
+
*/
|
|
2451
|
+
zod.z.object({
|
|
2452
|
+
message: zod.z.string(),
|
|
2453
|
+
headMoved: zod.z.literal(true)
|
|
2454
|
+
}),
|
|
2455
|
+
/**
|
|
2456
|
+
* The group this commit named has already been published.
|
|
2457
|
+
*
|
|
2458
|
+
* A third thing sharing 409, and flagged for the same reason
|
|
2459
|
+
* `headMoved` is: read as a plain not-fast-forward it looks
|
|
2460
|
+
* retryable, and it is the opposite — the id will never be writable
|
|
2461
|
+
* again, so retrying reproduces it forever.
|
|
2462
|
+
*
|
|
2463
|
+
* It means this author published from somewhere else. The client
|
|
2464
|
+
* forgets the id and falls back to the annotation, which is the
|
|
2465
|
+
* same recovery a 409 on stage or unstage triggers.
|
|
2466
|
+
*/
|
|
2467
|
+
zod.z.object({
|
|
2468
|
+
message: zod.z.string(),
|
|
2469
|
+
patchGroupPublished: zod.z.literal(true)
|
|
2470
|
+
})])
|
|
2056
2471
|
}), zod.z.object({
|
|
2057
2472
|
status: zod.z.literal(400),
|
|
2058
2473
|
json: zod.z.union([zod.z.object({
|
|
@@ -2080,6 +2495,144 @@ var Api = {
|
|
|
2080
2495
|
})])
|
|
2081
2496
|
}
|
|
2082
2497
|
},
|
|
2498
|
+
// #region history
|
|
2499
|
+
//
|
|
2500
|
+
// Reading the past. Split across three routes on purpose, because they cache
|
|
2501
|
+
// differently: a reconstructed commit cannot change and is immutable
|
|
2502
|
+
// forever, the comparison against current source changes with every edit, and
|
|
2503
|
+
// a file at a fixed commit is immutable too. Folding them together would mean
|
|
2504
|
+
// the cheapest thing dragging the most expensive one's cache headers down to
|
|
2505
|
+
// no-store.
|
|
2506
|
+
"/history/commits": {
|
|
2507
|
+
GET: {
|
|
2508
|
+
req: {
|
|
2509
|
+
query: {
|
|
2510
|
+
branch: onlyOneStringQueryParam,
|
|
2511
|
+
limit: onlyOneIntQueryParam.optional(),
|
|
2512
|
+
/** The previous page's `nextCursor`. */
|
|
2513
|
+
cursor: onlyOneStringQueryParam.optional()
|
|
2514
|
+
},
|
|
2515
|
+
cookies: {
|
|
2516
|
+
val_session: zod.z.string().optional()
|
|
2517
|
+
}
|
|
2518
|
+
},
|
|
2519
|
+
res: zod.z.union([unauthorizedResponse, notFoundResponse, zod.z.object({
|
|
2520
|
+
status: zod.z.literal(400),
|
|
2521
|
+
json: GenericError.and(zod.z.object({
|
|
2522
|
+
kind: zod.z.string().optional()
|
|
2523
|
+
}))
|
|
2524
|
+
}), zod.z.object({
|
|
2525
|
+
status: zod.z.literal(500),
|
|
2526
|
+
json: GenericError.and(zod.z.object({
|
|
2527
|
+
kind: zod.z.string().optional()
|
|
2528
|
+
}))
|
|
2529
|
+
}), zod.z.object({
|
|
2530
|
+
status: zod.z.literal(200),
|
|
2531
|
+
json: zod.z.object({
|
|
2532
|
+
commits: zod.z.array(HistoricalCommit),
|
|
2533
|
+
nextCursor: zod.z.string().nullable()
|
|
2534
|
+
})
|
|
2535
|
+
})])
|
|
2536
|
+
}
|
|
2537
|
+
},
|
|
2538
|
+
/**
|
|
2539
|
+
* One commit, reconstructed. IMMUTABLE for a given sha - it says nothing
|
|
2540
|
+
* about the current source or schema, which is what lets it be cached
|
|
2541
|
+
* forever and what makes comparing many commits cheap.
|
|
2542
|
+
*/
|
|
2543
|
+
"/history/commit": {
|
|
2544
|
+
GET: {
|
|
2545
|
+
req: {
|
|
2546
|
+
query: {
|
|
2547
|
+
commit_sha: onlyOneStringQueryParam
|
|
2548
|
+
},
|
|
2549
|
+
cookies: {
|
|
2550
|
+
val_session: zod.z.string().optional()
|
|
2551
|
+
}
|
|
2552
|
+
},
|
|
2553
|
+
res: zod.z.union([unauthorizedResponse, notFoundResponse, zod.z.object({
|
|
2554
|
+
status: zod.z.literal(400),
|
|
2555
|
+
json: GenericError
|
|
2556
|
+
}), zod.z.object({
|
|
2557
|
+
status: zod.z.literal(500),
|
|
2558
|
+
json: GenericError.and(zod.z.object({
|
|
2559
|
+
kind: zod.z.string().optional()
|
|
2560
|
+
}))
|
|
2561
|
+
}), zod.z.object({
|
|
2562
|
+
status: zod.z.literal(200),
|
|
2563
|
+
json: HistoricalPatchSet
|
|
2564
|
+
})])
|
|
2565
|
+
}
|
|
2566
|
+
},
|
|
2567
|
+
/**
|
|
2568
|
+
* ONE module, as of a commit — including a commit that did not change it.
|
|
2569
|
+
*
|
|
2570
|
+
* `/history/commit` covers what a commit changed, which is the narrow case:
|
|
2571
|
+
* navigate the history pane to anything else and there would be nothing to
|
|
2572
|
+
* show. This answers "how did this module look at that point", which is the
|
|
2573
|
+
* question someone comparing two panes is actually asking. Immutable for the
|
|
2574
|
+
* same reason: what a commit left behind cannot change.
|
|
2575
|
+
*/
|
|
2576
|
+
"/history/module": {
|
|
2577
|
+
GET: {
|
|
2578
|
+
req: {
|
|
2579
|
+
query: {
|
|
2580
|
+
commit_sha: onlyOneStringQueryParam,
|
|
2581
|
+
module_file_path: onlyOneStringQueryParam
|
|
2582
|
+
},
|
|
2583
|
+
cookies: {
|
|
2584
|
+
val_session: zod.z.string().optional()
|
|
2585
|
+
}
|
|
2586
|
+
},
|
|
2587
|
+
res: zod.z.union([unauthorizedResponse, notFoundResponse, zod.z.object({
|
|
2588
|
+
status: zod.z.literal(400),
|
|
2589
|
+
json: GenericError
|
|
2590
|
+
}), zod.z.object({
|
|
2591
|
+
status: zod.z.literal(500),
|
|
2592
|
+
json: GenericError.and(zod.z.object({
|
|
2593
|
+
kind: zod.z.string().optional()
|
|
2594
|
+
}))
|
|
2595
|
+
}), zod.z.object({
|
|
2596
|
+
status: zod.z.literal(200),
|
|
2597
|
+
json: zod.z.object({
|
|
2598
|
+
moduleFilePath: zod.z.string(),
|
|
2599
|
+
/**
|
|
2600
|
+
* Null when history has no record of this module at or before the
|
|
2601
|
+
* commit — it was last edited before recording started, or never.
|
|
2602
|
+
* Distinct from a module the commit deleted.
|
|
2603
|
+
*/
|
|
2604
|
+
module: HistoricalModule.nullable()
|
|
2605
|
+
})
|
|
2606
|
+
})])
|
|
2607
|
+
}
|
|
2608
|
+
},
|
|
2609
|
+
/**
|
|
2610
|
+
* One file as it was at one commit.
|
|
2611
|
+
*
|
|
2612
|
+
* The lazy half: `/history/commit` NAMES a commit's binary files and this is
|
|
2613
|
+
* where their bytes come from, so nothing is fetched until an `<img>`
|
|
2614
|
+
* actually mounts. A file at a fixed commit cannot change, so the response is
|
|
2615
|
+
* immutable and the browser's own cache handles flipping between commits.
|
|
2616
|
+
*/
|
|
2617
|
+
"/history/files": {
|
|
2618
|
+
GET: {
|
|
2619
|
+
req: {
|
|
2620
|
+
query: {
|
|
2621
|
+
commit_sha: onlyOneStringQueryParam,
|
|
2622
|
+
path: onlyOneStringQueryParam,
|
|
2623
|
+
remote: onlyOneStringQueryParam.optional()
|
|
2624
|
+
}
|
|
2625
|
+
},
|
|
2626
|
+
res: zod.z.union([unauthorizedResponse, notFoundResponse, zod.z.object({
|
|
2627
|
+
status: zod.z.literal(400),
|
|
2628
|
+
json: GenericError
|
|
2629
|
+
}), zod.z.object({
|
|
2630
|
+
status: zod.z.literal(200),
|
|
2631
|
+
body: zod.z["instanceof"](ReadableStream)
|
|
2632
|
+
})])
|
|
2633
|
+
}
|
|
2634
|
+
},
|
|
2635
|
+
// #endregion history
|
|
2083
2636
|
"/files": {
|
|
2084
2637
|
GET: {
|
|
2085
2638
|
req: {
|
|
@@ -2133,7 +2686,16 @@ var Api = {
|
|
|
2133
2686
|
limit: onlyOneIntQueryParam.refine(function (arg) {
|
|
2134
2687
|
return arg > 0 && arg <= JSON_ENTRIES_BATCH_MAX;
|
|
2135
2688
|
}, "limit must be between 1 and ".concat(JSON_ENTRIES_BATCH_MAX)).optional(),
|
|
2136
|
-
apply_patches: onlyOneBooleanQueryParam.optional()
|
|
2689
|
+
apply_patches: onlyOneBooleanQueryParam.optional(),
|
|
2690
|
+
/**
|
|
2691
|
+
* The caller's own staged work, and nobody else's.
|
|
2692
|
+
*
|
|
2693
|
+
* The same flag `/sources/~` takes, and for the same reason — a draft
|
|
2694
|
+
* page renders both, so a scoped module beside an unscoped
|
|
2695
|
+
* `jsonValues` entry showed one person's view and everybody's pending
|
|
2696
|
+
* work on the same screen.
|
|
2697
|
+
*/
|
|
2698
|
+
own_patch_groups_only: onlyOneBooleanQueryParam.optional()
|
|
2137
2699
|
},
|
|
2138
2700
|
cookies: _defineProperty({}, VAL_SESSION_COOKIE, zod.z.string().optional())
|
|
2139
2701
|
},
|
|
@@ -2707,6 +3269,392 @@ var urlOf = function urlOf() {
|
|
|
2707
3269
|
return "".concat(route);
|
|
2708
3270
|
};
|
|
2709
3271
|
|
|
3272
|
+
/**
|
|
3273
|
+
* Can this value, taken from one schema, be written into another?
|
|
3274
|
+
*
|
|
3275
|
+
* The question restore asks, and it is NOT the question validation asks.
|
|
3276
|
+
* Validation checks a value against the schema it belongs to. This compares two
|
|
3277
|
+
* schemas — the one a value was stored under and the one it is being written
|
|
3278
|
+
* into — because a restore moves a value across a schema change, and possibly
|
|
3279
|
+
* across paths.
|
|
3280
|
+
*
|
|
3281
|
+
* Three answers, not two. `unknown` is where the comparison genuinely cannot
|
|
3282
|
+
* decide, and it exists so that an editor is told "we are not sure" rather than
|
|
3283
|
+
* being given a confident answer we made up. Treating unknown as compatible
|
|
3284
|
+
* writes values that break; treating it as incompatible blocks restores that
|
|
3285
|
+
* would have been fine.
|
|
3286
|
+
*/
|
|
3287
|
+
|
|
3288
|
+
var compatible = {
|
|
3289
|
+
status: "compatible"
|
|
3290
|
+
};
|
|
3291
|
+
|
|
3292
|
+
/**
|
|
3293
|
+
* `Array.isArray` cannot narrow `JsonArray` out of `Json`, because it is
|
|
3294
|
+
* `readonly Json[]` — so the check that reads naturally does not type. This
|
|
3295
|
+
* predicate is that check, said once.
|
|
3296
|
+
*/
|
|
3297
|
+
function isJsonObject(value) {
|
|
3298
|
+
return _typeof(value) === "object" && value !== null && !Array.isArray(value);
|
|
3299
|
+
}
|
|
3300
|
+
function incompatible(reason) {
|
|
3301
|
+
return {
|
|
3302
|
+
status: "incompatible",
|
|
3303
|
+
reason: reason
|
|
3304
|
+
};
|
|
3305
|
+
}
|
|
3306
|
+
|
|
3307
|
+
/**
|
|
3308
|
+
* "an object", "a string".
|
|
3309
|
+
*
|
|
3310
|
+
* Schema type names are data — `object`, `array`, `image` — so an interpolated
|
|
3311
|
+
* "a" is wrong for three of them, in a sentence shown to editors the moment a
|
|
3312
|
+
* restore is refused.
|
|
3313
|
+
*/
|
|
3314
|
+
function withArticle(type) {
|
|
3315
|
+
return /^[aeiou]/i.test(type) ? "an ".concat(type) : "a ".concat(type);
|
|
3316
|
+
}
|
|
3317
|
+
|
|
3318
|
+
/**
|
|
3319
|
+
* A sentence an editor can act on, for the popup that explains a refusal.
|
|
3320
|
+
*
|
|
3321
|
+
* Kept beside the reasons rather than in the UI so that adding a reason without
|
|
3322
|
+
* wording for it is a type error rather than a blank dialog.
|
|
3323
|
+
*/
|
|
3324
|
+
function explainIncompatible(reason) {
|
|
3325
|
+
switch (reason.kind) {
|
|
3326
|
+
case "type-changed":
|
|
3327
|
+
return "This was ".concat(withArticle(reason.from), " and the field here is ").concat(withArticle(reason.to), ".");
|
|
3328
|
+
case "no-matching-variant":
|
|
3329
|
+
return "This does not match any of the shapes allowed here: ".concat(reason.variants.join(", "), ".");
|
|
3330
|
+
case "unknown-field":
|
|
3331
|
+
return "The old value has ".concat(reason.keys.length === 1 ? "a field" : "fields", " that no longer exist here: ").concat(reason.keys.join(", "), ".");
|
|
3332
|
+
case "missing-required":
|
|
3333
|
+
return "The field here needs ".concat(reason.keys.join(", "), ", which the old value does not have.");
|
|
3334
|
+
case "not-optional":
|
|
3335
|
+
return "The old value was empty, and this field cannot be empty.";
|
|
3336
|
+
case "literal-changed":
|
|
3337
|
+
return "This has to be exactly \"".concat(reason.to, "\", and the old value was \"").concat(reason.from, "\".");
|
|
3338
|
+
case "different-module":
|
|
3339
|
+
return "This points into ".concat(reason.to, ", and the old value pointed into ").concat(reason.from, ".");
|
|
3340
|
+
}
|
|
3341
|
+
}
|
|
3342
|
+
|
|
3343
|
+
/**
|
|
3344
|
+
* The variant of a union that a value actually is.
|
|
3345
|
+
*
|
|
3346
|
+
* `undefined` when the value does not identify itself — which is a real answer,
|
|
3347
|
+
* not a failure: it is what makes the caller return `unknown` rather than guess.
|
|
3348
|
+
*/
|
|
3349
|
+
function variantOf(schema, value) {
|
|
3350
|
+
if (schema.type !== "union") {
|
|
3351
|
+
return undefined;
|
|
3352
|
+
}
|
|
3353
|
+
// String union: the value IS the discriminator.
|
|
3354
|
+
if (typeof schema.key !== "string") {
|
|
3355
|
+
if (typeof value !== "string") {
|
|
3356
|
+
return undefined;
|
|
3357
|
+
}
|
|
3358
|
+
return schema.items.find(function (item) {
|
|
3359
|
+
return item.type === "literal" && item.value === value;
|
|
3360
|
+
});
|
|
3361
|
+
}
|
|
3362
|
+
// Object union: the discriminator is a literal at `key`.
|
|
3363
|
+
var discriminator = schema.key;
|
|
3364
|
+
if (!isJsonObject(value)) {
|
|
3365
|
+
return undefined;
|
|
3366
|
+
}
|
|
3367
|
+
var tag = value[discriminator];
|
|
3368
|
+
if (typeof tag !== "string") {
|
|
3369
|
+
return undefined;
|
|
3370
|
+
}
|
|
3371
|
+
return schema.items.find(function (item) {
|
|
3372
|
+
if (item.type !== "object") {
|
|
3373
|
+
return false;
|
|
3374
|
+
}
|
|
3375
|
+
var keySchema = item.items[discriminator];
|
|
3376
|
+
return (keySchema === null || keySchema === void 0 ? void 0 : keySchema.type) === "literal" && keySchema.value === tag;
|
|
3377
|
+
});
|
|
3378
|
+
}
|
|
3379
|
+
function describeVariant(schema, key) {
|
|
3380
|
+
if (schema.type === "literal") {
|
|
3381
|
+
return schema.value;
|
|
3382
|
+
}
|
|
3383
|
+
if (schema.type === "object") {
|
|
3384
|
+
var tag = schema.items[key];
|
|
3385
|
+
if ((tag === null || tag === void 0 ? void 0 : tag.type) === "literal") {
|
|
3386
|
+
return tag.value;
|
|
3387
|
+
}
|
|
3388
|
+
}
|
|
3389
|
+
return schema.type;
|
|
3390
|
+
}
|
|
3391
|
+
function checkCompatibility(from, to) {
|
|
3392
|
+
// Emptiness first: a null that lands in a field which cannot be empty is a
|
|
3393
|
+
// break regardless of what the two schemas otherwise say.
|
|
3394
|
+
if (from.value === null) {
|
|
3395
|
+
return to.schema.opt ? compatible : incompatible({
|
|
3396
|
+
kind: "not-optional"
|
|
3397
|
+
});
|
|
3398
|
+
}
|
|
3399
|
+
|
|
3400
|
+
// A changed union is not itself disqualifying. What matters is whether the
|
|
3401
|
+
// variant being restored still has somewhere to go — comparing the unions
|
|
3402
|
+
// wholesale would refuse a restore that is perfectly safe.
|
|
3403
|
+
if (to.schema.type === "union") {
|
|
3404
|
+
var key = typeof to.schema.key === "string" ? to.schema.key : "";
|
|
3405
|
+
var _iterator = _createForOfIteratorHelper(to.schema.items),
|
|
3406
|
+
_step;
|
|
3407
|
+
try {
|
|
3408
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
3409
|
+
var variant = _step.value;
|
|
3410
|
+
if (checkCompatibility(from, {
|
|
3411
|
+
schema: variant
|
|
3412
|
+
}).status === "compatible") {
|
|
3413
|
+
return compatible;
|
|
3414
|
+
}
|
|
3415
|
+
}
|
|
3416
|
+
} catch (err) {
|
|
3417
|
+
_iterator.e(err);
|
|
3418
|
+
} finally {
|
|
3419
|
+
_iterator.f();
|
|
3420
|
+
}
|
|
3421
|
+
return incompatible({
|
|
3422
|
+
kind: "no-matching-variant",
|
|
3423
|
+
variants: to.schema.items.map(function (item) {
|
|
3424
|
+
return describeVariant(item, key);
|
|
3425
|
+
})
|
|
3426
|
+
});
|
|
3427
|
+
}
|
|
3428
|
+
|
|
3429
|
+
// Coming FROM a union into something that is not one: only the variant this
|
|
3430
|
+
// value actually is matters, so narrow before comparing.
|
|
3431
|
+
if (from.schema.type === "union") {
|
|
3432
|
+
var _variant = variantOf(from.schema, from.value);
|
|
3433
|
+
if (_variant === undefined) {
|
|
3434
|
+
return {
|
|
3435
|
+
status: "unknown",
|
|
3436
|
+
message: "The old value does not say which shape it is, so we cannot tell whether it fits here."
|
|
3437
|
+
};
|
|
3438
|
+
}
|
|
3439
|
+
return checkCompatibility({
|
|
3440
|
+
schema: _variant,
|
|
3441
|
+
value: from.value
|
|
3442
|
+
}, to);
|
|
3443
|
+
}
|
|
3444
|
+
if (from.schema.type !== to.schema.type) {
|
|
3445
|
+
return incompatible({
|
|
3446
|
+
kind: "type-changed",
|
|
3447
|
+
from: from.schema.type,
|
|
3448
|
+
to: to.schema.type
|
|
3449
|
+
});
|
|
3450
|
+
}
|
|
3451
|
+
switch (to.schema.type) {
|
|
3452
|
+
case "literal":
|
|
3453
|
+
{
|
|
3454
|
+
var fromValue = from.schema.type === "literal" ? from.schema.value : String(from.value);
|
|
3455
|
+
return fromValue === to.schema.value ? compatible : incompatible({
|
|
3456
|
+
kind: "literal-changed",
|
|
3457
|
+
from: fromValue,
|
|
3458
|
+
to: to.schema.value
|
|
3459
|
+
});
|
|
3460
|
+
}
|
|
3461
|
+
case "object":
|
|
3462
|
+
{
|
|
3463
|
+
if (from.schema.type !== "object" || !isJsonObject(from.value)) {
|
|
3464
|
+
return {
|
|
3465
|
+
status: "unknown",
|
|
3466
|
+
message: "The old value is not shaped like an object."
|
|
3467
|
+
};
|
|
3468
|
+
}
|
|
3469
|
+
var _fromValue = from.value;
|
|
3470
|
+
var target = to.schema.items;
|
|
3471
|
+
var source = from.schema.items;
|
|
3472
|
+
|
|
3473
|
+
// Keys the old value carries that the field no longer has. Writing them
|
|
3474
|
+
// would put data into a schema with nowhere to hold it.
|
|
3475
|
+
var extra = Object.keys(source).filter(function (key) {
|
|
3476
|
+
return !(key in target);
|
|
3477
|
+
});
|
|
3478
|
+
if (extra.length > 0) {
|
|
3479
|
+
return incompatible({
|
|
3480
|
+
kind: "unknown-field",
|
|
3481
|
+
keys: extra
|
|
3482
|
+
});
|
|
3483
|
+
}
|
|
3484
|
+
|
|
3485
|
+
// Keys the field requires that the old value cannot supply.
|
|
3486
|
+
var missing = Object.keys(target).filter(function (key) {
|
|
3487
|
+
return !target[key].opt && !(key in source);
|
|
3488
|
+
});
|
|
3489
|
+
if (missing.length > 0) {
|
|
3490
|
+
return incompatible({
|
|
3491
|
+
kind: "missing-required",
|
|
3492
|
+
keys: missing
|
|
3493
|
+
});
|
|
3494
|
+
}
|
|
3495
|
+
var unknown = null;
|
|
3496
|
+
for (var _i = 0, _Object$entries = Object.entries(target); _i < _Object$entries.length; _i++) {
|
|
3497
|
+
var _fromValue$_key;
|
|
3498
|
+
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
3499
|
+
_key = _Object$entries$_i[0],
|
|
3500
|
+
targetItem = _Object$entries$_i[1];
|
|
3501
|
+
var sourceItem = source[_key];
|
|
3502
|
+
if (sourceItem === undefined) {
|
|
3503
|
+
continue; // optional and absent — already allowed above
|
|
3504
|
+
}
|
|
3505
|
+
var res = checkCompatibility({
|
|
3506
|
+
schema: sourceItem,
|
|
3507
|
+
value: (_fromValue$_key = _fromValue[_key]) !== null && _fromValue$_key !== void 0 ? _fromValue$_key : null
|
|
3508
|
+
}, {
|
|
3509
|
+
schema: targetItem
|
|
3510
|
+
});
|
|
3511
|
+
if (res.status === "incompatible") {
|
|
3512
|
+
return res;
|
|
3513
|
+
}
|
|
3514
|
+
if (res.status === "unknown" && unknown === null) {
|
|
3515
|
+
unknown = res;
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
3518
|
+
return unknown !== null && unknown !== void 0 ? unknown : compatible;
|
|
3519
|
+
}
|
|
3520
|
+
case "array":
|
|
3521
|
+
{
|
|
3522
|
+
if (from.schema.type !== "array" || !Array.isArray(from.value)) {
|
|
3523
|
+
return {
|
|
3524
|
+
status: "unknown",
|
|
3525
|
+
message: "The old value is not a list."
|
|
3526
|
+
};
|
|
3527
|
+
}
|
|
3528
|
+
// An empty list has nothing to probe the item schema with. The item
|
|
3529
|
+
// TYPES still have to agree, and that much can be decided without a
|
|
3530
|
+
// value - so decide it rather than passing an empty list as proof.
|
|
3531
|
+
if (from.value.length === 0) {
|
|
3532
|
+
return from.schema.item.type === to.schema.item.type ? compatible : incompatible({
|
|
3533
|
+
kind: "type-changed",
|
|
3534
|
+
from: from.schema.item.type,
|
|
3535
|
+
to: to.schema.item.type
|
|
3536
|
+
});
|
|
3537
|
+
}
|
|
3538
|
+
var _unknown = null;
|
|
3539
|
+
var _iterator2 = _createForOfIteratorHelper(from.value),
|
|
3540
|
+
_step2;
|
|
3541
|
+
try {
|
|
3542
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
3543
|
+
var item = _step2.value;
|
|
3544
|
+
var _res = checkCompatibility({
|
|
3545
|
+
schema: from.schema.item,
|
|
3546
|
+
value: item
|
|
3547
|
+
}, {
|
|
3548
|
+
schema: to.schema.item
|
|
3549
|
+
});
|
|
3550
|
+
if (_res.status === "incompatible") {
|
|
3551
|
+
return _res;
|
|
3552
|
+
}
|
|
3553
|
+
if (_res.status === "unknown" && _unknown === null) {
|
|
3554
|
+
_unknown = _res;
|
|
3555
|
+
}
|
|
3556
|
+
}
|
|
3557
|
+
} catch (err) {
|
|
3558
|
+
_iterator2.e(err);
|
|
3559
|
+
} finally {
|
|
3560
|
+
_iterator2.f();
|
|
3561
|
+
}
|
|
3562
|
+
return _unknown !== null && _unknown !== void 0 ? _unknown : compatible;
|
|
3563
|
+
}
|
|
3564
|
+
case "record":
|
|
3565
|
+
{
|
|
3566
|
+
if (from.schema.type !== "record" || !isJsonObject(from.value)) {
|
|
3567
|
+
return {
|
|
3568
|
+
status: "unknown",
|
|
3569
|
+
message: "The old value is not a record."
|
|
3570
|
+
};
|
|
3571
|
+
}
|
|
3572
|
+
var _unknown2 = null;
|
|
3573
|
+
for (var _i2 = 0, _Object$values = Object.values(from.value); _i2 < _Object$values.length; _i2++) {
|
|
3574
|
+
var entry = _Object$values[_i2];
|
|
3575
|
+
var _res2 = checkCompatibility({
|
|
3576
|
+
schema: from.schema.item,
|
|
3577
|
+
value: entry !== null && entry !== void 0 ? entry : null
|
|
3578
|
+
}, {
|
|
3579
|
+
schema: to.schema.item
|
|
3580
|
+
});
|
|
3581
|
+
if (_res2.status === "incompatible") {
|
|
3582
|
+
return _res2;
|
|
3583
|
+
}
|
|
3584
|
+
if (_res2.status === "unknown" && _unknown2 === null) {
|
|
3585
|
+
_unknown2 = _res2;
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
return _unknown2 !== null && _unknown2 !== void 0 ? _unknown2 : compatible;
|
|
3589
|
+
}
|
|
3590
|
+
case "keyOf":
|
|
3591
|
+
{
|
|
3592
|
+
// A key is only meaningful against the module it indexes.
|
|
3593
|
+
if (from.schema.type !== "keyOf") {
|
|
3594
|
+
return compatible;
|
|
3595
|
+
}
|
|
3596
|
+
return from.schema.path === to.schema.path ? compatible : incompatible({
|
|
3597
|
+
kind: "different-module",
|
|
3598
|
+
from: from.schema.path,
|
|
3599
|
+
to: to.schema.path
|
|
3600
|
+
});
|
|
3601
|
+
}
|
|
3602
|
+
case "richtext":
|
|
3603
|
+
{
|
|
3604
|
+
// The options decide which nodes are legal, and comparing them properly
|
|
3605
|
+
// means comparing node trees against them. Not yet done, and saying so is
|
|
3606
|
+
// better than a confident answer we cannot back.
|
|
3607
|
+
return {
|
|
3608
|
+
status: "unknown",
|
|
3609
|
+
message: "Rich text can be restored, but we cannot yet confirm every mark and block is still allowed here."
|
|
3610
|
+
};
|
|
3611
|
+
}
|
|
3612
|
+
default:
|
|
3613
|
+
// Primitives and media: same type is the whole test. Constraints
|
|
3614
|
+
// (maxLength, accept, …) are validated on write, which reports them
|
|
3615
|
+
// better than a schema comparison could.
|
|
3616
|
+
return compatible;
|
|
3617
|
+
}
|
|
3618
|
+
}
|
|
3619
|
+
|
|
3620
|
+
/**
|
|
3621
|
+
* The newest commit the client has been told about, or `null` if none.
|
|
3622
|
+
*
|
|
3623
|
+
* This is the **publish head**: unlike `baseSha`, which only moves once a
|
|
3624
|
+
* deployment lands, it moves the instant somebody publishes. That makes it the
|
|
3625
|
+
* one thing a client can carry to `/save` to say "this is the world I decided
|
|
3626
|
+
* against" — and the only way the server can tell that somebody else has
|
|
3627
|
+
* published since the review screen was read.
|
|
3628
|
+
*
|
|
3629
|
+
* In `shared` because both sides need the SAME answer: the client names a head
|
|
3630
|
+
* and the server compares against one, so two implementations of "newest" is two
|
|
3631
|
+
* ways to disagree about whether a publish is stale.
|
|
3632
|
+
*
|
|
3633
|
+
* By `createdAt` rather than by position, because the list's order is the
|
|
3634
|
+
* content API's business and nothing here should depend on it. Ties keep the
|
|
3635
|
+
* first seen, which is arbitrary and does not matter: two commits sharing a
|
|
3636
|
+
* timestamp are equally "since", and either answer refuses the same publishes.
|
|
3637
|
+
*/
|
|
3638
|
+
function newestCommitSha(commits) {
|
|
3639
|
+
var _newest$commitSha, _newest;
|
|
3640
|
+
var newest = null;
|
|
3641
|
+
var _iterator = _createForOfIteratorHelper(commits !== null && commits !== void 0 ? commits : []),
|
|
3642
|
+
_step;
|
|
3643
|
+
try {
|
|
3644
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
3645
|
+
var commit = _step.value;
|
|
3646
|
+
if (newest === null || commit.createdAt > newest.createdAt) {
|
|
3647
|
+
newest = commit;
|
|
3648
|
+
}
|
|
3649
|
+
}
|
|
3650
|
+
} catch (err) {
|
|
3651
|
+
_iterator.e(err);
|
|
3652
|
+
} finally {
|
|
3653
|
+
_iterator.f();
|
|
3654
|
+
}
|
|
3655
|
+
return (_newest$commitSha = (_newest = newest) === null || _newest === void 0 ? void 0 : _newest.commitSha) !== null && _newest$commitSha !== void 0 ? _newest$commitSha : null;
|
|
3656
|
+
}
|
|
3657
|
+
|
|
2710
3658
|
var VAL_CONFIG_SESSION_STORAGE_KEY = "val-config";
|
|
2711
3659
|
var VAL_THEME_SESSION_STORAGE_KEY = "val-theme";
|
|
2712
3660
|
var VAL_AI_SESSION_STORAGE_KEY = "val-ai-session";
|
|
@@ -2722,14 +3670,6 @@ var SharedValConfig = zod.z.object({
|
|
|
2722
3670
|
ai: zod.z.object({
|
|
2723
3671
|
commitMessages: zod.z.object({
|
|
2724
3672
|
disabled: zod.z["boolean"]().optional()
|
|
2725
|
-
}).optional(),
|
|
2726
|
-
chat: zod.z.object({
|
|
2727
|
-
experimental: zod.z.object({
|
|
2728
|
-
enable: zod.z["boolean"]().optional()
|
|
2729
|
-
}).optional(),
|
|
2730
|
-
suggestions: zod.z.array(zod.z.string()).optional(),
|
|
2731
|
-
title: zod.z.string().optional(),
|
|
2732
|
-
description: zod.z.string().optional()
|
|
2733
3673
|
}).optional()
|
|
2734
3674
|
}).optional()
|
|
2735
3675
|
});
|
|
@@ -3514,6 +4454,11 @@ function emptyOf(schema) {
|
|
|
3514
4454
|
return [];
|
|
3515
4455
|
} else if (schema.type === "record") {
|
|
3516
4456
|
return {};
|
|
4457
|
+
} else if (schema.type === "settings") {
|
|
4458
|
+
// Not an object of empty sections: every settings key is optional, and
|
|
4459
|
+
// absent IS the empty value. Filling the sections in would write a shape
|
|
4460
|
+
// the project never asked for.
|
|
4461
|
+
return {};
|
|
3517
4462
|
} else if (schema.opt) {
|
|
3518
4463
|
return null;
|
|
3519
4464
|
} else if (schema.type === "richtext") {
|
|
@@ -4177,6 +5122,13 @@ function isSkippableFixCode(fix) {
|
|
|
4177
5122
|
// rewriting the module) and saving does not repair it either, so surface
|
|
4178
5123
|
// it: the message names the command (`val validate --fix`) that does.
|
|
4179
5124
|
return false;
|
|
5125
|
+
case "external:upload":
|
|
5126
|
+
// Same shape as `jsonValues:extract-entry` — an entry inlined in a
|
|
5127
|
+
// `.val.ts` that belongs elsewhere — and more emphatically not skippable.
|
|
5128
|
+
// Fixing it writes to a live store, which is why even the CLI does it only
|
|
5129
|
+
// under `val external upload` and never under a blanket `--fix`. Surfacing
|
|
5130
|
+
// it is the whole point: someone has to decide.
|
|
5131
|
+
return false;
|
|
4180
5132
|
default:
|
|
4181
5133
|
{
|
|
4182
5134
|
return false;
|
|
@@ -4217,17 +5169,25 @@ function filterBlockingValidationErrors(validationErrors, schemas, sources) {
|
|
|
4217
5169
|
}
|
|
4218
5170
|
|
|
4219
5171
|
exports.Api = Api;
|
|
5172
|
+
exports.BinaryFileRef = BinaryFileRef;
|
|
4220
5173
|
exports.CodeOptions = CodeOptions;
|
|
4221
5174
|
exports.ColorOptions = ColorOptions;
|
|
4222
5175
|
exports.DEFAULT_ERROR_MESSAGE = DEFAULT_ERROR_MESSAGE;
|
|
4223
5176
|
exports.DateOptions = DateOptions;
|
|
4224
5177
|
exports.FileOptions = FileOptions;
|
|
5178
|
+
exports.HistoricalCommit = HistoricalCommit;
|
|
5179
|
+
exports.HistoricalModule = HistoricalModule;
|
|
5180
|
+
exports.HistoricalPatchSet = HistoricalPatchSet;
|
|
5181
|
+
exports.HistoryError = HistoryError;
|
|
4225
5182
|
exports.ImageEncodeOption = ImageEncodeOption;
|
|
4226
5183
|
exports.ImageOptions = ImageOptions;
|
|
5184
|
+
exports.JSONValue = JSONValue;
|
|
4227
5185
|
exports.JSON_ENTRIES_BATCH_MAX = JSON_ENTRIES_BATCH_MAX;
|
|
5186
|
+
exports.ModuleComparison = ModuleComparison;
|
|
4228
5187
|
exports.ParentRef = ParentRef$1;
|
|
4229
5188
|
exports.Patch = Patch;
|
|
4230
5189
|
exports.PatchBlock = PatchBlock;
|
|
5190
|
+
exports.PatchGroup = PatchGroup;
|
|
4231
5191
|
exports.PatchId = PatchId;
|
|
4232
5192
|
exports.PatchJSON = PatchJSON;
|
|
4233
5193
|
exports.RemirrorBr = RemirrorBr;
|
|
@@ -4241,6 +5201,7 @@ exports.RemirrorOrderedList = RemirrorOrderedList;
|
|
|
4241
5201
|
exports.RemirrorParagraph = RemirrorParagraph;
|
|
4242
5202
|
exports.RemirrorText = RemirrorText;
|
|
4243
5203
|
exports.RemirrorTextMark = RemirrorTextMark;
|
|
5204
|
+
exports.RestoreVerdict = RestoreVerdict;
|
|
4244
5205
|
exports.RichTextOptions = RichTextOptions;
|
|
4245
5206
|
exports.SerializedArraySchema = SerializedArraySchema;
|
|
4246
5207
|
exports.SerializedBooleanSchema = SerializedBooleanSchema;
|
|
@@ -4258,6 +5219,7 @@ exports.SerializedRecordSchema = SerializedRecordSchema;
|
|
|
4258
5219
|
exports.SerializedRichTextSchema = SerializedRichTextSchema;
|
|
4259
5220
|
exports.SerializedRouteSchema = SerializedRouteSchema;
|
|
4260
5221
|
exports.SerializedSchema = SerializedSchema;
|
|
5222
|
+
exports.SerializedSettingsSchema = SerializedSettingsSchema;
|
|
4261
5223
|
exports.SerializedStringSchema = SerializedStringSchema;
|
|
4262
5224
|
exports.SerializedUnionSchema = SerializedUnionSchema;
|
|
4263
5225
|
exports.SharedValConfig = SharedValConfig;
|
|
@@ -4276,10 +5238,12 @@ exports.buildEmptyAtPathPatch = buildEmptyAtPathPatch;
|
|
|
4276
5238
|
exports.buildFileRefValue = buildFileRefValue;
|
|
4277
5239
|
exports.buildImageGalleryPatch = buildImageGalleryPatch;
|
|
4278
5240
|
exports.buildRemoveImageGalleryEntryPatch = buildRemoveImageGalleryEntryPatch;
|
|
5241
|
+
exports.checkCompatibility = checkCompatibility;
|
|
4279
5242
|
exports.createRegExpFromPattern = createRegExpFromPattern;
|
|
4280
5243
|
exports.createValClient = createValClient;
|
|
4281
5244
|
exports.describeContainerAtPath = describeContainerAtPath;
|
|
4282
5245
|
exports.emptyOf = emptyOf;
|
|
5246
|
+
exports.explainIncompatible = explainIncompatible;
|
|
4283
5247
|
exports.filterBlockingValidationErrors = filterBlockingValidationErrors;
|
|
4284
5248
|
exports.filterRoutesByPatterns = filterRoutesByPatterns;
|
|
4285
5249
|
exports.findSimilar = findSimilar;
|
|
@@ -4296,6 +5260,7 @@ exports.isValCanvasFrame = isValCanvasFrame;
|
|
|
4296
5260
|
exports.isValCanvasPageMessage = isValCanvasPageMessage;
|
|
4297
5261
|
exports.isValCanvasStudioMessage = isValCanvasStudioMessage;
|
|
4298
5262
|
exports.levenshtein = levenshtein;
|
|
5263
|
+
exports.newestCommitSha = newestCommitSha;
|
|
4299
5264
|
exports.parseRoutePattern = parseRoutePattern;
|
|
4300
5265
|
exports.partitionValidationErrors = partitionValidationErrors;
|
|
4301
5266
|
exports.remirrorToRichTextSource = remirrorToRichTextSource;
|