Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: update error-extender lib #612

Merged
merged 4 commits into from
Oct 2, 2024
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
18 changes: 18 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,24 @@ on:
- "**"

jobs:
common_checks:
name: Common checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.8.0
cache: 'npm'
cache-dependency-path: '**/package-lock.json'

- name: Install dependencies
run: npm ci

- name: Check formatting
run: npm run format:check
build_ilc:
name: Build ILC
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion ilc/client/registry/errors.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import extendError from '@namecheap/error-extender';
import { extendError } from '../../common/utils';

const errors = {};
errors.RegistryError = extendError('RegistryError');
Expand Down
3 changes: 1 addition & 2 deletions ilc/common/CacheWrapper.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const extendError = require('@namecheap/error-extender');
const { withTimeout } = require('./utils');
const { withTimeout, extendError } = require('./utils');

const errors = {};
errors.CacheWrapperError = extendError('CacheWrapperError', { defaultData: {} });
Expand Down
2 changes: 1 addition & 1 deletion ilc/common/guard/errors.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const extendError = require('@namecheap/error-extender');
const { extendError } = require('../utils');

const errors = {};

Expand Down
2 changes: 1 addition & 1 deletion ilc/common/router/errors.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const extendError = require('@namecheap/error-extender');
const { extendError } = require('../utils');

const errors = {};
errors.RouterError = extendError('RouterError', { defaultData: {} });
Expand Down
52 changes: 24 additions & 28 deletions ilc/common/utils.js → ilc/common/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
const deepmerge = require('deepmerge');
import errorExtender, { type ExtendConfig } from '@namecheap/error-extender';
import deepmerge from 'deepmerge';

