Skip to content

Commit 44853a8

Browse files
committed
fix: switch to org/site
1 parent 21ad084 commit 44853a8

File tree

4 files changed

+102
-40
lines changed

4 files changed

+102
-40
lines changed

src/config.js

+20-7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
* governing permissions and limitations under the License.
1111
*/
1212

13+
import { errorWithResponse } from './util.js';
14+
1315
/**
1416
* @param {string[]} patterns
1517
* @param {string} path
@@ -43,13 +45,25 @@ function extractPathParams(pattern, path) {
4345
* @param {Partial<Config>} [overrides={}]
4446
* @returns {Promise<Config|null>}
4547
*/
46-
export async function resolveConfig(ctx, tenant, overrides = {}) {
47-
const confMap = await ctx.env.CONFIGS.get(tenant, 'json');
48+
export async function resolveConfig(ctx, overrides = {}) {
49+
const [_, org, site, route] = ctx.url.pathname.split('/');
50+
if (!org) {
51+
throw errorWithResponse(404, 'missing org');
52+
}
53+
if (!site) {
54+
throw errorWithResponse(404, 'missing site');
55+
}
56+
if (!route) {
57+
throw errorWithResponse(404, 'missing route');
58+
}
59+
60+
const siteKey = `${org}--${site}`;
61+
const confMap = await ctx.env.CONFIGS.get(siteKey, 'json');
4862
if (!confMap) {
4963
return null;
5064
}
5165
if (typeof confMap !== 'object') {
52-
ctx.log.warn('invalid config for tenant', tenant);
66+
ctx.log.warn('invalid config for', siteKey);
5367
return null;
5468
}
5569

@@ -60,8 +74,6 @@ export async function resolveConfig(ctx, tenant, overrides = {}) {
6074
suffix,
6175
);
6276

63-
const [org, repo] = tenant.split('--');
64-
6577
// merge configs
6678
/** @type {Config} */
6779
const resolved = {
@@ -82,13 +94,14 @@ export async function resolveConfig(ctx, tenant, overrides = {}) {
8294
params: {},
8395
}),
8496
org,
85-
repo,
97+
site,
98+
route,
8699
...overrides,
87100
};
88101
// ensure validity
89102
// TODO: make this more robust
90103
if (!resolved.pageType) {
91-
ctx.log.warn('invalid config for tenant (missing pageType)', tenant);
104+
ctx.log.warn('invalid config for tenant site (missing pageType)', siteKey);
92105
return null;
93106
}
94107

src/index.js

+2-10
Original file line numberDiff line numberDiff line change
@@ -225,23 +225,15 @@ export default {
225225
return errorResponse(405, 'method not allowed');
226226
}
227227

228-
const [_, tenant, route] = ctx.url.pathname.split('/');
229-
if (!tenant) {
230-
return errorResponse(404, 'missing tenant');
231-
}
232-
if (!route) {
233-
return errorResponse(404, 'missing route');
234-
}
235-
236228
try {
237229
const overrides = Object.fromEntries(ctx.url.searchParams.entries());
238-
const config = await resolveConfig(ctx, tenant, overrides);
230+
const config = await resolveConfig(ctx, overrides);
239231
console.debug('resolved config: ', JSON.stringify(config));
240232
if (!config) {
241233
return errorResponse(404, 'config not found');
242234
}
243235

244-
return handlers[route](ctx, config);
236+
return handlers[config.route](ctx, config);
245237
} catch (e) {
246238
if (e.response) {
247239
return e.response;

src/types.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import type { ExecutionContext, KVNamespace } from "@cloudflare/workers-types/ex
22

33
declare global {
44
export interface Config {
5+
org: string;
6+
site: string;
7+
route: string;
58
pageType: 'product' | string;
69
origin?: string;
710
apiKey: string;

test/config.test.js

+77-23
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,39 @@ import { resolveConfig } from '../src/config.js';
1616
/**
1717
* @param {string} path
1818
* @param {Record<string, Config>} configMap
19+
* @param {string} [baseUrl='https://www.example.com/org/site/content']
1920
* @returns {Context}
2021
*/
21-
const TEST_CONTEXT = (path, configMap) => ({
22+
const TEST_CONTEXT = (path, configMap, baseUrl = 'https://www.example.com/org/site/content') => ({
2223
env: {
2324
CONFIGS: {
2425
get: async (tenant) => configMap[tenant],
2526
},
2627
},
2728
log: console,
28-
url: new URL(`https://www.example.com/org--repo/content${path}`),
29+
url: new URL(`${baseUrl}${path}`),
2930
info: {
3031
method: 'GET',
3132
headers: {},
3233
},
3334
});
3435

36+
const defaultTenantConfigs = {
37+
'org--site': {
38+
base: {
39+
apiKey: 'bad',
40+
},
41+
'/us/p/{{urlkey}}/{{sku}}': {
42+
pageType: 'product',
43+
apiKey: 'good',
44+
},
45+
},
46+
};
47+
3548
describe('config tests', () => {
3649
it('should extract path params', async () => {
3750
const tenantConfigs = {
38-
'org--repo': {
51+
'org--site': {
3952
base: {
4053
apiKey: 'bad',
4154
},
@@ -45,23 +58,21 @@ describe('config tests', () => {
4558
},
4659
},
4760
};
48-
const config = await resolveConfig(
49-
TEST_CONTEXT('/us/p/my-url-key/some-sku', tenantConfigs),
50-
'org--repo',
51-
);
61+
const config = await resolveConfig(TEST_CONTEXT('/us/p/my-url-key/some-sku', tenantConfigs));
5262
assert.deepStrictEqual(config, {
5363
apiKey: 'good',
5464
params: { urlkey: 'my-url-key', sku: 'some-sku' },
5565
headers: {},
5666
pageType: 'product',
5767
org: 'org',
58-
repo: 'repo',
68+
site: 'site',
69+
route: 'content',
5970
});
6071
});
6172

6273
it('should combine headers objects', async () => {
6374
const tenantConfigs = {
64-
'org--repo': {
75+
'org--site': {
6576
base: {
6677
apiKey: 'bad',
6778
headers: {
@@ -79,23 +90,21 @@ describe('config tests', () => {
7990
},
8091
},
8192
};
82-
const config = await resolveConfig(
83-
TEST_CONTEXT('/us/p/my-url-key/some-sku', tenantConfigs),
84-
'org--repo',
85-
);
93+
const config = await resolveConfig(TEST_CONTEXT('/us/p/my-url-key/some-sku', tenantConfigs));
8694
assert.deepStrictEqual(config, {
8795
apiKey: 'good',
8896
params: { urlkey: 'my-url-key', sku: 'some-sku' },
8997
headers: { foo: '2', baz: '1', bar: '2' },
9098
pageType: 'product',
9199
org: 'org',
92-
repo: 'repo',
100+
site: 'site',
101+
route: 'content',
93102
});
94103
});
95104

96105
it('should allow wildcard path segments', async () => {
97106
const tenantConfigs = {
98-
'org--repo': {
107+
'org--site': {
99108
base: {
100109
apiKey: 'bad',
101110
},
@@ -105,23 +114,21 @@ describe('config tests', () => {
105114
},
106115
},
107116
};
108-
const config = await resolveConfig(
109-
TEST_CONTEXT('/us/p/something-here/some-sku', tenantConfigs),
110-
'org--repo',
111-
);
117+
const config = await resolveConfig(TEST_CONTEXT('/us/p/something-here/some-sku', tenantConfigs));
112118
assert.deepStrictEqual(config, {
113119
apiKey: 'good',
114120
params: { sku: 'some-sku' },
115121
headers: {},
116122
pageType: 'product',
117123
org: 'org',
118-
repo: 'repo',
124+
site: 'site',
125+
route: 'content',
119126
});
120127
});
121128

122129
it('should allow overrides', async () => {
123130
const tenantConfigs = {
124-
'org--repo': {
131+
'org--site': {
125132
base: {
126133
apiKey: 'bad1',
127134
},
@@ -133,7 +140,6 @@ describe('config tests', () => {
133140
};
134141
const config = await resolveConfig(
135142
TEST_CONTEXT('/us/p/some-sku', tenantConfigs),
136-
'org--repo',
137143
{ apiKey: 'good' },
138144
);
139145
assert.deepStrictEqual(config, {
@@ -142,7 +148,55 @@ describe('config tests', () => {
142148
pageType: 'product',
143149
headers: {},
144150
org: 'org',
145-
repo: 'repo',
151+
site: 'site',
152+
route: 'content',
146153
});
147154
});
155+
156+
it('should throw if org is missing', async () => {
157+
await assert.rejects(
158+
resolveConfig(TEST_CONTEXT('', defaultTenantConfigs, 'http://www.example.com')),
159+
new Error('missing org'),
160+
);
161+
});
162+
163+
it('should throw if site is missing', async () => {
164+
await assert.rejects(
165+
resolveConfig(TEST_CONTEXT('', defaultTenantConfigs, 'http://www.example.com/org')),
166+
new Error('missing site'),
167+
);
168+
});
169+
170+
it('should throw if route is missing', async () => {
171+
await assert.rejects(
172+
resolveConfig(TEST_CONTEXT('', defaultTenantConfigs, 'http://www.example.com/org/site')),
173+
new Error('missing route'),
174+
);
175+
});
176+
177+
it('should return null for invalid config', async () => {
178+
const config = await resolveConfig(TEST_CONTEXT('/us/p/some-sku', {}));
179+
assert.deepStrictEqual(config, null);
180+
});
181+
182+
it('should return null if config is not an object', async () => {
183+
const ctx = TEST_CONTEXT('/us/p/some-sku', {});
184+
ctx.env.CONFIGS.get = async () => 'not an object';
185+
const config = await resolveConfig(ctx);
186+
assert.deepStrictEqual(config, null);
187+
});
188+
189+
it('should log a warning if pageType is missing', async () => {
190+
const tenantConfigs = {
191+
'org--site': {
192+
base: {
193+
apiKey: 'good',
194+
},
195+
'/us/p/{{sku}}': {},
196+
},
197+
};
198+
const ctx = TEST_CONTEXT('/us/p/some-sku', tenantConfigs);
199+
const config = await resolveConfig(ctx);
200+
assert.deepStrictEqual(config, null);
201+
});
148202
});

0 commit comments

Comments
 (0)