@jpmorganchase/mosaic-site-middleware 0.1.0-beta.13 → 0.1.0-beta.15
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +30 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/loaders/index.d.ts +2 -0
- package/dist/loaders/index.js +8 -0
- package/dist/loaders/index.js.map +1 -0
- package/dist/loaders/loadS3File.d.ts +2 -0
- package/dist/loaders/loadS3File.js +38 -0
- package/dist/loaders/loadS3File.js.map +1 -0
- package/dist/middlewarePresets.d.ts +1 -1
- package/dist/middlewarePresets.js +2 -2
- package/dist/middlewarePresets.js.map +1 -1
- package/dist/{withStaticContent.d.ts → withMDXContent.d.ts} +2 -2
- package/dist/withMDXContent.js +96 -0
- package/dist/withMDXContent.js.map +1 -0
- package/dist/withSharedConfig.d.ts +1 -2
- package/dist/withSharedConfig.js +36 -60
- package/dist/withSharedConfig.js.map +1 -1
- package/package.json +8 -3
- package/src/__tests__/withMDXContent.test.ts +92 -0
- package/src/__tests__/withSharedConfig.test.ts +87 -0
- package/src/index.ts +1 -2
- package/src/loaders/index.ts +9 -0
- package/src/loaders/loadS3File.ts +48 -0
- package/src/middlewarePresets.ts +3 -2
- package/src/withMDXContent.ts +113 -0
- package/src/withSharedConfig.ts +41 -66
- package/dist/withContent.d.ts +0 -17
- package/dist/withContent.js +0 -54
- package/dist/withContent.js.map +0 -1
- package/dist/withStaticContent.js +0 -42
- package/dist/withStaticContent.js.map +0 -1
- package/src/__tests__/createMDXScope.test.ts +0 -79
- package/src/withContent.ts +0 -67
- package/src/withStaticContent.ts +0 -45
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
@jpmorganchase/mosaic-site-middleware:build: cache hit, replaying output
|
|
1
|
+
@jpmorganchase/mosaic-site-middleware:build: cache hit, replaying output a7287f9d02fb07cd
|
|
2
2
|
@jpmorganchase/mosaic-site-middleware:build: $ tsc
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @jpmorganchase/mosaic-site-middleware
|
|
2
2
|
|
|
3
|
+
## 0.1.0-beta.15
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- aaaf255: initial release of HTTP Source package.
|
|
8
|
+
|
|
9
|
+
An HTTP source accepts a collection of endpoints and a path to a transformer module.
|
|
10
|
+
The response from fetching is transformed and merged together into 1 single collection of pages.
|
|
11
|
+
Should 1 of the endpoints request fail then it will have no impact on the other requests.
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [aaaf255]
|
|
14
|
+
- @jpmorganchase/mosaic-schemas@0.1.0-beta.15
|
|
15
|
+
- @jpmorganchase/mosaic-store@0.1.0-beta.15
|
|
16
|
+
- @jpmorganchase/mosaic-types@0.1.0-beta.15
|
|
17
|
+
|
|
18
|
+
## 0.1.0-beta.14
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- dde3b5a: Feature release
|
|
23
|
+
|
|
24
|
+
- Enhanced generators now have defaults.
|
|
25
|
+
With one command (`yarn mosaic-create-site create`) it will generate a fully working site with both local and remote sources
|
|
26
|
+
- Fix an issue where we could not clone from the master branch of git repos
|
|
27
|
+
- Migrate to Next 13 image
|
|
28
|
+
|
|
29
|
+
- Updated dependencies [dde3b5a]
|
|
30
|
+
- @jpmorganchase/mosaic-store@0.1.0-beta.14
|
|
31
|
+
- @jpmorganchase/mosaic-types@0.1.0-beta.14
|
|
32
|
+
|
|
3
33
|
## 0.1.0-beta.13
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,7 @@ export * from './compileMdx.js';
|
|
|
2
2
|
export * from './createMiddlewareRunner.js';
|
|
3
3
|
export * from './MiddlewareError.js';
|
|
4
4
|
export * from './middlewarePresets.js';
|
|
5
|
-
export * from './
|
|
5
|
+
export * from './withMDXContent.js';
|
|
6
6
|
export * from './withMosaicMode.js';
|
|
7
7
|
export * from './withSession.js';
|
|
8
8
|
export * from './withSharedConfig.js';
|
|
9
|
-
export * from './withStaticContent.js';
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,8 @@ export * from './compileMdx.js';
|
|
|
2
2
|
export * from './createMiddlewareRunner.js';
|
|
3
3
|
export * from './MiddlewareError.js';
|
|
4
4
|
export * from './middlewarePresets.js';
|
|
5
|
-
export * from './
|
|
5
|
+
export * from './withMDXContent.js';
|
|
6
6
|
export * from './withMosaicMode.js';
|
|
7
7
|
export * from './withSession.js';
|
|
8
8
|
export * from './withSharedConfig.js';
|
|
9
|
-
export * from './withStaticContent.js';
|
|
10
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
export * from './loadS3File.js';
|
|
3
|
+
export const loadLocalFile = async (filePath) => {
|
|
4
|
+
const realPath = await fs.promises.realpath(filePath);
|
|
5
|
+
const data = await fs.promises.readFile(realPath, 'utf-8');
|
|
6
|
+
return data.toString();
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/loaders/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,cAAc,iBAAiB,CAAC;AAEhC,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,QAAgB,EAAmB,EAAE;IACvE,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;AACzB,CAAC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3';
|
|
2
|
+
import { s3LoaderProcessEnvSchema } from '@jpmorganchase/mosaic-schemas';
|
|
3
|
+
let client;
|
|
4
|
+
function createClient(region, accessKeyId, secretAccessKey) {
|
|
5
|
+
return new S3Client({
|
|
6
|
+
region,
|
|
7
|
+
credentials: {
|
|
8
|
+
accessKeyId,
|
|
9
|
+
secretAccessKey
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export async function readFile(client, bucket, key) {
|
|
14
|
+
const params = {
|
|
15
|
+
Bucket: bucket,
|
|
16
|
+
Key: key
|
|
17
|
+
};
|
|
18
|
+
const command = new GetObjectCommand(params);
|
|
19
|
+
const response = await client.send(command);
|
|
20
|
+
return response;
|
|
21
|
+
}
|
|
22
|
+
export const loadS3File = async (key) => {
|
|
23
|
+
const env = s3LoaderProcessEnvSchema.safeParse(process.env);
|
|
24
|
+
if (!env.success) {
|
|
25
|
+
env.error.issues.forEach(issue => {
|
|
26
|
+
console.error(`Missing process.env.${issue.path.join()} environment variable required to load S3 ${key}`);
|
|
27
|
+
});
|
|
28
|
+
throw new Error(`Environment variables missing for loading of S3 content for key ${key}`);
|
|
29
|
+
}
|
|
30
|
+
const { MOSAIC_S3_BUCKET: bucket, MOSAIC_S3_REGION: region, MOSAIC_S3_ACCESS_KEY_ID: accessKeyId, MOSAIC_S3_SECRET_ACCESS_KEY: secretAccessKey } = env.data;
|
|
31
|
+
if (!client) {
|
|
32
|
+
client = createClient(region, accessKeyId, secretAccessKey);
|
|
33
|
+
}
|
|
34
|
+
const data = await readFile(client, bucket, key);
|
|
35
|
+
const text = await data.Body.transformToString();
|
|
36
|
+
return text;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=loadS3File.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadS3File.js","sourceRoot":"","sources":["../../src/loaders/loadS3File.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,IAAI,MAAM,CAAC;AAEX,SAAS,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,eAAe;IACxD,OAAO,IAAI,QAAQ,CAAC;QAClB,MAAM;QACN,WAAW,EAAE;YACX,WAAW;YACX,eAAe;SAChB;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG;IAChD,MAAM,MAAM,GAAG;QACb,MAAM,EAAE,MAAM;QACd,GAAG,EAAE,GAAG;KACT,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,GAAW,EAAmB,EAAE;IAC/D,MAAM,GAAG,GAAG,wBAAwB,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC5D,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE;QAChB,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YAC/B,OAAO,CAAC,KAAK,CACX,uBAAuB,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,6CAA6C,GAAG,EAAE,CAC3F,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,MAAM,IAAI,KAAK,CAAC,mEAAmE,GAAG,EAAE,CAAC,CAAC;KAC3F;IACD,MAAM,EACJ,gBAAgB,EAAE,MAAM,EACxB,gBAAgB,EAAE,MAAM,EACxB,uBAAuB,EAAE,WAAW,EACpC,2BAA2B,EAAE,eAAe,EAC7C,GAAG,GAAG,CAAC,IAAI,CAAC;IACb,IAAI,CAAC,MAAM,EAAE;QACX,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;KAC7D;IACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;IACjD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Redirect } from 'next';
|
|
2
2
|
import { SharedConfigSlice } from '@jpmorganchase/mosaic-store';
|
|
3
|
+
import type { ContentProps } from '@jpmorganchase/mosaic-types';
|
|
3
4
|
import { type SessionProps, type SessionOptions } from './withSession.js';
|
|
4
|
-
import { type ContentProps } from './withContent.js';
|
|
5
5
|
import { MosaicMiddleware, MosaicMiddlewareWithConfig } from './createMiddlewareRunner.js';
|
|
6
6
|
import { type MosaicModeProps } from './withMosaicMode.js';
|
|
7
7
|
export declare type BaseMosaicAppProps = {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { withSession } from './withSession.js';
|
|
2
2
|
import { withSharedConfig } from './withSharedConfig.js';
|
|
3
|
-
import {
|
|
3
|
+
import { withMDXContent } from './withMDXContent.js';
|
|
4
4
|
import { withMosaicMode } from './withMosaicMode.js';
|
|
5
5
|
/** A collection of preset [[`Middleware`]] plugins that will compose together the page props */
|
|
6
6
|
export const middlewarePresets = [
|
|
7
7
|
[withSession, { loginRequired: process.env.DISABLE_GLOBAL_AUTH !== 'true' }],
|
|
8
8
|
withMosaicMode,
|
|
9
9
|
withSharedConfig,
|
|
10
|
-
|
|
10
|
+
withMDXContent
|
|
11
11
|
];
|
|
12
12
|
//# sourceMappingURL=middlewarePresets.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middlewarePresets.js","sourceRoot":"","sources":["../src/middlewarePresets.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"middlewarePresets.js","sourceRoot":"","sources":["../src/middlewarePresets.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAA0C,MAAM,kBAAkB,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,cAAc,EAAwB,MAAM,qBAAqB,CAAC;AAmC3E,gGAAgG;AAChG,MAAM,CAAC,MAAM,iBAAiB,GAG1B;IACF,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,MAAM,EAAE,CAAC;IAC5E,cAAc;IACd,gBAAgB;IAChB,cAAc;CACf,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type { ContentProps } from '@jpmorganchase/mosaic-types';
|
|
1
2
|
import { MosaicMiddleware } from './createMiddlewareRunner.js';
|
|
2
|
-
import { ContentProps } from './withContent.js';
|
|
3
3
|
/**
|
|
4
4
|
* Adds the [[`ContentProps`]] object to the page props
|
|
5
5
|
* @param context
|
|
6
6
|
*/
|
|
7
|
-
export declare const
|
|
7
|
+
export declare const withMDXContent: MosaicMiddleware<ContentProps>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { fileLoaderProcessEnvSchema } from '@jpmorganchase/mosaic-schemas';
|
|
3
|
+
import MiddlewareError from './MiddlewareError.js';
|
|
4
|
+
import { loadLocalFile, loadS3File } from './loaders/index.js';
|
|
5
|
+
import { compileMDX } from './compileMdx.js';
|
|
6
|
+
if (typeof window !== 'undefined') {
|
|
7
|
+
throw new Error('This file should not be loaded on the client.');
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Adds the [[`ContentProps`]] object to the page props
|
|
11
|
+
* @param context
|
|
12
|
+
*/
|
|
13
|
+
export const withMDXContent = async (context) => {
|
|
14
|
+
const { resolvedUrl } = context;
|
|
15
|
+
const mosaicMode = context.res.getHeader('X-Mosaic-Mode' || 'active');
|
|
16
|
+
const extname = path.extname(resolvedUrl);
|
|
17
|
+
// Any urls which are not prefixed, will default to MDX
|
|
18
|
+
const isMDX = extname === '.mdx' || extname === '';
|
|
19
|
+
if (!isMDX) {
|
|
20
|
+
return {};
|
|
21
|
+
}
|
|
22
|
+
const normalizedUrl = /\/index$/.test(resolvedUrl) ? `${resolvedUrl}.mdx` : resolvedUrl;
|
|
23
|
+
let text;
|
|
24
|
+
if (mosaicMode === 'snapshot-file') {
|
|
25
|
+
const env = fileLoaderProcessEnvSchema.safeParse(process.env);
|
|
26
|
+
if (!env.success) {
|
|
27
|
+
env.error.issues.forEach(issue => {
|
|
28
|
+
console.error(`Missing process.env.${issue.path.join()} environment variable required to load MDX for ${resolvedUrl}`);
|
|
29
|
+
});
|
|
30
|
+
throw new Error(`Environment variables missing for loading of MDX content ${resolvedUrl}`);
|
|
31
|
+
}
|
|
32
|
+
const { MOSAIC_SNAPSHOT_DIR: mosaicSnapshotDir } = env.data;
|
|
33
|
+
const filePath = path.posix.join(process.cwd(), mosaicSnapshotDir, normalizedUrl);
|
|
34
|
+
try {
|
|
35
|
+
text = await loadLocalFile(filePath);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (error instanceof Error) {
|
|
39
|
+
console.error(error.message);
|
|
40
|
+
}
|
|
41
|
+
throw new MiddlewareError(404, resolvedUrl, [`Could not read local file '${filePath}' for '${resolvedUrl}'`], {
|
|
42
|
+
show404: true
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else if (mosaicMode === 'snapshot-s3') {
|
|
47
|
+
try {
|
|
48
|
+
const s3Key = normalizedUrl.replace(/^\//, '');
|
|
49
|
+
text = await loadS3File(s3Key);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (error instanceof Error) {
|
|
53
|
+
console.error(error.message);
|
|
54
|
+
}
|
|
55
|
+
throw new MiddlewareError(404, resolvedUrl, [`Could not find an S3 object for '${resolvedUrl}'`], {
|
|
56
|
+
show404: true
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const mosaicUrl = context.res.getHeader('X-Mosaic-Content-Url');
|
|
62
|
+
const response = await fetch(`${mosaicUrl}${normalizedUrl}`);
|
|
63
|
+
if (response.ok) {
|
|
64
|
+
text = await response.text();
|
|
65
|
+
// If redirect url was returned
|
|
66
|
+
}
|
|
67
|
+
else if (response.status === 302) {
|
|
68
|
+
return {
|
|
69
|
+
redirect: {
|
|
70
|
+
destination: (await response.json()).redirect,
|
|
71
|
+
permanent: true
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
throw new MiddlewareError(404, resolvedUrl, [`Could not fetch any content for ${resolvedUrl}`], {
|
|
77
|
+
show404: true
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const mdxSource = await compileMDX(text);
|
|
83
|
+
return { props: { type: 'mdx', source: mdxSource, raw: text } };
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (error instanceof Error) {
|
|
87
|
+
console.error(error.message);
|
|
88
|
+
throw new MiddlewareError(500, resolvedUrl, [error.message], { show500: true });
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
console.error('unexpected error');
|
|
92
|
+
throw new MiddlewareError(500, resolvedUrl, ['unexpected error'], { show500: true });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=withMDXContent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withMDXContent.js","sourceRoot":"","sources":["../src/withMDXContent.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SharedConfigSlice } from '@jpmorganchase/mosaic-store';
|
|
2
2
|
import { MosaicMiddleware } from './createMiddlewareRunner.js';
|
|
3
|
-
export { SharedConfig };
|
|
4
3
|
/**
|
|
5
4
|
* Adds the [[`SharedConfig`]] props to the page props
|
|
6
5
|
* @param _context
|
package/dist/withSharedConfig.js
CHANGED
|
@@ -1,42 +1,10 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
-
import
|
|
2
|
+
import { fileLoaderProcessEnvSchema } from '@jpmorganchase/mosaic-schemas';
|
|
3
3
|
import MiddlewareError from './MiddlewareError.js';
|
|
4
|
+
import { loadLocalFile, loadS3File } from './loaders';
|
|
4
5
|
if (typeof window !== 'undefined') {
|
|
5
6
|
throw new Error('This file should not be loaded on the client.');
|
|
6
7
|
}
|
|
7
|
-
/**
|
|
8
|
-
* Fetch from mosaic the shared-config.json.
|
|
9
|
-
*
|
|
10
|
-
* @param url the shared config file URL
|
|
11
|
-
* @returns shared config JSON
|
|
12
|
-
*/
|
|
13
|
-
async function fetchSharedConfig(url) {
|
|
14
|
-
const response = await fetch(url, {
|
|
15
|
-
headers: {
|
|
16
|
-
'Content-Type': 'application/json'
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
return response;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Read from the file system the shared config
|
|
23
|
-
*
|
|
24
|
-
* @param url the shared config file URL
|
|
25
|
-
* @returns shared config JSON
|
|
26
|
-
*/
|
|
27
|
-
async function readSharedConfig(url) {
|
|
28
|
-
const mosaicSnapshotDir = process.env.MOSAIC_SNAPSHOT_DIR || '';
|
|
29
|
-
const filePath = path.posix.join(process.cwd(), mosaicSnapshotDir, url);
|
|
30
|
-
try {
|
|
31
|
-
const realPath = await fs.promises.realpath(filePath);
|
|
32
|
-
const data = await fs.promises.readFile(realPath, 'utf-8');
|
|
33
|
-
return new Response(data.toString(), { status: 200 });
|
|
34
|
-
}
|
|
35
|
-
catch (e) {
|
|
36
|
-
// it doesn't matter if no shared config file was found
|
|
37
|
-
return new Response('', { status: 204 });
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
8
|
/**
|
|
41
9
|
* Adds the [[`SharedConfig`]] props to the page props
|
|
42
10
|
* @param _context
|
|
@@ -44,40 +12,48 @@ async function readSharedConfig(url) {
|
|
|
44
12
|
*/
|
|
45
13
|
export const withSharedConfig = async (context) => {
|
|
46
14
|
const { resolvedUrl, res } = context;
|
|
47
|
-
const
|
|
15
|
+
const isSnapshotFile = res.getHeader('X-Mosaic-Mode') === 'snapshot-file';
|
|
16
|
+
const isSnapshotS3 = res.getHeader('X-Mosaic-Mode') === 'snapshot-s3';
|
|
48
17
|
const matches = resolvedUrl.match(/(.*)[!/]/);
|
|
49
18
|
const urlPath = matches?.length ? matches[1] : '';
|
|
50
|
-
const mosaicUrl = isStatic ? '' : res.getHeader('X-Mosaic-Content-Url');
|
|
51
|
-
const sharedConfigUrl = `${mosaicUrl}${urlPath}/shared-config.json`;
|
|
52
|
-
let response;
|
|
53
19
|
try {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
20
|
+
let sharedConfig;
|
|
21
|
+
if (isSnapshotFile) {
|
|
22
|
+
const env = fileLoaderProcessEnvSchema.safeParse(process.env);
|
|
23
|
+
if (!env.success) {
|
|
24
|
+
env.error.issues.forEach(issue => {
|
|
25
|
+
console.error(`Missing process.env.${issue.path.join()} environment variable required to load shared-config for ${resolvedUrl}`);
|
|
26
|
+
});
|
|
27
|
+
throw new Error(`Environment variables missing for loading of shared-config required by ${resolvedUrl}`);
|
|
28
|
+
}
|
|
29
|
+
const { MOSAIC_SNAPSHOT_DIR: mosaicSnapshotDir } = env.data;
|
|
30
|
+
const filePath = path.join(process.cwd(), mosaicSnapshotDir, urlPath, 'shared-config.json');
|
|
31
|
+
const rawSharedConfig = await loadLocalFile(filePath);
|
|
32
|
+
sharedConfig = JSON.parse(rawSharedConfig);
|
|
60
33
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
throw new MiddlewareError(500, sharedConfigUrl, [error.message], { show500: true });
|
|
34
|
+
else if (isSnapshotS3) {
|
|
35
|
+
const s3Key = `${urlPath}/shared-config.json`.replace(/^\//, '');
|
|
36
|
+
const rawSharedConfig = await loadS3File(s3Key);
|
|
37
|
+
sharedConfig = JSON.parse(rawSharedConfig);
|
|
66
38
|
}
|
|
67
39
|
else {
|
|
68
|
-
|
|
69
|
-
|
|
40
|
+
const mosaicUrl = res.getHeader('X-Mosaic-Content-Url');
|
|
41
|
+
const response = await fetch(`${mosaicUrl}${urlPath}/shared-config.json`, {
|
|
42
|
+
headers: {
|
|
43
|
+
'Content-Type': 'application/json'
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
sharedConfig = await response.json();
|
|
70
47
|
}
|
|
48
|
+
const { config } = sharedConfig;
|
|
49
|
+
return { props: { sharedConfig: config } };
|
|
71
50
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
51
|
+
catch (error) {
|
|
52
|
+
let errorMessage = `Could not load any shared config for ${resolvedUrl}`;
|
|
53
|
+
throw new MiddlewareError(500, resolvedUrl, [errorMessage], {
|
|
54
|
+
show404: false,
|
|
55
|
+
show500: true
|
|
56
|
+
});
|
|
77
57
|
}
|
|
78
|
-
throw new MiddlewareError(response.status, sharedConfigUrl, [errorMessage], {
|
|
79
|
-
show404,
|
|
80
|
-
show500
|
|
81
|
-
});
|
|
82
58
|
};
|
|
83
59
|
//# sourceMappingURL=withSharedConfig.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withSharedConfig.js","sourceRoot":"","sources":["../src/withSharedConfig.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"withSharedConfig.js","sourceRoot":"","sources":["../src/withSharedConfig.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jpmorganchase/mosaic-site-middleware",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.15",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Mosaic - Site middleware",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -20,11 +20,16 @@
|
|
|
20
20
|
"lint": "eslint --ignore-pattern \"**/__tests__/**\""
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
+
"aws-sdk-client-mock": "^2.0.1",
|
|
24
|
+
"jest-fetch-mock": "^3.0.3",
|
|
25
|
+
"mock-fs": "^4.14.0",
|
|
23
26
|
"typescript": "^4.8.3"
|
|
24
27
|
},
|
|
25
28
|
"dependencies": {
|
|
26
|
-
"@
|
|
27
|
-
"@jpmorganchase/mosaic-
|
|
29
|
+
"@aws-sdk/client-s3": "^3.256.0",
|
|
30
|
+
"@jpmorganchase/mosaic-schemas": "^0.1.0-beta.15",
|
|
31
|
+
"@jpmorganchase/mosaic-store": "^0.1.0-beta.15",
|
|
32
|
+
"@jpmorganchase/mosaic-types": "^0.1.0-beta.15",
|
|
28
33
|
"@types/mdast": "^3.0.0",
|
|
29
34
|
"acorn": "^8.0.0",
|
|
30
35
|
"acorn-jsx": "^5.0.0",
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3';
|
|
2
|
+
import { mockClient } from 'aws-sdk-client-mock';
|
|
3
|
+
import { sdkStreamMixin } from '@aws-sdk/util-stream-node';
|
|
4
|
+
import { Readable } from 'stream';
|
|
5
|
+
import { default as fetchMock, disableFetchMocks, enableFetchMocks } from 'jest-fetch-mock';
|
|
6
|
+
|
|
7
|
+
const mockFs = require('mock-fs');
|
|
8
|
+
|
|
9
|
+
import { withMDXContent } from '../withMDXContent';
|
|
10
|
+
|
|
11
|
+
jest.mock('../compileMdx.js', () => ({
|
|
12
|
+
compileMDX: async value => Promise.resolve(value)
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
describe('GIVEN withMDXContent', () => {
|
|
16
|
+
describe('WHEN snapshot-s3 Mosaic mode is set', () => {
|
|
17
|
+
let savedEnv = process.env;
|
|
18
|
+
let s3ClientMock;
|
|
19
|
+
beforeAll(() => {
|
|
20
|
+
process.env = {
|
|
21
|
+
...process.env,
|
|
22
|
+
MOSAIC_S3_BUCKET: 'some-bucket',
|
|
23
|
+
MOSAIC_S3_REGION: 'some-region',
|
|
24
|
+
MOSAIC_S3_ACCESS_KEY_ID: 'some-access-key',
|
|
25
|
+
MOSAIC_S3_SECRET_ACCESS_KEY: 'some-secret-key'
|
|
26
|
+
};
|
|
27
|
+
s3ClientMock = mockClient(S3Client);
|
|
28
|
+
const stream = new Readable();
|
|
29
|
+
stream.push('my content');
|
|
30
|
+
stream.push(null); // end of stream
|
|
31
|
+
const contentStream = sdkStreamMixin(stream);
|
|
32
|
+
s3ClientMock.on(GetObjectCommand).resolves({ Body: contentStream });
|
|
33
|
+
});
|
|
34
|
+
afterAll(() => {
|
|
35
|
+
process.env = savedEnv;
|
|
36
|
+
s3ClientMock.reset();
|
|
37
|
+
});
|
|
38
|
+
test('THEN a snapshot can be loaded from an S3 bucket', async () => {
|
|
39
|
+
// arrange
|
|
40
|
+
const content = await withMDXContent({
|
|
41
|
+
resolvedUrl: '/mynamespace/mypage.mdx',
|
|
42
|
+
res: { getHeader: () => 'snapshot-s3' }
|
|
43
|
+
});
|
|
44
|
+
// assert
|
|
45
|
+
expect(content).toEqual({ props: { raw: 'my content', source: 'my content', type: 'mdx' } });
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('WHEN snapshot-file Mosaic mode is set', () => {
|
|
50
|
+
let savedEnv = process.env;
|
|
51
|
+
beforeAll(() => {
|
|
52
|
+
process.env = { ...process.env, MOSAIC_SNAPSHOT_DIR: '/some/snapshots' };
|
|
53
|
+
mockFs({
|
|
54
|
+
'some/snapshots/mynamespace/mydir': {
|
|
55
|
+
'mypage.mdx': 'my content'
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
afterAll(() => {
|
|
60
|
+
mockFs.restore();
|
|
61
|
+
process.env = savedEnv;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('THEN a snapshot can be loaded from a local file', async () => {
|
|
65
|
+
// arrange
|
|
66
|
+
const content = await withMDXContent({
|
|
67
|
+
resolvedUrl: '/mynamespace/mydir/mypage.mdx',
|
|
68
|
+
res: { getHeader: () => 'snapshot-file' }
|
|
69
|
+
});
|
|
70
|
+
expect(content).toEqual({ props: { raw: 'my content', source: 'my content', type: 'mdx' } });
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe('WHEN dynamic Mosaic mode is set', () => {
|
|
75
|
+
beforeAll(() => {
|
|
76
|
+
enableFetchMocks();
|
|
77
|
+
fetchMock.mockOnce('my content');
|
|
78
|
+
});
|
|
79
|
+
afterAll(() => {
|
|
80
|
+
disableFetchMocks();
|
|
81
|
+
});
|
|
82
|
+
test('THEN content is fetched from the data source', async () => {
|
|
83
|
+
// arrange
|
|
84
|
+
const content = await withMDXContent({
|
|
85
|
+
resolvedUrl: '/mynamespace/mypage.mdx',
|
|
86
|
+
res: { getHeader: () => '/dynamic' }
|
|
87
|
+
});
|
|
88
|
+
// assert
|
|
89
|
+
expect(content).toEqual({ props: { raw: 'my content', source: 'my content', type: 'mdx' } });
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3';
|
|
2
|
+
import { mockClient } from 'aws-sdk-client-mock';
|
|
3
|
+
import { sdkStreamMixin } from '@aws-sdk/util-stream-node';
|
|
4
|
+
import { Readable } from 'stream';
|
|
5
|
+
import { default as fetchMock, disableFetchMocks, enableFetchMocks } from 'jest-fetch-mock';
|
|
6
|
+
const mockFs = require('mock-fs');
|
|
7
|
+
|
|
8
|
+
import { withSharedConfig } from '../withSharedConfig';
|
|
9
|
+
describe('GIVEN withSharedConfig', () => {
|
|
10
|
+
describe('WHEN snapshot-s3 Mosaic mode is set', () => {
|
|
11
|
+
let savedEnv = process.env;
|
|
12
|
+
let s3ClientMock;
|
|
13
|
+
beforeAll(() => {
|
|
14
|
+
process.env = {
|
|
15
|
+
...process.env,
|
|
16
|
+
MOSAIC_S3_BUCKET: 'some-bucket',
|
|
17
|
+
MOSAIC_S3_REGION: 'some-region',
|
|
18
|
+
MOSAIC_S3_ACCESS_KEY_ID: 'some-access-key',
|
|
19
|
+
MOSAIC_S3_SECRET_ACCESS_KEY: 'some-secret-key'
|
|
20
|
+
};
|
|
21
|
+
s3ClientMock = mockClient(S3Client);
|
|
22
|
+
const stream = new Readable();
|
|
23
|
+
stream.push('{"config": { "someValue": true }}');
|
|
24
|
+
stream.push(null); // end of stream
|
|
25
|
+
const contentStream = sdkStreamMixin(stream);
|
|
26
|
+
s3ClientMock.on(GetObjectCommand).resolves({ Body: contentStream });
|
|
27
|
+
});
|
|
28
|
+
afterAll(() => {
|
|
29
|
+
process.env = savedEnv;
|
|
30
|
+
s3ClientMock.reset();
|
|
31
|
+
});
|
|
32
|
+
test('THEN shared-config can be loaded from an S3 bucket', async () => {
|
|
33
|
+
// arrange
|
|
34
|
+
const content = await withSharedConfig({
|
|
35
|
+
resolvedUrl: '/mynamespace/mypage.mdx',
|
|
36
|
+
res: { getHeader: () => 'snapshot-s3' }
|
|
37
|
+
});
|
|
38
|
+
// assert
|
|
39
|
+
expect(content).toEqual({ props: { sharedConfig: { someValue: true } } });
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('WHEN snapshot-file Mosaic mode is set', () => {
|
|
44
|
+
let savedEnv = process.env;
|
|
45
|
+
beforeAll(() => {
|
|
46
|
+
process.env = { MOSAIC_SNAPSHOT_DIR: '/some/snapshots' };
|
|
47
|
+
mockFs({
|
|
48
|
+
'some/snapshots/mynamespace/mydir': {
|
|
49
|
+
'shared-config.json': '{"config": { "someValue": true }}'
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
afterAll(() => {
|
|
54
|
+
mockFs.restore();
|
|
55
|
+
process.env = savedEnv;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('THEN reads shared-config from a local file', async () => {
|
|
59
|
+
// arrange
|
|
60
|
+
process.env = { MOSAIC_SNAPSHOT_DIR: '/some/snapshots' };
|
|
61
|
+
const content = await withSharedConfig({
|
|
62
|
+
resolvedUrl: '/mynamespace/mydir/mypage.mdx',
|
|
63
|
+
res: { getHeader: () => 'snapshot-file' }
|
|
64
|
+
});
|
|
65
|
+
expect(content).toEqual({ props: { sharedConfig: { someValue: true } } });
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('WHEN dynamic Mosaic mode is set', () => {
|
|
70
|
+
beforeAll(() => {
|
|
71
|
+
enableFetchMocks();
|
|
72
|
+
fetchMock.mockOnce('{"config": { "someValue": true }}');
|
|
73
|
+
});
|
|
74
|
+
afterAll(() => {
|
|
75
|
+
disableFetchMocks();
|
|
76
|
+
});
|
|
77
|
+
test('THEN shared-config is fetched from the data source', async () => {
|
|
78
|
+
// arrange
|
|
79
|
+
const content = await withSharedConfig({
|
|
80
|
+
resolvedUrl: '/mynamespace/mypage.mdx',
|
|
81
|
+
res: { getHeader: () => '/dynamic' }
|
|
82
|
+
});
|
|
83
|
+
// assert
|
|
84
|
+
expect(content).toEqual({ props: { sharedConfig: { someValue: true } } });
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|