🎯 MapView v2.0 - Global Deployment Ready

 MAJOR FEATURES:
• Auto-zoom intelligence với smart bounds fitting
• Enhanced 3D GPS markers với pulsing effects
• Professional route display với 6-layer rendering
• Status-based parking icons với availability indicators
• Production-ready build optimizations

🗺️ AUTO-ZOOM FEATURES:
• Smart bounds fitting cho GPS + selected parking
• Adaptive padding (50px) cho visual balance
• Max zoom control (level 16) để tránh quá gần
• Dynamic centering khi không có selection

🎨 ENHANCED VISUALS:
• 3D GPS marker với multi-layer pulse effects
• Advanced parking icons với status colors
• Selection highlighting với animation
• Dimming system cho non-selected items

🛣️ ROUTE SYSTEM:
• OpenRouteService API integration
• Multi-layer route rendering (glow, shadow, main, animated)
• Real-time distance & duration calculation
• Visual route info trong popup

📱 PRODUCTION READY:
• SSR safe với dynamic imports
• Build errors resolved
• Global deployment via Vercel
• Optimized performance

🌍 DEPLOYMENT:
• Vercel: https://whatever-ctk2auuxr-phong12hexdockworks-projects.vercel.app
• Bundle size: 22.8 kB optimized
• Global CDN distribution
• HTTPS enabled

💾 VERSION CONTROL:
• MapView-v2.0.tsx backup created
• MAPVIEW_VERSIONS.md documentation
• Full version history tracking
This commit is contained in:
2025-07-20 19:52:16 +07:00
parent 3203463a6a
commit c65cc97a33
64624 changed files with 7199453 additions and 6462 deletions

View File

@@ -0,0 +1,5 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginConfig } from '../plugin-config';
import type { ForkTsCheckerWebpackPluginState } from '../plugin-state';
declare function interceptDoneToGetDevServerTap(compiler: webpack.Compiler, config: ForkTsCheckerWebpackPluginConfig, state: ForkTsCheckerWebpackPluginState): void;
export { interceptDoneToGetDevServerTap };

View File

@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.interceptDoneToGetDevServerTap = void 0;
const infrastructure_logger_1 = require("../infrastructure-logger");
function interceptDoneToGetDevServerTap(compiler, config, state) {
const { debug } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
// inspired by https://github.com/ypresto/fork-ts-checker-async-overlay-webpack-plugin
compiler.hooks.done.intercept({
register: (tap) => {
if (tap.name === 'webpack-dev-server' && tap.type === 'sync' && config.devServer) {
debug('Intercepting webpack-dev-server tap.');
state.webpackDevServerDoneTap = tap;
}
return tap;
},
});
}
exports.interceptDoneToGetDevServerTap = interceptDoneToGetDevServerTap;

View File

@@ -0,0 +1,5 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginConfig } from '../plugin-config';
import type { ForkTsCheckerWebpackPluginState } from '../plugin-state';
declare function tapAfterCompileToAddDependencies(compiler: webpack.Compiler, config: ForkTsCheckerWebpackPluginConfig, state: ForkTsCheckerWebpackPluginState): void;
export { tapAfterCompileToAddDependencies };

View File

@@ -0,0 +1,31 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.tapAfterCompileToAddDependencies = void 0;
const infrastructure_logger_1 = require("../infrastructure-logger");
function tapAfterCompileToAddDependencies(compiler, config, state) {
const { debug } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
compiler.hooks.afterCompile.tapPromise('ForkTsCheckerWebpackPlugin', (compilation) => __awaiter(this, void 0, void 0, function* () {
if (compilation.compiler !== compiler) {
// run only for the compiler that the plugin was registered for
return;
}
const dependencies = yield state.dependenciesPromise;
debug(`Got dependencies from the getDependenciesWorker.`, dependencies);
if (dependencies) {
state.lastDependencies = dependencies;
dependencies.files.forEach((file) => {
compilation.fileDependencies.add(file);
});
}
}));
}
exports.tapAfterCompileToAddDependencies = tapAfterCompileToAddDependencies;

