From 78e30cb5e401290f0b645d24538aa5aa21337cae Mon Sep 17 00:00:00 2001 From: kptdobe Date: Fri, 7 Aug 2026 09:54:51 +0200 Subject: [PATCH] feat: derive source contentUrl from DA_CONTENT env var The contentUrl in the source response was hardcoded to https://content.da.live. On stage/ci/dev/it the worker should point to https://stage-content.da.live instead. Add a DA_CONTENT var per wrangler environment (production = content.da.live, all others = stage-content.da.live) and thread env into sourceRespObject so the base URL comes from config. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/helpers/source.js | 4 ++-- src/index.d.ts | 2 ++ src/storage/object/put.js | 2 +- test/helpers/source.test.js | 40 ++++++++++++++++++++++++++++++++++++- test/it/it-tests.js | 2 +- test/utils/mocks/env.js | 1 + wrangler.toml | 5 +++++ 7 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/helpers/source.js b/src/helpers/source.js index 1be034ff..42f2f88f 100644 --- a/src/helpers/source.js +++ b/src/helpers/source.js @@ -16,7 +16,7 @@ import normalizeCharset from '../utils/charset.js'; * Builds a source response * @param {*} key */ -export function sourceRespObject(daCtx) { +export function sourceRespObject(env, daCtx) { const { org, site, isFile, pathname, aemPathname, } = daCtx; @@ -24,7 +24,7 @@ export function sourceRespObject(daCtx) { const obj = { source: { editUrl: `https://da.live/${isFile ? 'edit#/' : ''}${org}${pathname}`, - contentUrl: `https://content.da.live/${org}${pathname}`, + contentUrl: `${env.DA_CONTENT}/${org}${pathname}`, }, }; diff --git a/src/index.d.ts b/src/index.d.ts index 77490c90..2eea1aeb 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -17,6 +17,8 @@ export interface Env { S3_SECRET_ACCESS_KEY: string; IMS_ORIGIN: string; AEM_BUCKET_NAME: string; + // base URL for source content links (eg https://content.da.live) + DA_CONTENT: string; // shared secret used as authorization when invoking the collab service (eg for syncadmin) COLLAB_SHARED_SECRET: string; DA_OPS_IMS_ORG: string; diff --git a/src/storage/object/put.js b/src/storage/object/put.js index 10febbcc..32d0def2 100644 --- a/src/storage/object/put.js +++ b/src/storage/object/put.js @@ -66,7 +66,7 @@ export default async function putObject(env, daCtx, obj) { await client.send(command); } - const body = sourceRespObject(daCtx); + const body = sourceRespObject(env, daCtx); return { body: JSON.stringify(body), status, contentType: 'application/json', metadata, etag, }; diff --git a/test/helpers/source.test.js b/test/helpers/source.test.js index fea37345..22f81e71 100644 --- a/test/helpers/source.test.js +++ b/test/helpers/source.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ import assert from 'node:assert'; -import { putHelper } from '../../src/helpers/source.js'; +import { putHelper, sourceRespObject } from '../../src/helpers/source.js'; import env from '../utils/mocks/env.js'; @@ -19,6 +19,44 @@ const daCtx = { org: 'cq', key: 'geometrixx/hello.html', propsKey: 'geometrixx/h const MOCK_URL = 'https://da.live/source/cq/geometrixx/hello'; describe('Source helper', () => { + describe('sourceRespObject', () => { + it('builds contentUrl from env.DA_CONTENT', () => { + const obj = sourceRespObject( + { DA_CONTENT: 'https://stage-content.da.live' }, + { org: 'cq', pathname: '/geometrixx/hello.html' }, + ); + assert.strictEqual(obj.source.contentUrl, 'https://stage-content.da.live/cq/geometrixx/hello.html'); + assert.strictEqual(obj.source.editUrl, 'https://da.live/cq/geometrixx/hello.html'); + }); + + it('uses production DA_CONTENT when provided', () => { + const obj = sourceRespObject( + { DA_CONTENT: 'https://content.da.live' }, + { org: 'cq', pathname: '/geometrixx/hello.html' }, + ); + assert.strictEqual(obj.source.contentUrl, 'https://content.da.live/cq/geometrixx/hello.html'); + }); + + it('adds aem urls when site is present', () => { + const obj = sourceRespObject( + { DA_CONTENT: 'https://content.da.live' }, + { + org: 'cq', site: 'geometrixx', pathname: '/index.html', aemPathname: '/index', + }, + ); + assert.strictEqual(obj.aem.previewUrl, 'https://main--geometrixx--cq.aem.page/index'); + assert.strictEqual(obj.aem.liveUrl, 'https://main--geometrixx--cq.aem.live/index'); + }); + + it('uses edit#/ prefix for files', () => { + const obj = sourceRespObject( + { DA_CONTENT: 'https://content.da.live' }, + { org: 'cq', isFile: true, pathname: '/geometrixx/hello.html' }, + ); + assert.strictEqual(obj.source.editUrl, 'https://da.live/edit#/cq/geometrixx/hello.html'); + }); + }); + describe('Put success', async () => { it('Returns null if no content type', async () => { const req = new Request(MOCK_URL); diff --git a/test/it/it-tests.js b/test/it/it-tests.js index f5eda1a8..10b6c8f0 100644 --- a/test/it/it-tests.js +++ b/test/it/it-tests.js @@ -263,7 +263,7 @@ export default (ctx) => describe('Integration Tests: it tests', function () { let body = await resp.json(); assert.strictEqual(body.source.editUrl, `https://da.live/edit#/${org}/${repo}/${key}`); - assert.strictEqual(body.source.contentUrl, `https://content.da.live/${org}/${repo}/${key}`); + assert.strictEqual(body.source.contentUrl, `https://stage-content.da.live/${org}/${repo}/${key}`); assert.strictEqual(body.aem.previewUrl, `https://main--${repo}--${org}.aem.page/${key}`); assert.strictEqual(body.aem.liveUrl, `https://main--${repo}--${org}.aem.live/${key}`); diff --git a/test/utils/mocks/env.js b/test/utils/mocks/env.js index 57698965..76d4e9ca 100644 --- a/test/utils/mocks/env.js +++ b/test/utils/mocks/env.js @@ -34,6 +34,7 @@ const DA_CONFIG = { }; const env = { + DA_CONTENT: 'https://stage-content.da.live', S3_DEF_URL: 'https://s3.com', S3_ACCESS_KEY_ID: 'an-id', S3_SECRET_ACCESS_KEY: 'too-many-secrets', diff --git a/wrangler.toml b/wrangler.toml index 505caeb7..30efad06 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -25,6 +25,7 @@ r2_buckets = [ ENVIRONMENT = "production" VERSION = "@@VERSION@@" DA_COLLAB = "https://collab.da.page" +DA_CONTENT = "https://content.da.live" AEM_BUCKET_NAME = "aem-content" AEM_ADMIN_MEDIA_API = "https://admin.hlx.page/media" @@ -50,6 +51,7 @@ r2_buckets = [ ENVIRONMENT = "stage" VERSION = "@@VERSION@@-stage" DA_COLLAB = "https://collab.da.page" +DA_CONTENT = "https://stage-content.da.live" AEM_BUCKET_NAME = "aem-content-stage" AEM_ADMIN_MEDIA_API = "https://admin.hlx.page/media" @@ -75,6 +77,7 @@ r2_buckets = [ ENVIRONMENT = "ci" VERSION = "@@VERSION@@-stage" DA_COLLAB = "https://collab.da.page" +DA_CONTENT = "https://stage-content.da.live" AEM_BUCKET_NAME = "aem-content-stage" AEM_ADMIN_MEDIA_API = "https://admin.hlx.page/media" @@ -101,6 +104,7 @@ r2_buckets = [ ENVIRONMENT = "dev" VERSION="0.0.0-dev" DA_COLLAB = "http://localhost:4711" +DA_CONTENT = "https://stage-content.da.live" AEM_BUCKET_NAME = "aem-content-stage" AEM_ADMIN_MEDIA_API = "https://admin.hlx.page/media" @@ -126,6 +130,7 @@ r2_buckets = [ ENVIRONMENT = "it" VERSION="0.0.0-it" DA_COLLAB = "http://localhost:4711" +DA_CONTENT = "https://stage-content.da.live" AEM_BUCKET_NAME = "aem-content-local" AEM_ADMIN_MEDIA_API = "https://admin.hlx.page/media"