Skip to content

Commit

Permalink
fix: core backend undefined fallback not working (#3326)
Browse files Browse the repository at this point in the history
  • Loading branch information
stepan662 committed Apr 11, 2024
1 parent a51b0a0 commit 0244269
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 29 deletions.
31 changes: 14 additions & 17 deletions packages/core/src/Controller/Cache/Cache.ts
Expand Up @@ -57,15 +57,13 @@ export function Cache(
/**
* Fetches production data
*/
function fetchProd(keyObject: CacheDescriptorInternal) {
async function fetchProd(keyObject: CacheDescriptorInternal) {
let dataOrPromise = undefined as
| Promise<TreeTranslationsData | undefined>
| undefined;
if (!dataOrPromise) {
const staticDataValue = staticData[encodeCacheKey(keyObject)];
if (typeof staticDataValue === 'function') {
dataOrPromise = staticDataValue();
}
const staticDataValue = staticData[encodeCacheKey(keyObject)];
if (typeof staticDataValue === 'function') {
dataOrPromise = staticDataValue();
}

if (!dataOrPromise) {
Expand All @@ -85,26 +83,25 @@ export function Cache(
}
}

function fetchData(keyObject: CacheDescriptorInternal, isDev: boolean) {
let dataOrPromise = undefined as
| Promise<TreeTranslationsData | undefined>
| undefined;
async function fetchData(keyObject: CacheDescriptorInternal, isDev: boolean) {
let result = undefined as TreeTranslationsData | undefined;

if (isDev) {
dataOrPromise = backendGetDevRecord(keyObject)?.catch((e) => {
try {
result = await backendGetDevRecord(keyObject);
} catch (e) {
const error = new RecordFetchError(keyObject, e, true);
events.onError.emit(error);
// eslint-disable-next-line no-console
console.warn(error);
// fallback to prod fetch if dev fails
return fetchProd(keyObject);
});
}
}

if (!dataOrPromise) {
dataOrPromise = fetchProd(keyObject);
if (!result) {
result = await fetchProd(keyObject);
}

return dataOrPromise;
return result;
}

const self = Object.freeze({
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/Controller/Plugins/Plugins.ts
Expand Up @@ -243,9 +243,9 @@ export function Plugins(
return instances.devBackend;
},

getBackendRecord: (({ language, namespace }) => {
getBackendRecord: (async ({ language, namespace }) => {
for (const backend of instances.backends) {
const data = backend.getRecord({
const data = await backend.getRecord({
language,
namespace,
...getCommonProps(),
Expand All @@ -257,7 +257,7 @@ export function Plugins(
return undefined;
}) as BackendGetRecordInternal,

getBackendDevRecord: (({ language, namespace }) => {
getBackendDevRecord: (async ({ language, namespace }) => {
const { apiKey, apiUrl, projectId } = getInitialOptions();
return instances.devBackend?.getRecord({
apiKey,
Expand Down
72 changes: 72 additions & 0 deletions packages/core/src/__test/backend.test.ts
@@ -1,3 +1,4 @@
/* eslint-disable no-console */
import { TolgeeCore } from '../TolgeeCore';
import { BackendMiddleware, TolgeePlugin } from '../types';

Expand All @@ -12,6 +13,18 @@ const data = {
},
} as any;

const backendReturningUndefined: BackendMiddleware = {
async getRecord() {
return Promise.resolve(undefined);
},
};

const backendThrowing: BackendMiddleware = {
async getRecord() {
throw new Error('Failed to fetch');
},
};

const backendNormal: BackendMiddleware = {
getRecord({ language, namespace = '' }) {
return data[language]?.[namespace];
Expand All @@ -31,11 +44,16 @@ const backendPlugin: TolgeePlugin = (tolgee, tools) => {
};

describe('backend plugins', () => {
afterEach(() => {
jest.resetAllMocks();
});

it('uses plugin to fetch', async () => {
const tolgee = TolgeeCore()
.use(backendPlugin)
.init({
ns: ['common', 'test'],
defaultNs: 'common',
language: 'en',
});
await tolgee.run();
Expand All @@ -45,4 +63,58 @@ describe('backend plugins', () => {
await tolgee.run();
expect(tolgee.t({ key: 'cancel', ns: 'common' })).toEqual('Dev');
});

it('falls back if backend returns undefined', async () => {
const tolgee = TolgeeCore()
.use((tolgee, tools) => {
tools.addBackend(backendReturningUndefined);
tools.addBackend(backendNormal);
return tolgee;
})
.init({
ns: ['common', 'test'],
defaultNs: 'common',
language: 'en',
});
await tolgee.run();
expect(tolgee.t({ key: 'cancel', ns: 'common' })).toEqual('Cancel');
tolgee.stop();
});

it('uses backends in correct order', async () => {
const tolgee = TolgeeCore()
.use((tolgee, tools) => {
tools.addBackend(backendThrowing);
tools.addBackend(backendNormal);
return tolgee;
})
.init({
ns: ['common', 'test'],
defaultNs: 'common',
language: 'en',
});
const errLogger = console.error;
console.error = jest.fn();
await expect(() => tolgee.run()).rejects.toThrow('Failed to fetch');
console.error = errLogger;
tolgee.stop();
});

it('uses backends in correct order 2', async () => {
const tolgee = TolgeeCore()
.use((tolgee, tools) => {
tools.addBackend(backendNormal);
tools.addBackend(backendThrowing);
return tolgee;
})
.init({
ns: ['common', 'test'],
defaultNs: 'common',
language: 'en',
});

await tolgee.run();
expect(tolgee.t({ key: 'cancel', ns: 'common' })).toEqual('Cancel');
tolgee.stop();
});
});
6 changes: 3 additions & 3 deletions packages/core/src/types/plugin.ts
Expand Up @@ -27,19 +27,19 @@ export type BackendGetRecordProps = {

export type BackendGetRecord = (
data: BackendGetRecordProps & CommonProps
) => Promise<TreeTranslationsData | undefined> | undefined;
) => Promise<TreeTranslationsData | undefined>;

export interface BackendMiddleware {
getRecord: BackendGetRecord;
}

export type BackendGetDevRecord = (
data: BackendGetRecordProps & CommonProps & BackendDevProps
) => Promise<TreeTranslationsData | undefined> | undefined;
) => Promise<TreeTranslationsData | undefined>;

export type BackendGetRecordInternal = (
data: BackendGetRecordProps & BackendDevProps
) => Promise<TreeTranslationsData | undefined> | undefined;
) => Promise<TreeTranslationsData | undefined>;

export type BackendDevMiddleware = {
getRecord: BackendGetDevRecord;
Expand Down
5 changes: 4 additions & 1 deletion packages/ngx/angular.json
Expand Up @@ -42,5 +42,8 @@
}
}
},
"defaultProject": "ngx-tolgee"
"defaultProject": "ngx-tolgee",
"cli": {
"analytics": false
}
}
6 changes: 3 additions & 3 deletions packages/web/src/app/App.tsx
Expand Up @@ -16,10 +16,10 @@ export const App = () => {

return (
<StyledContainer>
<div title="test">{tolgee.t('on-the-road-title')}</div>
<div title="test">{tolgee.t('app-title')}</div>
<div>
{tolgee.t('on-the-road-title')}
{tolgee.t('on-the-road-subtitle')}
{tolgee.t('app-title')}
{tolgee.t('add-item-input-placeholder')}
</div>
<button disabled>{tolgee.t('app-title')}</button>
<div style={{ pointerEvents: 'none' }}>
Expand Down
5 changes: 3 additions & 2 deletions testapps/ngx/angular.json
Expand Up @@ -3,7 +3,8 @@
"version": 1,
"newProjectRoot": "projects",
"cli": {
"packageManager": "pnpm"
"packageManager": "pnpm",
"analytics": false
},
"projects": {
"sampleapp": {
Expand Down Expand Up @@ -151,7 +152,7 @@
"options": {
"outputPath": "dist/sampleapp/server",
"main": "projects/sampleapp/server.ts",
"tsConfig": "projects/sampleapp/tsconfig.server.json",
"tsConfig": "projects/sampleapp/tsconfig.server.json"
},
"configurations": {
"production": {
Expand Down

0 comments on commit 0244269

Please sign in to comment.