canopycms 0.5.0 → 0.7.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.
Files changed (107) hide show
  1. package/CHANGELOG.md +185 -46
  2. package/dist/api/branch-review.d.ts +11 -1
  3. package/dist/api/branch-review.js +96 -18
  4. package/dist/api/branch-status.d.ts +26 -2
  5. package/dist/api/branch-status.js +38 -2
  6. package/dist/api/branch-withdraw.js +4 -7
  7. package/dist/api/branch.d.ts +2 -0
  8. package/dist/api/client.d.ts +3 -3
  9. package/dist/api/client.js +4 -4
  10. package/dist/api/comments.d.ts +2 -2
  11. package/dist/api/comments.js +4 -0
  12. package/dist/api/content.d.ts +2 -2
  13. package/dist/api/github-sync.d.ts +4 -0
  14. package/dist/api/github-sync.js +38 -6
  15. package/dist/api/pr-comment-sync.d.ts +18 -0
  16. package/dist/api/pr-comment-sync.js +77 -0
  17. package/dist/api/request-deadline.d.ts +15 -7
  18. package/dist/api/request-deadline.js +15 -7
  19. package/dist/api/schema.d.ts +16 -16
  20. package/dist/authorization/review-role.d.ts +33 -0
  21. package/dist/authorization/review-role.js +17 -0
  22. package/dist/branch-metadata-file.d.ts +3 -0
  23. package/dist/branch-metadata-file.js +1 -0
  24. package/dist/cli/cli.js +704 -131
  25. package/dist/cli/generate-ai-content.js +524 -59
  26. package/dist/cli/github-app-output.d.ts +34 -0
  27. package/dist/cli/github-app-output.js +85 -0
  28. package/dist/cli/init-github-app.d.ts +18 -0
  29. package/dist/cli/init-github-app.js +66 -58
  30. package/dist/cli/init.js +15 -2
  31. package/dist/cli/template-files/cms-stack.ts.template +3 -0
  32. package/dist/cli/templates.js +5 -1
  33. package/dist/comment-store.d.ts +5 -0
  34. package/dist/comment-store.js +24 -0
  35. package/dist/config/helpers.js +1 -3
  36. package/dist/config/schemas/collection.d.ts +2 -2
  37. package/dist/config/schemas/config.d.ts +3 -0
  38. package/dist/config/schemas/config.js +2 -1
  39. package/dist/config/schemas/url.d.ts +6 -0
  40. package/dist/config/schemas/url.js +16 -0
  41. package/dist/config/types.d.ts +12 -1
  42. package/dist/content-id-index.d.ts +9 -0
  43. package/dist/content-id-index.js +31 -0
  44. package/dist/editor/BranchManager.d.ts +3 -0
  45. package/dist/editor/BranchManager.js +75 -44
  46. package/dist/editor/CanopyEditor.js +2 -2
  47. package/dist/editor/CanopyEditorPage.js +3 -4
  48. package/dist/editor/Editor.js +47 -8
  49. package/dist/editor/branch-lock.d.ts +7 -0
  50. package/dist/editor/branch-lock.js +9 -2
  51. package/dist/editor/client-reference-resolver.d.ts +5 -3
  52. package/dist/editor/client-reference-resolver.js +10 -5
  53. package/dist/editor/components/BranchesLoadFailedNotice.d.ts +13 -0
  54. package/dist/editor/components/BranchesLoadFailedNotice.js +12 -0
  55. package/dist/editor/components/EditorHeader.d.ts +10 -4
  56. package/dist/editor/components/EditorHeader.js +108 -28
  57. package/dist/editor/components/EntryHeader.d.ts +5 -1
  58. package/dist/editor/components/EntryHeader.js +3 -1
  59. package/dist/editor/components/ReasonedMenuItem.d.ts +8 -0
  60. package/dist/editor/components/ReasonedMenuItem.js +2 -2
  61. package/dist/editor/components/ReviewDialogs.d.ts +19 -0
  62. package/dist/editor/components/ReviewDialogs.js +41 -0
  63. package/dist/editor/copy.d.ts +4 -0
  64. package/dist/editor/copy.js +4 -0
  65. package/dist/editor/fields/MarkdownField.js +1 -1
  66. package/dist/editor/hooks/create-branch-request.d.ts +6 -2
  67. package/dist/editor/hooks/create-branch-request.js +7 -2
  68. package/dist/editor/hooks/useBranchManager.d.ts +7 -2
  69. package/dist/editor/hooks/useBranchManager.js +252 -37
  70. package/dist/editor-url.d.ts +20 -0
  71. package/dist/editor-url.js +71 -0
  72. package/dist/git-manager.js +10 -6
  73. package/dist/github-service.d.ts +2 -2
  74. package/dist/github-service.js +4 -2
  75. package/dist/pr-comments.d.ts +33 -0
  76. package/dist/pr-comments.js +41 -0
  77. package/dist/schema/schema-store.d.ts +8 -8
  78. package/dist/services.d.ts +2 -17
  79. package/dist/services.js +38 -1
  80. package/dist/settings-workspace.d.ts +21 -7
  81. package/dist/settings-workspace.js +91 -16
  82. package/dist/submission-attribution.d.ts +38 -1
  83. package/dist/submission-attribution.js +197 -18
  84. package/dist/task-queue/cms-task-queue.d.ts +1 -1
  85. package/dist/types.d.ts +6 -0
  86. package/dist/utils/content-serialize.js +7 -6
  87. package/dist/utils/markdown-body-splice.d.ts +15 -10
  88. package/dist/utils/markdown-body-splice.js +71 -28
  89. package/dist/utils/markdown-export-options.d.ts +13 -0
  90. package/dist/utils/markdown-export-options.js +13 -0
  91. package/dist/utils/markdown-restyle.d.ts +58 -0
  92. package/dist/utils/markdown-restyle.js +482 -0
  93. package/dist/version.d.ts +1 -1
  94. package/dist/version.js +1 -1
  95. package/dist/worker/bundle-header.d.ts +13 -9
  96. package/dist/worker/bundle-header.js +17 -11
  97. package/dist/worker/git-process.d.ts +2 -2
  98. package/dist/worker/github-gateway-http.js +5 -4
  99. package/dist/worker/github-gateway-wire.d.ts +3 -0
  100. package/dist/worker/github-gateway-wire.js +1 -0
  101. package/dist/worker/github-gateway.d.ts +1 -1
  102. package/dist/worker/github-gateway.js +2 -2
  103. package/dist/worker/github-transfer.js +72 -2
  104. package/dist/worker/task-runner.js +53 -3
  105. package/package.json +2 -2
  106. package/dist/editor/fields/markdown-export-options.d.ts +0 -2
  107. package/dist/editor/fields/markdown-export-options.js +0 -8
