mirror of
https://github.com/LightZirconite/Microsoft-Rewards-Bot.git
synced 2026-01-09 17:06:15 +00:00
feat: Centralize browser instance creation to eliminate duplication in Desktop and Mobile flows
fix: Update error message for HTTP 400 checks to English refactor: Improve logging for network idle wait timeout in Workers fix: Initialize lastError in Axios client to prevent undefined errors chore: Update tsconfig to include path mappings for better module resolution
This commit is contained in:
@@ -25,13 +25,15 @@ async function main(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Banner
|
// Banner
|
||||||
console.log('\n' + '='.repeat(60))
|
log(false, 'CREATOR-CLI', '', 'log') // Empty line
|
||||||
|
log(false, 'CREATOR-CLI', '='.repeat(60), 'log', 'cyan')
|
||||||
log(false, 'CREATOR-CLI', '🚀 Microsoft Account Creator', 'log', 'cyan')
|
log(false, 'CREATOR-CLI', '🚀 Microsoft Account Creator', 'log', 'cyan')
|
||||||
console.log('='.repeat(60))
|
log(false, 'CREATOR-CLI', '='.repeat(60), 'log', 'cyan')
|
||||||
console.log('\x1b[33m⚠️ DO NOT INTERACT WITH THE BROWSER DURING AUTOMATION\x1b[0m')
|
log(false, 'CREATOR-CLI', '⚠️ DO NOT INTERACT WITH THE BROWSER DURING AUTOMATION', 'warn', 'yellow')
|
||||||
console.log('\x1b[33m Everything is fully automated. Any interaction may break the process.\x1b[0m')
|
log(false, 'CREATOR-CLI', ' Everything is fully automated. Any interaction may break the process.', 'warn', 'yellow')
|
||||||
console.log('\x1b[33m Only interact when explicitly asked (e.g., CAPTCHA solving).\x1b[0m')
|
log(false, 'CREATOR-CLI', ' Only interact when explicitly asked (e.g., CAPTCHA solving).', 'warn', 'yellow')
|
||||||
console.log('='.repeat(60) + '\n')
|
log(false, 'CREATOR-CLI', '='.repeat(60), 'log', 'cyan')
|
||||||
|
log(false, 'CREATOR-CLI', '', 'log') // Empty line
|
||||||
|
|
||||||
// Display detected arguments
|
// Display detected arguments
|
||||||
if (referralUrl) {
|
if (referralUrl) {
|
||||||
@@ -52,7 +54,7 @@ async function main(): Promise<void> {
|
|||||||
log(false, 'CREATOR-CLI', '💡 Tip: Use -y flag to auto-accept all prompts', 'log', 'gray')
|
log(false, 'CREATOR-CLI', '💡 Tip: Use -y flag to auto-accept all prompts', 'log', 'gray')
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log()
|
log(false, 'CREATOR-CLI', '', 'log') // Empty line
|
||||||
|
|
||||||
// Create a temporary bot instance to access browser creation
|
// Create a temporary bot instance to access browser creation
|
||||||
const bot = new MicrosoftRewardsBot(false)
|
const bot = new MicrosoftRewardsBot(false)
|
||||||
@@ -81,9 +83,10 @@ async function main(): Promise<void> {
|
|||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
// Success banner
|
// Success banner
|
||||||
console.log('\n' + '='.repeat(60))
|
log(false, 'CREATOR-CLI', '', 'log') // Empty line
|
||||||
|
log(false, 'CREATOR-CLI', '='.repeat(60), 'log', 'green')
|
||||||
log(false, 'CREATOR-CLI', '✅ ACCOUNT CREATED SUCCESSFULLY!', 'log', 'green')
|
log(false, 'CREATOR-CLI', '✅ ACCOUNT CREATED SUCCESSFULLY!', 'log', 'green')
|
||||||
console.log('='.repeat(60))
|
log(false, 'CREATOR-CLI', '='.repeat(60), 'log', 'green')
|
||||||
|
|
||||||
// Display account details
|
// Display account details
|
||||||
log(false, 'CREATOR-CLI', `📧 Email: ${result.email}`, 'log', 'cyan')
|
log(false, 'CREATOR-CLI', `📧 Email: ${result.email}`, 'log', 'cyan')
|
||||||
@@ -95,9 +98,10 @@ async function main(): Promise<void> {
|
|||||||
log(false, 'CREATOR-CLI', '🔗 Referral: Linked', 'log', 'green')
|
log(false, 'CREATOR-CLI', '🔗 Referral: Linked', 'log', 'green')
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('='.repeat(60))
|
log(false, 'CREATOR-CLI', '='.repeat(60), 'log', 'green')
|
||||||
log(false, 'CREATOR-CLI', '💾 Account details saved to accounts-created/ directory', 'log', 'green')
|
log(false, 'CREATOR-CLI', '💾 Account details saved to accounts-created/ directory', 'log', 'green')
|
||||||
console.log('='.repeat(60) + '\n')
|
log(false, 'CREATOR-CLI', '='.repeat(60), 'log', 'green')
|
||||||
|
log(false, 'CREATOR-CLI', '', 'log') // Empty line
|
||||||
|
|
||||||
// Keep browser open - don't close
|
// Keep browser open - don't close
|
||||||
log(false, 'CREATOR-CLI', '✅ Account creation complete! Browser will remain open.', 'log', 'green')
|
log(false, 'CREATOR-CLI', '✅ Account creation complete! Browser will remain open.', 'log', 'green')
|
||||||
@@ -108,9 +112,11 @@ async function main(): Promise<void> {
|
|||||||
await new Promise(() => {}) // Never resolves
|
await new Promise(() => {}) // Never resolves
|
||||||
} else {
|
} else {
|
||||||
// Failure
|
// Failure
|
||||||
console.log('\n' + '='.repeat(60))
|
log(false, 'CREATOR-CLI', '', 'log') // Empty line
|
||||||
|
log(false, 'CREATOR-CLI', '='.repeat(60), 'error')
|
||||||
log(false, 'CREATOR-CLI', '❌ ACCOUNT CREATION FAILED', 'error')
|
log(false, 'CREATOR-CLI', '❌ ACCOUNT CREATION FAILED', 'error')
|
||||||
console.log('='.repeat(60) + '\n')
|
log(false, 'CREATOR-CLI', '='.repeat(60), 'error')
|
||||||
|
log(false, 'CREATOR-CLI', '', 'log') // Empty line
|
||||||
|
|
||||||
await browserContext.close()
|
await browserContext.close()
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
@@ -118,9 +124,11 @@ async function main(): Promise<void> {
|
|||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const msg = error instanceof Error ? error.message : String(error)
|
const msg = error instanceof Error ? error.message : String(error)
|
||||||
console.log('\n' + '='.repeat(60))
|
log(false, 'CREATOR-CLI', '', 'log') // Empty line
|
||||||
|
log(false, 'CREATOR-CLI', '='.repeat(60), 'error')
|
||||||
log(false, 'CREATOR-CLI', `❌ Fatal error: ${msg}`, 'error')
|
log(false, 'CREATOR-CLI', `❌ Fatal error: ${msg}`, 'error')
|
||||||
console.log('='.repeat(60) + '\n')
|
log(false, 'CREATOR-CLI', '='.repeat(60), 'error')
|
||||||
|
log(false, 'CREATOR-CLI', '', 'log') // Empty line
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,9 +50,10 @@ export default class BrowserFunc {
|
|||||||
this.bot.log(this.bot.isMobile, 'GO-HOME', `Account suspension detected by content text (iteration ${iteration})`, 'error')
|
this.bot.log(this.bot.isMobile, 'GO-HOME', `Account suspension detected by content text (iteration ${iteration})`, 'error')
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
// Ignore errors in text check - not critical
|
// Ignore errors in text check - not critical
|
||||||
this.bot.log(this.bot.isMobile, 'GO-HOME', `Suspension text check skipped: ${e}`, 'warn')
|
const errorMsg = error instanceof Error ? error.message : String(error)
|
||||||
|
this.bot.log(this.bot.isMobile, 'GO-HOME', `Suspension text check skipped: ${errorMsg}`, 'warn')
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
@@ -141,7 +142,8 @@ export default class BrowserFunc {
|
|||||||
await target.waitForSelector(SELECTORS.MORE_ACTIVITIES, { timeout: TIMEOUTS.DASHBOARD_WAIT }).catch((error) => {
|
await target.waitForSelector(SELECTORS.MORE_ACTIVITIES, { timeout: TIMEOUTS.DASHBOARD_WAIT }).catch((error) => {
|
||||||
// Continuing is intentional: page may still be functional even if this specific element is missing
|
// Continuing is intentional: page may still be functional even if this specific element is missing
|
||||||
// The script extraction will catch any real issues
|
// The script extraction will catch any real issues
|
||||||
this.bot.log(this.bot.isMobile, 'GET-DASHBOARD-DATA', `Activities element not found after ${TIMEOUTS.DASHBOARD_WAIT}ms timeout, attempting to proceed: ${error instanceof Error ? error.message : String(error)}`, 'warn')
|
const errorMsg = error instanceof Error ? error.message : String(error)
|
||||||
|
this.bot.log(this.bot.isMobile, 'GET-DASHBOARD-DATA', `Activities element not found after ${TIMEOUTS.DASHBOARD_WAIT}ms timeout, attempting to proceed: ${errorMsg}`, 'warn')
|
||||||
})
|
})
|
||||||
|
|
||||||
let scriptContent = await this.extractDashboardScript(target)
|
let scriptContent = await this.extractDashboardScript(target)
|
||||||
@@ -151,7 +153,10 @@ export default class BrowserFunc {
|
|||||||
|
|
||||||
// Force a navigation retry once before failing hard
|
// Force a navigation retry once before failing hard
|
||||||
await this.goHome(target)
|
await this.goHome(target)
|
||||||
await target.waitForLoadState('domcontentloaded', { timeout: TIMEOUTS.VERY_LONG }).catch(logError('BROWSER-FUNC', 'Dashboard recovery load failed', this.bot.isMobile))
|
await target.waitForLoadState('domcontentloaded', { timeout: TIMEOUTS.VERY_LONG }).catch((error) => {
|
||||||
|
const errorMsg = error instanceof Error ? error.message : String(error)
|
||||||
|
this.bot.log(this.bot.isMobile, 'BROWSER-FUNC', `Dashboard recovery load failed: ${errorMsg}`, 'warn')
|
||||||
|
})
|
||||||
await this.bot.utils.wait(this.bot.isMobile ? TIMEOUTS.LONG : TIMEOUTS.MEDIUM)
|
await this.bot.utils.wait(this.bot.isMobile ? TIMEOUTS.LONG : TIMEOUTS.MEDIUM)
|
||||||
|
|
||||||
scriptContent = await this.extractDashboardScript(target)
|
scriptContent = await this.extractDashboardScript(target)
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ export default class BrowserUtil {
|
|||||||
const isNetworkError = $('body.neterror').length
|
const isNetworkError = $('body.neterror').length
|
||||||
const hasHttp400Error = html.includes('HTTP ERROR 400') ||
|
const hasHttp400Error = html.includes('HTTP ERROR 400') ||
|
||||||
html.includes('This page isn\'t working') ||
|
html.includes('This page isn\'t working') ||
|
||||||
html.includes('Cette page ne fonctionne pas')
|
html.includes('This page is not working')
|
||||||
|
|
||||||
if (isNetworkError || hasHttp400Error) {
|
if (isNetworkError || hasHttp400Error) {
|
||||||
const errorType = hasHttp400Error ? 'HTTP 400' : 'network error'
|
const errorType = hasHttp400Error ? 'HTTP 400' : 'network error'
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
import type { MicrosoftRewardsBot } from '../index'
|
import type { MicrosoftRewardsBot } from '../index'
|
||||||
import type { Account } from '../interface/Account'
|
import type { Account } from '../interface/Account'
|
||||||
|
import { createBrowserInstance } from '../util/BrowserFactory'
|
||||||
import { saveSessionData } from '../util/Load'
|
import { saveSessionData } from '../util/Load'
|
||||||
|
|
||||||
export interface DesktopFlowResult {
|
export interface DesktopFlowResult {
|
||||||
@@ -34,11 +35,8 @@ export class DesktopFlow {
|
|||||||
async run(account: Account): Promise<DesktopFlowResult> {
|
async run(account: Account): Promise<DesktopFlowResult> {
|
||||||
this.bot.log(false, 'DESKTOP-FLOW', 'Starting desktop automation flow')
|
this.bot.log(false, 'DESKTOP-FLOW', 'Starting desktop automation flow')
|
||||||
|
|
||||||
// FIXED: Use proper typed access instead of unsafe type assertion
|
// IMPROVED: Use centralized browser factory to eliminate duplication
|
||||||
const browserModule = await import('../browser/Browser')
|
const browser = await createBrowserInstance(this.bot, account.proxy, account.email)
|
||||||
const Browser = browserModule.default
|
|
||||||
const browserInstance = new Browser(this.bot)
|
|
||||||
const browser = await browserInstance.createBrowser(account.proxy, account.email)
|
|
||||||
|
|
||||||
let keepBrowserOpen = false
|
let keepBrowserOpen = false
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
import type { MicrosoftRewardsBot } from '../index'
|
import type { MicrosoftRewardsBot } from '../index'
|
||||||
import type { Account } from '../interface/Account'
|
import type { Account } from '../interface/Account'
|
||||||
|
import { createBrowserInstance } from '../util/BrowserFactory'
|
||||||
import { saveSessionData } from '../util/Load'
|
import { saveSessionData } from '../util/Load'
|
||||||
import { MobileRetryTracker } from '../util/MobileRetryTracker'
|
import { MobileRetryTracker } from '../util/MobileRetryTracker'
|
||||||
|
|
||||||
@@ -40,11 +41,8 @@ export class MobileFlow {
|
|||||||
): Promise<MobileFlowResult> {
|
): Promise<MobileFlowResult> {
|
||||||
this.bot.log(true, 'MOBILE-FLOW', 'Starting mobile automation flow')
|
this.bot.log(true, 'MOBILE-FLOW', 'Starting mobile automation flow')
|
||||||
|
|
||||||
// FIXED: Use proper typed access instead of unsafe type assertion
|
// IMPROVED: Use centralized browser factory to eliminate duplication
|
||||||
const browserModule = await import('../browser/Browser')
|
const browser = await createBrowserInstance(this.bot, account.proxy, account.email)
|
||||||
const Browser = browserModule.default
|
|
||||||
const browserInstance = new Browser(this.bot)
|
|
||||||
const browser = await browserInstance.createBrowser(account.proxy, account.email)
|
|
||||||
|
|
||||||
let keepBrowserOpen = false
|
let keepBrowserOpen = false
|
||||||
let browserClosed = false
|
let browserClosed = false
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ export class Login {
|
|||||||
const content = await page.content().catch(() => '')
|
const content = await page.content().catch(() => '')
|
||||||
const hasHttp400 = content.includes('HTTP ERROR 400') ||
|
const hasHttp400 = content.includes('HTTP ERROR 400') ||
|
||||||
content.includes('This page isn\'t working') ||
|
content.includes('This page isn\'t working') ||
|
||||||
content.includes('Cette page ne fonctionne pas')
|
content.includes('This page is not working')
|
||||||
|
|
||||||
if (hasHttp400) {
|
if (hasHttp400) {
|
||||||
this.bot.log(this.bot.isMobile, 'LOGIN', 'HTTP 400 detected in content, reloading...', 'warn')
|
this.bot.log(this.bot.isMobile, 'LOGIN', 'HTTP 400 detected in content, reloading...', 'warn')
|
||||||
@@ -188,12 +188,20 @@ export class Login {
|
|||||||
|
|
||||||
await this.disableFido(page)
|
await this.disableFido(page)
|
||||||
|
|
||||||
const [, , portalCheck] = await Promise.allSettled([
|
const [reloadResult, totpResult, portalCheck] = await Promise.allSettled([
|
||||||
this.bot.browser.utils.reloadBadPage(page),
|
this.bot.browser.utils.reloadBadPage(page),
|
||||||
this.tryAutoTotp(page, 'initial landing'),
|
this.tryAutoTotp(page, 'initial landing'),
|
||||||
page.waitForSelector('html[data-role-name="RewardsPortal"]', { timeout: 3000 })
|
page.waitForSelector('html[data-role-name="RewardsPortal"]', { timeout: 3000 })
|
||||||
])
|
])
|
||||||
|
|
||||||
|
// Log any failures for debugging (non-critical)
|
||||||
|
if (reloadResult.status === 'rejected') {
|
||||||
|
this.bot.log(this.bot.isMobile, 'LOGIN', `Reload check failed (non-critical): ${reloadResult.reason}`, 'warn')
|
||||||
|
}
|
||||||
|
if (totpResult.status === 'rejected') {
|
||||||
|
this.bot.log(this.bot.isMobile, 'LOGIN', `Auto-TOTP check failed (non-critical): ${totpResult.reason}`, 'warn')
|
||||||
|
}
|
||||||
|
|
||||||
await this.checkAccountLocked(page)
|
await this.checkAccountLocked(page)
|
||||||
|
|
||||||
const alreadyAuthenticated = portalCheck.status === 'fulfilled'
|
const alreadyAuthenticated = portalCheck.status === 'fulfilled'
|
||||||
@@ -293,10 +301,13 @@ export class Login {
|
|||||||
|
|
||||||
if (!recoveryUsed) {
|
if (!recoveryUsed) {
|
||||||
await this.bot.utils.wait(500)
|
await this.bot.utils.wait(500)
|
||||||
const content = await page.content().catch(() => '')
|
const content = await page.content().catch((err) => {
|
||||||
|
this.bot.log(this.bot.isMobile, 'LOGIN-APP', `Failed to get page content for HTTP 400 check: ${err}`, 'warn')
|
||||||
|
return ''
|
||||||
|
})
|
||||||
const hasHttp400 = content.includes('HTTP ERROR 400') ||
|
const hasHttp400 = content.includes('HTTP ERROR 400') ||
|
||||||
content.includes('This page isn\'t working') ||
|
content.includes('This page isn\'t working') ||
|
||||||
content.includes('Cette page ne fonctionne pas')
|
content.includes('This page is not working')
|
||||||
|
|
||||||
if (hasHttp400) {
|
if (hasHttp400) {
|
||||||
this.bot.log(this.bot.isMobile, 'LOGIN-APP', 'HTTP 400 detected, reloading...', 'warn')
|
this.bot.log(this.bot.isMobile, 'LOGIN-APP', 'HTTP 400 detected, reloading...', 'warn')
|
||||||
@@ -435,7 +446,7 @@ export class Login {
|
|||||||
const content = await page.content().catch(() => '')
|
const content = await page.content().catch(() => '')
|
||||||
const hasHttp400 = content.includes('HTTP ERROR 400') ||
|
const hasHttp400 = content.includes('HTTP ERROR 400') ||
|
||||||
content.includes('This page isn\'t working') ||
|
content.includes('This page isn\'t working') ||
|
||||||
content.includes('Cette page ne fonctionne pas')
|
content.includes('This page is not working')
|
||||||
|
|
||||||
if (hasHttp400) {
|
if (hasHttp400) {
|
||||||
this.bot.log(this.bot.isMobile, 'LOGIN', 'HTTP 400 on session check, reloading...', 'warn')
|
this.bot.log(this.bot.isMobile, 'LOGIN', 'HTTP 400 on session check, reloading...', 'warn')
|
||||||
@@ -1289,7 +1300,7 @@ export class Login {
|
|||||||
const content = await page.content().catch(() => '')
|
const content = await page.content().catch(() => '')
|
||||||
const hasHttp400 = content.includes('HTTP ERROR 400') ||
|
const hasHttp400 = content.includes('HTTP ERROR 400') ||
|
||||||
content.includes('This page isn\'t working') ||
|
content.includes('This page isn\'t working') ||
|
||||||
content.includes('Cette page ne fonctionne pas')
|
content.includes('This page is not working')
|
||||||
|
|
||||||
if (hasHttp400) {
|
if (hasHttp400) {
|
||||||
this.bot.log(this.bot.isMobile, 'LOGIN-BING', 'HTTP 400 detected during Bing verification, reloading...', 'warn')
|
this.bot.log(this.bot.isMobile, 'LOGIN-BING', 'HTTP 400 detected during Bing verification, reloading...', 'warn')
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ export class Workers {
|
|||||||
await page.goto(punchCard.parentPromotion.destinationUrl, { referer: this.bot.config.baseURL })
|
await page.goto(punchCard.parentPromotion.destinationUrl, { referer: this.bot.config.baseURL })
|
||||||
|
|
||||||
// Wait for new page to load, max 10 seconds, however try regardless in case of error
|
// Wait for new page to load, max 10 seconds, however try regardless in case of error
|
||||||
await page.waitForLoadState('networkidle', { timeout: 5000 }).catch(() => { })
|
await page.waitForLoadState('networkidle', { timeout: 5000 }).catch(logError('PUNCH-CARD', 'Network idle wait timeout (non-critical)', this.bot.isMobile))
|
||||||
|
|
||||||
await this.solveActivities(page, activitiesUncompleted, punchCard)
|
await this.solveActivities(page, activitiesUncompleted, punchCard)
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ class AxiosClient {
|
|||||||
return bypassInstance.request(config)
|
return bypassInstance.request(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastError: unknown
|
// FIXED: Initialize lastError to prevent throwing undefined
|
||||||
|
let lastError: unknown = new Error('Request failed with unknown error')
|
||||||
const maxAttempts = 2
|
const maxAttempts = 2
|
||||||
|
|
||||||
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
||||||
|
|||||||
33
src/util/BrowserFactory.ts
Normal file
33
src/util/BrowserFactory.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Browser Factory Utility
|
||||||
|
* Eliminates code duplication between Desktop and Mobile flows
|
||||||
|
*
|
||||||
|
* Centralized browser instance creation logic
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { BrowserContext } from 'rebrowser-playwright'
|
||||||
|
import type { MicrosoftRewardsBot } from '../index'
|
||||||
|
import type { AccountProxy } from '../interface/Account'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a browser instance for the given account
|
||||||
|
* IMPROVEMENT: Extracted from DesktopFlow and MobileFlow to eliminate duplication
|
||||||
|
*
|
||||||
|
* @param bot Bot instance
|
||||||
|
* @param proxy Account proxy configuration
|
||||||
|
* @param email Account email for session naming
|
||||||
|
* @returns Browser context ready to use
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const browser = await createBrowserInstance(bot, account.proxy, account.email)
|
||||||
|
*/
|
||||||
|
export async function createBrowserInstance(
|
||||||
|
bot: MicrosoftRewardsBot,
|
||||||
|
proxy: AccountProxy,
|
||||||
|
email: string
|
||||||
|
): Promise<BrowserContext> {
|
||||||
|
const browserModule = await import('../browser/Browser')
|
||||||
|
const Browser = browserModule.default
|
||||||
|
const browserInstance = new Browser(bot)
|
||||||
|
return await browserInstance.createBrowser(proxy, email)
|
||||||
|
}
|
||||||
@@ -28,6 +28,15 @@
|
|||||||
|
|
||||||
/* Module Resolution Options */
|
/* Module Resolution Options */
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
|
"baseUrl": "./src",
|
||||||
|
"paths": {
|
||||||
|
"@constants": ["constants"],
|
||||||
|
"@interfaces/*": ["interface/*"],
|
||||||
|
"@utils/*": ["util/*"],
|
||||||
|
"@browser/*": ["browser/*"],
|
||||||
|
"@functions/*": ["functions/*"],
|
||||||
|
"@flows/*": ["flows/*"]
|
||||||
|
},
|
||||||
"types": ["node"],
|
"types": ["node"],
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user