function appIdToNameAndSlot(appId) {
type NameAndSlot = {
appName: string;
slotName: string;
};
export function appIdToNameAndSlot(appId: string): NameAndSlot {
const [appNameWithoutPrefix, slotName] = appId.split('__at__');

// Case for shared libraries
Expand All @@ -17,24 +22,25 @@ function appIdToNameAndSlot(appId) {
};
}

function makeAppId(appName, slotName) {
export function makeAppId(appName: string, slotName: string): string {
return `${appName.replace('@portal/', '')}__at__${slotName}`;
}

function cloneDeep(source) {
return deepmerge({}, source);
export function cloneDeep<T extends object>(source: T): T {
return deepmerge<T>({}, source);
}

const uniqueArray = (array) => [...new Set(array)];
export const uniqueArray = <T>(array: T[]): T[] => [...new Set(array)];

const encodeHtmlEntities = (value) => value.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
const decodeHtmlEntities = (value) =>
export const encodeHtmlEntities = (value: string): string =>
value.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
export const decodeHtmlEntities = (value: string): string =>
value
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&quot;/g, '"');

const removeQueryParams = (url) => {
export const removeQueryParams = (url: string): string => {
const index = url.indexOf('?');
if (index !== -1) {
return url.substring(0, index);
Expand All @@ -43,15 +49,15 @@ const removeQueryParams = (url) => {
}
};

const addTrailingSlash = (url) => {
export const addTrailingSlash = (url: string): string => {
if (url.endsWith('/')) {
return url;
}

return `${url}/`;
};

function addTrailingSlashToPath(url) {
export function addTrailingSlashToPath(url: string): string {
const isFullUrl = url.includes('://');
const parsedUrl = isFullUrl ? new URL(url) : new URL(`https://example.com/${url}`);
const hasTrailingSlash = parsedUrl.pathname.endsWith('/');
Expand All @@ -60,32 +66,22 @@ function addTrailingSlashToPath(url) {
return isFullUrl ? parsedUrl.toString() : parsedUrl.pathname.slice(1);
}

class TimeoutError extends Error {}
export class TimeoutError extends Error {}

/**
*
* @param {Promise}
* @param {number} timeout
*/
async function withTimeout(promise, ms, message = 'Promise timeout') {
let timeoutId;
const timeoutPromise = new Promise((resolve, reject) => {
export async function withTimeout<T>(promise: Promise<T>, ms: number, message = 'Promise timeout'): Promise<T> {
let timeoutId: NodeJS.Timeout;
const timeoutPromise = new Promise<T>((resolve, reject) => {
timeoutId = setTimeout(() => reject(new TimeoutError(message)), ms);
});
const decoratedPromise = promise.finally(() => clearTimeout(timeoutId));
return Promise.race([decoratedPromise, timeoutPromise]);
}

module.exports = {
appIdToNameAndSlot,
makeAppId,
cloneDeep,
uniqueArray,
encodeHtmlEntities,
decodeHtmlEntities,
removeQueryParams,
addTrailingSlash,
addTrailingSlashToPath,
withTimeout,
TimeoutError,
};
export function extendError<T>(name: string, options: ExtendConfig<T> = {}) {
return errorExtender(name, { ...options, inverse: true });
}
8 changes: 4 additions & 4 deletions ilc/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ilc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"author": "",
"license": "Apache-2.0",
"dependencies": {
"@namecheap/error-extender": "^2.1.0",
"@namecheap/error-extender": "^2.2.1",
"@namecheap/tailorx": "^8.1.0",
"@newrelic/native-metrics": "^11.0.0",
"agentkeepalive": "^4.5.0",
Expand Down
2 changes: 1 addition & 1 deletion ilc/server/errorHandler/ErrorHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const path = require('path');
const { StatusCodes, getReasonPhrase } = require('http-status-codes');
const safeJsonStringify = require('safe-json-stringify');
const uuidv4 = require('uuid/v4');
const extendError = require('@namecheap/error-extender');
const { extendError } = require('../../common/utils');
const config = require('config');
const { readFileSync } = require('fs');
const { setErrorData } = require('../utils/helpers');
Expand Down
2 changes: 1 addition & 1 deletion ilc/server/registry/errors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import extendError from '@namecheap/error-extender';
import { extendError } from '../../common/utils';

export const RegistryError = extendError('RegistryError', { defaultData: {} });
export const ValidationRegistryError = extendError('ValidationRegistryError', {
Expand Down
2 changes: 1 addition & 1 deletion ilc/server/tailor/errors.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const extendError = require('@namecheap/error-extender');
const { extendError } = require('../../common/utils');

const errors = {};
errors.TailorError = extendError('TailorError', { defaultData: {} });
Expand Down
4 changes: 2 additions & 2 deletions ilc/server/tailor/fragment-hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ function insertStart(logger, stream, attributes, headers) {
isAsync
? `<!-- Async fragments are not fully implemented yet: ${uri} -->`
: id
? asyncStylesLoadTemplate(uri, id)
: '',
? asyncStylesLoadTemplate(uri, id)
: '',
harnyk marked this conversation as resolved.
Show resolved Hide resolved
);
} else if (ref.rel === 'fragment-script') {
bundleVersionOverrides.spaBundle = fixUri(attributes, ref.uri);
Expand Down
8 changes: 4 additions & 4 deletions registry/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion registry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"typescript": "^5.6.2"
},
"dependencies": {
"@namecheap/error-extender": "^2.1.0",
"@namecheap/error-extender": "^2.2.1",
"@newrelic/native-metrics": "^11.0.0",
"axios": "^1.7.7",
"bcrypt": "^5.1.1",
Expand Down
2 changes: 1 addition & 1 deletion registry/server/errorHandler/httpErrors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import extendError from '@namecheap/error-extender';
import { extendError } from '../util/extendError';

export const HttpError = extendError('HttpError', { defaultData: {} });
export const NotFoundError = extendError('NotFoundError', {
Expand Down
12 changes: 3 additions & 9 deletions registry/server/settings/services/SettingsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,9 @@ export class SettingsService {
.from('settings')
.innerJoin('settings_domain_value', 'settings.key', 'settings_domain_value.key')
.where('settings_domain_value.domainId', domainId)
.select<SettingRaw[]>(
'settings.key',
'settings.default',
'settings.scope',
'settings.secret',
'settings.meta',
'settings_domain_value.value as value',
'settings_domain_value.domainId as domainId',
)
.select<
SettingRaw[]
>('settings.key', 'settings.default', 'settings.scope', 'settings.secret', 'settings.meta', 'settings_domain_value.value as value', 'settings_domain_value.domainId as domainId')
harnyk marked this conversation as resolved.
Show resolved Hide resolved
.range(options.range);

const parsedSettings = this.parseSettings(settings.data);
Expand Down
6 changes: 3 additions & 3 deletions registry/server/templates/errors.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import errorExtender from '@namecheap/error-extender';
import { extendError } from '../util/extendError';

export default {
FetchIncludeError: errorExtender('FetchIncludeError', { defaultData: {} }),
InvalidTemplateError: errorExtender('InvalidTemplateError', { defaultData: {} }),
FetchIncludeError: extendError('FetchIncludeError', { defaultData: {} }),
InvalidTemplateError: extendError('InvalidTemplateError', { defaultData: {} }),
};
6 changes: 3 additions & 3 deletions registry/server/util/axiosErrorTransformer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import errorExtender from '@namecheap/error-extender';
import type { AxiosError } from 'axios';
import { type AxiosError } from 'axios';
import { extendError } from './extendError';

const IlcAxiosError = errorExtender('AxiosError');
const IlcAxiosError = extendError('AxiosError');

export function isAxiosError(err: unknown): err is AxiosError {
return Boolean((err as AxiosError)?.isAxiosError);
Expand Down
5 changes: 5 additions & 0 deletions registry/server/util/extendError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import errorExtender, { type ExtendConfig } from '@namecheap/error-extender';

export function extendError<T = any>(name: string, options: ExtendConfig<T> = {}) {
return errorExtender(name, { ...options, inverse: true });
}
2 changes: 1 addition & 1 deletion registry/server/versioning/errors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import extendError from '@namecheap/error-extender';
import { extendError } from '../util/extendError';

export const VersioningError = extendError('VersioningError', { defaultData: {} });
export const NonRevertableError = extendError<{ reason: string }>('NonRevertableError', { parent: VersioningError });
Expand Down
5 changes: 2 additions & 3 deletions registry/tests/logging.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import sinon, { SinonSpy } from 'sinon';
import supertest from 'supertest';

import errorExtender from '@namecheap/error-extender';

import createApplication from '../server/app';
import { getLogger } from '../server/util/logger';
import { getPluginManagerInstance, loadPlugins } from '../server/util/pluginManager';

import type { Handler } from 'express';
import { extendError } from '../server/util/extendError';

async function runScenario(handler: Handler) {
const app = await createApplication(true);
Expand Down Expand Up @@ -96,7 +95,7 @@ describe('Logging', () => {

it('should log extended error json format', async () => {
const logObjectHandler: Handler = (req, res, next) => {
const CustomError = errorExtender('Custom');
const CustomError = extendError('Custom');
try {
getLogger().error(new CustomError({ message: 'desc', data: { a: 1 }, cause: new Error('cause') }));
} catch (e) {
Expand Down
Loading