@@ -4,18 +4,26 @@
4
4
  * past it, rejects with {@link ApiTimeoutError}: a thrown error, as a network failure is, but
5
5
  * distinguishable from one. HTTP error statuses stay `ok: false` responses.
6
6
  */
7
+ /**
8
+ * The longest a gateway in front of the API holds a request before answering 504: CloudFront's
9
+ * default origin response timeout quota, which canopycms-cdk's `MAX_CLOUDFRONT_ORIGIN_READ_TIMEOUT`
10
+ * caps its origin at. The two are pinned equal by canopycms-cdk's `request-deadline-pin.test.ts`.
11
+ * @internal Exported for tests and `create-branch-request.ts`.
12
+ */
13
+ export declare const GATEWAY_MAX_TIMEOUT_MS = 120000;
14
+ /** @internal Exported for tests. What the browser allows past the gateway's limit before giving up. */
15
+ export declare const GATEWAY_MARGIN_MS = 15000;
7
16
  /**
8
17
  * @internal Exported for tests.
9
18
  *
10
- * How long each class of request may take. `standard` is past the 60 s an API behind CloudFront
11
- * gets (canopycms-cdk's `assertOriginReadTimeout`), so a server still working answers, or its
12
- * proxy's 504 does, before the editor gives up; reads get it too, since any request may first
13
- * provision the base branch's workspace (`http/handler.ts`). `long` is
14
- * for the operations that legitimately run longer: branch create, submit, admin scans and
15
- * repairs, and an upload without progress.
19
+ * How long each class of request may take. `standard` is past {@link GATEWAY_MAX_TIMEOUT_MS}, so
20
+ * a server still working answers, or its proxy's 504 does, before the editor gives up; reads get
21
+ * it too, since any request may first provision the base branch's workspace (`http/handler.ts`).
22
+ * `long` is for the operations that legitimately run longer: branch create, submit, admin scans
23
+ * and repairs, and an upload without progress.
16
24
  */
