@anthusai/papyrus 2.0.0-next.8 → 2.0.0-next.81
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/auth/resource.js +16 -1
- package/amplify/auth/resource.ts +19 -1
- 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 +45 -3
- package/amplify/site-backend.ts +51 -3
- 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,15 +11,22 @@ 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";
|
|
17
18
|
import { revalidateSecretReadStatement } from "./revalidate-secret-policy.js";
|
|
18
19
|
import { revalidateDistributionEnvironment, revalidateInvalidationStatement, validateRevalidateDistributionIds, } from "./revalidate-invalidation-settings.js";
|
|
19
20
|
import { addInvalidationPathAlarm } from "./publication/invalidation-alarm.js";
|
|
20
|
-
import { applyCognitoDomainPrefix, authConfigFromEnv, defineSiteAuth, siteAuthRedirectUrls } from "./auth/resource.js";
|
|
21
|
+
import { applyCognitoDomainPrefix, applyGoogleEmailVerifiedMapping, 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,
|
|
@@ -102,6 +116,9 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
102
116
|
slackDelivery,
|
|
103
117
|
storage,
|
|
104
118
|
});
|
|
119
|
+
if (authConfig.disableGoogleOAuth !== true) {
|
|
120
|
+
applyGoogleEmailVerifiedMapping(backend.auth.stack);
|
|
121
|
+
}
|
|
105
122
|
orderModelStacksInWaves(backend.data.resources.graphqlApi.node.scope, Object.keys(backend.data.resources.tables), site.resolverWaveSize ?? DEFAULT_RESOLVER_WAVE_SIZE);
|
|
106
123
|
const requestedCognitoDomainPrefix = (authConfig.cognitoDomainPrefix ?? "").trim();
|
|
107
124
|
if (authConfig.applyCognitoDomainPrefix === true
|
|
@@ -310,6 +327,14 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
310
327
|
grantNewsroomReadWrite(backend.newsroomSummary.resources.lambda);
|
|
311
328
|
const contentActionsLambda = backend.contentActions.resources.lambda;
|
|
312
329
|
grantNewsroomReadWriteDelete(contentActionsLambda);
|
|
330
|
+
if ((activeBrand?.corpusKey ?? "").trim() !== "") {
|
|
331
|
+
// A deploy creates the publication's canonical corpus from the brand when the backend has none.
|
|
332
|
+
contentActionsLambda.addEnvironment("PAPYRUS_PUBLICATION_CORPUS_KEY", (activeBrand?.corpusKey ?? "").trim());
|
|
333
|
+
contentActionsLambda.addEnvironment("PAPYRUS_PUBLICATION_NAME", (activeBrand?.publicationName ?? activeBrand?.corpusKey ?? "").trim());
|
|
334
|
+
}
|
|
335
|
+
// AppSync validates the token; pending intake additionally binds its actor
|
|
336
|
+
// and publication to this deployment's pool and existing API endpoint.
|
|
337
|
+
contentActionsLambda.addEnvironment("PAPYRUS_USER_POOL_ISSUER", `https://cognito-idp.${Stack.of(contentActionsLambda).region}.amazonaws.com/${backend.auth.resources.userPool.userPoolId}`);
|
|
313
338
|
contentActionsLambda.addEnvironment("PAPYRUS_GRAPHQL_ENDPOINT", backend.data.resources.cfnResources.cfnGraphqlApi.attrGraphQlUrl);
|
|
314
339
|
contentActionsLambda.addToRolePolicy(new PolicyStatement({
|
|
315
340
|
actions: ["appsync:GraphQL"],
|
|
@@ -342,6 +367,7 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
342
367
|
}
|
|
343
368
|
if (s3ProjectionPublication !== undefined) {
|
|
344
369
|
addProjectionRetries(contentActionsLambda, s3ProjectionPublication.deadLetterQueue);
|
|
370
|
+
addProjectionLeaseAccess(contentActionsLambda);
|
|
345
371
|
}
|
|
346
372
|
const publicationWiring = contentActionsPublicationWiring(s3ProjectionPublication);
|
|
347
373
|
for (const [name, value] of Object.entries(publicationWiring.environment)) {
|
|
@@ -446,7 +472,7 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
446
472
|
resources: ["*"],
|
|
447
473
|
}));
|
|
448
474
|
const inboundEventStack = Stack.of(receiveLambda);
|
|
449
|
-
// SES allows one active receipt rule set per region, so a non-legacy site
|
|
475
|
+
// SES allows one active receipt rule set per account and region, so a non-legacy site
|
|
450
476
|
// creates its own brand-named rule set and never activates it here.
|
|
451
477
|
const inboundSesPlan = planInboundEmailSes(siteBackendIdentity, enableInboundEmail, site.inboundEmailSes);
|
|
452
478
|
if (inboundSesPlan.createReceiptRules) {
|
|
@@ -550,8 +576,21 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
550
576
|
: []),
|
|
551
577
|
],
|
|
552
578
|
}));
|
|
579
|
+
const publicFormsEndpoint = wirePublicForms(backend, {
|
|
580
|
+
allowedOrigins: derivePublicFormOrigins({
|
|
581
|
+
explicit: site.publicForms?.allowedOrigins,
|
|
582
|
+
hosts: [activeBrand?.readerDeployment?.domain, ...(publication?.distribution?.aliases ?? [])],
|
|
583
|
+
urls: [site.revalidateBaseUrl, ...siteAuthRedirectUrls(authConfig)],
|
|
584
|
+
}),
|
|
585
|
+
honeypotFields: site.publicForms?.honeypotFields,
|
|
586
|
+
});
|
|
553
587
|
backend.addOutput({
|
|
554
588
|
custom: {
|
|
589
|
+
publicForms: { endpoint: publicFormsEndpoint },
|
|
590
|
+
// Lets the operator CLI re-project on publish without PAPYRUS_PUBLICATION_KIND / PAPYRUS_CONTENT_ACTIONS_FUNCTION (PPY-0c0b75).
|
|
591
|
+
publication: s3ProjectionPublication !== undefined
|
|
592
|
+
? { kind: "s3-projection", contentActionsFunction: contentActionsLambda.functionName }
|
|
593
|
+
: null,
|
|
555
594
|
prospectusSignIn: prospectusGoogleOnlyClient
|
|
556
595
|
? { clientId: prospectusGoogleOnlyClient.ref, callbackPath: PROSPECTUS_SIGN_IN_CALLBACK_PATH }
|
|
557
596
|
: null,
|
|
@@ -586,6 +625,9 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
586
625
|
: null,
|
|
587
626
|
},
|
|
588
627
|
});
|
|
628
|
+
wireEditorialChecks(backend);
|
|
629
|
+
wireMonitoringView(backend);
|
|
630
|
+
wireAutomationView(backend);
|
|
589
631
|
wirePlugins(backend, plugins, contentActionsLambda);
|
|
590
632
|
return backend;
|
|
591
633
|
}
|
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";
|
|
@@ -24,9 +25,15 @@ import {
|
|
|
24
25
|
validateRevalidateDistributionIds,
|
|
25
26
|
} from "./revalidate-invalidation-settings";
|
|
26
27
|
import { addInvalidationPathAlarm } from "./publication/invalidation-alarm";
|
|
27
|
-
import { applyCognitoDomainPrefix, authConfigFromEnv, defineSiteAuth, siteAuthRedirectUrls } from "./auth/resource";
|
|
28
|
+
import { applyCognitoDomainPrefix, applyGoogleEmailVerifiedMapping, 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,
|
|
@@ -124,6 +138,10 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
124
138
|
storage,
|
|
125
139
|
});
|
|
126
140
|
|
|
141
|
+
if (authConfig.disableGoogleOAuth !== true) {
|
|
142
|
+
applyGoogleEmailVerifiedMapping(backend.auth.stack);
|
|
143
|
+
}
|
|
144
|
+
|
|
127
145
|
orderModelStacksInWaves(
|
|
128
146
|
backend.data.resources.graphqlApi.node.scope as Construct,
|
|
129
147
|
Object.keys(backend.data.resources.tables),
|
|
@@ -396,6 +414,17 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
396
414
|
grantNewsroomReadWrite(backend.newsroomSummary.resources.lambda as LambdaFunction);
|
|
397
415
|
const contentActionsLambda = backend.contentActions.resources.lambda as LambdaFunction;
|
|
398
416
|
grantNewsroomReadWriteDelete(contentActionsLambda);
|
|
417
|
+
if ((activeBrand?.corpusKey ?? "").trim() !== "") {
|
|
418
|
+
// A deploy creates the publication's canonical corpus from the brand when the backend has none.
|
|
419
|
+
contentActionsLambda.addEnvironment("PAPYRUS_PUBLICATION_CORPUS_KEY", (activeBrand?.corpusKey ?? "").trim());
|
|
420
|
+
contentActionsLambda.addEnvironment("PAPYRUS_PUBLICATION_NAME", (activeBrand?.publicationName ?? activeBrand?.corpusKey ?? "").trim());
|
|
421
|
+
}
|
|
422
|
+
// AppSync validates the token; pending intake additionally binds its actor
|
|
423
|
+
// and publication to this deployment's pool and existing API endpoint.
|
|
424
|
+
contentActionsLambda.addEnvironment(
|
|
425
|
+
"PAPYRUS_USER_POOL_ISSUER",
|
|
426
|
+
`https://cognito-idp.${Stack.of(contentActionsLambda).region}.amazonaws.com/${backend.auth.resources.userPool.userPoolId}`,
|
|
427
|
+
);
|
|
399
428
|
contentActionsLambda.addEnvironment(
|
|
400
429
|
"PAPYRUS_GRAPHQL_ENDPOINT",
|
|
401
430
|
backend.data.resources.cfnResources.cfnGraphqlApi.attrGraphQlUrl,
|
|
@@ -435,6 +464,7 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
435
464
|
}
|
|
436
465
|
if (s3ProjectionPublication !== undefined) {
|
|
437
466
|
addProjectionRetries(contentActionsLambda, s3ProjectionPublication.deadLetterQueue);
|
|
467
|
+
addProjectionLeaseAccess(contentActionsLambda);
|
|
438
468
|
}
|
|
439
469
|
const publicationWiring = contentActionsPublicationWiring(s3ProjectionPublication);
|
|
440
470
|
for (const [name, value] of Object.entries(publicationWiring.environment)) {
|
|
@@ -575,7 +605,7 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
575
605
|
|
|
576
606
|
const inboundEventStack = Stack.of(receiveLambda);
|
|
577
607
|
|
|
578
|
-
// SES allows one active receipt rule set per region, so a non-legacy site
|
|
608
|
+
// SES allows one active receipt rule set per account and region, so a non-legacy site
|
|
579
609
|
// creates its own brand-named rule set and never activates it here.
|
|
580
610
|
const inboundSesPlan = planInboundEmailSes(siteBackendIdentity, enableInboundEmail, site.inboundEmailSes);
|
|
581
611
|
if (inboundSesPlan.createReceiptRules) {
|
|
@@ -690,8 +720,23 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
690
720
|
}),
|
|
691
721
|
);
|
|
692
722
|
|
|
723
|
+
const publicFormsEndpoint = wirePublicForms(backend, {
|
|
724
|
+
allowedOrigins: derivePublicFormOrigins({
|
|
725
|
+
explicit: site.publicForms?.allowedOrigins,
|
|
726
|
+
hosts: [activeBrand?.readerDeployment?.domain, ...(publication?.distribution?.aliases ?? [])],
|
|
727
|
+
urls: [site.revalidateBaseUrl, ...siteAuthRedirectUrls(authConfig)],
|
|
728
|
+
}),
|
|
729
|
+
honeypotFields: site.publicForms?.honeypotFields,
|
|
730
|
+
});
|
|
731
|
+
|
|
693
732
|
backend.addOutput({
|
|
694
733
|
custom: {
|
|
734
|
+
publicForms: { endpoint: publicFormsEndpoint },
|
|
735
|
+
// Lets the operator CLI re-project on publish without PAPYRUS_PUBLICATION_KIND / PAPYRUS_CONTENT_ACTIONS_FUNCTION (PPY-0c0b75).
|
|
736
|
+
publication:
|
|
737
|
+
s3ProjectionPublication !== undefined
|
|
738
|
+
? { kind: "s3-projection", contentActionsFunction: contentActionsLambda.functionName }
|
|
739
|
+
: null,
|
|
695
740
|
prospectusSignIn: prospectusGoogleOnlyClient
|
|
696
741
|
? { clientId: prospectusGoogleOnlyClient.ref, callbackPath: PROSPECTUS_SIGN_IN_CALLBACK_PATH }
|
|
697
742
|
: null,
|
|
@@ -726,6 +771,9 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
726
771
|
: null,
|
|
727
772
|
},
|
|
728
773
|
});
|
|
774
|
+
wireEditorialChecks(backend);
|
|
775
|
+
wireMonitoringView(backend);
|
|
776
|
+
wireAutomationView(backend);
|
|
729
777
|
wirePlugins(backend, plugins, contentActionsLambda);
|
|
730
778
|
|
|
731
779
|
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
|
+
}
|