-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0540260
commit cecb5fa
Showing
6 changed files
with
169 additions
and
228 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import matter from 'gray-matter'; | ||
import type { SafeParseError } from 'zod'; | ||
import { activeEnvSchema } from '@jpmorganchase/mosaic-schemas'; | ||
|
||
import type { LoaderPage } from './types/index.js'; | ||
|
||
export * from './types/index.js'; | ||
|
||
const normalizePageUrl = (url: string): string => (/\/index$/.test(url) ? `${url}.mdx` : url); | ||
|
||
type ActiveModeUrlEnv = { | ||
MOSAIC_ACTIVE_MODE_URL: string; | ||
}; | ||
|
||
export class LoadPageError extends Error { | ||
statusCode: number; | ||
constructor({ message, statusCode }: { message: string; statusCode: number }) { | ||
super(message); | ||
this.statusCode = statusCode; | ||
} | ||
} | ||
|
||
const getFSRootUrl = (): string => { | ||
const env = activeEnvSchema.safeParse(process.env); | ||
if (!env.success) { | ||
const { error } = env as SafeParseError<ActiveModeUrlEnv>; | ||
error.issues.forEach(issue => { | ||
console.error( | ||
`Missing process.env.${issue.path.join()} environment variable required to load pages` | ||
); | ||
}); | ||
throw new LoadPageError({ | ||
message: `Environment variables missing to load pages`, | ||
statusCode: 500 | ||
}); | ||
} | ||
return env.data.MOSAIC_ACTIVE_MODE_URL; | ||
}; | ||
|
||
export const loadActiveMosaicData = async <T>(url: string): Promise<T> => { | ||
const fsRootUrl = getFSRootUrl(); | ||
const dataUrl = new URL(url, fsRootUrl); | ||
const response = await fetch(dataUrl); | ||
|
||
if (!response.ok) { | ||
// This will activate the closest `error.js` Error Boundary | ||
throw new Error(`Failed to fetch mosaic data @ ${dataUrl}`); | ||
} | ||
return response.json(); | ||
}; | ||
|
||
export const loadActiveContent = async (route: string): Promise<LoaderPage> => { | ||
const fsRootUrl = getFSRootUrl(); | ||
const pageUrl = normalizePageUrl(`${fsRootUrl}${route}`); | ||
const response = await fetch(pageUrl); | ||
if (response.status === 302) { | ||
const { redirect } = await response.json(); | ||
return loadActiveContent(redirect); | ||
} | ||
if (response.ok) { | ||
const source = await response.text(); | ||
const { content, data } = matter(source); | ||
return { source: content, data }; | ||
} | ||
throw new LoadPageError({ | ||
message: `Could not load page : ${pageUrl} ${response.status}/${response.statusText}`, | ||
statusCode: 404 | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { snapshotFileEnvSchema } from '@jpmorganchase/mosaic-schemas'; | ||
|
||
import type { LoaderPage } from './types/index.js'; | ||
import path from 'path'; | ||
import fs from 'node:fs/promises'; | ||
import matter from 'gray-matter'; | ||
|
||
export * from './types/index.js'; | ||
|
||
const normalizePageUrl = (url: string): string => (/\/index$/.test(url) ? `${url}.mdx` : url); | ||
|
||
export class LoadPageError extends Error { | ||
statusCode: number; | ||
constructor({ message, statusCode }: { message: string; statusCode: number }) { | ||
super(message); | ||
this.statusCode = statusCode; | ||
} | ||
} | ||
|
||
const getFSRootUrl = (): string => { | ||
const env = snapshotFileEnvSchema.safeParse(process.env); | ||
if (!env.success) { | ||
env.error.issues.forEach(issue => { | ||
console.error( | ||
`Missing process.env.${issue.path.join()} environment variable required to load pages` | ||
); | ||
}); | ||
throw new LoadPageError({ | ||
message: `Environment variables missing to load pages`, | ||
statusCode: 500 | ||
}); | ||
} | ||
return env.data.MOSAIC_SNAPSHOT_DIR; | ||
}; | ||
|
||
export const loadSnapshotFileMosaicData = async <T>(url: string): Promise<T> => { | ||
const matches = url.match(/(.*)[!/]/); | ||
const urlPath = matches?.length ? matches[1] : ''; | ||
|
||
const fsRootUrl = getFSRootUrl(); | ||
const filePath = path.join(process.cwd(), fsRootUrl, urlPath); | ||
|
||
let fileExists = false; | ||
try { | ||
await fs.stat(filePath); | ||
fileExists = true; | ||
} catch {} | ||
if (fileExists) { | ||
let localPath = filePath; | ||
if ((await fs.stat(filePath)).isDirectory()) { | ||
localPath = path.posix.join(localPath, 'index'); | ||
} | ||
const realPath = await fs.realpath(localPath); | ||
console.log(localPath, realPath); | ||
const source = await fs.readFile(realPath, 'utf-8'); | ||
return JSON.parse(source); | ||
} | ||
throw new Error(`Failed to fetch mosaic data @ ${url}`); | ||
}; | ||
|
||
export const loadSnapshotFileContent = async (route: string): Promise<LoaderPage> => { | ||
const fsRootUrl = getFSRootUrl(); | ||
const pageUrl = normalizePageUrl(route); | ||
const filePath = path.posix.join(process.cwd(), fsRootUrl, pageUrl); | ||
try { | ||
let localPath = filePath; | ||
if ((await fs.stat(filePath)).isDirectory()) { | ||
localPath = path.posix.join(localPath, 'index'); | ||
} | ||
const realPath = await fs.realpath(localPath); | ||
const source = await fs.readFile(realPath, 'utf-8'); | ||
const { content, data } = matter(source); | ||
return { source: content, data }; | ||
} catch (error) { | ||
if (error instanceof Error) { | ||
console.error(error.message); | ||
} | ||
throw new LoadPageError({ | ||
message: `Could not read local file '${filePath}' for '${route}'`, | ||
statusCode: 404 | ||
}); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.