View File

@@ -0,0 +1,5 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginConfig } from '../plugin-config';
import type { ForkTsCheckerWebpackPluginState } from '../plugin-state';
declare function tapAfterCompileToGetIssues(compiler: webpack.Compiler, config: ForkTsCheckerWebpackPluginConfig, state: ForkTsCheckerWebpackPluginState): void;
export { tapAfterCompileToGetIssues };

View File

@@ -0,0 +1,52 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.tapAfterCompileToGetIssues = void 0;
const infrastructure_logger_1 = require("../infrastructure-logger");
const issue_webpack_error_1 = require("../issue/issue-webpack-error");
const plugin_hooks_1 = require("../plugin-hooks");
function tapAfterCompileToGetIssues(compiler, config, state) {
const hooks = (0, plugin_hooks_1.getPluginHooks)(compiler);
const { debug } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
compiler.hooks.afterCompile.tapPromise('ForkTsCheckerWebpackPlugin', (compilation) => __awaiter(this, void 0, void 0, function* () {
if (compilation.compiler !== compiler) {
// run only for the compiler that the plugin was registered for
return;
}
let issues = [];
try {
issues = yield state.issuesPromise;
}
catch (error) {
hooks.error.call(error, compilation);
return;
}
debug('Got issues from getIssuesWorker.', issues === null || issues === void 0 ? void 0 : issues.length);
if (!issues) {
// some error has been thrown or it was canceled
return;
}
// filter list of issues by provided issue predicate
issues = issues.filter(config.issue.predicate);
// modify list of issues in the plugin hooks
issues = hooks.issues.call(issues, compilation);
issues.forEach((issue) => {
const error = new issue_webpack_error_1.IssueWebpackError(config.formatter.format(issue), config.formatter.pathType, issue);
if (issue.severity === 'warning') {
compilation.warnings.push(error);
}
else {
compilation.errors.push(error);
}
});
}));
}
exports.tapAfterCompileToGetIssues = tapAfterCompileToGetIssues;

View File

@@ -0,0 +1,4 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginState } from '../plugin-state';
declare function tapAfterEnvironmentToPatchWatching(compiler: webpack.Compiler, state: ForkTsCheckerWebpackPluginState): void;
export { tapAfterEnvironmentToPatchWatching };

View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tapAfterEnvironmentToPatchWatching = void 0;
const infrastructure_logger_1 = require("../infrastructure-logger");
const inclusive_node_watch_file_system_1 = require("../watch/inclusive-node-watch-file-system");
function tapAfterEnvironmentToPatchWatching(compiler, state) {
const { debug } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
compiler.hooks.afterEnvironment.tap('ForkTsCheckerWebpackPlugin', () => {
const watchFileSystem = compiler.watchFileSystem;
if (watchFileSystem) {
debug("Overwriting webpack's watch file system.");
// wrap original watch file system
compiler.watchFileSystem = new inclusive_node_watch_file_system_1.InclusiveNodeWatchFileSystem(
// we use some internals here
watchFileSystem, compiler, state);
}
else {
debug('No watch file system found - plugin may not work correctly.');
}
});
}
exports.tapAfterEnvironmentToPatchWatching = tapAfterEnvironmentToPatchWatching;

View File

@@ -0,0 +1,5 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginConfig } from '../plugin-config';
import type { ForkTsCheckerWebpackPluginState } from '../plugin-state';
declare function tapDoneToAsyncGetIssues(compiler: webpack.Compiler, config: ForkTsCheckerWebpackPluginConfig, state: ForkTsCheckerWebpackPluginState): void;
export { tapDoneToAsyncGetIssues };

View File

