@ekino/rendr-loader
Advanced tools
Comparing version 0.0.15 to 0.0.16
@@ -24,3 +24,4 @@ declare module "types" { | ||
declare module "index" { | ||
import { Loader } from "types"; | ||
import { Loader, MaybePage } from "types"; | ||
import { Page, RendrError, RequestCtx } from "@ekino/rendr-core"; | ||
export * from "types"; | ||
@@ -30,3 +31,10 @@ export * from "services/inmemory"; | ||
export const createChainedLoader: (loaders: Loader[]) => Loader; | ||
export const errorBoundaryLoader: Loader; | ||
type Logger = Partial<{ | ||
log: (message?: any, ...optionalParams: any[]) => void; | ||
error: (message?: any, ...optionalParams: any[]) => void; | ||
warn: (message?: any, ...optionalParams: any[]) => void; | ||
info: (message?: any, ...optionalParams: any[]) => void; | ||
}>; | ||
export function generateErrorHandler(logger: Logger): (err: RendrError | Error, ctx: RequestCtx, page: Page) => MaybePage; | ||
export function createErrorBoundaryLoader(logger?: Logger): Loader; | ||
} |
@@ -68,5 +68,5 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return function (ctx, page, next) { return __awaiter(_this, void 0, void 0, function () { | ||
var result; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
var result, _a; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
@@ -85,4 +85,5 @@ result = routes.find(function (conf) { | ||
} | ||
_a = next; | ||
return [4, result.pageBuilder(ctx, page, function () { })]; | ||
case 1: return [2, _a.sent()]; | ||
case 1: return [2, _a.apply(void 0, [_b.sent()])]; | ||
} | ||
@@ -232,23 +233,53 @@ }); | ||
}; | ||
exports.errorBoundaryLoader = function (ctx, page, next) { return __awaiter(void 0, void 0, void 0, function () { | ||
var resultPage, err_1; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
_a.trys.push([0, 2, , 3]); | ||
return [4, next()]; | ||
case 1: | ||
resultPage = _a.sent(); | ||
return [3, 3]; | ||
case 2: | ||
err_1 = _a.sent(); | ||
resultPage = rendr_core_3.createPage(); | ||
resultPage.statusCode = err_1 instanceof rendr_core_3.NotFoundError ? 404 : 500; | ||
resultPage.settings.message = err_1.message; | ||
return [3, 3]; | ||
case 3: return [2, resultPage]; | ||
function flattenStackTrace(err, stack) { | ||
if (stack === void 0) { stack = []; } | ||
if (err instanceof rendr_core_3.RendrError && err.previousError) { | ||
flattenStackTrace(err.previousError, stack); | ||
} | ||
stack.push(err.stack); | ||
return stack; | ||
} | ||
function generateErrorHandler(logger) { | ||
return function (err, ctx, page) { | ||
var fullStack = flattenStackTrace(err); | ||
fullStack.forEach(function (stack) { return logger.log(stack); }); | ||
if (ctx.res && ctx.res.headersSent) { | ||
ctx.res.end(); | ||
return; | ||
} | ||
}); | ||
}); }; | ||
var resultPage = rendr_core_3.createPage(); | ||
resultPage.statusCode = err instanceof rendr_core_3.NotFoundError ? 404 : 500; | ||
resultPage.settings.message = err.message; | ||
if (ctx.isServerSide && process.env.NODE_ENV !== "production") { | ||
resultPage.settings.stackTrace = fullStack; | ||
} | ||
if (ctx.isClientSide) { | ||
throw err; | ||
} | ||
return resultPage; | ||
}; | ||
} | ||
exports.generateErrorHandler = generateErrorHandler; | ||
function createErrorBoundaryLoader(logger) { | ||
var _this = this; | ||
if (logger === void 0) { logger = console; } | ||
return function (ctx, page, next) { return __awaiter(_this, void 0, void 0, function () { | ||
var err_1, handler; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
_a.trys.push([0, 2, , 3]); | ||
return [4, next()]; | ||
case 1: return [2, _a.sent()]; | ||
case 2: | ||
err_1 = _a.sent(); | ||
handler = generateErrorHandler(logger); | ||
return [2, handler(err_1, ctx, page)]; | ||
case 3: return [2]; | ||
} | ||
}); | ||
}); }; | ||
} | ||
exports.createErrorBoundaryLoader = createErrorBoundaryLoader; | ||
}); | ||
//# sourceMappingURL=rendr-core.js.map |
@@ -1,2 +0,3 @@ | ||
import { Loader } from "./types"; | ||
import { Loader, MaybePage } from "./types"; | ||
import { Page, RendrError, RequestCtx } from "@ekino/rendr-core"; | ||
export * from "./types"; | ||
@@ -6,2 +7,9 @@ export * from "./services/inmemory"; | ||
export declare const createChainedLoader: (loaders: Loader[]) => Loader; | ||
export declare const errorBoundaryLoader: Loader; | ||
declare type Logger = Partial<{ | ||
log: (message?: any, ...optionalParams: any[]) => void; | ||
error: (message?: any, ...optionalParams: any[]) => void; | ||
warn: (message?: any, ...optionalParams: any[]) => void; | ||
info: (message?: any, ...optionalParams: any[]) => void; | ||
}>; | ||
export declare function generateErrorHandler(logger: Logger): (err: RendrError | Error, ctx: RequestCtx, page: Page) => MaybePage; | ||
export declare function createErrorBoundaryLoader(logger?: Logger): Loader; |
@@ -37,3 +37,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
}; | ||
import { Page, createPage, NotFoundError } from "@ekino/rendr-core"; | ||
import { Page, createPage, NotFoundError, RendrError } from "@ekino/rendr-core"; | ||
export * from "./services/inmemory"; | ||
@@ -75,22 +75,50 @@ export * from "./services/api"; | ||
}; | ||
export var errorBoundaryLoader = function (ctx, page, next) { return __awaiter(void 0, void 0, void 0, function () { | ||
var resultPage, err_1; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
_a.trys.push([0, 2, , 3]); | ||
return [4, next()]; | ||
case 1: | ||
resultPage = _a.sent(); | ||
return [3, 3]; | ||
case 2: | ||
err_1 = _a.sent(); | ||
resultPage = createPage(); | ||
resultPage.statusCode = err_1 instanceof NotFoundError ? 404 : 500; | ||
resultPage.settings.message = err_1.message; | ||
return [3, 3]; | ||
case 3: return [2, resultPage]; | ||
function flattenStackTrace(err, stack) { | ||
if (stack === void 0) { stack = []; } | ||
if (err instanceof RendrError && err.previousError) { | ||
flattenStackTrace(err.previousError, stack); | ||
} | ||
stack.push(err.stack); | ||
return stack; | ||
} | ||
export function generateErrorHandler(logger) { | ||
return function (err, ctx, page) { | ||
var fullStack = flattenStackTrace(err); | ||
fullStack.forEach(function (stack) { return logger.log(stack); }); | ||
if (ctx.res && ctx.res.headersSent) { | ||
ctx.res.end(); | ||
return; | ||
} | ||
}); | ||
}); }; | ||
var resultPage = createPage(); | ||
resultPage.statusCode = err instanceof NotFoundError ? 404 : 500; | ||
resultPage.settings.message = err.message; | ||
if (ctx.isServerSide && process.env.NODE_ENV !== "production") { | ||
resultPage.settings.stackTrace = fullStack; | ||
} | ||
if (ctx.isClientSide) { | ||
throw err; | ||
} | ||
return resultPage; | ||
}; | ||
} | ||
export function createErrorBoundaryLoader(logger) { | ||
var _this = this; | ||
if (logger === void 0) { logger = console; } | ||
return function (ctx, page, next) { return __awaiter(_this, void 0, void 0, function () { | ||
var err_1, handler; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
_a.trys.push([0, 2, , 3]); | ||
return [4, next()]; | ||
case 1: return [2, _a.sent()]; | ||
case 2: | ||
err_1 = _a.sent(); | ||
handler = generateErrorHandler(logger); | ||
return [2, handler(err_1, ctx, page)]; | ||
case 3: return [2]; | ||
} | ||
}); | ||
}); }; | ||
} | ||
//# sourceMappingURL=index.js.map |
@@ -59,5 +59,5 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return function (ctx, page, next) { return __awaiter(_this, void 0, void 0, function () { | ||
var result; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
var result, _a; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
@@ -76,4 +76,5 @@ result = routes.find(function (conf) { | ||
} | ||
_a = next; | ||
return [4, result.pageBuilder(ctx, page, function () { })]; | ||
case 1: return [2, _a.sent()]; | ||
case 1: return [2, _a.apply(void 0, [_b.sent()])]; | ||
} | ||
@@ -80,0 +81,0 @@ }); |
@@ -1,2 +0,3 @@ | ||
import { Loader } from "./types"; | ||
import { Loader, MaybePage } from "./types"; | ||
import { Page, RendrError, RequestCtx } from "@ekino/rendr-core"; | ||
export * from "./types"; | ||
@@ -6,2 +7,9 @@ export * from "./services/inmemory"; | ||
export declare const createChainedLoader: (loaders: Loader[]) => Loader; | ||
export declare const errorBoundaryLoader: Loader; | ||
declare type Logger = Partial<{ | ||
log: (message?: any, ...optionalParams: any[]) => void; | ||
error: (message?: any, ...optionalParams: any[]) => void; | ||
warn: (message?: any, ...optionalParams: any[]) => void; | ||
info: (message?: any, ...optionalParams: any[]) => void; | ||
}>; | ||
export declare function generateErrorHandler(logger: Logger): (err: RendrError | Error, ctx: RequestCtx, page: Page) => MaybePage; | ||
export declare function createErrorBoundaryLoader(logger?: Logger): Loader; |
@@ -79,22 +79,52 @@ "use strict"; | ||
}; | ||
exports.errorBoundaryLoader = function (ctx, page, next) { return __awaiter(void 0, void 0, void 0, function () { | ||
var resultPage, err_1; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
_a.trys.push([0, 2, , 3]); | ||
return [4, next()]; | ||
case 1: | ||
resultPage = _a.sent(); | ||
return [3, 3]; | ||
case 2: | ||
err_1 = _a.sent(); | ||
resultPage = rendr_core_1.createPage(); | ||
resultPage.statusCode = err_1 instanceof rendr_core_1.NotFoundError ? 404 : 500; | ||
resultPage.settings.message = err_1.message; | ||
return [3, 3]; | ||
case 3: return [2, resultPage]; | ||
function flattenStackTrace(err, stack) { | ||
if (stack === void 0) { stack = []; } | ||
if (err instanceof rendr_core_1.RendrError && err.previousError) { | ||
flattenStackTrace(err.previousError, stack); | ||
} | ||
stack.push(err.stack); | ||
return stack; | ||
} | ||
function generateErrorHandler(logger) { | ||
return function (err, ctx, page) { | ||
var fullStack = flattenStackTrace(err); | ||
fullStack.forEach(function (stack) { return logger.log(stack); }); | ||
if (ctx.res && ctx.res.headersSent) { | ||
ctx.res.end(); | ||
return; | ||
} | ||
}); | ||
}); }; | ||
var resultPage = rendr_core_1.createPage(); | ||
resultPage.statusCode = err instanceof rendr_core_1.NotFoundError ? 404 : 500; | ||
resultPage.settings.message = err.message; | ||
if (ctx.isServerSide && process.env.NODE_ENV !== "production") { | ||
resultPage.settings.stackTrace = fullStack; | ||
} | ||
if (ctx.isClientSide) { | ||
throw err; | ||
} | ||
return resultPage; | ||
}; | ||
} | ||
exports.generateErrorHandler = generateErrorHandler; | ||
function createErrorBoundaryLoader(logger) { | ||
var _this = this; | ||
if (logger === void 0) { logger = console; } | ||
return function (ctx, page, next) { return __awaiter(_this, void 0, void 0, function () { | ||
var err_1, handler; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
_a.trys.push([0, 2, , 3]); | ||
return [4, next()]; | ||
case 1: return [2, _a.sent()]; | ||
case 2: | ||
err_1 = _a.sent(); | ||
handler = generateErrorHandler(logger); | ||
return [2, handler(err_1, ctx, page)]; | ||
case 3: return [2]; | ||
} | ||
}); | ||
}); }; | ||
} | ||
exports.createErrorBoundaryLoader = createErrorBoundaryLoader; | ||
//# sourceMappingURL=index.js.map |
@@ -64,5 +64,5 @@ "use strict"; | ||
return function (ctx, page, next) { return __awaiter(_this, void 0, void 0, function () { | ||
var result; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
var result, _a; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
@@ -81,4 +81,5 @@ result = routes.find(function (conf) { | ||
} | ||
_a = next; | ||
return [4, result.pageBuilder(ctx, page, function () { })]; | ||
case 1: return [2, _a.sent()]; | ||
case 1: return [2, _a.apply(void 0, [_b.sent()])]; | ||
} | ||
@@ -85,0 +86,0 @@ }); |
{ | ||
"name": "@ekino/rendr-loader", | ||
"license": "MIT", | ||
"version": "0.0.15", | ||
"version": "0.0.16", | ||
"main": "dist/lib/index.js", | ||
@@ -13,3 +13,3 @@ "typing": "dist/lib/index.d.ts", | ||
"dependencies": { | ||
"@ekino/rendr-core": "0.0.15", | ||
"@ekino/rendr-core": "0.0.16", | ||
"axios": "^0.19.0", | ||
@@ -26,3 +26,3 @@ "path-match": "^1.2.4", | ||
}, | ||
"gitHead": "5c773d43e512291a844b999855ee6d6b23b0cc79" | ||
"gitHead": "42720e423cf54b2976e74fe476d588c891becb91" | ||
} |
@@ -1,5 +0,8 @@ | ||
import { createChainedLoader } from "./index"; | ||
import { createChainedLoader, createErrorBoundaryLoader } from "./index"; | ||
import { Page, RequestCtx } from "@ekino/rendr-core"; | ||
import { Loader } from "./types"; | ||
const logger = { log: jest.fn() }; | ||
const errorBoundaryLoader = createErrorBoundaryLoader(logger); | ||
let mainPage: Page; | ||
@@ -11,6 +14,12 @@ let witnessPage: Page; | ||
// @ts-ignore | ||
res: jest.fn(), | ||
res: { | ||
statusCode: 200, | ||
end: jest.fn() | ||
}, | ||
isServerSide: true, | ||
isClientSide: false, | ||
pathname: "/", | ||
query: {}, | ||
asPath: "/" | ||
asPath: "/", | ||
settings: {} | ||
}; | ||
@@ -40,7 +49,7 @@ | ||
page.head.title = "block execution of the next loaders"; | ||
console.log("No call to the next function"); | ||
// console.log("No call to the next function"); | ||
}; | ||
const exitingLoader: Loader = (ctx, page, next) => { | ||
console.log("Return a page object"); | ||
// console.log("Return a page object"); | ||
return witnessPage; | ||
@@ -50,3 +59,3 @@ }; | ||
const referenceChangeLoader: Loader = (ctx, page, next) => { | ||
console.log("Pass a new page to the next loader"); | ||
// console.log("Pass a new page to the next loader"); | ||
return next(witnessPage); | ||
@@ -56,3 +65,3 @@ }; | ||
const resultPageNullifierLoader: Loader = (ctx, page, next) => { | ||
console.log("Call next but do not return it"); | ||
// console.log("Call next but do not return it"); | ||
next(); | ||
@@ -66,2 +75,4 @@ }; | ||
witnessPage.head.title = "witness"; | ||
ctx.isServerSide = true; | ||
ctx.isClientSide = false; | ||
}); | ||
@@ -132,1 +143,81 @@ | ||
}); | ||
describe("test errorBoundaryLoader", () => { | ||
it("should return the page reference given to it if no error", async () => { | ||
const loader = createChainedLoader([errorBoundaryLoader, loader1]); | ||
const resultPage = await loader(ctx, mainPage, () => {}); | ||
expect(mainPage.head.title).toEqual("main"); | ||
expect(mainPage.blocks.length).toEqual(1); | ||
expect(mainPage.blocks[0].type).toEqual("block1"); | ||
expect(resultPage).toEqual(mainPage); | ||
}); | ||
it("should catch errors and return a new page instance", async () => { | ||
const loader = createChainedLoader([ | ||
errorBoundaryLoader, | ||
(context, page, next) => { | ||
throw new Error("An error"); | ||
} | ||
]); | ||
const resultPage = await loader(ctx, mainPage, () => {}); | ||
// @ts-ignore | ||
expect(resultPage.statusCode).toEqual(500); | ||
// @ts-ignore | ||
expect(resultPage.settings.message).toEqual("An error"); | ||
expect(resultPage).not.toEqual(mainPage); | ||
}); | ||
it("should still throw the exception when client side", async () => { | ||
const loader = createChainedLoader([ | ||
errorBoundaryLoader, | ||
(context, page, next) => { | ||
throw new Error("An error"); | ||
} | ||
]); | ||
ctx.isServerSide = false; | ||
ctx.isClientSide = true; | ||
let witnessError; | ||
try { | ||
const resultPage = await loader(ctx, mainPage, () => {}); | ||
} catch (err) { | ||
witnessError = err; | ||
} | ||
// @ts-ignore | ||
expect(witnessError).toBeInstanceOf(Error); | ||
}); | ||
it("should not return the stack trace in the page when in production mode", async () => { | ||
const loader = createChainedLoader([ | ||
errorBoundaryLoader, | ||
(context, page, next) => { | ||
throw new Error("An error"); | ||
} | ||
]); | ||
const oldEnv = process.env.NODE_ENV; | ||
process.env.NODE_ENV = "production"; | ||
const resultPage = await loader(ctx, mainPage, () => {}); | ||
// @ts-ignore | ||
expect(resultPage.settings.message).toEqual("An error"); | ||
// @ts-ignore | ||
expect(resultPage.settings.stackTrace).toBeUndefined(); | ||
process.env.NODE_ENV = oldEnv; | ||
}); | ||
it("should call response end if headers have been sent", async () => { | ||
const loader = createChainedLoader([ | ||
errorBoundaryLoader, | ||
(context, page, next) => { | ||
context.res.headersSent = true; | ||
throw new Error("An error"); | ||
} | ||
]); | ||
const resultPage = await loader(ctx, mainPage, () => {}); | ||
// @ts-ignore | ||
expect(resultPage).toBeUndefined(); | ||
// @ts-ignore | ||
expect(ctx.res.end).toHaveBeenCalled(); | ||
}); | ||
}); |
@@ -1,3 +0,10 @@ | ||
import { Loader } from "./types"; | ||
import { Page, createPage, NotFoundError } from "@ekino/rendr-core"; | ||
import { Loader, MaybePage } from "./types"; | ||
import { | ||
Page, | ||
createPage, | ||
NotFoundError, | ||
RendrError, | ||
RequestCtx | ||
} from "@ekino/rendr-core"; | ||
import { type } from "os"; | ||
@@ -31,15 +38,61 @@ export * from "./types"; | ||
// Simple version of a loader that catches errors during the execution of | ||
// following loaders | ||
// Feel free to use your own if you want to manage other error codes | ||
export const errorBoundaryLoader: Loader = async (ctx, page, next) => { | ||
let resultPage: Page | void; | ||
try { | ||
resultPage = await next(); | ||
} catch (err) { | ||
resultPage = createPage(); | ||
function flattenStackTrace(err: Error | RendrError, stack: string[] = []) { | ||
if (err instanceof RendrError && err.previousError) { | ||
flattenStackTrace(err.previousError, stack); | ||
} | ||
stack.push(err.stack); | ||
return stack; | ||
} | ||
type Logger = Partial<{ | ||
log: (message?: any, ...optionalParams: any[]) => void; | ||
error: (message?: any, ...optionalParams: any[]) => void; | ||
warn: (message?: any, ...optionalParams: any[]) => void; | ||
info: (message?: any, ...optionalParams: any[]) => void; | ||
}>; | ||
// Behaviour is as follow: | ||
// 1. Always log the error stack | ||
// 2. If headers were sent, just ends the response | ||
// 3. The resultPage receives the message of the error in the key message of its settings | ||
// 4. In non production mode, resultPage also receives the error trace | ||
// 5. Client side, the error is thrown as normal for browser to catch it | ||
export function generateErrorHandler(logger: Logger) { | ||
return (err: Error | RendrError, ctx: RequestCtx, page: Page): MaybePage => { | ||
const fullStack = flattenStackTrace(err); | ||
fullStack.forEach(stack => logger.log(stack)); | ||
if (ctx.res && ctx.res.headersSent) { | ||
ctx.res.end(); | ||
return; | ||
} | ||
const resultPage = createPage(); | ||
resultPage.statusCode = err instanceof NotFoundError ? 404 : 500; | ||
resultPage.settings.message = err.message; | ||
} | ||
return resultPage; | ||
}; | ||
if (ctx.isServerSide && process.env.NODE_ENV !== "production") { | ||
resultPage.settings.stackTrace = fullStack; | ||
} | ||
if (ctx.isClientSide) { | ||
throw err; | ||
} | ||
return resultPage; | ||
}; | ||
} | ||
export function createErrorBoundaryLoader(logger: Logger = console): Loader { | ||
return async (ctx, page, next) => { | ||
try { | ||
return await next(); | ||
} catch (err) { | ||
const handler = generateErrorHandler(logger); | ||
return handler(err, ctx, page); | ||
} | ||
}; | ||
} |
@@ -86,6 +86,3 @@ import { createPage, Page } from "@ekino/rendr-core"; | ||
return pipe( | ||
response.data, | ||
ctx.res | ||
); | ||
return pipe(response.data, ctx.res); | ||
} | ||
@@ -134,8 +131,5 @@ } | ||
return pipe( | ||
source, | ||
dest | ||
).then(() => { | ||
return pipe(source, dest).then(() => { | ||
return createPage(JSON.parse(data)); | ||
}); | ||
} |
@@ -50,4 +50,4 @@ import { NotFoundError } from "@ekino/rendr-core"; | ||
return await result.pageBuilder(ctx, page, () => {}); | ||
return next(await result.pageBuilder(ctx, page, () => {})); | ||
}; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
89101
1670
3
+ Added@ekino/rendr-core@0.0.16(transitive)
- Removed@ekino/rendr-core@0.0.15(transitive)
Updated@ekino/rendr-core@0.0.16