diff --git a/.storybook/__mocks__/server-mock.ts b/.storybook/__mocks__/server-mock.ts index 4155f3a..97987c6 100644 --- a/.storybook/__mocks__/server-mock.ts +++ b/.storybook/__mocks__/server-mock.ts @@ -1,6 +1,5 @@ import { ReactRenderer } from '@storybook/react'; import { DecoratorFunction } from '@storybook/types'; -// import * as actualServerFunctions from '../../src/server'; enum StrategyOption { AuroraFinancialGroup = 'aurora', diff --git a/package-lock.json b/package-lock.json index 6326f2a..b182834 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,6 +56,7 @@ "module-to-cdn": "^3.1.5", "storybook": "^8.3.6", "style-loader": "^4.0.0", + "typescript": "^5.6.3", "vitest": "^2.1.3", "webpack": "^5.95.0", "webpack-bundle-analyzer": "^4.10.2", @@ -2607,6 +2608,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@google/clasp/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/@google/clasp/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -14031,6 +14045,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ts2gas/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/tsconfig-paths": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", @@ -14089,16 +14116,16 @@ } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/undici-types": { diff --git a/package.json b/package.json index 362f1cd..d327c6b 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "dev": "npm run storybook", "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": "NODE_ENV=production webpack --progress", + "build": "NODE_ENV=production tsc && webpack --progress", + "typecheck": "tsc", "deploy": "rm -rf dist && npm run build && npm run publish", "test": "vitest", "test:coverage": "vitest --coverage", @@ -40,7 +41,6 @@ "@babel/preset-react": "^7.25.9", "@babel/preset-typescript": "^7.25.9", "@effortlessmotion/dynamic-cdn-webpack-plugin": "^5.0.1", - "html-inline-script-webpack-plugin": "^3.2.1", "@google/clasp": "^2.4.2", "@storybook/addon-essentials": "^8.3.6", "@storybook/addon-interactions": "^8.3.6", @@ -64,10 +64,12 @@ "gas-client": "^1.1.1", "gas-types-detailed": "^1.1.2", "gas-webpack-plugin": "^2.6.0", + "html-inline-script-webpack-plugin": "^3.2.1", "html-webpack-plugin": "^5.6.3", "module-to-cdn": "^3.1.5", "storybook": "^8.3.6", "style-loader": "^4.0.0", + "typescript": "^5.6.3", "vitest": "^2.1.3", "webpack": "^5.95.0", "webpack-bundle-analyzer": "^4.10.2", diff --git a/src/client/import-dialog/utils.ts b/src/client/import-dialog/utils.ts index fdea999..d76f6a6 100644 --- a/src/client/import-dialog/utils.ts +++ b/src/client/import-dialog/utils.ts @@ -1,4 +1,4 @@ -import { Table } from '../../server/types'; +import { Table } from '../../common/types'; export const acceptedMimeTypes = ['text/csv', 'application/vnd.ms-excel']; diff --git a/src/client/settings-dialog/components/AutomaticCategorizationForm.tsx b/src/client/settings-dialog/components/AutomaticCategorizationForm.tsx index 7cdf799..73962cb 100644 --- a/src/client/settings-dialog/components/AutomaticCategorizationForm.tsx +++ b/src/client/settings-dialog/components/AutomaticCategorizationForm.tsx @@ -1,6 +1,5 @@ import { Alert, Button, Divider, Grid, Stack, Typography } from '@mui/material'; import { FormEvent, Fragment, useEffect, useState } from 'react'; -import { serverFunctions } from '../../utils/serverFunctions'; import { FireColumnRules } from '../../../server/types'; import { FormRule } from './FormRule'; @@ -28,12 +27,12 @@ export const AutomaticCategorizationForm = () => { console.log(formData); }; - const saveAutomaticCategorizationConfig = () => { - // parse form data into configuration data - const formData = new FormData(); + // const saveAutomaticCategorizationConfig = () => { + // // parse form data into configuration data + // const formData = new FormData(); - // send configuration data to server - }; + // // send configuration data to server + // }; useEffect(() => { // serverFunctions diff --git a/src/client/settings-dialog/components/ImportRulesForm.tsx b/src/client/settings-dialog/components/ImportRulesForm.tsx index 71e34e7..f8d91a2 100644 --- a/src/client/settings-dialog/components/ImportRulesForm.tsx +++ b/src/client/settings-dialog/components/ImportRulesForm.tsx @@ -1,5 +1,4 @@ -import { Alert, Button } from '@mui/material'; -import React from 'react'; +import { Alert } from '@mui/material'; export const ImportRulesForm = () => { return ( diff --git a/src/server/category-detection/index.ts b/src/server/category-detection/index.ts index 68650d5..2fc7c96 100644 --- a/src/server/category-detection/index.ts +++ b/src/server/category-detection/index.ts @@ -57,6 +57,7 @@ export const categoriesTermsMap: CategoryDetectionConfigOld = { Miscellaneous: [], }; +// @ts-ignore const getCategoryMatchesMap = (): CategoryDetectionConfig => { try { const storeObject = PropertiesService.getDocumentProperties().getProperty( diff --git a/src/server/remote-calls.ts b/src/server/remote-calls.ts index 38bd387..4e7b003 100644 --- a/src/server/remote-calls.ts +++ b/src/server/remote-calls.ts @@ -101,29 +101,21 @@ export function generatePreview( result: Table; newBalance?: number; } { - // perform before import rules and return the data for preview - - const config = Config.getConfig(); - let amounts = []; - let decimalSeparator = '.'; switch (strategy) { case StrategyOption.N26: - decimalSeparator = config.n26.decimalSeparator; amounts = TableUtils.retrieveColumn(table, n26Cols.Amount); break; case StrategyOption.OPENBANK: - decimalSeparator = config.openbank.decimalSeparator; amounts = TableUtils.retrieveColumn(table, openbankCols.Importe); break; case StrategyOption.RABO: - decimalSeparator = config.rabobank.decimalSeparator; amounts = TableUtils.retrieveColumn(table, raboCols.Bedrag); break; } const amountNumbers = amounts - .map((value) => Transformers.transformMoney(value, '.')) + .map((value) => Transformers.transformMoney(value)) .filter(isNumeric); const newBalance = calculateNewBalance(strategy, amountNumbers); diff --git a/src/server/table-utils.ts b/src/server/table-utils.ts index cd7f617..e52d352 100644 --- a/src/server/table-utils.ts +++ b/src/server/table-utils.ts @@ -72,7 +72,7 @@ export class TableUtils { */ static transpose(outerlist: T[][]): T[][] { let i = 0; - let result = []; + let result: T[][] = []; while (i < outerlist.length) { let innerlist = outerlist[i]; let j = 0; diff --git a/test-setup.ts b/test-setup.ts index 72dd962..0a1924f 100644 --- a/test-setup.ts +++ b/test-setup.ts @@ -17,7 +17,7 @@ class Sheet { class Spreadsheet { static getSheets = vi.fn(() => [Sheet]); - static getRangeByName = vi.fn((name: string) => Range); + static getRangeByName = vi.fn(() => Range); } class SpreadSheetApp { diff --git a/tsconfig.json b/tsconfig.json index 258c0b0..752d2e0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,17 +1,24 @@ { "compilerOptions": { + // because we use Babel compiler we don't let TS emit any files + // we just want to use it as a type checker + "noEmit": true, "strict": true, - "moduleResolution": "Bundler", + "moduleResolution": "Node", "allowSyntheticDefaultImports": true, "module": "ES6", "esModuleInterop": true, "noImplicitAny": true, "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, "strictNullChecks": true, + "skipLibCheck": true, "lib": ["ES2023", "DOM", "DOM.Iterable"], "types": ["gas-types-detailed", "vitest/globals"], "jsx": "react-jsx" }, + "exclude": ["node_modules/*"], "include": [ // include normal sources "src/**/*", diff --git a/webpack.config.ts b/webpack.config.ts index 4f4ab85..50cbae0 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -3,12 +3,12 @@ ********************************/ import path from 'path'; import { DefinePlugin, Configuration } from 'webpack'; -import CopyWebpackPlugin from 'copy-webpack-plugin'; +import CopyPlugin from 'copy-webpack-plugin'; import GasPlugin from 'gas-webpack-plugin'; import HtmlWebpackPlugin from 'html-webpack-plugin'; import HtmlInlineScriptPlugin from 'html-inline-script-webpack-plugin'; -import DynamicCdnWebpackPlugin from '@effortlessmotion/dynamic-cdn-webpack-plugin'; -import moduleToCdn from 'module-to-cdn'; +import DynamicCDNPlugin from '@effortlessmotion/dynamic-cdn-webpack-plugin'; +import moduleToCDN from 'module-to-cdn'; const isProd = process.env.NODE_ENV === 'production'; @@ -72,7 +72,7 @@ const copyFilesConfig: Configuration = { publicPath, }, plugins: [ - new CopyWebpackPlugin({ + new CopyPlugin({ patterns: [ { from: copyAppscriptEntry, @@ -152,7 +152,7 @@ type DynamicCDNEntry = { // DynamicCdnWebpackPlugin settings // these settings help us load 'react', 'react-dom' and the packages defined below from a CDN -const DynamicCdnWebpackPluginConfig = { +const DynamicCDNWebpackPluginConfig = { // set "verbose" to true to print console logs on CDN usage while webpack builds verbose: process.env.VERBOSE ? true : false, only: [ @@ -169,7 +169,7 @@ const DynamicCdnWebpackPluginConfig = { version: string, options: { env: string } ): DynamicCDNEntry | null => { - const moduleDetails = moduleToCdn(packageName, version, options); + const moduleDetails = moduleToCDN(packageName, version, options); const packageSuffix = isProd ? '.min.js' : '.js'; // don't externalize react during development due to issue with react-refresh @@ -239,7 +239,7 @@ const clientConfigs = clientEntrypoints.map( inject: 'body', }), // this plugin allows us to add dynamically load packages from a CDN - new DynamicCdnWebpackPlugin(DynamicCdnWebpackPluginConfig), + new DynamicCDNPlugin(DynamicCDNWebpackPluginConfig), // add the generated js code to the html file inline new HtmlInlineScriptPlugin(), ],