@@ -0,0 +1,86 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.tapDoneToAsyncGetIssues = void 0;
const chalk_1 = __importDefault(require("chalk"));
const stats_formatter_1 = require("../formatter/stats-formatter");
const webpack_formatter_1 = require("../formatter/webpack-formatter");
const infrastructure_logger_1 = require("../infrastructure-logger");
const issue_webpack_error_1 = require("../issue/issue-webpack-error");
const plugin_hooks_1 = require("../plugin-hooks");
const is_pending_1 = require("../utils/async/is-pending");
const wait_1 = require("../utils/async/wait");
function tapDoneToAsyncGetIssues(compiler, config, state) {
const hooks = (0, plugin_hooks_1.getPluginHooks)(compiler);
const { debug } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
compiler.hooks.done.tap('ForkTsCheckerWebpackPlugin', (stats) => __awaiter(this, void 0, void 0, function* () {
if (stats.compilation.compiler !== compiler) {
// run only for the compiler that the plugin was registered for
return;
}
const issuesPromise = state.issuesPromise;
let issues;
try {
if (yield (0, is_pending_1.isPending)(issuesPromise)) {
hooks.waiting.call(stats.compilation);
config.logger.log(chalk_1.default.cyan('Type-checking in progress...'));
}
else {
// wait 10ms to log issues after webpack stats
yield (0, wait_1.wait)(10);
}
issues = yield issuesPromise;
}
catch (error) {
hooks.error.call(error, stats.compilation);
return;
}
if (!issues || // some error has been thrown
state.issuesPromise !== issuesPromise // we have a new request - don't show results for the old one
) {
return;
}
debug(`Got ${(issues === null || issues === void 0 ? void 0 : issues.length) || 0} issues from getIssuesWorker.`);
// filter list of issues by provided issue predicate
issues = issues.filter(config.issue.predicate);
// modify list of issues in the plugin hooks
issues = hooks.issues.call(issues, stats.compilation);
const formatter = (0, webpack_formatter_1.createWebpackFormatter)(config.formatter.format, config.formatter.pathType);
if (issues.length) {
// follow webpack's approach - one process.write to stderr with all errors and warnings
config.logger.error(issues.map((issue) => formatter(issue)).join('\n'));
// print stats of the compilation
config.logger.log((0, stats_formatter_1.statsFormatter)(issues, stats));
}
else {
config.logger.log(chalk_1.default.green('No errors found.'));
}
// report issues to webpack-dev-server, if it's listening
// skip reporting if there are no issues, to avoid an extra hot reload
if (issues.length && state.webpackDevServerDoneTap) {
issues.forEach((issue) => {
const error = new issue_webpack_error_1.IssueWebpackError(config.formatter.format(issue), config.formatter.pathType, issue);
if (issue.severity === 'warning') {
stats.compilation.warnings.push(error);
}
else {
stats.compilation.errors.push(error);
}
});
debug('Sending issues to the webpack-dev-server.');
state.webpackDevServerDoneTap.fn(stats);
}
}));
}
exports.tapDoneToAsyncGetIssues = tapDoneToAsyncGetIssues;

View File

@@ -0,0 +1,4 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginConfig } from '../plugin-config';
declare function tapErrorToLogMessage(compiler: webpack.Compiler, config: ForkTsCheckerWebpackPluginConfig): void;
export { tapErrorToLogMessage };

View File

@@ -0,0 +1,32 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.tapErrorToLogMessage = void 0;
const chalk_1 = __importDefault(require("chalk"));
const plugin_hooks_1 = require("../plugin-hooks");
const rpc_1 = require("../rpc");
const abort_error_1 = require("../utils/async/abort-error");
function tapErrorToLogMessage(compiler, config) {
const hooks = (0, plugin_hooks_1.getPluginHooks)(compiler);
hooks.error.tap('ForkTsCheckerWebpackPlugin', (error) => {
if (error instanceof abort_error_1.AbortError) {
return;
}
config.logger.error(String(error));
if (error instanceof rpc_1.RpcExitError) {
if (error.signal === 'SIGINT') {
config.logger.error(chalk_1.default.red('Issues checking service interrupted - If running in a docker container, this may be caused ' +
"by the container running out of memory. If so, try increasing the container's memory limit " +
'or lowering the `memoryLimit` value in the ForkTsCheckerWebpackPlugin configuration.'));
}
else {
config.logger.error(chalk_1.default.red('Issues checking service aborted - probably out of memory. ' +
'Check the `memoryLimit` option in the ForkTsCheckerWebpackPlugin configuration.\n' +
"If increasing the memory doesn't solve the issue, it's most probably a bug in the TypeScript."));
}
}
});
}
exports.tapErrorToLogMessage = tapErrorToLogMessage;

