@anthusai/papyrus 2.0.0-next.8 → 2.0.0-next.80
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/amplify/data/function-handler.js +20 -0
- package/amplify/data/function-handler.ts +40 -0
- package/amplify/data/resource.js +151 -61
- package/amplify/data/resource.ts +157 -61
- package/amplify/data/schema.js +2096 -1980
- package/amplify/data/schema.ts +198 -69
- package/amplify/functions/assignment-action/data-access.js +14 -15
- package/amplify/functions/assignment-action/data-access.ts +13 -14
- package/amplify/functions/assignment-action/handler.ts +1 -1
- package/amplify/functions/automation-view/handler.py +17 -0
- package/amplify/functions/automation-view/resource.js +24 -0
- package/amplify/functions/automation-view/resource.ts +34 -0
- package/amplify/functions/automation-view/schema.js +26 -0
- package/amplify/functions/automation-view/schema.ts +28 -0
- package/amplify/functions/automation-view/wire.js +56 -0
- package/amplify/functions/automation-view/wire.ts +76 -0
- package/amplify/functions/content-actions/handler.py +61 -2
- package/amplify/functions/content-actions/requirements.txt +1 -0
- package/amplify/functions/content-actions/resource.js +1 -1
- package/amplify/functions/content-actions/resource.ts +1 -1
- package/amplify/{plugins/editorial-checks/function → functions/editorial-checks}/handler.py +3 -3
- package/amplify/functions/editorial-checks/requirements.txt +1 -0
- package/amplify/{plugins/editorial-checks/function → functions/editorial-checks}/resource.js +7 -7
- package/amplify/{plugins/editorial-checks/function → functions/editorial-checks}/resource.ts +7 -7
- package/amplify/functions/editorial-checks/schema.js +122 -0
- package/amplify/{plugins → functions}/editorial-checks/schema.ts +40 -12
- package/amplify/functions/editorial-checks/wire.js +53 -0
- package/amplify/functions/editorial-checks/wire.ts +61 -0
- package/amplify/functions/monitoring-view/handler.py +11 -0
- package/amplify/functions/monitoring-view/resource.js +24 -0
- package/amplify/functions/monitoring-view/resource.ts +34 -0
- package/amplify/functions/monitoring-view/schema.js +17 -0
- package/amplify/functions/monitoring-view/schema.ts +19 -0
- package/amplify/functions/monitoring-view/wire.js +37 -0
- package/amplify/functions/monitoring-view/wire.ts +47 -0
- package/amplify/functions/public-forms/core.js +247 -0
- package/amplify/functions/public-forms/core.ts +310 -0
- package/amplify/functions/public-forms/handler.ts +41 -0
- package/amplify/functions/public-forms/origins.js +35 -0
- package/amplify/functions/public-forms/origins.ts +43 -0
- package/amplify/functions/public-forms/resource.js +9 -0
- package/amplify/functions/public-forms/resource.ts +10 -0
- package/amplify/functions/public-forms/wire.js +25 -0
- package/amplify/functions/public-forms/wire.ts +32 -0
- package/amplify/functions/shared/editorial-context.ts +63 -4
- package/amplify/functions/shared/python-bundle.js +20 -14
- package/amplify/functions/shared/python-bundle.ts +25 -18
- package/amplify/plugins/newsletter/config.js +245 -0
- package/amplify/plugins/newsletter/config.ts +305 -0
- package/amplify/plugins/newsletter/function/handler.py +6 -0
- package/amplify/plugins/newsletter/function/requirements.txt +5 -0
- package/amplify/plugins/newsletter/ops/handler.py +12 -0
- package/amplify/plugins/newsletter/ops/resource.js +27 -0
- package/amplify/plugins/newsletter/ops/resource.ts +37 -0
- package/amplify/plugins/newsletter/papyrus.plugin.js +263 -0
- package/amplify/plugins/newsletter/papyrus.plugin.ts +311 -0
- package/amplify/plugins/newsletter/schema.js +57 -0
- package/amplify/plugins/newsletter/schema.ts +62 -0
- package/amplify/plugins/newsletter/secure-string-parameter.js +107 -0
- package/amplify/plugins/newsletter/secure-string-parameter.ts +120 -0
- package/amplify/plugins/newsletter/sending.js +140 -0
- package/amplify/plugins/newsletter/sending.ts +186 -0
- package/amplify/plugins/reader-steering/config.js +182 -0
- package/amplify/plugins/reader-steering/config.ts +290 -0
- package/amplify/plugins/reader-steering/function/ai_moderation.py +246 -0
- package/amplify/plugins/reader-steering/function/handler.py +1554 -0
- package/amplify/plugins/reader-steering/function/moderation-prompt.md +27 -0
- package/amplify/plugins/reader-steering/function/moderation.py +316 -0
- package/amplify/plugins/reader-steering/function/proposals.py +255 -0
- package/amplify/plugins/reader-steering/function/resource.js +27 -0
- package/amplify/plugins/reader-steering/function/resource.ts +35 -0
- package/amplify/plugins/reader-steering/papyrus.plugin.js +186 -0
- package/amplify/plugins/reader-steering/papyrus.plugin.ts +212 -0
- package/amplify/plugins/reader-steering/schema.js +205 -0
- package/amplify/plugins/reader-steering/schema.ts +207 -0
- package/amplify/plugins/registry.js +4 -2
- package/amplify/plugins/registry.ts +4 -2
- package/amplify/plugins/signup/schema.js +2 -1
- package/amplify/plugins/signup/schema.ts +2 -1
- package/amplify/plugins/types.ts +5 -0
- package/amplify/plugins/wire.js +1 -0
- package/amplify/plugins/wire.ts +1 -0
- package/amplify/publication/projection-lease.js +30 -0
- package/amplify/publication/projection-lease.ts +39 -0
- package/amplify/publication/redirect-and-index.js +105 -0
- package/amplify/publication/redirect-rules.js +73 -0
- package/amplify/publication/redirect-rules.ts +93 -0
- package/amplify/publication/s3-projection.js +7 -1
- package/amplify/publication/s3-projection.ts +9 -1
- package/amplify/site-backend-config.ts +18 -1
- package/amplify/site-backend-names.js +4 -2
- package/amplify/site-backend-names.ts +4 -2
- package/amplify/site-backend.js +41 -2
- package/amplify/site-backend.ts +46 -2
- package/app/api/auth/prospectus/sign-in/route.ts +4 -0
- package/app/api/newsletter/confirm/route.ts +13 -0
- package/app/api/newsletter/preferences/route.ts +13 -0
- package/app/api/newsletter/state/route.ts +9 -0
- package/app/api/newsletter/subscribe/route.ts +9 -0
- package/app/api/newsletter/unsubscribe/route.ts +13 -0
- package/app/api/newsroom/curation/context/route.ts +9 -0
- package/app/api/newsroom/curation/priming/route.ts +9 -0
- package/app/api/newsroom/curation/publication/route.ts +9 -0
- package/app/api/reader/comment/delete/route.ts +9 -0
- package/app/api/reader/comment/edit/route.ts +9 -0
- package/app/api/reader/comment/route.ts +9 -0
- package/app/api/reader/flag/route.ts +9 -0
- package/app/api/reader/handle/route.ts +9 -0
- package/app/api/reader/me/route.ts +9 -0
- package/app/api/reader/rating/route.ts +9 -0
- package/app/api/reader/report/route.ts +9 -0
- package/app/api/reader/retired/route.ts +9 -0
- package/app/api/reader/submit/route.ts +9 -0
- package/app/api/reader/vote/route.ts +9 -0
- package/bin/papyrus-infra.mjs +20 -1
- package/components/automation-panel.tsx +49 -0
- package/components/automation-run-now.tsx +97 -0
- package/components/automation-view.tsx +192 -0
- package/components/editorial-checks-admin-panel.tsx +36 -11
- package/components/moderation-panel.tsx +248 -0
- package/components/monitoring-overview-view.tsx +241 -0
- package/components/monitoring-panel.tsx +40 -0
- package/components/news-desk-client-provider.tsx +18 -18
- package/components/news-desk-taxonomy-client.ts +28 -8
- package/components/newsletter-panel.tsx +474 -0
- package/components/newsletter-sections.tsx +163 -0
- package/components/newsroom-access-gate.tsx +15 -1
- package/components/newsroom-article-editor.tsx +6 -6
- package/components/newsroom-articles-view.tsx +6 -6
- package/components/newsroom-board-view.tsx +8 -3
- package/components/newsroom-curation-bootstrap.tsx +45 -0
- package/components/newsroom-ops-overview.tsx +22 -92
- package/components/newsroom-ops-shell.tsx +2 -2
- package/components/newsroom-organizer.css +33 -0
- package/components/newsroom-overview-skeleton.tsx +25 -0
- package/components/newsroom-references-view.tsx +192 -49
- package/components/notification-center.tsx +273 -0
- package/components/publication-cyclotron-panel.tsx +15 -10
- package/components/reader-auth-state.ts +1 -1
- package/components/reference-add-entry.tsx +75 -0
- package/components/reference-curation-controls.tsx +31 -22
- package/components/reference-cyclotron-priming.tsx +58 -19
- package/components/reference-cyclotron-suggestion.tsx +10 -6
- package/components/reference-priming.tsx +14 -10
- package/components/reference-relevance-review.tsx +3 -3
- package/components/reference-section-suggestion.tsx +1 -1
- package/components/topic-steering-workspace.tsx +223 -144
- package/components/use-editorial-checks.ts +12 -10
- package/infra/amplify-app-shell.js +94 -16
- package/infra/amplify-app-shell.ts +106 -18
- package/infra/cloud-email-config.js +32 -0
- package/infra/cloud-email-config.ts +39 -0
- package/infra/cloud-email.js +57 -0
- package/infra/cloud-email.test.js +69 -0
- package/infra/cloud-email.test.ts +66 -0
- package/infra/cloud-email.ts +60 -0
- package/infra/index.js +1 -0
- package/infra/secure-string-parameter-handler.js +41 -0
- package/infra/secure-string-parameter-handler.ts +41 -0
- package/infra/secure-string-parameter.js +79 -0
- package/infra/secure-string-parameter.ts +91 -0
- package/infra/site-config.js +88 -6
- package/infra/site-config.ts +134 -6
- package/lib/automation-client.ts +54 -0
- package/lib/automation-fixture.ts +93 -0
- package/lib/automation-overview.ts +232 -0
- package/lib/category-repository.ts +11 -9
- package/lib/curation-routes.ts +345 -0
- package/lib/cyclotron-suggestions.ts +4 -4
- package/lib/editorial-checks-backend.ts +1 -1
- package/lib/editorial-checks-client.ts +19 -1
- package/lib/editorial-checks-demo.ts +2 -2
- package/lib/editorial-checks-settings.ts +3 -0
- package/lib/editorial-checks.ts +8 -11
- package/lib/editorial-preview.ts +5 -5
- package/lib/monitoring-client.ts +29 -0
- package/lib/monitoring-overview-fixture.ts +51 -0
- package/lib/monitoring-overview.ts +145 -0
- package/lib/news-desk-session.ts +12 -21
- package/lib/newsletter-api.ts +418 -0
- package/lib/newsletter-client.ts +46 -0
- package/lib/newsletter-fixture.ts +184 -0
- package/lib/newsletter-model.ts +202 -0
- package/lib/newsroom-organizer-nav.ts +2 -1
- package/lib/prospectus-session.ts +15 -14
- package/lib/prospectus-sign-in-routes.ts +84 -19
- package/lib/prospectus-site-identity.ts +24 -1
- package/lib/reader-api.ts +145 -0
- package/lib/reader-moderation.ts +220 -0
- package/lib/reader-retirement-route.ts +89 -0
- package/lib/reader-subject.md +29 -0
- package/lib/reader-subject.ts +53 -0
- package/lib/reference-review-details.ts +71 -0
- package/lib/reference-review-request.ts +14 -0
- package/lib/relevance-decisions.ts +42 -10
- package/lib/relevance-status.ts +2 -2
- package/lib/review-client.ts +99 -0
- package/lib/review-fixture.ts +45 -0
- package/lib/review-requests.ts +238 -0
- package/lib/semantic-graph.ts +2 -0
- package/lib/site-brand-tenant.ts +11 -6
- package/lib/site-brand.ts +6 -3
- package/lib/site-origin.ts +67 -0
- package/lib/use-reference-review-data.ts +44 -0
- package/middleware.ts +14 -3
- package/package.json +56 -3
- package/routes.manifest.json +215 -2
- package/amplify/plugins/editorial-checks/function/requirements.txt +0 -1
- package/amplify/plugins/editorial-checks/papyrus.plugin.js +0 -71
- package/amplify/plugins/editorial-checks/papyrus.plugin.ts +0 -87
- package/amplify/plugins/editorial-checks/schema.js +0 -94
|
@@ -7,11 +7,13 @@ import { SqsDestination } from "aws-cdk-lib/aws-lambda-destinations";
|
|
|
7
7
|
import * as route53 from "aws-cdk-lib/aws-route53";
|
|
8
8
|
import * as s3 from "aws-cdk-lib/aws-s3";
|
|
9
9
|
import * as sqs from "aws-cdk-lib/aws-sqs";
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
10
11
|
import { dirname, resolve } from "node:path";
|
|
11
12
|
import { fileURLToPath } from "node:url";
|
|
12
13
|
import { assertValidPublicationConfig } from "../site-backend-config.js";
|
|
13
14
|
import { addRenditionsFunction } from "./renditions-function.js";
|
|
14
15
|
import { RENDITIONS_FUNCTION_NAME_ENV } from "./renditions-settings.js";
|
|
16
|
+
import { compileRedirectFunctionSource, readEdgeConfig } from "./redirect-rules.js";
|
|
15
17
|
import { addInvalidationPathAlarm } from "./invalidation-alarm.js";
|
|
16
18
|
import { distributionIdFromArn, s3ProjectionEnvironment, s3ProjectionPolicyStatements } from "./s3-projection-settings.js";
|
|
17
19
|
const redirectFunctionSourcePath = resolve(dirname(fileURLToPath(import.meta.url)), "redirect-and-index.js");
|
|
@@ -68,9 +70,13 @@ export function addS3ProjectionPublication(scope, props, media) {
|
|
|
68
70
|
assertValidPublicationConfig({ kind: "s3-projection", ...props });
|
|
69
71
|
const bucket = createSiteBucket(scope, props.retainBucketOnDelete !== false);
|
|
70
72
|
const keyValueStore = new cloudfront.KeyValueStore(scope, "RedirectsKeyValueStore");
|
|
73
|
+
const edgeConfig = readEdgeConfig(props.staticDir);
|
|
71
74
|
const redirectFunction = new cloudfront.Function(scope, "RedirectAndIndexFunction", {
|
|
72
75
|
runtime: cloudfront.FunctionRuntime.JS_2_0,
|
|
73
|
-
code: cloudfront.FunctionCode.
|
|
76
|
+
code: cloudfront.FunctionCode.fromInline(compileRedirectFunctionSource(readFileSync(redirectFunctionSourcePath, "utf8"), edgeConfig.rules, {
|
|
77
|
+
negotiateMarkdown: edgeConfig.negotiateMarkdown,
|
|
78
|
+
directoryTwins: edgeConfig.directoryTwins,
|
|
79
|
+
})),
|
|
74
80
|
keyValueStore,
|
|
75
81
|
});
|
|
76
82
|
const deadLetterQueue = new sqs.Queue(scope, "ProjectionDeadLetterQueue", {
|
|
@@ -10,11 +10,13 @@ import * as route53 from "aws-cdk-lib/aws-route53";
|
|
|
10
10
|
import * as s3 from "aws-cdk-lib/aws-s3";
|
|
11
11
|
import * as sqs from "aws-cdk-lib/aws-sqs";
|
|
12
12
|
import type { Construct } from "constructs";
|
|
13
|
+
import { readFileSync } from "node:fs";
|
|
13
14
|
import { dirname, resolve } from "node:path";
|
|
14
15
|
import { fileURLToPath } from "node:url";
|
|
15
16
|
import { assertValidPublicationConfig, type PapyrusPublicationConfig } from "../site-backend-config";
|
|
16
17
|
import { addRenditionsFunction, type RenditionsFunction } from "./renditions-function";
|
|
17
18
|
import { RENDITIONS_FUNCTION_NAME_ENV, type RenditionsPlan } from "./renditions-settings";
|
|
19
|
+
import { compileRedirectFunctionSource, readEdgeConfig } from "./redirect-rules";
|
|
18
20
|
import { addInvalidationPathAlarm } from "./invalidation-alarm";
|
|
19
21
|
import { distributionIdFromArn, s3ProjectionEnvironment, s3ProjectionPolicyStatements } from "./s3-projection-settings";
|
|
20
22
|
|
|
@@ -110,9 +112,15 @@ export function addS3ProjectionPublication(
|
|
|
110
112
|
const bucket = createSiteBucket(scope, props.retainBucketOnDelete !== false);
|
|
111
113
|
|
|
112
114
|
const keyValueStore = new cloudfront.KeyValueStore(scope, "RedirectsKeyValueStore");
|
|
115
|
+
const edgeConfig = readEdgeConfig(props.staticDir);
|
|
113
116
|
const redirectFunction = new cloudfront.Function(scope, "RedirectAndIndexFunction", {
|
|
114
117
|
runtime: cloudfront.FunctionRuntime.JS_2_0,
|
|
115
|
-
code: cloudfront.FunctionCode.
|
|
118
|
+
code: cloudfront.FunctionCode.fromInline(
|
|
119
|
+
compileRedirectFunctionSource(readFileSync(redirectFunctionSourcePath, "utf8"), edgeConfig.rules, {
|
|
120
|
+
negotiateMarkdown: edgeConfig.negotiateMarkdown,
|
|
121
|
+
directoryTwins: edgeConfig.directoryTwins,
|
|
122
|
+
}),
|
|
123
|
+
),
|
|
116
124
|
keyValueStore,
|
|
117
125
|
});
|
|
118
126
|
const deadLetterQueue = new sqs.Queue(scope, "ProjectionDeadLetterQueue", {
|
|
@@ -145,6 +145,13 @@ export type PapyrusSiteBackendConfig = {
|
|
|
145
145
|
* DependsOn ordering; no resource changes. Default 12; 0 turns it off.
|
|
146
146
|
*/
|
|
147
147
|
resolverWaveSize?: number;
|
|
148
|
+
/**
|
|
149
|
+
* Optional model groups to leave out of the data API (see `OPTIONAL_MODEL_GROUPS`; today `editions`).
|
|
150
|
+
* CloudFormation allows 2,500 resources per stack operation, nested stacks included, and a fresh create of the full
|
|
151
|
+
* model set exceeds it. Deploy a new site once with a group excluded, then remove the exclusion and deploy again:
|
|
152
|
+
* the second deploy is an ordinary update that adds the models.
|
|
153
|
+
*/
|
|
154
|
+
excludeModelGroups?: string[];
|
|
148
155
|
/** Static reader app (Markus-static sites) that a publish rebuilds through IAM `amplify:StartJob`. */
|
|
149
156
|
reader?: { amplifyAppId: string; branchName?: string };
|
|
150
157
|
/** Lets the newsroom start the `staging` branch build of this CMS app. */
|
|
@@ -159,7 +166,7 @@ export type PapyrusSiteBackendConfig = {
|
|
|
159
166
|
/**
|
|
160
167
|
* SES receipt options for a site that is not the legacy p.apyr.us backend.
|
|
161
168
|
* By default the site gets its own brand-named rule set that is never
|
|
162
|
-
* activated by CloudFormation (SES allows one active rule set per region).
|
|
169
|
+
* activated by CloudFormation (SES allows one active rule set per account/region).
|
|
163
170
|
*/
|
|
164
171
|
inboundEmailSes?: {
|
|
165
172
|
/** Add this site's rule to a rule set another stack owns instead of creating one. */
|
|
@@ -178,6 +185,16 @@ export type PapyrusSiteBackendConfig = {
|
|
|
178
185
|
* Unset: no plugin, and the synthesized backend is exactly what it was before plugins existed.
|
|
179
186
|
*/
|
|
180
187
|
plugins?: PluginRequest[];
|
|
188
|
+
/**
|
|
189
|
+
* The public form receiving endpoint every site gets (docs/public-forms.md). It accepts posts only from the site's
|
|
190
|
+
* own public hosts (distribution aliases, reader domain, revalidate URL, sign-in redirect URLs) plus these.
|
|
191
|
+
*/
|
|
192
|
+
publicForms?: {
|
|
193
|
+
/** Extra https origins (or http://localhost) allowed to post, for example `https://www.example.org`. */
|
|
194
|
+
allowedOrigins?: string[];
|
|
195
|
+
/** Extra honeypot field names besides `website`. */
|
|
196
|
+
honeypotFields?: string[];
|
|
197
|
+
};
|
|
181
198
|
features?: {
|
|
182
199
|
consoleResponder?: boolean;
|
|
183
200
|
inboundEmail?: boolean;
|
|
@@ -68,8 +68,10 @@ export function deriveStorageBackupVaultName(identity, explicitName) {
|
|
|
68
68
|
/**
|
|
69
69
|
* The `papyrus-site-inbound-` prefix keeps a brand named `p-apyr-us` from
|
|
70
70
|
* colliding with the legacy `papyrus-inbound-p-apyr-us` set.
|
|
71
|
-
* SES allows one ACTIVE receipt rule set per region. A non-legacy
|
|
72
|
-
* its own brand-named rule set and never activates it from
|
|
71
|
+
* SES allows one ACTIVE receipt rule set per account and region. A non-legacy
|
|
72
|
+
* site creates its own brand-named rule set and never activates it from
|
|
73
|
+
* CloudFormation. SES accounts that receive the same domain process their
|
|
74
|
+
* matching rules independently; the limit does not span accounts.
|
|
73
75
|
*/
|
|
74
76
|
export function deriveReceiptRuleSetName(identity, inboundEmailDomain) {
|
|
75
77
|
const name = isLegacyProductionApp(identity)
|
|
@@ -109,8 +109,10 @@ export function deriveStorageBackupVaultName(identity: SiteBackendIdentity, expl
|
|
|
109
109
|
/**
|
|
110
110
|
* The `papyrus-site-inbound-` prefix keeps a brand named `p-apyr-us` from
|
|
111
111
|
* colliding with the legacy `papyrus-inbound-p-apyr-us` set.
|
|
112
|
-
* SES allows one ACTIVE receipt rule set per region. A non-legacy
|
|
113
|
-
* its own brand-named rule set and never activates it from
|
|
112
|
+
* SES allows one ACTIVE receipt rule set per account and region. A non-legacy
|
|
113
|
+
* site creates its own brand-named rule set and never activates it from
|
|
114
|
+
* CloudFormation. SES accounts that receive the same domain process their
|
|
115
|
+
* matching rules independently; the limit does not span accounts.
|
|
114
116
|
*/
|
|
115
117
|
export function deriveReceiptRuleSetName(identity: SiteBackendIdentity, inboundEmailDomain: string): string {
|
|
116
118
|
const name = isLegacyProductionApp(identity)
|
package/amplify/site-backend.js
CHANGED
|
@@ -11,6 +11,7 @@ import { resolveSitePublication } from "./publication/default-publication.js";
|
|
|
11
11
|
import { REPROJECT_ON_DEPLOY_TIMEOUT_SECONDS, addReprojectOnDeploy, reprojectDeployToken } from "./publication/reproject-on-deploy.js";
|
|
12
12
|
import { addProjectionRetries, addS3ProjectionPublication } from "./publication/s3-projection.js";
|
|
13
13
|
import { planRenditions } from "./publication/renditions-settings.js";
|
|
14
|
+
import { addProjectionLeaseAccess } from "./publication/projection-lease.js";
|
|
14
15
|
import { contentActionsPublicationWiring, planS3ProjectionBackend } from "./publication/s3-projection-settings.js";
|
|
15
16
|
import { rebuildTriggerSettings } from "./rebuild-trigger-settings.js";
|
|
16
17
|
import { assertValidPublicationConfig } from "./site-backend-config.js";
|
|
@@ -20,6 +21,12 @@ import { addInvalidationPathAlarm } from "./publication/invalidation-alarm.js";
|
|
|
20
21
|
import { applyCognitoDomainPrefix, authConfigFromEnv, defineSiteAuth, siteAuthRedirectUrls } from "./auth/resource.js";
|
|
21
22
|
import { PROSPECTUS_SIGN_IN_CALLBACK_PATH, addProspectusGoogleOnlyClient } from "./auth/prospectus-google-client.js";
|
|
22
23
|
import { defineSiteData } from "./data/resource.js";
|
|
24
|
+
import { editorialChecks } from "./functions/editorial-checks/resource.js";
|
|
25
|
+
import { automationView } from "./functions/automation-view/resource.js";
|
|
26
|
+
import { wireAutomationView } from "./functions/automation-view/wire.js";
|
|
27
|
+
import { monitoringView } from "./functions/monitoring-view/resource.js";
|
|
28
|
+
import { wireMonitoringView } from "./functions/monitoring-view/wire.js";
|
|
29
|
+
import { wireEditorialChecks } from "./functions/editorial-checks/wire.js";
|
|
23
30
|
import { resolvePlugins } from "./plugins/registry.js";
|
|
24
31
|
import { wirePlugins } from "./plugins/wire.js";
|
|
25
32
|
import { assignmentAction } from "./functions/assignment-action/resource.js";
|
|
@@ -31,6 +38,9 @@ import { knowledgeQuery } from "./functions/knowledge-query/resource.js";
|
|
|
31
38
|
import { manageUserRole } from "./functions/manage-user-role/resource.js";
|
|
32
39
|
import { modelAttachmentUpload } from "./functions/model-attachment-upload/resource.js";
|
|
33
40
|
import { newsroomSummary } from "./functions/newsroom-summary/resource.js";
|
|
41
|
+
import { derivePublicFormOrigins } from "./functions/public-forms/origins.js";
|
|
42
|
+
import { publicForms } from "./functions/public-forms/resource.js";
|
|
43
|
+
import { wirePublicForms } from "./functions/public-forms/wire.js";
|
|
34
44
|
import { procedureAction } from "./functions/procedure-action/resource.js";
|
|
35
45
|
import { readerSettings } from "./functions/reader-settings/resource.js";
|
|
36
46
|
import { emailSubmissionProcessor } from "./functions/email-submission-processor/resource.js";
|
|
@@ -86,15 +96,19 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
86
96
|
const backend = defineBackend({
|
|
87
97
|
...pluginFunctions,
|
|
88
98
|
assignmentAction,
|
|
99
|
+
automationView,
|
|
89
100
|
auth: defineSiteAuth(authConfig),
|
|
90
101
|
categoryAction,
|
|
91
102
|
contentActions,
|
|
92
|
-
|
|
103
|
+
editorialChecks,
|
|
104
|
+
data: defineSiteData(pluginDefinitions, site.excludeModelGroups ?? []),
|
|
93
105
|
knowledgeQuery,
|
|
94
106
|
manageUserRole,
|
|
107
|
+
monitoringView,
|
|
95
108
|
modelAttachmentUpload,
|
|
96
109
|
newsroomSummary,
|
|
97
110
|
procedureAction,
|
|
111
|
+
publicForms,
|
|
98
112
|
readerSettings,
|
|
99
113
|
emailSubmissionProcessor,
|
|
100
114
|
sesInboundReceive,
|
|
@@ -310,6 +324,14 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
310
324
|
grantNewsroomReadWrite(backend.newsroomSummary.resources.lambda);
|
|
311
325
|
const contentActionsLambda = backend.contentActions.resources.lambda;
|
|
312
326
|
grantNewsroomReadWriteDelete(contentActionsLambda);
|
|
327
|
+
if ((activeBrand?.corpusKey ?? "").trim() !== "") {
|
|
328
|
+
// A deploy creates the publication's canonical corpus from the brand when the backend has none.
|
|
329
|
+
contentActionsLambda.addEnvironment("PAPYRUS_PUBLICATION_CORPUS_KEY", (activeBrand?.corpusKey ?? "").trim());
|
|
330
|
+
contentActionsLambda.addEnvironment("PAPYRUS_PUBLICATION_NAME", (activeBrand?.publicationName ?? activeBrand?.corpusKey ?? "").trim());
|
|
331
|
+
}
|
|
332
|
+
// AppSync validates the token; pending intake additionally binds its actor
|
|
333
|
+
// and publication to this deployment's pool and existing API endpoint.
|
|
334
|
+
contentActionsLambda.addEnvironment("PAPYRUS_USER_POOL_ISSUER", `https://cognito-idp.${Stack.of(contentActionsLambda).region}.amazonaws.com/${backend.auth.resources.userPool.userPoolId}`);
|
|
313
335
|
contentActionsLambda.addEnvironment("PAPYRUS_GRAPHQL_ENDPOINT", backend.data.resources.cfnResources.cfnGraphqlApi.attrGraphQlUrl);
|
|
314
336
|
contentActionsLambda.addToRolePolicy(new PolicyStatement({
|
|
315
337
|
actions: ["appsync:GraphQL"],
|
|
@@ -342,6 +364,7 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
342
364
|
}
|
|
343
365
|
if (s3ProjectionPublication !== undefined) {
|
|
344
366
|
addProjectionRetries(contentActionsLambda, s3ProjectionPublication.deadLetterQueue);
|
|
367
|
+
addProjectionLeaseAccess(contentActionsLambda);
|
|
345
368
|
}
|
|
346
369
|
const publicationWiring = contentActionsPublicationWiring(s3ProjectionPublication);
|
|
347
370
|
for (const [name, value] of Object.entries(publicationWiring.environment)) {
|
|
@@ -446,7 +469,7 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
446
469
|
resources: ["*"],
|
|
447
470
|
}));
|
|
448
471
|
const inboundEventStack = Stack.of(receiveLambda);
|
|
449
|
-
// SES allows one active receipt rule set per region, so a non-legacy site
|
|
472
|
+
// SES allows one active receipt rule set per account and region, so a non-legacy site
|
|
450
473
|
// creates its own brand-named rule set and never activates it here.
|
|
451
474
|
const inboundSesPlan = planInboundEmailSes(siteBackendIdentity, enableInboundEmail, site.inboundEmailSes);
|
|
452
475
|
if (inboundSesPlan.createReceiptRules) {
|
|
@@ -550,8 +573,21 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
550
573
|
: []),
|
|
551
574
|
],
|
|
552
575
|
}));
|
|
576
|
+
const publicFormsEndpoint = wirePublicForms(backend, {
|
|
577
|
+
allowedOrigins: derivePublicFormOrigins({
|
|
578
|
+
explicit: site.publicForms?.allowedOrigins,
|
|
579
|
+
hosts: [activeBrand?.readerDeployment?.domain, ...(publication?.distribution?.aliases ?? [])],
|
|
580
|
+
urls: [site.revalidateBaseUrl, ...siteAuthRedirectUrls(authConfig)],
|
|
581
|
+
}),
|
|
582
|
+
honeypotFields: site.publicForms?.honeypotFields,
|
|
583
|
+
});
|
|
553
584
|
backend.addOutput({
|
|
554
585
|
custom: {
|
|
586
|
+
publicForms: { endpoint: publicFormsEndpoint },
|
|
587
|
+
// Lets the operator CLI re-project on publish without PAPYRUS_PUBLICATION_KIND / PAPYRUS_CONTENT_ACTIONS_FUNCTION (PPY-0c0b75).
|
|
588
|
+
publication: s3ProjectionPublication !== undefined
|
|
589
|
+
? { kind: "s3-projection", contentActionsFunction: contentActionsLambda.functionName }
|
|
590
|
+
: null,
|
|
555
591
|
prospectusSignIn: prospectusGoogleOnlyClient
|
|
556
592
|
? { clientId: prospectusGoogleOnlyClient.ref, callbackPath: PROSPECTUS_SIGN_IN_CALLBACK_PATH }
|
|
557
593
|
: null,
|
|
@@ -586,6 +622,9 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
586
622
|
: null,
|
|
587
623
|
},
|
|
588
624
|
});
|
|
625
|
+
wireEditorialChecks(backend);
|
|
626
|
+
wireMonitoringView(backend);
|
|
627
|
+
wireAutomationView(backend);
|
|
589
628
|
wirePlugins(backend, plugins, contentActionsLambda);
|
|
590
629
|
return backend;
|
|
591
630
|
}
|
package/amplify/site-backend.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { resolveSitePublication } from "./publication/default-publication";
|
|
|
14
14
|
import { REPROJECT_ON_DEPLOY_TIMEOUT_SECONDS, addReprojectOnDeploy, reprojectDeployToken } from "./publication/reproject-on-deploy";
|
|
15
15
|
import { addProjectionRetries, addS3ProjectionPublication, type S3ProjectionPublication } from "./publication/s3-projection";
|
|
16
16
|
import { planRenditions } from "./publication/renditions-settings";
|
|
17
|
+
import { addProjectionLeaseAccess } from "./publication/projection-lease";
|
|
17
18
|
import { contentActionsPublicationWiring, planS3ProjectionBackend } from "./publication/s3-projection-settings";
|
|
18
19
|
import { rebuildTriggerSettings } from "./rebuild-trigger-settings";
|
|
19
20
|
import { assertValidPublicationConfig } from "./site-backend-config";
|
|
@@ -27,6 +28,12 @@ import { addInvalidationPathAlarm } from "./publication/invalidation-alarm";
|
|
|
27
28
|
import { applyCognitoDomainPrefix, authConfigFromEnv, defineSiteAuth, siteAuthRedirectUrls } from "./auth/resource";
|
|
28
29
|
import { PROSPECTUS_SIGN_IN_CALLBACK_PATH, addProspectusGoogleOnlyClient } from "./auth/prospectus-google-client";
|
|
29
30
|
import { defineSiteData } from "./data/resource";
|
|
31
|
+
import { editorialChecks } from "./functions/editorial-checks/resource";
|
|
32
|
+
import { automationView } from "./functions/automation-view/resource";
|
|
33
|
+
import { wireAutomationView } from "./functions/automation-view/wire";
|
|
34
|
+
import { monitoringView } from "./functions/monitoring-view/resource";
|
|
35
|
+
import { wireMonitoringView } from "./functions/monitoring-view/wire";
|
|
36
|
+
import { wireEditorialChecks } from "./functions/editorial-checks/wire";
|
|
30
37
|
import { resolvePlugins } from "./plugins/registry";
|
|
31
38
|
import { wirePlugins } from "./plugins/wire";
|
|
32
39
|
import { assignmentAction } from "./functions/assignment-action/resource";
|
|
@@ -38,6 +45,9 @@ import { knowledgeQuery } from "./functions/knowledge-query/resource";
|
|
|
38
45
|
import { manageUserRole } from "./functions/manage-user-role/resource";
|
|
39
46
|
import { modelAttachmentUpload } from "./functions/model-attachment-upload/resource";
|
|
40
47
|
import { newsroomSummary } from "./functions/newsroom-summary/resource";
|
|
48
|
+
import { derivePublicFormOrigins } from "./functions/public-forms/origins";
|
|
49
|
+
import { publicForms } from "./functions/public-forms/resource";
|
|
50
|
+
import { wirePublicForms } from "./functions/public-forms/wire";
|
|
41
51
|
import { procedureAction } from "./functions/procedure-action/resource";
|
|
42
52
|
import { readerSettings } from "./functions/reader-settings/resource";
|
|
43
53
|
import { emailSubmissionProcessor } from "./functions/email-submission-processor/resource";
|
|
@@ -107,15 +117,19 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
107
117
|
const backend = defineBackend({
|
|
108
118
|
...pluginFunctions,
|
|
109
119
|
assignmentAction,
|
|
120
|
+
automationView,
|
|
110
121
|
auth: defineSiteAuth(authConfig),
|
|
111
122
|
categoryAction,
|
|
112
123
|
contentActions,
|
|
113
|
-
|
|
124
|
+
editorialChecks,
|
|
125
|
+
data: defineSiteData(pluginDefinitions, site.excludeModelGroups ?? []),
|
|
114
126
|
knowledgeQuery,
|
|
115
127
|
manageUserRole,
|
|
128
|
+
monitoringView,
|
|
116
129
|
modelAttachmentUpload,
|
|
117
130
|
newsroomSummary,
|
|
118
131
|
procedureAction,
|
|
132
|
+
publicForms,
|
|
119
133
|
readerSettings,
|
|
120
134
|
emailSubmissionProcessor,
|
|
121
135
|
sesInboundReceive,
|
|
@@ -396,6 +410,17 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
396
410
|
grantNewsroomReadWrite(backend.newsroomSummary.resources.lambda as LambdaFunction);
|
|
397
411
|
const contentActionsLambda = backend.contentActions.resources.lambda as LambdaFunction;
|
|
398
412
|
grantNewsroomReadWriteDelete(contentActionsLambda);
|
|
413
|
+
if ((activeBrand?.corpusKey ?? "").trim() !== "") {
|
|
414
|
+
// A deploy creates the publication's canonical corpus from the brand when the backend has none.
|
|
415
|
+
contentActionsLambda.addEnvironment("PAPYRUS_PUBLICATION_CORPUS_KEY", (activeBrand?.corpusKey ?? "").trim());
|
|
416
|
+
contentActionsLambda.addEnvironment("PAPYRUS_PUBLICATION_NAME", (activeBrand?.publicationName ?? activeBrand?.corpusKey ?? "").trim());
|
|
417
|
+
}
|
|
418
|
+
// AppSync validates the token; pending intake additionally binds its actor
|
|
419
|
+
// and publication to this deployment's pool and existing API endpoint.
|
|
420
|
+
contentActionsLambda.addEnvironment(
|
|
421
|
+
"PAPYRUS_USER_POOL_ISSUER",
|
|
422
|
+
`https://cognito-idp.${Stack.of(contentActionsLambda).region}.amazonaws.com/${backend.auth.resources.userPool.userPoolId}`,
|
|
423
|
+
);
|
|
399
424
|
contentActionsLambda.addEnvironment(
|
|
400
425
|
"PAPYRUS_GRAPHQL_ENDPOINT",
|
|
401
426
|
backend.data.resources.cfnResources.cfnGraphqlApi.attrGraphQlUrl,
|
|
@@ -435,6 +460,7 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
435
460
|
}
|
|
436
461
|
if (s3ProjectionPublication !== undefined) {
|
|
437
462
|
addProjectionRetries(contentActionsLambda, s3ProjectionPublication.deadLetterQueue);
|
|
463
|
+
addProjectionLeaseAccess(contentActionsLambda);
|
|
438
464
|
}
|
|
439
465
|
const publicationWiring = contentActionsPublicationWiring(s3ProjectionPublication);
|
|
440
466
|
for (const [name, value] of Object.entries(publicationWiring.environment)) {
|
|
@@ -575,7 +601,7 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
575
601
|
|
|
576
602
|
const inboundEventStack = Stack.of(receiveLambda);
|
|
577
603
|
|
|
578
|
-
// SES allows one active receipt rule set per region, so a non-legacy site
|
|
604
|
+
// SES allows one active receipt rule set per account and region, so a non-legacy site
|
|
579
605
|
// creates its own brand-named rule set and never activates it here.
|
|
580
606
|
const inboundSesPlan = planInboundEmailSes(siteBackendIdentity, enableInboundEmail, site.inboundEmailSes);
|
|
581
607
|
if (inboundSesPlan.createReceiptRules) {
|
|
@@ -690,8 +716,23 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
690
716
|
}),
|
|
691
717
|
);
|
|
692
718
|
|
|
719
|
+
const publicFormsEndpoint = wirePublicForms(backend, {
|
|
720
|
+
allowedOrigins: derivePublicFormOrigins({
|
|
721
|
+
explicit: site.publicForms?.allowedOrigins,
|
|
722
|
+
hosts: [activeBrand?.readerDeployment?.domain, ...(publication?.distribution?.aliases ?? [])],
|
|
723
|
+
urls: [site.revalidateBaseUrl, ...siteAuthRedirectUrls(authConfig)],
|
|
724
|
+
}),
|
|
725
|
+
honeypotFields: site.publicForms?.honeypotFields,
|
|
726
|
+
});
|
|
727
|
+
|
|
693
728
|
backend.addOutput({
|
|
694
729
|
custom: {
|
|
730
|
+
publicForms: { endpoint: publicFormsEndpoint },
|
|
731
|
+
// Lets the operator CLI re-project on publish without PAPYRUS_PUBLICATION_KIND / PAPYRUS_CONTENT_ACTIONS_FUNCTION (PPY-0c0b75).
|
|
732
|
+
publication:
|
|
733
|
+
s3ProjectionPublication !== undefined
|
|
734
|
+
? { kind: "s3-projection", contentActionsFunction: contentActionsLambda.functionName }
|
|
735
|
+
: null,
|
|
695
736
|
prospectusSignIn: prospectusGoogleOnlyClient
|
|
696
737
|
? { clientId: prospectusGoogleOnlyClient.ref, callbackPath: PROSPECTUS_SIGN_IN_CALLBACK_PATH }
|
|
697
738
|
: null,
|
|
@@ -726,6 +767,9 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
726
767
|
: null,
|
|
727
768
|
},
|
|
728
769
|
});
|
|
770
|
+
wireEditorialChecks(backend);
|
|
771
|
+
wireMonitoringView(backend);
|
|
772
|
+
wireAutomationView(backend);
|
|
729
773
|
wirePlugins(backend, plugins, contentActionsLambda);
|
|
730
774
|
|
|
731
775
|
return backend;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleNewsletterConfirm } from "../../../../lib/newsletter-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function GET(request: NextRequest) {
|
|
8
|
+
return handleNewsletterConfirm(request);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function POST(request: NextRequest) {
|
|
12
|
+
return handleNewsletterConfirm(request);
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleNewsletterPreferences } from "../../../../lib/newsletter-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function GET(request: NextRequest) {
|
|
8
|
+
return handleNewsletterPreferences(request);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function POST(request: NextRequest) {
|
|
12
|
+
return handleNewsletterPreferences(request);
|
|
13
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleNewsletterState } from "../../../../lib/newsletter-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function GET(request: NextRequest) {
|
|
8
|
+
return handleNewsletterState(request);
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleNewsletterSubscribe } from "../../../../lib/newsletter-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function POST(request: NextRequest) {
|
|
8
|
+
return handleNewsletterSubscribe(request);
|
|
9
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleNewsletterUnsubscribe } from "../../../../lib/newsletter-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function GET(request: NextRequest) {
|
|
8
|
+
return handleNewsletterUnsubscribe(request);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function POST(request: NextRequest) {
|
|
12
|
+
return handleNewsletterUnsubscribe(request);
|
|
13
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleCurationRoute } from "../../../../../lib/curation-routes";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function GET(request: NextRequest) {
|
|
8
|
+
return handleCurationRoute(request, "context");
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleCurationRoute } from "../../../../../lib/curation-routes";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function POST(request: NextRequest) {
|
|
8
|
+
return handleCurationRoute(request, "priming");
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleCurationRoute } from "../../../../../lib/curation-routes";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function POST(request: NextRequest) {
|
|
8
|
+
return handleCurationRoute(request, "publication");
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleReaderRequest } from "../../../../../lib/reader-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function POST(request: NextRequest) {
|
|
8
|
+
return handleReaderRequest(request, "comment-delete");
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleReaderRequest } from "../../../../../lib/reader-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function POST(request: NextRequest) {
|
|
8
|
+
return handleReaderRequest(request, "comment-edit");
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleReaderRequest } from "../../../../lib/reader-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function POST(request: NextRequest) {
|
|
8
|
+
return handleReaderRequest(request, "comment");
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleReaderRequest } from "../../../../lib/reader-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function POST(request: NextRequest) {
|
|
8
|
+
return handleReaderRequest(request, "flag");
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleReaderRequest } from "../../../../lib/reader-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function POST(request: NextRequest) {
|
|
8
|
+
return handleReaderRequest(request, "handle");
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleReaderRequest } from "../../../../lib/reader-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function GET(request: NextRequest) {
|
|
8
|
+
return handleReaderRequest(request, "me");
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleReaderRequest } from "../../../../lib/reader-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function POST(request: NextRequest) {
|
|
8
|
+
return handleReaderRequest(request, "rating");
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleReaderRequest } from "../../../../lib/reader-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function POST(request: NextRequest) {
|
|
8
|
+
return handleReaderRequest(request, "report");
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleReaderRetiredSubjects } from "../../../../lib/reader-retirement-route";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function GET(request: NextRequest) {
|
|
8
|
+
return handleReaderRetiredSubjects(request);
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleReaderRequest } from "../../../../lib/reader-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function POST(request: NextRequest) {
|
|
8
|
+
return handleReaderRequest(request, "submit");
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NextRequest } from "next/server";
|
|
2
|
+
import { handleReaderRequest } from "../../../../lib/reader-api";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export function POST(request: NextRequest) {
|
|
8
|
+
return handleReaderRequest(request, "vote");
|
|
9
|
+
}
|
package/bin/papyrus-infra.mjs
CHANGED
|
@@ -19,6 +19,7 @@ const USAGE = [
|
|
|
19
19
|
" papyrus-infra synth --account-stack github-oidc [--out cdk.out] [--account A] [--region R]",
|
|
20
20
|
" papyrus-infra print-buildspec --site infra/site.json --app cms-production|cms-staging|reader",
|
|
21
21
|
" papyrus-infra deploy-edge --stack NAME --template FILE [--adoption-template FILE --adopt-resources FILE] [--parameter KEY=VALUE]... [--delete-function NAME] [--only-branch main] [--only-app-id ID] [--region R]",
|
|
22
|
+
" papyrus-infra compile-edge-function --static-dir web [--out FILE]",
|
|
22
23
|
" papyrus-infra deploy --site infra/site.json [--only-branch main] [--only-app-id ID] [--out cdk.out] [--account A] [--region R]",
|
|
23
24
|
].join("\n");
|
|
24
25
|
|
|
@@ -36,11 +37,29 @@ const resolveEnvironmentOrExit = () => {
|
|
|
36
37
|
}
|
|
37
38
|
};
|
|
38
39
|
const command = args[0];
|
|
39
|
-
if (command !== "synth" && command !== "print-buildspec" && command !== "deploy" && command !== "deploy-edge") {
|
|
40
|
+
if (command !== "synth" && command !== "print-buildspec" && command !== "deploy" && command !== "deploy-edge" && command !== "compile-edge-function") {
|
|
40
41
|
console.error(USAGE);
|
|
41
42
|
process.exit(command ? 1 : 0);
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
if (command === "compile-edge-function") {
|
|
46
|
+
// The viewer-request CloudFront Function with the site's projection.json rules compiled in: for an edge stack that is
|
|
47
|
+
// not deployed by the CMS backend, so that no site writes its own redirect function.
|
|
48
|
+
const staticDir = opt("static-dir");
|
|
49
|
+
if (!staticDir) {
|
|
50
|
+
console.error(USAGE);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
const { compileRedirectFunctionSource, readEdgeConfig } = await import("../amplify/publication/redirect-rules.js");
|
|
54
|
+
const functionSource = fs.readFileSync(new URL("../amplify/publication/redirect-and-index.js", import.meta.url), "utf8");
|
|
55
|
+
const config = readEdgeConfig(staticDir);
|
|
56
|
+
const compiled = compileRedirectFunctionSource(functionSource, config.rules, { negotiateMarkdown: config.negotiateMarkdown, directoryTwins: config.directoryTwins });
|
|
57
|
+
const out = opt("out");
|
|
58
|
+
if (out) fs.writeFileSync(path.resolve(out), compiled);
|
|
59
|
+
else process.stdout.write(compiled);
|
|
60
|
+
process.exit(0);
|
|
61
|
+
}
|
|
62
|
+
|
|
44
63
|
if (command === "deploy-edge") {
|
|
45
64
|
const buildAppId = process.env.AWS_APP_ID;
|
|
46
65
|
const buildBranch = process.env.AWS_BRANCH;
|