17
25
  export declare const REQUEST_TIMEOUT_MS: {
18
- readonly standard: 75000;
26
+ readonly standard: number;
19
27
  readonly long: 180000;
20
28
  };
21
29
  /** An endpoint's timeout class; `none` waits as long as the browser does. */
@@ -4,18 +4,26 @@
4
4
  * past it, rejects with {@link ApiTimeoutError}: a thrown error, as a network failure is, but
5
5
  * distinguishable from one. HTTP error statuses stay `ok: false` responses.
6
6
  */
7
+ /**
8
+ * The longest a gateway in front of the API holds a request before answering 504: CloudFront's
9
+ * default origin response timeout quota, which canopycms-cdk's `MAX_CLOUDFRONT_ORIGIN_READ_TIMEOUT`
10
+ * caps its origin at. The two are pinned equal by canopycms-cdk's `request-deadline-pin.test.ts`.
11
+ * @internal Exported for tests and `create-branch-request.ts`.
12
+ */
13
+ export const GATEWAY_MAX_TIMEOUT_MS = 120_000;
14
+ /** @internal Exported for tests. What the browser allows past the gateway's limit before giving up. */
15
+ export const GATEWAY_MARGIN_MS = 15_000;
7
16
  /**
8
17
  * @internal Exported for tests.
9
18
  *
10
- * How long each class of request may take. `standard` is past the 60 s an API behind CloudFront
11
- * gets (canopycms-cdk's `assertOriginReadTimeout`), so a server still working answers, or its
12
- * proxy's 504 does, before the editor gives up; reads get it too, since any request may first
13
- * provision the base branch's workspace (`http/handler.ts`). `long` is
14
- * for the operations that legitimately run longer: branch create, submit, admin scans and
15
- * repairs, and an upload without progress.
19
+ * How long each class of request may take. `standard` is past {@link GATEWAY_MAX_TIMEOUT_MS}, so
20
+ * a server still working answers, or its proxy's 504 does, before the editor gives up; reads get
21
+ * it too, since any request may first provision the base branch's workspace (`http/handler.ts`).
22
+ * `long` is for the operations that legitimately run longer: branch create, submit, admin scans
23
+ * and repairs, and an upload without progress.
16
24
  */
17
25
  export const REQUEST_TIMEOUT_MS = {
18
- standard: 75_000,
26
+ standard: GATEWAY_MAX_TIMEOUT_MS + GATEWAY_MARGIN_MS,
19
27
  long: 180_000,
20
28
  };
21
29
  /** @internal Exported for tests. A timed-out read's message: retrying it is safe. */
@@ -185,14 +185,14 @@ export declare const createCollection: import("./route-builder.js").RouteDefinit
185
185
  maxItems: z.ZodOptional<z.ZodNumber>;