View File

@@ -0,0 +1,8 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginConfig } from '../plugin-config';
import type { ForkTsCheckerWebpackPluginState } from '../plugin-state';
import type { RpcWorker } from '../rpc';
import type { GetDependenciesWorker } from '../typescript/worker/get-dependencies-worker';
import type { GetIssuesWorker } from '../typescript/worker/get-issues-worker';
declare function tapStartToRunWorkers(compiler: webpack.Compiler, getIssuesWorker: RpcWorker<GetIssuesWorker>, getDependenciesWorker: RpcWorker<GetDependenciesWorker>, config: ForkTsCheckerWebpackPluginConfig, state: ForkTsCheckerWebpackPluginState): void;
export { tapStartToRunWorkers };

View File

@@ -0,0 +1,132 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.tapStartToRunWorkers = void 0;
const node_abort_controller_1 = require("node-abort-controller");
const files_change_1 = require("../files-change");
const infrastructure_logger_1 = require("../infrastructure-logger");
const plugin_hooks_1 = require("../plugin-hooks");
const plugin_pools_1 = require("../plugin-pools");
const intercept_done_to_get_dev_server_tap_1 = require("./intercept-done-to-get-dev-server-tap");
const tap_after_compile_to_get_issues_1 = require("./tap-after-compile-to-get-issues");
const tap_done_to_async_get_issues_1 = require("./tap-done-to-async-get-issues");
function tapStartToRunWorkers(compiler, getIssuesWorker, getDependenciesWorker, config, state) {
const hooks = (0, plugin_hooks_1.getPluginHooks)(compiler);
const { log, debug } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
compiler.hooks.run.tap('ForkTsCheckerWebpackPlugin', () => {
if (!state.initialized) {
debug('Initializing plugin for single run (not async).');
state.initialized = true;
state.watching = false;
(0, tap_after_compile_to_get_issues_1.tapAfterCompileToGetIssues)(compiler, config, state);
}
});
compiler.hooks.watchRun.tap('ForkTsCheckerWebpackPlugin', () => __awaiter(this, void 0, void 0, function* () {
if (!state.initialized) {
state.initialized = true;
state.watching = true;
if (config.async) {
debug('Initializing plugin for watch run (async).');
(0, tap_done_to_async_get_issues_1.tapDoneToAsyncGetIssues)(compiler, config, state);
(0, intercept_done_to_get_dev_server_tap_1.interceptDoneToGetDevServerTap)(compiler, config, state);
}
else {
debug('Initializing plugin for watch run (not async).');
(0, tap_after_compile_to_get_issues_1.tapAfterCompileToGetIssues)(compiler, config, state);
}
}
}));
compiler.hooks.compilation.tap('ForkTsCheckerWebpackPlugin', (compilation) => __awaiter(this, void 0, void 0, function* () {
if (compilation.compiler !== compiler) {
// run only for the compiler that the plugin was registered for
return;
}
// get current iteration number
const iteration = ++state.iteration;
// abort previous iteration
if (state.abortController) {
debug(`Aborting iteration ${iteration - 1}.`);
state.abortController.abort();
}
// create new abort controller for the new iteration
const abortController = new node_abort_controller_1.AbortController();
state.abortController = abortController;
let filesChange = {};
if (state.watching) {
filesChange = (0, files_change_1.consumeFilesChange)(compiler);
log([
'Calling reporter service for incremental check.',
` Changed files: ${JSON.stringify(filesChange.changedFiles)}`,
` Deleted files: ${JSON.stringify(filesChange.deletedFiles)}`,
].join('\n'));
}
else {
log('Calling reporter service for single check.');
}
filesChange = yield hooks.start.promise(filesChange, compilation);
let aggregatedFilesChange = filesChange;
if (state.aggregatedFilesChange) {
aggregatedFilesChange = (0, files_change_1.aggregateFilesChanges)([aggregatedFilesChange, filesChange]);
debug([
`Aggregating with previous files change, iteration ${iteration}.`,
` Changed files: ${JSON.stringify(aggregatedFilesChange.changedFiles)}`,
` Deleted files: ${JSON.stringify(aggregatedFilesChange.deletedFiles)}`,
].join('\n'));
}
state.aggregatedFilesChange = aggregatedFilesChange;
// submit one at a time for a single compiler
state.issuesPromise = (state.issuesPromise || Promise.resolve())
// resolve to undefined on error
.catch(() => undefined)
.then(() => {
// early return
if (abortController.signal.aborted) {
return undefined;
}
debug(`Submitting the getIssuesWorker to the pool, iteration ${iteration}.`);
return plugin_pools_1.issuesPool.submit(() => __awaiter(this, void 0, void 0, function* () {
try {
debug(`Running the getIssuesWorker, iteration ${iteration}.`);
const issues = yield getIssuesWorker(aggregatedFilesChange, state.watching);
if (state.aggregatedFilesChange === aggregatedFilesChange) {
state.aggregatedFilesChange = undefined;
}
if (state.abortController === abortController) {
state.abortController = undefined;
}
return issues;
}
catch (error) {
hooks.error.call(error, compilation);
return undefined;
}
finally {
debug(`The getIssuesWorker finished its job, iteration ${iteration}.`);
}
}), abortController.signal);
});
debug(`Submitting the getDependenciesWorker to the pool, iteration ${iteration}.`);
state.dependenciesPromise = plugin_pools_1.dependenciesPool.submit(() => __awaiter(this, void 0, void 0, function* () {
try {
debug(`Running the getDependenciesWorker, iteration ${iteration}.`);
return yield getDependenciesWorker(filesChange);
}
catch (error) {
hooks.error.call(error, compilation);
return undefined;
}
finally {
debug(`The getDependenciesWorker finished its job, iteration ${iteration}.`);
}
})); // don't pass abortController.signal because getDependencies() is blocking
}));
}
exports.tapStartToRunWorkers = tapStartToRunWorkers;

View File

@@ -0,0 +1,5 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginState } from '../plugin-state';
import type { RpcWorker } from '../rpc';
declare function tapStopToTerminateWorkers(compiler: webpack.Compiler, getIssuesWorker: RpcWorker, getDependenciesWorker: RpcWorker, state: ForkTsCheckerWebpackPluginState): void;
export { tapStopToTerminateWorkers };

View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tapStopToTerminateWorkers = void 0;
const infrastructure_logger_1 = require("../infrastructure-logger");
function tapStopToTerminateWorkers(compiler, getIssuesWorker, getDependenciesWorker, state) {
const { debug } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
const terminateWorkers = () => {
debug('Compiler is going to close - terminating workers...');
getIssuesWorker.terminate();
getDependenciesWorker.terminate();
};
compiler.hooks.watchClose.tap('ForkTsCheckerWebpackPlugin', () => {
terminateWorkers();
});
compiler.hooks.done.tap('ForkTsCheckerWebpackPlugin', () => {
if (!state.watching) {
terminateWorkers();
}
});
compiler.hooks.failed.tap('ForkTsCheckerWebpackPlugin', () => {
if (!state.watching) {
terminateWorkers();
}
});
}
exports.tapStopToTerminateWorkers = tapStopToTerminateWorkers;