diff --git a/package.json b/package.json index a42d019..90fc5db 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "author": "Melle Dijkstra", "description": "Google App Script utilities to automate the FIRE google sheet", "license": "MIT", + "type": "module", "private": true, "workspaces": [ "client", @@ -18,6 +19,7 @@ "analyze:server": "ANALYZE=true webpack --config-name SERVER --profile --json > dist/stats.json && webpack-bundle-analyzer dist/stats.json", "analyze:client": "ANALYZE=true webpack --config-name 'CLIENT:import' --profile --json > dist/stats.json && webpack-bundle-analyzer dist/stats.json", "build": "(export NODE_ENV=production; tsc && webpack --progress)", + "build:dev": "NODE_ENV=development webpack --progress", "typecheck": "tsc", "deploy": "rm -rf dist && npm run build && npm run publish", "test": "vitest", diff --git a/src/server/category-detection/index.ts b/src/server/category-detection/index.ts index c55e5c2..ab257ac 100644 --- a/src/server/category-detection/index.ts +++ b/src/server/category-detection/index.ts @@ -1,4 +1,5 @@ import { PROP_AUTOMATIC_CATEGORIES_CONFIG } from '../../common/constants'; +import { Logger } from '../logger'; import { categoriesTermsMap } from './category-term-map'; import { CategoryDetectionConfig } from './types'; @@ -15,7 +16,7 @@ const getCategoryMatchesMap = (): CategoryDetectionConfig => { return JSON.parse(storeObject); } catch (ignore) { - console.log(ignore); + Logger.log('Error while fetching category detection config', ignore); } return {}; diff --git a/src/server/logger.test.ts b/src/server/logger.test.ts new file mode 100644 index 0000000..59b311e --- /dev/null +++ b/src/server/logger.test.ts @@ -0,0 +1,56 @@ +import { Logger } from './logger'; + +describe('Logger', () => { + let originalEnv: string | undefined; + + const consoleSpy = vi.spyOn(console, 'log'); + consoleSpy.mockImplementation(() => { + // no-op, prevent logging when running tests + }); + + beforeEach(() => { + originalEnv = process.env.APP_ENV; + Logger.disable(); + }); + + afterEach(() => { + process.env.APP_ENV = originalEnv; + consoleSpy.mockReset(); + }); + + test('should log message when enabled', () => { + Logger.enable(); + Logger.log('Test message'); + expect(consoleSpy).toHaveBeenCalledWith('[FIRE]:', 'Test message'); + }); + + test('should not log message when disabled', () => { + Logger.log('Test message'); + expect(consoleSpy).not.toHaveBeenCalled(); + }); + + test('should enable logging', () => { + Logger.enable(); + expect(Logger['isEnabled']).toBe(true); + }); + + test('should disable logging', () => { + Logger.enable(); + Logger.disable(); + expect(Logger['isEnabled']).toBe(false); + }); + + test('should log message if APP_ENV is development', () => { + process.env.APP_ENV = 'development'; + Logger.reset(); + Logger.log('Test message'); + expect(consoleSpy).toHaveBeenCalledWith('[FIRE]:', 'Test message'); + }); + + test('should not log message if APP_ENV is not development', () => { + process.env.APP_ENV = 'production'; + Logger.reset(); + Logger.log('Test message'); + expect(consoleSpy).not.toHaveBeenCalled(); + }); +}); diff --git a/src/server/logger.ts b/src/server/logger.ts new file mode 100644 index 0000000..8a26091 --- /dev/null +++ b/src/server/logger.ts @@ -0,0 +1,21 @@ +export class Logger { + private static isEnabled: boolean = process.env.APP_ENV === 'development'; + + static log(message?: any, ...optionalParams: any[]): void { + if (this.isEnabled) { + console.log(`[FIRE]:`, message, ...optionalParams); + } + } + + static enable(): void { + this.isEnabled = true; + } + + static disable(): void { + this.isEnabled = false; + } + + static reset(): void { + this.isEnabled = process.env.APP_ENV === 'development'; + } +} diff --git a/src/server/table-utils.ts b/src/server/table-utils.ts index e097d92..90af893 100644 --- a/src/server/table-utils.ts +++ b/src/server/table-utils.ts @@ -2,6 +2,7 @@ import type { Table } from '../common/types'; import { sourceSheet } from './globals'; import { FIRE_COLUMNS } from '../common/constants'; import { FireColumnRules, InputColumn } from './types'; +import { Logger } from './logger'; const EMPTY = ''; @@ -61,7 +62,7 @@ export class TableUtils { static importData(data: Table) { const rowCount = data.length; const colCount = data[0].length; - console.log(`importing data (rows: ${rowCount}, cols: ${colCount})`); + Logger.log(`importing data (rows: ${rowCount}, cols: ${colCount})`); sourceSheet ?.insertRowsBefore(2, rowCount) .getRange(2, 1, rowCount, colCount) diff --git a/webpack.config.ts b/webpack.config.ts index 3f537f3..3167dbb 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -24,7 +24,9 @@ const serverEntry = './src/server/index.ts'; // define appsscript.json file path const copyAppscriptEntry = './appsscript.json'; -const envVars = {}; +const envVars = { + APP_ENV: process.env.APP_ENV ?? process.env.NODE_ENV ?? 'development', +}; /********************************* * define entrypoints @@ -154,7 +156,7 @@ type DynamicCDNEntry = { // DynamicCdnWebpackPlugin settings // these settings help us load 'react', 'react-dom' and the packages defined below from a CDN const DynamicCDNWebpackPluginConfig = { - disable: false, + disable: !isProd ? true : false, // set "verbose" to true to print console logs on CDN usage while webpack builds verbose: process.env.VERBOSE ? true : false, only: [ @@ -298,6 +300,9 @@ const serverConfig: Configuration = { ], }, plugins: [ + new DefinePlugin({ + 'process.env': JSON.stringify(envVars), + }), new GasPlugin({ // removes need for assigning public server functions to "global" autoGlobalExportsFiles: [serverEntry],