186
186
  }, "strip", z.ZodTypeAny, {
187
187
  name: string;
188
- format: "mdx" | "md" | "json" | "yaml";
188
+ format: "md" | "mdx" | "json" | "yaml";
189
189
  schema: string;
190
190
  default?: boolean | undefined;
191
191
  label?: string | undefined;
192
192
  maxItems?: number | undefined;
193
193
  }, {
194
194
  name: string;
195
- format: "mdx" | "md" | "json" | "yaml";
195
+ format: "md" | "mdx" | "json" | "yaml";
196
196
  schema: string;
197
197
  default?: boolean | undefined;
198
198
  label?: string | undefined;
@@ -202,7 +202,7 @@ export declare const createCollection: import("./route-builder.js").RouteDefinit
202
202
  name: string;
203
203
  entries: {
204
204
  name: string;
205
- format: "mdx" | "md" | "json" | "yaml";
205
+ format: "md" | "mdx" | "json" | "yaml";
206
206
  schema: string;
207
207
  default?: boolean | undefined;
208
208
  label?: string | undefined;
@@ -214,7 +214,7 @@ export declare const createCollection: import("./route-builder.js").RouteDefinit
214
214
  name: string;
215
215
  entries: {
216
216
  name: string;
217
- format: "mdx" | "md" | "json" | "yaml";
217
+ format: "md" | "mdx" | "json" | "yaml";
218
218
  schema: string;
219
219
  default?: boolean | undefined;
220
220
  label?: string | undefined;
@@ -315,14 +315,14 @@ export declare const addEntryType: import("./route-builder.js").RouteDefinition<
315
315
  maxItems: z.ZodOptional<z.ZodNumber>;
316
316
  }, "strip", z.ZodTypeAny, {
317
317
  name: string;
318
- format: "mdx" | "md" | "json" | "yaml";
318
+ format: "md" | "mdx" | "json" | "yaml";
319
319
  schema: string;
320
320
  default?: boolean | undefined;
321
321
  label?: string | undefined;
322
322
  maxItems?: number | undefined;
323
323
  }, {
324
324
  name: string;
325
- format: "mdx" | "md" | "json" | "yaml";
325
+ format: "md" | "mdx" | "json" | "yaml";
326
326
  schema: string;
327
327
  default?: boolean | undefined;
328
328
  label?: string | undefined;
@@ -361,13 +361,13 @@ export declare const updateEntryType: import("./route-builder.js").RouteDefiniti
361
361
  maxItems: z.ZodOptional<z.ZodNumber>;
362
362
  }, "strip", z.ZodTypeAny, {
363
363
  default?: boolean | undefined;
364
- format?: "mdx" | "md" | "json" | "yaml" | undefined;
364
+ format?: "md" | "mdx" | "json" | "yaml" | undefined;
365
365
  label?: string | undefined;
366
366
  maxItems?: number | undefined;
367
367
  schema?: string | undefined;
368
368
  }, {
369
369
  default?: boolean | undefined;
370
- format?: "mdx" | "md" | "json" | "yaml" | undefined;
370
+ format?: "md" | "mdx" | "json" | "yaml" | undefined;
371
371
  label?: string | undefined;
372
372
  maxItems?: number | undefined;
373
373
  schema?: string | undefined;
@@ -482,14 +482,14 @@ export declare const SCHEMA_ROUTES: {
482
482
  maxItems: z.ZodOptional<z.ZodNumber>;
483
483
  }, "strip", z.ZodTypeAny, {
484
484
  name: string;
485
- format: "mdx" | "md" | "json" | "yaml";
485
+ format: "md" | "mdx" | "json" | "yaml";
486
486
  schema: string;
487
487
  default?: boolean | undefined;
488
488
  label?: string | undefined;
489
489
  maxItems?: number | undefined;
490
490
  }, {
491
491
  name: string;
492
- format: "mdx" | "md" | "json" | "yaml";
492
+ format: "md" | "mdx" | "json" | "yaml";
493
493
  schema: string;
494
494
  default?: boolean | undefined;
495
495
  label?: string | undefined;
@@ -499,7 +499,7 @@ export declare const SCHEMA_ROUTES: {
499
499
  name: string;
500
500
  entries: {
501
501
  name: string;
502
- format: "mdx" | "md" | "json" | "yaml";
502
+ format: "md" | "mdx" | "json" | "yaml";
503
503
  schema: string;
504
504
  default?: boolean | undefined;
505
505
  label?: string | undefined;
@@ -511,7 +511,7 @@ export declare const SCHEMA_ROUTES: {
511
511
  name: string;
512
512
  entries: {
513
513
  name: string;
514
- format: "mdx" | "md" | "json" | "yaml";
514
+ format: "md" | "mdx" | "json" | "yaml";
515
515
  schema: string;
516
516
  default?: boolean | undefined;
517
517
  label?: string | undefined;
@@ -597,14 +597,14 @@ export declare const SCHEMA_ROUTES: {
597
597
  maxItems: z.ZodOptional<z.ZodNumber>;
598
598
  }, "strip", z.ZodTypeAny, {
599
599
  name: string;
600
- format: "mdx" | "md" | "json" | "yaml";
600
+ format: "md" | "mdx" | "json" | "yaml";
601
601
  schema: string;
602
602
  default?: boolean | undefined;
603
603
  label?: string | undefined;
604
604
  maxItems?: number | undefined;
605
605
  }, {
606
606
  name: string;
607
- format: "mdx" | "md" | "json" | "yaml";
607
+ format: "md" | "mdx" | "json" | "yaml";
608
608
  schema: string;
609
609
  default?: boolean | undefined;
610
610
  label?: string | undefined;
@@ -638,13 +638,13 @@ export declare const SCHEMA_ROUTES: {
638
638
  maxItems: z.ZodOptional<z.ZodNumber>;
639
639
  }, "strip", z.ZodTypeAny, {
640
640
  default?: boolean | undefined;
641
- format?: "mdx" | "md" | "json" | "yaml" | undefined;
641
+ format?: "md" | "mdx" | "json" | "yaml" | undefined;
642
642
  label?: string | undefined;
643
643
  maxItems?: number | undefined;
644
644
  schema?: string | undefined;
645
645
  }, {
646
646
  default?: boolean | undefined;
647
- format?: "mdx" | "md" | "json" | "yaml" | undefined;
647
+ format?: "md" | "mdx" | "json" | "yaml" | undefined;
648
648
  label?: string | undefined;
649
649
  maxItems?: number | undefined;
650
650
  schema?: string | undefined;
@@ -0,0 +1,33 @@
1
+ import type { PullRequestState } from '../types.js';
2
+ /** What the review role depends on in a branch, whichever component holds it. */
3
+ export interface ReviewedBranch {
4
+ status: string | undefined;
5
+ createdBy: string | undefined;
6
+ /** Users on the branch's access list. */
7
+ users?: readonly string[];
8
+ /** Groups on the branch's access list. */
9
+ groups?: readonly string[];
10
+ /** The protected base branch, which is never approved: Withdraw recovers one stuck in review. */
11
+ isProtected?: boolean;
12
+ /** A closed pull request cannot be approved or sent back; the way forward is Withdraw. */
13
+ pullRequestState?: PullRequestState;
14
+ }
15
+ /**
16
+ * How `user` relates to `branch`'s review. A reviewer or admin who neither made the branch nor was
17
+ * given access to it by name or by group, on a submitted or approved branch that is not the
18
+ * protected base branch, is `reviewing`: Approve (on a submitted branch) and Request changes
19
+ * lead instead of Withdraw, which stays in the card's "…" menu. With a closed pull request the same user is `reviewing-closed`, since there is
20
+ * nothing to approve and Withdraw is the way forward. Anyone else is `none`.
21
+ */
22
+ export type ReviewRole = 'reviewing' | 'reviewing-closed' | 'none';
23
+ export declare function reviewRoleOf(branch: ReviewedBranch, user: {
24
+ userId: string;
25
+ groups?: readonly string[];
26
+ } | undefined): ReviewRole;
27
+ /** Whether `user` reviews `branch`, so its review actions lead; see {@link reviewRoleOf}. */
28
+ export declare const isReviewerOfOthersReview: (branch: ReviewedBranch, user: {
29
+ userId: string;
30
+ groups?: readonly string[];
31
+ } | undefined) => boolean;
32
+ /** Longest note a reviewer can attach to a request for changes; the editor's field and the API share it. */
33
+ export declare const REQUEST_CHANGES_NOTE_MAX_LENGTH = 2000;
@@ -0,0 +1,17 @@
1
+ import { isReviewer } from './helpers.js';
2
+ export function reviewRoleOf(branch, user) {
3
+ const reviews = !!user &&
4
+ isReviewer(user.groups) &&
5
+ !branch.isProtected &&
6
+ (branch.status === 'submitted' || branch.status === 'approved') &&
7
+ branch.createdBy !== user.userId &&
8
+ !branch.users?.includes(user.userId) &&
9
+ !user.groups?.some((g) => branch.groups?.includes(g));
10
+ if (!reviews)
11
+ return 'none';
12
+ return branch.pullRequestState === 'closed' ? 'reviewing-closed' : 'reviewing';
13
+ }
14
+ /** Whether `user` reviews `branch`, so its review actions lead; see {@link reviewRoleOf}. */
15
+ export const isReviewerOfOthersReview = (branch, user) => reviewRoleOf(branch, user) === 'reviewing';
16
+ /** Longest note a reviewer can attach to a request for changes; the editor's field and the API share it. */
17
+ export const REQUEST_CHANGES_NOTE_MAX_LENGTH = 2000;
@@ -51,6 +51,7 @@ export declare const branchMetadataSchema: z.ZodObject<{
51
51
  pullRequestNumber: z.ZodOptional<z.ZodNumber>;
52
52
  submittedAt: z.ZodOptional<z.ZodString>;
53
53
  pushedToGitHubAt: z.ZodOptional<z.ZodString>;
54
+ editorUrl: z.ZodOptional<z.ZodString>;
54
55
  syncStatus: z.ZodOptional<z.ZodNativeEnum<{
55
56
  synced: "synced";
56
57
  "pending-sync": "pending-sync";
@@ -115,6 +116,7 @@ export declare const branchMetadataSchema: z.ZodObject<{
115
116
  pullRequestNumber: z.ZodOptional<z.ZodNumber>;
116
117
  submittedAt: z.ZodOptional<z.ZodString>;
117
118
  pushedToGitHubAt: z.ZodOptional<z.ZodString>;
119
+ editorUrl: z.ZodOptional<z.ZodString>;
118
120
  syncStatus: z.ZodOptional<z.ZodNativeEnum<{
119
121
  synced: "synced";
120
122
  "pending-sync": "pending-sync";
@@ -179,6 +181,7 @@ export declare const branchMetadataSchema: z.ZodObject<{
179
181
  pullRequestNumber: z.ZodOptional<z.ZodNumber>;
180
182
  submittedAt: z.ZodOptional<z.ZodString>;
181
183
  pushedToGitHubAt: z.ZodOptional<z.ZodString>;
184
+ editorUrl: z.ZodOptional<z.ZodString>;
182
185
  syncStatus: z.ZodOptional<z.ZodNativeEnum<{
183
186
  synced: "synced";
184
187
  "pending-sync": "pending-sync";
@@ -60,6 +60,7 @@ const branchMetadataShape = {
60
60
  pullRequestNumber: z.number().int().optional(),
61
61
  submittedAt: z.string().optional(),
62
62
  pushedToGitHubAt: z.string().optional(),
63
+ editorUrl: z.string().optional(),
63
64
  syncStatus: enumOf({
64
65
  synced: 'synced',
65
66
  'pending-sync': 'pending-sync',