@hollware/core 0.2.0 → 0.4.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/dist/index.d.mts +421 -6
- package/dist/index.mjs +175 -14
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -290,6 +290,13 @@ interface SiteDefinition {
|
|
|
290
290
|
readonly styleGuide?: string;
|
|
291
291
|
/** The public origin of the site, such as `https://example.com`: entries' URLs start with it. */
|
|
292
292
|
readonly url?: string;
|
|
293
|
+
/**
|
|
294
|
+
* The origins whose pages may read the published content of the site from the browser, over
|
|
295
|
+
* the read API with a read token (`hw_read_`). None by default.
|
|
296
|
+
*/
|
|
297
|
+
readonly cors?: {
|
|
298
|
+
readonly origins: readonly string[];
|
|
299
|
+
};
|
|
293
300
|
/** Who hears about publications (ADR-025). */
|
|
294
301
|
readonly events?: {
|
|
295
302
|
/** Each gets every event, signed with HMAC-SHA256 by the Worker secret named in `secret`. */
|
|
@@ -311,6 +318,17 @@ interface HollwareConfig {
|
|
|
311
318
|
* content exists. v0.1 serves exactly one site per deployment.
|
|
312
319
|
*/
|
|
313
320
|
readonly sites: Readonly<Record<string, SiteDefinition>>;
|
|
321
|
+
/** How MCP clients and the admin get tokens (ADR-026). */
|
|
322
|
+
readonly auth?: AuthDefinition;
|
|
323
|
+
}
|
|
324
|
+
/** The OAuth server of a deployment. */
|
|
325
|
+
interface AuthDefinition {
|
|
326
|
+
/**
|
|
327
|
+
* Whether a client may register itself (RFC 7591), for MCP clients that cannot present a
|
|
328
|
+
* Client ID Metadata Document. Off by default: a registration is a write to KV that anyone can
|
|
329
|
+
* make, and MCP 2026-07-28 prefers metadata documents.
|
|
330
|
+
*/
|
|
331
|
+
readonly dynamicClientRegistration?: boolean;
|
|
314
332
|
}
|
|
315
333
|
/** A collection once the config is resolved: checked, with every default filled in. */
|
|
316
334
|
interface ResolvedCollection {
|
|
@@ -335,6 +353,10 @@ interface ResolvedSite {
|
|
|
335
353
|
readonly collections: ReadonlyMap<string, ResolvedCollection>;
|
|
336
354
|
/** The public origin of the site, or `null`. */
|
|
337
355
|
readonly url: string | null;
|
|
356
|
+
/** The origins that may call the read API from a page, each as `URL.origin` gives it. */
|
|
357
|
+
readonly cors: {
|
|
358
|
+
readonly origins: readonly string[];
|
|
359
|
+
};
|
|
338
360
|
readonly events: ResolvedEvents;
|
|
339
361
|
}
|
|
340
362
|
/** A webhook of a site; `secret` names the Worker secret that signs its deliveries. */
|
|
@@ -350,9 +372,14 @@ interface ResolvedEvents {
|
|
|
350
372
|
readonly key: string;
|
|
351
373
|
} | null;
|
|
352
374
|
}
|
|
353
|
-
/** The config once resolved, at the start of the Worker
|
|
375
|
+
/** The config once resolved, at the start of the Worker: one site or more (ADR-027). */
|
|
354
376
|
interface ResolvedConfig {
|
|
355
377
|
readonly sites: ReadonlyMap<string, ResolvedSite>;
|
|
378
|
+
readonly auth: ResolvedAuth;
|
|
379
|
+
}
|
|
380
|
+
/** The OAuth server once the config is resolved. */
|
|
381
|
+
interface ResolvedAuth {
|
|
382
|
+
readonly dynamicClientRegistration: boolean;
|
|
356
383
|
}
|
|
357
384
|
/**
|
|
358
385
|
* Checks a config and fills in its defaults. It throws one error that lists every problem, each
|
|
@@ -412,7 +439,7 @@ export declare const DEFAULT_MAX_MARKDOWN_BYTES = 524288;
|
|
|
412
439
|
*/
|
|
413
440
|
export declare const MAX_MARKDOWN_BYTES_CEILING = 786432;
|
|
414
441
|
declare namespace schemas_d_exports {
|
|
415
|
-
export { acknowledgedWarning, collectionDescription, collectionName, componentDescription, conflict, contractDescription, document, entry, entryId, entryStatus, entrySummary, format, locale, markdown, phase, publication, revisionId, severity, siteDescription, slug, verdict, version, violation };
|
|
442
|
+
export { acknowledgedWarning, collectionDescription, collectionName, componentDescription, conflict, contractDescription, document, entry, entryId, entryStatus, entrySummary, format, locale, markdown, phase, publication, review, reviewId, reviewStatus, revisionId, severity, siteDescription, slug, verdict, version, violation };
|
|
416
443
|
}
|
|
417
444
|
/**
|
|
418
445
|
* The pieces the operation schemas share. Their descriptions become the JSON Schema that agents
|
|
@@ -639,6 +666,34 @@ declare const entry: z.ZodObject<{
|
|
|
639
666
|
}, z.core.$strip>>;
|
|
640
667
|
html: z.ZodOptional<z.ZodString>;
|
|
641
668
|
}, z.core.$strip>;
|
|
669
|
+
declare const reviewId: z.ZodString;
|
|
670
|
+
declare const reviewStatus: z.ZodEnum<{
|
|
671
|
+
approved: "approved";
|
|
672
|
+
cancelled: "cancelled";
|
|
673
|
+
changes_requested: "changes_requested";
|
|
674
|
+
pending: "pending";
|
|
675
|
+
}>;
|
|
676
|
+
/**
|
|
677
|
+
* A request to publish a revision, made by someone who may write but not publish, and what a
|
|
678
|
+
* person who may publish decided about it.
|
|
679
|
+
*/
|
|
680
|
+
declare const review: z.ZodObject<{
|
|
681
|
+
id: z.ZodString;
|
|
682
|
+
entryId: z.ZodString;
|
|
683
|
+
revision: z.ZodString;
|
|
684
|
+
status: z.ZodEnum<{
|
|
685
|
+
approved: "approved";
|
|
686
|
+
cancelled: "cancelled";
|
|
687
|
+
changes_requested: "changes_requested";
|
|
688
|
+
pending: "pending";
|
|
689
|
+
}>;
|
|
690
|
+
requestedBy: z.ZodString;
|
|
691
|
+
requestedByName: z.ZodNullable<z.ZodString>;
|
|
692
|
+
requestedAt: z.ZodString;
|
|
693
|
+
decidedBy: z.ZodNullable<z.ZodString>;
|
|
694
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
695
|
+
note: z.ZodNullable<z.ZodString>;
|
|
696
|
+
}, z.core.$strip>;
|
|
642
697
|
declare const conflict: z.ZodObject<{
|
|
643
698
|
currentVersion: z.ZodNumber;
|
|
644
699
|
headRevision: z.ZodString;
|
|
@@ -910,7 +965,7 @@ export declare function describeResolvedSite(site: ResolvedSite, options?: {
|
|
|
910
965
|
/**
|
|
911
966
|
* Checks the config of the deployment and fills in its defaults, or throws a `ConfigError` with
|
|
912
967
|
* every problem it found, so that a broken `hollware.config.ts` stops the Worker at startup with
|
|
913
|
-
* a message that says what to change.
|
|
968
|
+
* a message that says what to change. A deployment serves one site or more.
|
|
914
969
|
*
|
|
915
970
|
* The parameter is `unknown` because the config comes from user code that may be plain
|
|
916
971
|
* JavaScript; a `HollwareConfig` is accepted as is, so this is a `ResolveConfig`. Notes on the
|
|
@@ -991,13 +1046,19 @@ export declare class HollwareError extends Error {
|
|
|
991
1046
|
*/
|
|
992
1047
|
/** The kinds of ids and their prefixes. A new kind adds its prefix here. */
|
|
993
1048
|
export declare const ID_PREFIXES: {
|
|
1049
|
+
readonly challenge: 'chl';
|
|
994
1050
|
readonly delivery: 'dlv';
|
|
995
1051
|
readonly entry: 'ent';
|
|
996
1052
|
readonly event: 'evt';
|
|
1053
|
+
readonly invitation: 'inv';
|
|
1054
|
+
readonly member: 'mbr';
|
|
1055
|
+
readonly passkey: 'pky';
|
|
997
1056
|
readonly publication: 'pub';
|
|
998
1057
|
readonly revision: 'rev';
|
|
999
1058
|
readonly revisionTag: 'tag';
|
|
1059
|
+
readonly review: 'rvw';
|
|
1000
1060
|
readonly schedule: 'sch';
|
|
1061
|
+
readonly session: 'ses';
|
|
1001
1062
|
readonly token: 'tok';
|
|
1002
1063
|
readonly user: 'usr';
|
|
1003
1064
|
};
|
|
@@ -1186,6 +1247,7 @@ export declare const getEntry: OperationSpec<"get_entry", z.ZodObject<{
|
|
|
1186
1247
|
html: "html";
|
|
1187
1248
|
markdown: "markdown";
|
|
1188
1249
|
}>>>;
|
|
1250
|
+
published: z.ZodDefault<z.ZodBoolean>;
|
|
1189
1251
|
}, z.core.$strict>, z.ZodObject<{
|
|
1190
1252
|
outcome: z.ZodEnum<{
|
|
1191
1253
|
not_found: "not_found";
|
|
@@ -1495,6 +1557,7 @@ export declare const publish: OperationSpec<"publish", z.ZodObject<{
|
|
|
1495
1557
|
conflict: "conflict";
|
|
1496
1558
|
needs_acknowledgement: "needs_acknowledgement";
|
|
1497
1559
|
not_found: "not_found";
|
|
1560
|
+
pending_review: "pending_review";
|
|
1498
1561
|
published: "published";
|
|
1499
1562
|
scheduled: "scheduled";
|
|
1500
1563
|
}>;
|
|
@@ -1550,6 +1613,23 @@ export declare const publish: OperationSpec<"publish", z.ZodObject<{
|
|
|
1550
1613
|
currentVersion: z.ZodNumber;
|
|
1551
1614
|
headRevision: z.ZodString;
|
|
1552
1615
|
}, z.core.$strip>>;
|
|
1616
|
+
review: z.ZodOptional<z.ZodObject<{
|
|
1617
|
+
id: z.ZodString;
|
|
1618
|
+
entryId: z.ZodString;
|
|
1619
|
+
revision: z.ZodString;
|
|
1620
|
+
status: z.ZodEnum<{
|
|
1621
|
+
approved: "approved";
|
|
1622
|
+
cancelled: "cancelled";
|
|
1623
|
+
changes_requested: "changes_requested";
|
|
1624
|
+
pending: "pending";
|
|
1625
|
+
}>;
|
|
1626
|
+
requestedBy: z.ZodString;
|
|
1627
|
+
requestedByName: z.ZodNullable<z.ZodString>;
|
|
1628
|
+
requestedAt: z.ZodString;
|
|
1629
|
+
decidedBy: z.ZodNullable<z.ZodString>;
|
|
1630
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
1631
|
+
note: z.ZodNullable<z.ZodString>;
|
|
1632
|
+
}, z.core.$strip>>;
|
|
1553
1633
|
failedEntry: z.ZodOptional<z.ZodString>;
|
|
1554
1634
|
}, z.core.$strip>>;
|
|
1555
1635
|
export declare const unpublish: OperationSpec<"unpublish", z.ZodObject<{
|
|
@@ -1578,8 +1658,242 @@ export declare const unpublish: OperationSpec<"unpublish", z.ZodObject<{
|
|
|
1578
1658
|
updatedAt: z.ZodString;
|
|
1579
1659
|
}, z.core.$strip>>;
|
|
1580
1660
|
}, z.core.$strip>>;
|
|
1581
|
-
|
|
1582
|
-
|
|
1661
|
+
export declare const listReviews: OperationSpec<"list_reviews", z.ZodObject<{
|
|
1662
|
+
status: z.ZodDefault<z.ZodEnum<{
|
|
1663
|
+
approved: "approved";
|
|
1664
|
+
cancelled: "cancelled";
|
|
1665
|
+
changes_requested: "changes_requested";
|
|
1666
|
+
pending: "pending";
|
|
1667
|
+
}>>;
|
|
1668
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
1669
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1670
|
+
outcome: z.ZodEnum<{
|
|
1671
|
+
ok: "ok";
|
|
1672
|
+
}>;
|
|
1673
|
+
reviews: z.ZodArray<z.ZodObject<{
|
|
1674
|
+
id: z.ZodString;
|
|
1675
|
+
entryId: z.ZodString;
|
|
1676
|
+
revision: z.ZodString;
|
|
1677
|
+
status: z.ZodEnum<{
|
|
1678
|
+
approved: "approved";
|
|
1679
|
+
cancelled: "cancelled";
|
|
1680
|
+
changes_requested: "changes_requested";
|
|
1681
|
+
pending: "pending";
|
|
1682
|
+
}>;
|
|
1683
|
+
requestedBy: z.ZodString;
|
|
1684
|
+
requestedByName: z.ZodNullable<z.ZodString>;
|
|
1685
|
+
requestedAt: z.ZodString;
|
|
1686
|
+
decidedBy: z.ZodNullable<z.ZodString>;
|
|
1687
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
1688
|
+
note: z.ZodNullable<z.ZodString>;
|
|
1689
|
+
entry: z.ZodObject<{
|
|
1690
|
+
id: z.ZodString;
|
|
1691
|
+
collection: z.ZodString;
|
|
1692
|
+
locale: z.ZodString;
|
|
1693
|
+
slug: z.ZodString;
|
|
1694
|
+
translationGroup: z.ZodNullable<z.ZodString>;
|
|
1695
|
+
status: z.ZodEnum<{
|
|
1696
|
+
draft: "draft";
|
|
1697
|
+
published: "published";
|
|
1698
|
+
scheduled: "scheduled";
|
|
1699
|
+
}>;
|
|
1700
|
+
version: z.ZodNumber;
|
|
1701
|
+
frontmatter: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
1702
|
+
tags: z.ZodArray<z.ZodString>;
|
|
1703
|
+
hasUnpublishedChanges: z.ZodBoolean;
|
|
1704
|
+
publishedAt: z.ZodNullable<z.ZodString>;
|
|
1705
|
+
updatedAt: z.ZodString;
|
|
1706
|
+
}, z.core.$strip>;
|
|
1707
|
+
}, z.core.$strip>>;
|
|
1708
|
+
}, z.core.$strip>>;
|
|
1709
|
+
export declare const approveReview: OperationSpec<"approve_review", z.ZodObject<{
|
|
1710
|
+
id: z.ZodString;
|
|
1711
|
+
acknowledgeWarnings: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1712
|
+
contract: z.ZodString;
|
|
1713
|
+
path: z.ZodString;
|
|
1714
|
+
}, z.core.$strip>>>;
|
|
1715
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1716
|
+
outcome: z.ZodEnum<{
|
|
1717
|
+
blocked: "blocked";
|
|
1718
|
+
needs_acknowledgement: "needs_acknowledgement";
|
|
1719
|
+
not_found: "not_found";
|
|
1720
|
+
not_pending: "not_pending";
|
|
1721
|
+
published: "published";
|
|
1722
|
+
}>;
|
|
1723
|
+
review: z.ZodOptional<z.ZodObject<{
|
|
1724
|
+
id: z.ZodString;
|
|
1725
|
+
entryId: z.ZodString;
|
|
1726
|
+
revision: z.ZodString;
|
|
1727
|
+
status: z.ZodEnum<{
|
|
1728
|
+
approved: "approved";
|
|
1729
|
+
cancelled: "cancelled";
|
|
1730
|
+
changes_requested: "changes_requested";
|
|
1731
|
+
pending: "pending";
|
|
1732
|
+
}>;
|
|
1733
|
+
requestedBy: z.ZodString;
|
|
1734
|
+
requestedByName: z.ZodNullable<z.ZodString>;
|
|
1735
|
+
requestedAt: z.ZodString;
|
|
1736
|
+
decidedBy: z.ZodNullable<z.ZodString>;
|
|
1737
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
1738
|
+
note: z.ZodNullable<z.ZodString>;
|
|
1739
|
+
}, z.core.$strip>>;
|
|
1740
|
+
entry: z.ZodOptional<z.ZodObject<{
|
|
1741
|
+
id: z.ZodString;
|
|
1742
|
+
collection: z.ZodString;
|
|
1743
|
+
locale: z.ZodString;
|
|
1744
|
+
slug: z.ZodString;
|
|
1745
|
+
translationGroup: z.ZodNullable<z.ZodString>;
|
|
1746
|
+
status: z.ZodEnum<{
|
|
1747
|
+
draft: "draft";
|
|
1748
|
+
published: "published";
|
|
1749
|
+
scheduled: "scheduled";
|
|
1750
|
+
}>;
|
|
1751
|
+
version: z.ZodNumber;
|
|
1752
|
+
frontmatter: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
1753
|
+
tags: z.ZodArray<z.ZodString>;
|
|
1754
|
+
hasUnpublishedChanges: z.ZodBoolean;
|
|
1755
|
+
publishedAt: z.ZodNullable<z.ZodString>;
|
|
1756
|
+
updatedAt: z.ZodString;
|
|
1757
|
+
}, z.core.$strip>>;
|
|
1758
|
+
verdict: z.ZodOptional<z.ZodObject<{
|
|
1759
|
+
ok: z.ZodBoolean;
|
|
1760
|
+
phase: z.ZodEnum<{
|
|
1761
|
+
publish: "publish";
|
|
1762
|
+
write: "write";
|
|
1763
|
+
}>;
|
|
1764
|
+
errors: z.ZodArray<z.ZodObject<{
|
|
1765
|
+
contract: z.ZodString;
|
|
1766
|
+
severity: z.ZodEnum<{
|
|
1767
|
+
error: "error";
|
|
1768
|
+
warning: "warning";
|
|
1769
|
+
}>;
|
|
1770
|
+
path: z.ZodString;
|
|
1771
|
+
message: z.ZodString;
|
|
1772
|
+
fix: z.ZodString;
|
|
1773
|
+
line: z.ZodOptional<z.ZodNumber>;
|
|
1774
|
+
}, z.core.$strip>>;
|
|
1775
|
+
warnings: z.ZodArray<z.ZodObject<{
|
|
1776
|
+
contract: z.ZodString;
|
|
1777
|
+
severity: z.ZodEnum<{
|
|
1778
|
+
error: "error";
|
|
1779
|
+
warning: "warning";
|
|
1780
|
+
}>;
|
|
1781
|
+
path: z.ZodString;
|
|
1782
|
+
message: z.ZodString;
|
|
1783
|
+
fix: z.ZodString;
|
|
1784
|
+
line: z.ZodOptional<z.ZodNumber>;
|
|
1785
|
+
}, z.core.$strip>>;
|
|
1786
|
+
contractsHash: z.ZodString;
|
|
1787
|
+
}, z.core.$strip>>;
|
|
1788
|
+
}, z.core.$strip>>;
|
|
1789
|
+
export declare const requestChanges: OperationSpec<"request_changes", z.ZodObject<{
|
|
1790
|
+
id: z.ZodString;
|
|
1791
|
+
note: z.ZodString;
|
|
1792
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1793
|
+
outcome: z.ZodEnum<{
|
|
1794
|
+
changes_requested: "changes_requested";
|
|
1795
|
+
not_found: "not_found";
|
|
1796
|
+
not_pending: "not_pending";
|
|
1797
|
+
}>;
|
|
1798
|
+
review: z.ZodOptional<z.ZodObject<{
|
|
1799
|
+
id: z.ZodString;
|
|
1800
|
+
entryId: z.ZodString;
|
|
1801
|
+
revision: z.ZodString;
|
|
1802
|
+
status: z.ZodEnum<{
|
|
1803
|
+
approved: "approved";
|
|
1804
|
+
cancelled: "cancelled";
|
|
1805
|
+
changes_requested: "changes_requested";
|
|
1806
|
+
pending: "pending";
|
|
1807
|
+
}>;
|
|
1808
|
+
requestedBy: z.ZodString;
|
|
1809
|
+
requestedByName: z.ZodNullable<z.ZodString>;
|
|
1810
|
+
requestedAt: z.ZodString;
|
|
1811
|
+
decidedBy: z.ZodNullable<z.ZodString>;
|
|
1812
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
1813
|
+
note: z.ZodNullable<z.ZodString>;
|
|
1814
|
+
}, z.core.$strip>>;
|
|
1815
|
+
}, z.core.$strip>>;
|
|
1816
|
+
/** Every operation, sorted by name: the order of `tools/list`. */
|
|
1817
|
+
export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.ZodObject<{
|
|
1818
|
+
id: z.ZodString;
|
|
1819
|
+
acknowledgeWarnings: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1820
|
+
contract: z.ZodString;
|
|
1821
|
+
path: z.ZodString;
|
|
1822
|
+
}, z.core.$strip>>>;
|
|
1823
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1824
|
+
outcome: z.ZodEnum<{
|
|
1825
|
+
blocked: "blocked";
|
|
1826
|
+
needs_acknowledgement: "needs_acknowledgement";
|
|
1827
|
+
not_found: "not_found";
|
|
1828
|
+
not_pending: "not_pending";
|
|
1829
|
+
published: "published";
|
|
1830
|
+
}>;
|
|
1831
|
+
review: z.ZodOptional<z.ZodObject<{
|
|
1832
|
+
id: z.ZodString;
|
|
1833
|
+
entryId: z.ZodString;
|
|
1834
|
+
revision: z.ZodString;
|
|
1835
|
+
status: z.ZodEnum<{
|
|
1836
|
+
approved: "approved";
|
|
1837
|
+
cancelled: "cancelled";
|
|
1838
|
+
changes_requested: "changes_requested";
|
|
1839
|
+
pending: "pending";
|
|
1840
|
+
}>;
|
|
1841
|
+
requestedBy: z.ZodString;
|
|
1842
|
+
requestedByName: z.ZodNullable<z.ZodString>;
|
|
1843
|
+
requestedAt: z.ZodString;
|
|
1844
|
+
decidedBy: z.ZodNullable<z.ZodString>;
|
|
1845
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
1846
|
+
note: z.ZodNullable<z.ZodString>;
|
|
1847
|
+
}, z.core.$strip>>;
|
|
1848
|
+
entry: z.ZodOptional<z.ZodObject<{
|
|
1849
|
+
id: z.ZodString;
|
|
1850
|
+
collection: z.ZodString;
|
|
1851
|
+
locale: z.ZodString;
|
|
1852
|
+
slug: z.ZodString;
|
|
1853
|
+
translationGroup: z.ZodNullable<z.ZodString>;
|
|
1854
|
+
status: z.ZodEnum<{
|
|
1855
|
+
draft: "draft";
|
|
1856
|
+
published: "published";
|
|
1857
|
+
scheduled: "scheduled";
|
|
1858
|
+
}>;
|
|
1859
|
+
version: z.ZodNumber;
|
|
1860
|
+
frontmatter: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
1861
|
+
tags: z.ZodArray<z.ZodString>;
|
|
1862
|
+
hasUnpublishedChanges: z.ZodBoolean;
|
|
1863
|
+
publishedAt: z.ZodNullable<z.ZodString>;
|
|
1864
|
+
updatedAt: z.ZodString;
|
|
1865
|
+
}, z.core.$strip>>;
|
|
1866
|
+
verdict: z.ZodOptional<z.ZodObject<{
|
|
1867
|
+
ok: z.ZodBoolean;
|
|
1868
|
+
phase: z.ZodEnum<{
|
|
1869
|
+
publish: "publish";
|
|
1870
|
+
write: "write";
|
|
1871
|
+
}>;
|
|
1872
|
+
errors: z.ZodArray<z.ZodObject<{
|
|
1873
|
+
contract: z.ZodString;
|
|
1874
|
+
severity: z.ZodEnum<{
|
|
1875
|
+
error: "error";
|
|
1876
|
+
warning: "warning";
|
|
1877
|
+
}>;
|
|
1878
|
+
path: z.ZodString;
|
|
1879
|
+
message: z.ZodString;
|
|
1880
|
+
fix: z.ZodString;
|
|
1881
|
+
line: z.ZodOptional<z.ZodNumber>;
|
|
1882
|
+
}, z.core.$strip>>;
|
|
1883
|
+
warnings: z.ZodArray<z.ZodObject<{
|
|
1884
|
+
contract: z.ZodString;
|
|
1885
|
+
severity: z.ZodEnum<{
|
|
1886
|
+
error: "error";
|
|
1887
|
+
warning: "warning";
|
|
1888
|
+
}>;
|
|
1889
|
+
path: z.ZodString;
|
|
1890
|
+
message: z.ZodString;
|
|
1891
|
+
fix: z.ZodString;
|
|
1892
|
+
line: z.ZodOptional<z.ZodNumber>;
|
|
1893
|
+
}, z.core.$strip>>;
|
|
1894
|
+
contractsHash: z.ZodString;
|
|
1895
|
+
}, z.core.$strip>>;
|
|
1896
|
+
}, z.core.$strip>>, OperationSpec<"create_draft", z.ZodObject<{
|
|
1583
1897
|
collection: z.ZodString;
|
|
1584
1898
|
locale: z.ZodString;
|
|
1585
1899
|
slug: z.ZodString;
|
|
@@ -1684,6 +1998,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"create_draft", z.ZodOb
|
|
|
1684
1998
|
html: "html";
|
|
1685
1999
|
markdown: "markdown";
|
|
1686
2000
|
}>>>;
|
|
2001
|
+
published: z.ZodDefault<z.ZodBoolean>;
|
|
1687
2002
|
}, z.core.$strict>, z.ZodObject<{
|
|
1688
2003
|
outcome: z.ZodEnum<{
|
|
1689
2004
|
not_found: "not_found";
|
|
@@ -1843,6 +2158,53 @@ export declare const OPERATIONS: readonly [OperationSpec<"create_draft", z.ZodOb
|
|
|
1843
2158
|
updatedAt: z.ZodString;
|
|
1844
2159
|
}, z.core.$strip>>;
|
|
1845
2160
|
nextCursor: z.ZodNullable<z.ZodString>;
|
|
2161
|
+
}, z.core.$strip>>, OperationSpec<"list_reviews", z.ZodObject<{
|
|
2162
|
+
status: z.ZodDefault<z.ZodEnum<{
|
|
2163
|
+
approved: "approved";
|
|
2164
|
+
cancelled: "cancelled";
|
|
2165
|
+
changes_requested: "changes_requested";
|
|
2166
|
+
pending: "pending";
|
|
2167
|
+
}>>;
|
|
2168
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
2169
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2170
|
+
outcome: z.ZodEnum<{
|
|
2171
|
+
ok: "ok";
|
|
2172
|
+
}>;
|
|
2173
|
+
reviews: z.ZodArray<z.ZodObject<{
|
|
2174
|
+
id: z.ZodString;
|
|
2175
|
+
entryId: z.ZodString;
|
|
2176
|
+
revision: z.ZodString;
|
|
2177
|
+
status: z.ZodEnum<{
|
|
2178
|
+
approved: "approved";
|
|
2179
|
+
cancelled: "cancelled";
|
|
2180
|
+
changes_requested: "changes_requested";
|
|
2181
|
+
pending: "pending";
|
|
2182
|
+
}>;
|
|
2183
|
+
requestedBy: z.ZodString;
|
|
2184
|
+
requestedByName: z.ZodNullable<z.ZodString>;
|
|
2185
|
+
requestedAt: z.ZodString;
|
|
2186
|
+
decidedBy: z.ZodNullable<z.ZodString>;
|
|
2187
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
2188
|
+
note: z.ZodNullable<z.ZodString>;
|
|
2189
|
+
entry: z.ZodObject<{
|
|
2190
|
+
id: z.ZodString;
|
|
2191
|
+
collection: z.ZodString;
|
|
2192
|
+
locale: z.ZodString;
|
|
2193
|
+
slug: z.ZodString;
|
|
2194
|
+
translationGroup: z.ZodNullable<z.ZodString>;
|
|
2195
|
+
status: z.ZodEnum<{
|
|
2196
|
+
draft: "draft";
|
|
2197
|
+
published: "published";
|
|
2198
|
+
scheduled: "scheduled";
|
|
2199
|
+
}>;
|
|
2200
|
+
version: z.ZodNumber;
|
|
2201
|
+
frontmatter: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
2202
|
+
tags: z.ZodArray<z.ZodString>;
|
|
2203
|
+
hasUnpublishedChanges: z.ZodBoolean;
|
|
2204
|
+
publishedAt: z.ZodNullable<z.ZodString>;
|
|
2205
|
+
updatedAt: z.ZodString;
|
|
2206
|
+
}, z.core.$strip>;
|
|
2207
|
+
}, z.core.$strip>>;
|
|
1846
2208
|
}, z.core.$strip>>, OperationSpec<"publish", z.ZodObject<{
|
|
1847
2209
|
id: z.ZodString;
|
|
1848
2210
|
version: z.ZodNumber;
|
|
@@ -1861,6 +2223,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"create_draft", z.ZodOb
|
|
|
1861
2223
|
conflict: "conflict";
|
|
1862
2224
|
needs_acknowledgement: "needs_acknowledgement";
|
|
1863
2225
|
not_found: "not_found";
|
|
2226
|
+
pending_review: "pending_review";
|
|
1864
2227
|
published: "published";
|
|
1865
2228
|
scheduled: "scheduled";
|
|
1866
2229
|
}>;
|
|
@@ -1916,7 +2279,50 @@ export declare const OPERATIONS: readonly [OperationSpec<"create_draft", z.ZodOb
|
|
|
1916
2279
|
currentVersion: z.ZodNumber;
|
|
1917
2280
|
headRevision: z.ZodString;
|
|
1918
2281
|
}, z.core.$strip>>;
|
|
2282
|
+
review: z.ZodOptional<z.ZodObject<{
|
|
2283
|
+
id: z.ZodString;
|
|
2284
|
+
entryId: z.ZodString;
|
|
2285
|
+
revision: z.ZodString;
|
|
2286
|
+
status: z.ZodEnum<{
|
|
2287
|
+
approved: "approved";
|
|
2288
|
+
cancelled: "cancelled";
|
|
2289
|
+
changes_requested: "changes_requested";
|
|
2290
|
+
pending: "pending";
|
|
2291
|
+
}>;
|
|
2292
|
+
requestedBy: z.ZodString;
|
|
2293
|
+
requestedByName: z.ZodNullable<z.ZodString>;
|
|
2294
|
+
requestedAt: z.ZodString;
|
|
2295
|
+
decidedBy: z.ZodNullable<z.ZodString>;
|
|
2296
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
2297
|
+
note: z.ZodNullable<z.ZodString>;
|
|
2298
|
+
}, z.core.$strip>>;
|
|
1919
2299
|
failedEntry: z.ZodOptional<z.ZodString>;
|
|
2300
|
+
}, z.core.$strip>>, OperationSpec<"request_changes", z.ZodObject<{
|
|
2301
|
+
id: z.ZodString;
|
|
2302
|
+
note: z.ZodString;
|
|
2303
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2304
|
+
outcome: z.ZodEnum<{
|
|
2305
|
+
changes_requested: "changes_requested";
|
|
2306
|
+
not_found: "not_found";
|
|
2307
|
+
not_pending: "not_pending";
|
|
2308
|
+
}>;
|
|
2309
|
+
review: z.ZodOptional<z.ZodObject<{
|
|
2310
|
+
id: z.ZodString;
|
|
2311
|
+
entryId: z.ZodString;
|
|
2312
|
+
revision: z.ZodString;
|
|
2313
|
+
status: z.ZodEnum<{
|
|
2314
|
+
approved: "approved";
|
|
2315
|
+
cancelled: "cancelled";
|
|
2316
|
+
changes_requested: "changes_requested";
|
|
2317
|
+
pending: "pending";
|
|
2318
|
+
}>;
|
|
2319
|
+
requestedBy: z.ZodString;
|
|
2320
|
+
requestedByName: z.ZodNullable<z.ZodString>;
|
|
2321
|
+
requestedAt: z.ZodString;
|
|
2322
|
+
decidedBy: z.ZodNullable<z.ZodString>;
|
|
2323
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
2324
|
+
note: z.ZodNullable<z.ZodString>;
|
|
2325
|
+
}, z.core.$strip>>;
|
|
1920
2326
|
}, z.core.$strip>>, OperationSpec<"unpublish", z.ZodObject<{
|
|
1921
2327
|
id: z.ZodString;
|
|
1922
2328
|
}, z.core.$strict>, z.ZodObject<{
|
|
@@ -2061,6 +2467,11 @@ type OperationByName<Name extends OperationName> = Extract<Operation, {
|
|
|
2061
2467
|
* row of a token has an id of its own (`tok_…`, see `ids.ts`), its scopes and its expiry.
|
|
2062
2468
|
*/
|
|
2063
2469
|
export declare const PERSONAL_TOKEN_PREFIX = "hw_pat_";
|
|
2470
|
+
/**
|
|
2471
|
+
* Read tokens: `hw_read_` and the same 52 characters. A read token reads the published content of
|
|
2472
|
+
* one site over the read API (`GET /v1/…`) and nothing else, so a site may ship one to a browser.
|
|
2473
|
+
*/
|
|
2474
|
+
export declare const READ_TOKEN_PREFIX = "hw_read_";
|
|
2064
2475
|
/** Days until a new personal token expires, unless whoever creates it asks for another expiry. */
|
|
2065
2476
|
export declare const PERSONAL_TOKEN_TTL_DAYS = 90;
|
|
2066
2477
|
/**
|
|
@@ -2069,8 +2480,12 @@ export declare const PERSONAL_TOKEN_TTL_DAYS = 90;
|
|
|
2069
2480
|
* tests pass their own bytes.
|
|
2070
2481
|
*/
|
|
2071
2482
|
export declare function generatePersonalToken(random?: Uint8Array): string;
|
|
2483
|
+
/** A new read token, made as a personal token is. */
|
|
2484
|
+
export declare function generateReadToken(random?: Uint8Array): string;
|
|
2072
2485
|
/** Whether a string has the shape of a personal token. It says nothing about whether one exists. */
|
|
2073
2486
|
export declare function isPersonalToken(value: string): boolean;
|
|
2487
|
+
/** Whether a string has the shape of a read token. It says nothing about whether one exists. */
|
|
2488
|
+
export declare function isReadToken(value: string): boolean;
|
|
2074
2489
|
/** The SHA-256 of a token, in lowercase hex: what the `tokens` table stores and looks up. */
|
|
2075
2490
|
export declare function hashPersonalToken(token: string): Promise<string>;
|
|
2076
2491
|
//#endregion
|
|
@@ -2104,4 +2519,4 @@ export declare function verifyWebhook(check: WebhookCheck): Promise<boolean>;
|
|
|
2104
2519
|
//#region src/index.d.ts
|
|
2105
2520
|
export declare const name = "@hollware/core";
|
|
2106
2521
|
//#endregion
|
|
2107
|
-
export { type AcknowledgedWarning, type BuiltInContractId, type BuiltInOptions, type CollectionDefinition, type ComponentDefinition, type ComponentUse, type ConfigProblem, type Contract, type ContractContext, type ContractDescription, type ContractFinding, type ContractText, type CustomContractOptions, type DescribedSchema, type DisallowedMarker, type Effect, type EntryDocument, type EntryFacts, type EntryLookup, type EntryRef, type ErrorCode, type ExtractedContent, type Heading, type HollwareConfig, type IdPrefix, type ImageRef, type LinkRef, type LinkTarget, type Operation, type OperationByName, type OperationName, type OperationSpec, type OutcomeInfo, type OutcomeOf, type Phase, type ProcessMarkdown, type ProcessMarkdownOptions, type ProcessResult, type ProcessedMarkdown, type RenderHtml, type ResolveConfig, type ResolvedCollection, type ResolvedConfig, type ResolvedSite, type RunContractsInput, type SchemaOutput, type Scope, type Severity, type SiteDefinition, type SiteDescription, type Verdict, type Violation, schemas_d_exports as schemas };
|
|
2522
|
+
export { type AcknowledgedWarning, type AuthDefinition, type BuiltInContractId, type BuiltInOptions, type CollectionDefinition, type ComponentDefinition, type ComponentUse, type ConfigProblem, type Contract, type ContractContext, type ContractDescription, type ContractFinding, type ContractText, type CustomContractOptions, type DescribedSchema, type DisallowedMarker, type Effect, type EntryDocument, type EntryFacts, type EntryLookup, type EntryRef, type ErrorCode, type ExtractedContent, type Heading, type HollwareConfig, type IdPrefix, type ImageRef, type LinkRef, type LinkTarget, type Operation, type OperationByName, type OperationName, type OperationSpec, type OutcomeInfo, type OutcomeOf, type Phase, type ProcessMarkdown, type ProcessMarkdownOptions, type ProcessResult, type ProcessedMarkdown, type RenderHtml, type ResolveConfig, type ResolvedAuth, type ResolvedCollection, type ResolvedConfig, type ResolvedSite, type RunContractsInput, type SchemaOutput, type Scope, type Severity, type SiteDefinition, type SiteDescription, type Verdict, type Violation, schemas_d_exports as schemas };
|
package/dist/index.mjs
CHANGED
|
@@ -1396,6 +1396,20 @@ function readSiteUrl(path, raw, problems) {
|
|
|
1396
1396
|
}
|
|
1397
1397
|
return url.origin;
|
|
1398
1398
|
}
|
|
1399
|
+
/** The origins of a site's pages that may read its published content from the browser. */
|
|
1400
|
+
function readCors(path, raw, problems) {
|
|
1401
|
+
if (raw === void 0) return { origins: [] };
|
|
1402
|
+
if (!isRecord$1(raw) || !Array.isArray(raw["origins"])) {
|
|
1403
|
+
problems.add(path, wrongType(raw, "an object with origins"), "Declare it as { origins: [\"https://example.com\"] }, or remove it.");
|
|
1404
|
+
return { origins: [] };
|
|
1405
|
+
}
|
|
1406
|
+
const origins = [];
|
|
1407
|
+
for (const [index, origin] of raw["origins"].entries()) {
|
|
1408
|
+
const read = readSiteUrl(itemPath(keyPath(path, "origins"), index), origin, problems);
|
|
1409
|
+
if (read !== null && !origins.includes(read)) origins.push(read);
|
|
1410
|
+
}
|
|
1411
|
+
return { origins };
|
|
1412
|
+
}
|
|
1399
1413
|
function readBindingName(path, raw, problems) {
|
|
1400
1414
|
if (typeof raw === "string" && BINDING_NAME.test(raw)) return raw;
|
|
1401
1415
|
problems.add(path, wrongType(raw, "the name of a Worker secret"), "Name the secret that holds the value, such as \"WEBHOOK_SECRET\", and set it with wrangler secret put.");
|
|
@@ -1573,6 +1587,7 @@ function readSite(key, raw, problems) {
|
|
|
1573
1587
|
styleGuide,
|
|
1574
1588
|
collections,
|
|
1575
1589
|
url,
|
|
1590
|
+
cors: readCors(keyPath(path, "cors"), raw["cors"], problems),
|
|
1576
1591
|
events: readEvents(keyPath(path, "events"), raw["events"], url, problems)
|
|
1577
1592
|
};
|
|
1578
1593
|
}
|
|
@@ -1583,18 +1598,32 @@ function readSites(raw, problems) {
|
|
|
1583
1598
|
return sites;
|
|
1584
1599
|
}
|
|
1585
1600
|
const keys = Object.keys(raw);
|
|
1586
|
-
if (keys.length === 0) problems.add("sites", "has no site, and
|
|
1587
|
-
else if (keys.length > 1) problems.add("sites", `has ${keys.length} sites (${keys.map(quote).join(", ")}), and v0.1 serves exactly one site per deployment`, "Keep exactly one site in sites.");
|
|
1601
|
+
if (keys.length === 0) problems.add("sites", "has no site, and a deployment serves at least one", SITE_FIX);
|
|
1588
1602
|
for (const key of keys) {
|
|
1589
1603
|
const site = readSite(key, raw[key], problems);
|
|
1590
1604
|
if (site !== null) sites.set(key, site);
|
|
1591
1605
|
}
|
|
1592
1606
|
return sites;
|
|
1593
1607
|
}
|
|
1608
|
+
/** `auth` of the config: absent, or an object whose `dynamicClientRegistration` is a boolean. */
|
|
1609
|
+
function readAuth(raw, problems) {
|
|
1610
|
+
if (raw === void 0) return { dynamicClientRegistration: false };
|
|
1611
|
+
if (!isRecord$1(raw)) {
|
|
1612
|
+
problems.add("auth", wrongType(raw, "an object"), "Write auth: { dynamicClientRegistration: true }, or leave auth out.");
|
|
1613
|
+
return { dynamicClientRegistration: false };
|
|
1614
|
+
}
|
|
1615
|
+
const value = raw["dynamicClientRegistration"];
|
|
1616
|
+
if (value === void 0) return { dynamicClientRegistration: false };
|
|
1617
|
+
if (typeof value !== "boolean") {
|
|
1618
|
+
problems.add("auth.dynamicClientRegistration", wrongType(value, "true or false"), "Write true to let MCP clients register themselves, or leave it out.");
|
|
1619
|
+
return { dynamicClientRegistration: false };
|
|
1620
|
+
}
|
|
1621
|
+
return { dynamicClientRegistration: value };
|
|
1622
|
+
}
|
|
1594
1623
|
/**
|
|
1595
1624
|
* Checks the config of the deployment and fills in its defaults, or throws a `ConfigError` with
|
|
1596
1625
|
* every problem it found, so that a broken `hollware.config.ts` stops the Worker at startup with
|
|
1597
|
-
* a message that says what to change.
|
|
1626
|
+
* a message that says what to change. A deployment serves one site or more.
|
|
1598
1627
|
*
|
|
1599
1628
|
* The parameter is `unknown` because the config comes from user code that may be plain
|
|
1600
1629
|
* JavaScript; a `HollwareConfig` is accepted as is, so this is a `ResolveConfig`. Notes on the
|
|
@@ -1620,10 +1649,16 @@ function readSites(raw, problems) {
|
|
|
1620
1649
|
function resolveConfig(config) {
|
|
1621
1650
|
const problems = new Problems();
|
|
1622
1651
|
let sites = /* @__PURE__ */ new Map();
|
|
1623
|
-
|
|
1624
|
-
|
|
1652
|
+
let auth = { dynamicClientRegistration: false };
|
|
1653
|
+
if (isRecord$1(config)) {
|
|
1654
|
+
sites = readSites(config["sites"], problems);
|
|
1655
|
+
auth = readAuth(config["auth"], problems);
|
|
1656
|
+
} else problems.add("config", wrongType(config, "an object"), "Export the result of defineConfig({ sites: { … } }) from hollware.config.ts.");
|
|
1625
1657
|
if (problems.list.length > 0) throw new ConfigError(problems.list);
|
|
1626
|
-
return {
|
|
1658
|
+
return {
|
|
1659
|
+
sites,
|
|
1660
|
+
auth
|
|
1661
|
+
};
|
|
1627
1662
|
}
|
|
1628
1663
|
//#endregion
|
|
1629
1664
|
//#region src/errors.ts
|
|
@@ -1665,13 +1700,19 @@ var HollwareError = class extends Error {
|
|
|
1665
1700
|
const CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
1666
1701
|
/** The kinds of ids and their prefixes. A new kind adds its prefix here. */
|
|
1667
1702
|
const ID_PREFIXES = {
|
|
1703
|
+
challenge: "chl",
|
|
1668
1704
|
delivery: "dlv",
|
|
1669
1705
|
entry: "ent",
|
|
1670
1706
|
event: "evt",
|
|
1707
|
+
invitation: "inv",
|
|
1708
|
+
member: "mbr",
|
|
1709
|
+
passkey: "pky",
|
|
1671
1710
|
publication: "pub",
|
|
1672
1711
|
revision: "rev",
|
|
1673
1712
|
revisionTag: "tag",
|
|
1713
|
+
review: "rvw",
|
|
1674
1714
|
schedule: "sch",
|
|
1715
|
+
session: "ses",
|
|
1675
1716
|
token: "tok",
|
|
1676
1717
|
user: "usr"
|
|
1677
1718
|
};
|
|
@@ -3007,6 +3048,9 @@ var schemas_exports = /* @__PURE__ */ __exportAll({
|
|
|
3007
3048
|
markdown: () => markdown,
|
|
3008
3049
|
phase: () => phase,
|
|
3009
3050
|
publication: () => publication,
|
|
3051
|
+
review: () => review,
|
|
3052
|
+
reviewId: () => reviewId,
|
|
3053
|
+
reviewStatus: () => reviewStatus,
|
|
3010
3054
|
revisionId: () => revisionId,
|
|
3011
3055
|
severity: () => severity,
|
|
3012
3056
|
siteDescription: () => siteDescription,
|
|
@@ -3086,6 +3130,29 @@ const entry = entrySummary.extend({
|
|
|
3086
3130
|
document: document.optional(),
|
|
3087
3131
|
html: z.string().optional()
|
|
3088
3132
|
});
|
|
3133
|
+
const reviewId = z.string().regex(/^rvw_[0-9A-HJKMNP-TV-Z]{26}$/).describe("The id of a review (rvw_…), as publish and list_reviews return it.");
|
|
3134
|
+
const reviewStatus = z.enum([
|
|
3135
|
+
"pending",
|
|
3136
|
+
"approved",
|
|
3137
|
+
"changes_requested",
|
|
3138
|
+
"cancelled"
|
|
3139
|
+
]);
|
|
3140
|
+
/**
|
|
3141
|
+
* A request to publish a revision, made by someone who may write but not publish, and what a
|
|
3142
|
+
* person who may publish decided about it.
|
|
3143
|
+
*/
|
|
3144
|
+
const review = z.object({
|
|
3145
|
+
id: reviewId,
|
|
3146
|
+
entryId,
|
|
3147
|
+
revision: revisionId.describe("The revision asked for."),
|
|
3148
|
+
status: reviewStatus.describe("pending until someone decides; cancelled when a new revision of the entry is saved."),
|
|
3149
|
+
requestedBy: z.string().describe("The user who asked."),
|
|
3150
|
+
requestedByName: z.string().nullable().describe("The name of the user who asked, if they gave one."),
|
|
3151
|
+
requestedAt: z.string(),
|
|
3152
|
+
decidedBy: z.string().nullable(),
|
|
3153
|
+
decidedAt: z.string().nullable(),
|
|
3154
|
+
note: z.string().nullable().describe("What the reviewer asked to change, or null.")
|
|
3155
|
+
});
|
|
3089
3156
|
const conflict = z.object({
|
|
3090
3157
|
currentVersion: z.number().int().min(1),
|
|
3091
3158
|
headRevision: revisionId
|
|
@@ -3181,7 +3248,8 @@ const getEntry = defineOperation({
|
|
|
3181
3248
|
collection: collectionName,
|
|
3182
3249
|
locale,
|
|
3183
3250
|
slug,
|
|
3184
|
-
formats: z.array(format).min(1).default(["markdown"]).describe("What to return of the revision: markdown, the Comark document, or html.")
|
|
3251
|
+
formats: z.array(format).min(1).default(["markdown"]).describe("What to return of the revision: markdown, the Comark document, or html."),
|
|
3252
|
+
published: z.boolean().default(false).describe("Read the revision that is live instead of the latest one: not_found when the entry is not published.")
|
|
3185
3253
|
}),
|
|
3186
3254
|
output: z.object({
|
|
3187
3255
|
outcome: z.enum(["ok", "not_found"]),
|
|
@@ -3287,7 +3355,7 @@ const validate = defineOperation({
|
|
|
3287
3355
|
const publish = defineOperation({
|
|
3288
3356
|
name: "publish",
|
|
3289
3357
|
title: "Publish an entry",
|
|
3290
|
-
description: "Publishes the latest revision of an entry, if the entry is still at the version you read, and with group, other entries in the same step. It is blocked while the contracts report errors. Warnings have to be acknowledged: an answer of needs_acknowledgement lists them, and publish again with them in acknowledgeWarnings. Publish entries that link to each other as one group.",
|
|
3358
|
+
description: "Publishes the latest revision of an entry, if the entry is still at the version you read, and with group, other entries in the same step. It is blocked while the contracts report errors. Warnings have to be acknowledged: an answer of needs_acknowledgement lists them, and publish again with them in acknowledgeWarnings. Publish entries that link to each other as one group. Without content:publish, the same checks run and the answer is pending_review: a person who may publish approves the revision or asks for changes, and a new revision of the entry cancels the request. A review is for one entry, now: never with group or publishAt.",
|
|
3291
3359
|
input: z.strictObject({
|
|
3292
3360
|
id: entryId,
|
|
3293
3361
|
version,
|
|
@@ -3304,21 +3372,24 @@ const publish = defineOperation({
|
|
|
3304
3372
|
"scheduled",
|
|
3305
3373
|
"blocked",
|
|
3306
3374
|
"needs_acknowledgement",
|
|
3375
|
+
"pending_review",
|
|
3307
3376
|
"conflict",
|
|
3308
3377
|
"not_found"
|
|
3309
3378
|
]),
|
|
3310
3379
|
entry: entrySummary.optional(),
|
|
3311
3380
|
verdict: verdict.optional(),
|
|
3312
3381
|
conflict: conflict.optional(),
|
|
3313
|
-
|
|
3382
|
+
review: review.optional().describe("With pending_review: the request, as list_reviews shows it."),
|
|
3383
|
+
failedEntry: entryId.optional().describe("In a group, the entry that kept the group from being published: blocked, stale, missing, or with a warning to acknowledge.")
|
|
3314
3384
|
}),
|
|
3315
|
-
scopes: ["content:
|
|
3385
|
+
scopes: ["content:write"],
|
|
3316
3386
|
effect: "write",
|
|
3317
3387
|
outcomes: {
|
|
3318
3388
|
published: { isError: false },
|
|
3319
3389
|
scheduled: { isError: false },
|
|
3320
3390
|
blocked: { isError: true },
|
|
3321
3391
|
needs_acknowledgement: { isError: false },
|
|
3392
|
+
pending_review: { isError: false },
|
|
3322
3393
|
conflict: { isError: true },
|
|
3323
3394
|
not_found: { isError: true }
|
|
3324
3395
|
}
|
|
@@ -3339,14 +3410,87 @@ const unpublish = defineOperation({
|
|
|
3339
3410
|
not_found: { isError: true }
|
|
3340
3411
|
}
|
|
3341
3412
|
});
|
|
3342
|
-
|
|
3413
|
+
const listReviews = defineOperation({
|
|
3414
|
+
name: "list_reviews",
|
|
3415
|
+
title: "List the reviews",
|
|
3416
|
+
description: "Lists the requests to publish, newest first, with the entry each one is for: the pending ones unless you name another status.",
|
|
3417
|
+
input: z.strictObject({
|
|
3418
|
+
status: reviewStatus.default("pending"),
|
|
3419
|
+
limit: z.number().int().min(1).max(100).default(50)
|
|
3420
|
+
}),
|
|
3421
|
+
output: z.object({
|
|
3422
|
+
outcome: z.enum(["ok"]),
|
|
3423
|
+
reviews: z.array(review.extend({ entry: entrySummary }))
|
|
3424
|
+
}),
|
|
3425
|
+
scopes: ["content:read"],
|
|
3426
|
+
effect: "read",
|
|
3427
|
+
outcomes: { ok: { isError: false } }
|
|
3428
|
+
});
|
|
3429
|
+
const approveReview = defineOperation({
|
|
3430
|
+
name: "approve_review",
|
|
3431
|
+
title: "Approve a review",
|
|
3432
|
+
description: "Publishes the revision a review asked for, in your name, after the contracts run again as publish runs them. The warnings the request acknowledged count as acknowledged; a new one answers needs_acknowledgement, and you approve again with it in acknowledgeWarnings.",
|
|
3433
|
+
input: z.strictObject({
|
|
3434
|
+
id: reviewId,
|
|
3435
|
+
acknowledgeWarnings: z.array(acknowledgedWarning).default([]).describe("Warnings you accept besides those the request acknowledged.")
|
|
3436
|
+
}),
|
|
3437
|
+
output: z.object({
|
|
3438
|
+
outcome: z.enum([
|
|
3439
|
+
"published",
|
|
3440
|
+
"blocked",
|
|
3441
|
+
"needs_acknowledgement",
|
|
3442
|
+
"not_pending",
|
|
3443
|
+
"not_found"
|
|
3444
|
+
]),
|
|
3445
|
+
review: review.optional(),
|
|
3446
|
+
entry: entrySummary.optional(),
|
|
3447
|
+
verdict: verdict.optional()
|
|
3448
|
+
}),
|
|
3449
|
+
scopes: ["content:publish"],
|
|
3450
|
+
effect: "write",
|
|
3451
|
+
outcomes: {
|
|
3452
|
+
published: { isError: false },
|
|
3453
|
+
blocked: { isError: true },
|
|
3454
|
+
needs_acknowledgement: { isError: false },
|
|
3455
|
+
not_pending: { isError: true },
|
|
3456
|
+
not_found: { isError: true }
|
|
3457
|
+
}
|
|
3458
|
+
});
|
|
3459
|
+
const requestChanges = defineOperation({
|
|
3460
|
+
name: "request_changes",
|
|
3461
|
+
title: "Ask for changes",
|
|
3462
|
+
description: "Closes a pending review without publishing, with a note that says what to change. The author saves a new revision and asks again.",
|
|
3463
|
+
input: z.strictObject({
|
|
3464
|
+
id: reviewId,
|
|
3465
|
+
note: z.string().trim().min(1).max(4e3).describe("What to change, for the author.")
|
|
3466
|
+
}),
|
|
3467
|
+
output: z.object({
|
|
3468
|
+
outcome: z.enum([
|
|
3469
|
+
"changes_requested",
|
|
3470
|
+
"not_pending",
|
|
3471
|
+
"not_found"
|
|
3472
|
+
]),
|
|
3473
|
+
review: review.optional()
|
|
3474
|
+
}),
|
|
3475
|
+
scopes: ["content:publish"],
|
|
3476
|
+
effect: "edit",
|
|
3477
|
+
outcomes: {
|
|
3478
|
+
changes_requested: { isError: false },
|
|
3479
|
+
not_pending: { isError: true },
|
|
3480
|
+
not_found: { isError: true }
|
|
3481
|
+
}
|
|
3482
|
+
});
|
|
3483
|
+
/** Every operation, sorted by name: the order of `tools/list`. */
|
|
3343
3484
|
const OPERATIONS = [
|
|
3485
|
+
approveReview,
|
|
3344
3486
|
createDraft,
|
|
3345
3487
|
describeSite,
|
|
3346
3488
|
getEntry,
|
|
3347
3489
|
getTranslations,
|
|
3348
3490
|
listEntries,
|
|
3491
|
+
listReviews,
|
|
3349
3492
|
publish,
|
|
3493
|
+
requestChanges,
|
|
3350
3494
|
unpublish,
|
|
3351
3495
|
updateDraft,
|
|
3352
3496
|
validate
|
|
@@ -3376,26 +3520,43 @@ function isScope(value) {
|
|
|
3376
3520
|
* row of a token has an id of its own (`tok_…`, see `ids.ts`), its scopes and its expiry.
|
|
3377
3521
|
*/
|
|
3378
3522
|
const PERSONAL_TOKEN_PREFIX = "hw_pat_";
|
|
3523
|
+
/**
|
|
3524
|
+
* Read tokens: `hw_read_` and the same 52 characters. A read token reads the published content of
|
|
3525
|
+
* one site over the read API (`GET /v1/…`) and nothing else, so a site may ship one to a browser.
|
|
3526
|
+
*/
|
|
3527
|
+
const READ_TOKEN_PREFIX = "hw_read_";
|
|
3379
3528
|
/** Days until a new personal token expires, unless whoever creates it asks for another expiry. */
|
|
3380
3529
|
const PERSONAL_TOKEN_TTL_DAYS = 90;
|
|
3381
3530
|
const ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz";
|
|
3382
3531
|
const SECRET_LENGTH = 52;
|
|
3383
3532
|
const TOKEN_PATTERN = /^hw_pat_[0-9a-hjkmnp-tv-z]{52}$/;
|
|
3533
|
+
const READ_TOKEN_PATTERN = /^hw_read_[0-9a-hjkmnp-tv-z]{52}$/;
|
|
3384
3534
|
/**
|
|
3385
3535
|
* A new personal token. Each of the 52 random bytes gives one character (its low 5 bits, which
|
|
3386
3536
|
* are uniform because 256 is a multiple of 32). `random` defaults to `crypto.getRandomValues`;
|
|
3387
3537
|
* tests pass their own bytes.
|
|
3388
3538
|
*/
|
|
3389
3539
|
function generatePersonalToken(random = crypto.getRandomValues(new Uint8Array(SECRET_LENGTH))) {
|
|
3390
|
-
|
|
3540
|
+
return PERSONAL_TOKEN_PREFIX + secretOf(random, "a personal token");
|
|
3541
|
+
}
|
|
3542
|
+
/** A new read token, made as a personal token is. */
|
|
3543
|
+
function generateReadToken(random = crypto.getRandomValues(new Uint8Array(SECRET_LENGTH))) {
|
|
3544
|
+
return READ_TOKEN_PREFIX + secretOf(random, "a read token");
|
|
3545
|
+
}
|
|
3546
|
+
function secretOf(random, what) {
|
|
3547
|
+
if (random.length !== SECRET_LENGTH) throw new RangeError(`${what} takes ${SECRET_LENGTH} random bytes, got ${random.length}`);
|
|
3391
3548
|
let secret = "";
|
|
3392
3549
|
for (const byte of random) secret += ALPHABET.charAt(byte & 31);
|
|
3393
|
-
return
|
|
3550
|
+
return secret;
|
|
3394
3551
|
}
|
|
3395
3552
|
/** Whether a string has the shape of a personal token. It says nothing about whether one exists. */
|
|
3396
3553
|
function isPersonalToken(value) {
|
|
3397
3554
|
return TOKEN_PATTERN.test(value);
|
|
3398
3555
|
}
|
|
3556
|
+
/** Whether a string has the shape of a read token. It says nothing about whether one exists. */
|
|
3557
|
+
function isReadToken(value) {
|
|
3558
|
+
return READ_TOKEN_PATTERN.test(value);
|
|
3559
|
+
}
|
|
3399
3560
|
/** The SHA-256 of a token, in lowercase hex: what the `tokens` table stores and looks up. */
|
|
3400
3561
|
async function hashPersonalToken(token) {
|
|
3401
3562
|
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(token));
|
|
@@ -3449,4 +3610,4 @@ async function verifyWebhook(check) {
|
|
|
3449
3610
|
//#region src/index.ts
|
|
3450
3611
|
const name = "@hollware/core";
|
|
3451
3612
|
//#endregion
|
|
3452
|
-
export { BUILT_IN_CONTRACT_IDS, COMARK_VERSION, ConfigError, DEFAULT_MAX_MARKDOWN_BYTES, ERROR_CODES, EVENT_ID_HEADER, HollwareError, ID_PREFIXES, MAX_MARKDOWN_BYTES_CEILING, OPERATIONS, PERSONAL_TOKEN_PREFIX, PERSONAL_TOKEN_TTL_DAYS, PIPELINE_VERSION, REFUSAL_CONTRACT_IDS, SCOPES, SIGNATURE_HEADER, SITE_KEY_MAX_LENGTH, SITE_KEY_PATTERN, TIMESTAMP_HEADER, contracts, createDraft, defineCollection, defineComponent, defineConfig, defineContract, defineOperation, describeBuiltInContracts, describeContract, describeResolvedSite, describeSite, generatePersonalToken, getEntry, getTranslations, hashPersonalToken, isBuiltInContract, isId, isPersonalToken, isScope, isSiteKey, listEntries, name, newId, processMarkdown, publish, renderHtml, resolveConfig, runContracts, schemas_exports as schemas, signWebhook, sizeLimitViolation, ulid, uniqueSlugViolation, uniqueTranslationViolation, unpublish, updateDraft, validate, verifyWebhook };
|
|
3613
|
+
export { BUILT_IN_CONTRACT_IDS, COMARK_VERSION, ConfigError, DEFAULT_MAX_MARKDOWN_BYTES, ERROR_CODES, EVENT_ID_HEADER, HollwareError, ID_PREFIXES, MAX_MARKDOWN_BYTES_CEILING, OPERATIONS, PERSONAL_TOKEN_PREFIX, PERSONAL_TOKEN_TTL_DAYS, PIPELINE_VERSION, READ_TOKEN_PREFIX, REFUSAL_CONTRACT_IDS, SCOPES, SIGNATURE_HEADER, SITE_KEY_MAX_LENGTH, SITE_KEY_PATTERN, TIMESTAMP_HEADER, approveReview, contracts, createDraft, defineCollection, defineComponent, defineConfig, defineContract, defineOperation, describeBuiltInContracts, describeContract, describeResolvedSite, describeSite, generatePersonalToken, generateReadToken, getEntry, getTranslations, hashPersonalToken, isBuiltInContract, isId, isPersonalToken, isReadToken, isScope, isSiteKey, listEntries, listReviews, name, newId, processMarkdown, publish, renderHtml, requestChanges, resolveConfig, runContracts, schemas_exports as schemas, signWebhook, sizeLimitViolation, ulid, uniqueSlugViolation, uniqueTranslationViolation, unpublish, updateDraft, validate, verifyWebhook };
|
package/package.json
CHANGED