Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@ const nameSelector = (segs) => {
return literals.join('-');
};

/**
* Routing table.
*/
export const router = new Router(nameSelector)
.add('/auth/*', auth)
.add('/discover', discover)
Expand Down Expand Up @@ -105,7 +102,7 @@ async function run(request, context) {
if (!handler) {
return new Response('', { status: 404 });
}
const info = RequestInfo.create(request, variables);
const info = RequestInfo.create(request, router, variables);
if (info.method === 'OPTIONS') {
return new Response('', {
status: 204,
Expand Down
2 changes: 1 addition & 1 deletion src/live/status.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default async function liveStatus(context, info) {
webPath: info.webPath,
resourcePath: info.resourcePath,
live,
// TODO links: getAPIUrls(ctx, info, 'status', 'preview', 'live', 'code'),
links: info.getAPIUrls('status', 'preview', 'live', 'code'),
};

return new Response(JSON.stringify(resp, null, 2), {
Expand Down
2 changes: 1 addition & 1 deletion src/preview/status.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default async function previewStatus(context, info) {
webPath: info.webPath,
resourcePath: info.resourcePath,
preview,
// TODO links: getAPIUrls(context, info, 'status', 'preview', 'live', 'code'),
links: info.getAPIUrls('status', 'preview', 'live', 'code'),
};

return new Response(JSON.stringify(resp, null, 2), {
Expand Down
52 changes: 48 additions & 4 deletions src/router/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
const NodeType = {
LITERAL: 1,
VARIABLE: 2,
PATH: 3,
};

/**
* Node in the router tree, either intermediate or leaf.
Expand All @@ -19,6 +24,16 @@ export class Node {
*/
#label;

/**
* Type of node.
*/
#type;

/**
* Parent for this node.
*/
#parent;

/**
* Literal children of this node.
*/
Expand All @@ -39,27 +54,29 @@ export class Node {
*/
#route;

constructor(label) {
constructor(label, type = NodeType.LITERAL, parent = undefined) {
this.#label = label;
this.#type = type;
this.#parent = parent;
this.#children = [];
}

#getOrCreateChild(seg) {
if (seg === '*') {
if (!this.#star) {
this.#star = new Node(seg);
this.#star = new Node(seg, NodeType.PATH, this);
}
return this.#star;
}
if (seg.startsWith(':')) {
if (!this.#variable) {
this.#variable = new Node(seg.substring(1));
this.#variable = new Node(seg.substring(1), NodeType.VARIABLE, this);
}
return this.#variable;
}
let ret = this.#children.find((child) => child.#label === seg);
if (!ret) {
ret = new Node(seg);
ret = new Node(seg, NodeType.LITERAL, this);
this.#children.push(ret);
}
return ret;
Expand Down Expand Up @@ -113,4 +130,31 @@ export class Node {
}
return null;
}

/**
* Returns the external path by traversing from a leaf back
* to the root.
*
* @param {string[]} segs path segments to collect
* @param {Map} variables variables
* @returns {void}
*/
external(segs, variables) {
const label = this.#label;

switch (this.#type) {
case NodeType.LITERAL:
segs.unshift(label);
break;
case NodeType.VARIABLE:
segs.unshift(variables[label]);
break;
case NodeType.PATH:
segs.unshift(variables.path);
break;
default:
break;
}
this.#parent?.external(segs, variables);
}
}
21 changes: 20 additions & 1 deletion src/router/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default class Router {
#routes;

constructor(nameSelector) {
this.#root = new Node('', (info, segs) => segs.push(''));
this.#root = new Node('');
this.#nameSelector = nameSelector;
this.#routes = new Map();
}
Expand Down Expand Up @@ -73,4 +73,23 @@ export default class Router {
}
return null;
}

/**
* Returns the external path for a route with some variables
* to fill in the variable segments traversing.
*
* @param {string} name route name
* @param {Map} variables variables
* @returns {string} external path
*/
external(name, variables) {
/** @type {Node} */
const route = this.#routes.get(name);
if (!route) {
throw new Error(`route not found: ${name}`);
}
const segs = [];
route.external(segs, variables);
return segs.join('/');
}
}
2 changes: 1 addition & 1 deletion src/status/status.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export default async function status(context, info) {
live: await getLiveInfo(context, info),
preview: await getPreviewInfo(context, info),
edit,
// TODO links: getAPIUrls(context, info, 'status', 'preview', 'live', 'code'),
links: info.getAPIUrls('status', 'preview', 'live', 'code'),
};

if (authInfo.profile) {
Expand Down
26 changes: 23 additions & 3 deletions src/support/RequestInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ class PathInfo {
export class RequestInfo {
#request;

#router;

#pathInfo;

#owner;
Expand All @@ -215,8 +217,9 @@ export class RequestInfo {

#ref;

constructor(request, pathInfo) {
constructor(request, router, pathInfo) {
this.#request = request;
this.#router = router;
this.#pathInfo = pathInfo;
}

Expand Down Expand Up @@ -310,6 +313,7 @@ export class RequestInfo {
* Create a new request info.
*
* @param {import('@adobe/fetch').Request} request request
* @param {import('../router/router.js').default} router router
* @param {object} param0 params
* @param {string} [param0.org] org, optional
* @param {string} [param0.site] site, optional
Expand All @@ -318,13 +322,13 @@ export class RequestInfo {
* @param {string} [param0.route] route, optional
* @returns {RequestInfo}
*/
static create(request, {
static create(request, router, {
org, site, path, ref, route,
} = {}) {
const httpRequest = new HttpRequest(request);
const pathInfo = new PathInfo(route, org, site, path);

return Object.freeze(new RequestInfo(httpRequest, pathInfo).withRef(ref));
return Object.freeze(new RequestInfo(httpRequest, router, pathInfo).withRef(ref));
}

/**
Expand All @@ -343,6 +347,7 @@ export class RequestInfo {
}) {
const info = new RequestInfo(
other.#request,
other.#router,
PathInfo.clone(other.#pathInfo, {
org, site, path, route,
}),
Expand Down Expand Up @@ -375,6 +380,21 @@ export class RequestInfo {
return url.href;
}

getAPIUrls(...routes) {
const links = {};
const variables = {
org: this.org,
site: this.site,
path: this.webPath.slice(1),
ref: this.ref,
};
routes.forEach((name) => {
const path = this.#router.external(name, variables);
links[name] = this.getLinkUrl(path);
});
return links;
}

toResourcePath() {
return toResourcePath(this.webPath);
}
Expand Down
6 changes: 6 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ describe('Index Tests', () => {
assert.strictEqual(result.status, 200);
assert.deepStrictEqual(await result.json(), {
edit: {},
links: {
code: 'https://api.aem.live/org/sites/site/code/main/document',
live: 'https://api.aem.live/org/sites/site/live/document',
preview: 'https://api.aem.live/org/sites/site/preview/document',
status: 'https://api.aem.live/org/sites/site/status/document',
},
live: {
contentBusId: `helix-content-bus/${SITE_CONFIG.content.contentBusId}/live/document.md`,
contentType: 'text/plain; charset=utf-8',
Expand Down
6 changes: 6 additions & 0 deletions test/live/info.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ describe('Live Info Tests', () => {

assert.strictEqual(response.status, 200);
assert.deepStrictEqual(await response.json(), {
links: {
code: 'https://api.aem.live/org/sites/site/code/main/document',
live: 'https://api.aem.live/org/sites/site/live/document',
preview: 'https://api.aem.live/org/sites/site/preview/document',
status: 'https://api.aem.live/org/sites/site/status/document',
},
live: {
contentBusId: `helix-content-bus/${SITE_CONFIG.content.contentBusId}/live/document.md`,
contentType: 'text/plain; charset=utf-8',
Expand Down
6 changes: 6 additions & 0 deletions test/live/publish.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,12 @@ describe('Publish Action Tests', () => {

assert.strictEqual(response.status, 200);
assert.deepStrictEqual(await response.json(), {
links: {
code: 'https://api.aem.live/org/sites/site/code/main/',
live: 'https://api.aem.live/org/sites/site/live/',
preview: 'https://api.aem.live/org/sites/site/preview/',
status: 'https://api.aem.live/org/sites/site/status/',
},
live: {
configRedirectLocation: '/target',
contentBusId: `helix-content-bus/${SITE_CONFIG.content.contentBusId}/live/index.md`,
Expand Down
6 changes: 6 additions & 0 deletions test/preview/info.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ describe('Preview Info Tests', () => {

assert.strictEqual(response.status, 200);
assert.deepStrictEqual(await response.json(), {
links: {
code: 'https://api.aem.live/org/sites/site/code/main/document',
live: 'https://api.aem.live/org/sites/site/live/document',
preview: 'https://api.aem.live/org/sites/site/preview/document',
status: 'https://api.aem.live/org/sites/site/status/document',
},
preview: {
contentBusId: `helix-content-bus/${SITE_CONFIG.content.contentBusId}/preview/document.md`,
contentType: 'text/plain; charset=utf-8',
Expand Down
6 changes: 6 additions & 0 deletions test/preview/preview.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ describe('Preview Action Tests', () => {

assert.strictEqual(response.status, 200);
assert.deepStrictEqual(await response.json(), {
links: {
code: 'https://api.aem.live/org/sites/site/code/main/',
live: 'https://api.aem.live/org/sites/site/live/',
preview: 'https://api.aem.live/org/sites/site/preview/',
status: 'https://api.aem.live/org/sites/site/status/',
},
preview: {
configRedirectLocation: '/target',
contentBusId: `helix-content-bus/${SITE_CONFIG.content.contentBusId}/preview/index.md`,
Expand Down
Loading