开发者
DBNavigator – An DataGrip-inspired Database IDE Built with JavaFX
After months of development, I'm excited to share DBNavigator, a cross-platform database IDE that I've been building from scratch using Java and JavaFX. ✨ Current Features ✅ PostgreSQL support ✅ MySQL support ✅ Modern Datagrip-inspired UI ✅ Multi-tab SQL editor ✅ Syntax highlighting ✅ Schema explorer ✅ Query execution ✅ Professional dark theme ✅ Cross-platform (Windows, Linux & macOS) This project has been an incredible learning journey in desktop application development, JavaFX UI design, database connectivity, and IDE architecture. I'm sharing it with the developer community because I'd genuinely appreciate your honest feedback. I'd love to hear your thoughts on: UI/UX design Performance Missing features Overall developer experience Architecture and code quality Any bugs or improvements you notice Whether you're a Java developer, DBA, or someone who works with databases every day, your feedback would mean a lot and help shape the next version of the project. ⭐ If you find the project interesting, please consider giving it a star on GitHub. GitHub: DBNavigator Thank you for taking the time to review it. Every suggestion, issue report, and critique is greatly appreciated! 🙌
AI 资讯
The SVG Path Data Format, Explained (M, L, C, Q, A, Z)
If you've opened a <path d="..."> string and had no idea what you were looking at, here's the short version: it's a tiny drawing language. A pen moves around a coordinate space, and each letter in the string is an instruction telling it what to do next. TL;DR M / m moves the pen, L / l draws a straight line, C / c and Q / q draw bezier curves, A / a draws an arc, Z / z closes the shape. Uppercase is absolute coordinates, lowercase is relative to the pen's current position. A visual path editor drags the exact same numbers you'd type by hand, it just shows you the curve instead of making you compute it. Reading a path string <path d="M10 10 L90 10 L90 90 Z" /> Broken down: move to (10, 10), draw a line to (90, 10), draw a line to (90, 90), close the path back to the start. That's a right triangle. Every path, no matter how complex, is this same pattern: a command letter followed by however many numbers that command needs, repeated. The command set Command Name What it takes M / m Move to x, y L / l Line to x, y C / c Cubic bezier control1 x/y, control2 x/y, end x/y Q / q Quadratic bezier control x/y, end x/y A / a Arc rx, ry, rotation, large-arc-flag, sweep-flag, end x/y Z / z Close path none C and Q are both bezier curves, the difference is one control point ( Q ) vs two ( C ). Two control points give you more independent influence over each end of the curve; one control point gives you a simpler, more symmetric curve. There are also shorthand continuations ( S / s , T / t ) for chaining smooth curves without repeating a control point, but the six above are what you'll hit constantly. A is the one people avoid writing by hand. Six parameters, two of which are flags (0 or 1) that determine which of four possible arcs you get for the same radii and endpoints. Flip one and you're not slightly off, you're on the opposite side of the ellipse. Absolute vs relative is the part that bites Every command above has an uppercase and lowercase form, and it's not cosmetic: <!-- a
AI 资讯
I Built a Self-Hosted AI Support Widget with Spring Boot (No Monthly SaaS Fees)
Every new SaaS seems to embed ChatGPT these days. Most AI support solutions rely on third-party platforms, monthly subscriptions, and vendor lock-in. While they're great products, I wanted something different. I wanted complete ownership. I wanted to deploy everything on my own server, use my own OpenAI API key, customize every part of the experience, and embed the widget into any website with a single script tag. So I built my own self-hosted AI support widget using Spring Boot and Vanilla JavaScript. Why I Built It When building small products and websites, I realized that customer support quickly becomes a problem. Users have questions about pricing, features, returns, or simply get stuck. Most developers solve this by integrating services like Intercom, Crisp, or Tidio. Those platforms are excellent, but they also mean: Monthly subscription costs Vendor lock-in Customer conversations stored on third-party platforms Limited customization Another external dependency I wanted something that developers could completely own. The Goal The goal was simple. Build an AI-powered customer support widget that developers can deploy on their own server and integrate into any website in less than a minute. The widget should: Answer customer questions using AI Learn from a custom knowledge base Match the company's branding Store conversation history Allow human handoff Be easy to deploy Require only one script tag to embed Technology Stack Java 17 Spring Boot 3 Spring Security Spring Data JPA Thymeleaf Vanilla JavaScript H2 Database (MySQL supported) OpenAI API Architecture The overall architecture is intentionally simple. Visitor │ ▼ AI Chat Widget (Vanilla JavaScript) │ ▼ Spring Boot REST API │ ▼ OpenAI API │ ▼ Database (H2 / MySQL) Keeping the frontend framework-free makes the widget lightweight and easy to embed into virtually any website. One-Line Integration Adding the widget to a website only requires a single script. <script src="/widget/widget.js" data-api-base=""></sc
AI 资讯
How to Repair Corrupted PDFs in the Browser with Vue 3 and pdf-lib
A corrupted PDF is one of the most frustrating file problems. You have important content inside, but the document won't open, opens with garbled text, or shows missing pages. The file might be damaged from a bad download, a converter error, or a storage glitch. Recovering content from a broken PDF doesn't require complex forensic tools. Often, the individual pages are still readable — it's the document's structure (cross-reference tables, object streams) that's damaged. By extracting pages one by one into a fresh PDF, we can bypass the structural corruption. Here's how to build a browser-based PDF repair tool with Vue 3 and pdf-lib . The repair strategy The core insight: PDF structure and page content are somewhat independent . A PDF can have a broken cross-reference table or missing trailer objects, but the actual page content streams may still be perfectly readable. The repair approach: Load the damaged PDF and attempt to read each page For each successfully read page, copy it to a new PDF document Discard unreadable pages (they're lost anyway) Save the new document This is fundamentally different from "fixing" the original PDF. We're extracting what we can and rebuilding from the ground up. The stack Vue 3 with Composition API pdf-lib for PDF reading and page extraction Vite for bundling The core implementation < script setup lang= "ts" > import { ref } from ' vue ' import { PDFDocument } from ' pdf-lib ' const file = ref < File | null > ( null ) const totalPages = ref ( 0 ) const recoveredPages = ref ( 0 ) const repairing = ref ( false ) const result = ref < Uint8Array | null > ( null ) const error = ref < string | null > ( null ) async function repairPdf () { if ( ! file . value ) return repairing . value = true error . value = null try { const arrayBuffer = await file . value . arrayBuffer () const damaged = await PDFDocument . load ( arrayBuffer , { ignoreEncryption : true , updateMetadata : false , }) totalPages . value = damaged . getPageCount () const resu
开发者
Using JooqTemplate implement UserService Demo
No need annotation,No need check null, No need inherit,No need scan,Based on JOOQ 1.Quer User Paramater public class UserParam { String name ; LocalDate beginBirthday ; LocalDate endBirthday ; int offset ; int limit ; ... } 2. User Bean public class User { private Integer id ; private String name ; private LocalDate birthday ; private String nickName ; private Gender gender ; private String avatarAddress ; ... } 3.UserService @Service public class UserService { @Autowired private JooqTemplate jt ; public int insertUser ( User user ) { //Bean to camel map Map values = JooqMaps . toCamelCase ( user ); //Add additional data values . put ( "create_time" , LocalDateTime . now ()); // Insert record return jt . insertReturningv ( "user_table" , values , "id" ). get ( "id" , Integer . class ); } public void updateUser ( User user ) { Map values = JooqMaps . toSnakeCase ( user ); //Regardless of whether it is null or not, update in Map. Update statement does not include in Map values . remove ( "id" ); values . remove ( "name" ); //jt.updatev("some_table",values,"column1",param1,"column2",param2...); //Variable parameter condition update UPDATE user_table SET ... WHERE id=? jt . updatev ( "user_table" , values , "id" , user . getId ()); } public void deleteUser ( int id ) { //jt.deletev("some_table","column1",param1,"column2",param2...); //DELETE FROM user_table WHERE id=? jt . deletev ( "user_table" , "id" , id ); } public User loadUser ( int id ) { //1 Variable parameter condition loading SELECT * FROM user_table WHERE id=? LIMIT 1 return jt . loadv ( "user_table" , User . class , "id" , id ); } public List < User > selectUser ( UserParam param ) { //Automatically ignore null parameters //SELECT * FROM user_table WHERE name LIKE '%?%' AND birthday BETWEEN ? AND ? ORDER BY name ASC,birthday desc; return jt . queryv ( "user_table" , User . class , "name%" , param . getName (), "birthday:between" , param . getBeginBirthday (), param . getEndBirthday (), "name:asc" , "birthday
AI 资讯
TypeScript Enums Are Still Controversial in 2026: Here Is When to Use Them and When to Reach for `const` Objects
TypeScript Enums Are Still Controversial in 2026: Here Is When to Use Them and When to Reach for const Objects This article was written with the assistance of AI, under human supervision and review. Most TypeScript enum debates stem from a single misunderstanding: developers treat enums as a pure type-level construct when they generate real runtime code. This disconnect creates bundle bloat, unexpected behavior at runtime, and type safety gaps that only surface in production. Teams that reach for enums by default pay a hidden cost in every build. The enum controversy persists because TypeScript enums violate a core expectation: types should disappear at compile time. Unlike interfaces or type aliases that vanish during transpilation, enums produce JavaScript objects that ship to the browser. This runtime footprint matters when bundle size directly affects load time and business metrics. The alternative pattern— const objects with as const assertions—delivers the same developer experience without the runtime overhead. When developers understand the tradeoffs, the choice becomes mechanical: use enums where their runtime behavior adds value, use const objects everywhere else. Key Takeaways TypeScript enums generate runtime JavaScript objects that increase bundle size, while const objects with as const provide the same type safety with zero runtime overhead. Numeric enums enable reverse mapping and bitwise flags, making them valuable for low-level APIs and performance-critical code where runtime lookup is required. The const enum feature eliminates runtime code but breaks module boundaries and fails with external libraries, creating maintenance hazards in shared codebases. Const objects work seamlessly with tree-shaking, module systems, and JSON serialization, making them the default choice for API contracts and configuration. Migration from enums to const objects requires runtime validation at module boundaries to preserve type safety guarantees when data enters your s
AI 资讯
« J'ai fini le tuto Node, et là je suis bloqué » — le mur dont personne ne parle
Tu as fini le tuto. Le vrai, le gros, celui de douze heures. Tu as tout suivi, tout tapé, tout fait tourner. À la fin, l'application marchait. Tu t'es senti capable. Tu t'es dit : « ça y est, je sais faire une API ». Et puis tu as ouvert un dossier vide pour faire la tienne. Curseur qui clignote. index.js . Rien. Pas parce que tu as oublié la syntaxe. Tu la connais. Mais là, tout seul, sans quelqu'un qui te dit quoi taper à la ligne suivante, tu ne sais pas par où commencer. Et cette sensation-là, ce vide entre « j'ai fini le tuto » et « je sais faire », personne ne t'avait prévenu qu'elle existait. C'est de ce mur que je veux parler. Parce que ce n'est pas un défaut chez toi. C'est une étape. 1. Le piège n'est pas le tuto, c'est ce qu'il te cache Un tuto, c'est une suite de bonnes décisions déjà prises pour toi. Quel dossier créer. Quel package installer. Où mettre le fichier de config. Quand extraire une fonction. À chaque embranchement, le formateur a choisi le bon chemin, et toi tu l'as suivi. Tu as tapé du code, oui. Mais tu n'as pris aucune décision. Or coder, le vrai coder, c'est presque que ça : décider. Choisir entre deux structures. Trancher un nom de variable. Décider si ce bout de logique mérite sa propre fonction. Un développeur qui bosse, ce n'est pas quelqu'un qui connaît toutes les réponses — c'est quelqu'un qui sait avancer quand il n'y en a pas. Le tuto t'a entraîné à taper. Il ne t'a pas entraîné à décider. Et c'est exactement la compétence qui te manque devant ton dossier vide. Ce n'est pas un trou dans ton savoir. C'est un muscle que tu n'as jamais sollicité, parce qu'on ne te l'a jamais laissé faire. 2. Pourquoi « un tuto de plus » ne réglera rien Ta réaction instinctive face au blocage, c'est de retourner là où tu te sens compétent. Un autre tuto. Un cours de plus. Une nouvelle techno à cocher. Je comprends le réflexe. Le tuto, c'est confortable : il y a une barre de progression, une fin, une petite dose de « j'ai réussi » à chaque étape. Le d
AI 资讯
I Built a Photo-to-Cross-Stitch Pattern Maker That Runs in Your Browser
Photo-to-cross-stitch conversion looks like a resizing problem. It is not. A pixelated preview can look convincing and still be frustrating to stitch. It may contain too many colors, lack readable symbols, provide no reliable dimensions, or become useless when printed. I built StitchFromPhoto to handle the practical part of that workflow. It turns an image into a counted cross-stitch chart in the browser, lets you tune the result before committing to it, and keeps the source photo on your device. The useful output is a pattern, not a pixelated image A cross-stitch preview only answers one question. It shows roughly what the finished piece might look like. A usable pattern must also tell you how many stitches wide and tall the design is, which thread color belongs in each square, whether similar colors remain distinguishable on paper, and how large the result will be on your chosen fabric. That distinction shaped the app. The color preview is useful, but the symbol chart, thread key, stitch totals, fabric dimensions, and printable pages are the real deliverables. What the photo-to-cross-stitch pattern maker does The workflow starts with a sample image, so anyone can explore the controls before uploading a file. It also accepts JPG, PNG, and WebP images up to 20 MB. The main controls are stitch width, DMC color count, and fabric count. You can choose a pattern from 30 to 120 stitches wide, limit the palette to between 6 and 36 DMC colors, and calculate the finished size for 14, 16, 18, or 22 count Aida. You can move between the original photo, a color stitch preview, and a high-contrast symbol view. The thread key lists every retained DMC color code and the number of stitches assigned to it. Creating and previewing a pattern is free. High-resolution PNG and print-ready PDF downloads are unlocked per source image. I wanted that boundary to be visible before checkout rather than hidden behind the final button. How the browser turns pixels into stitches The conversion pi
开发者
Prototype Design Pattern in Java: A Practical Guide with Real-World Examples
Understanding the Prototype Design Pattern in Java Introduction When developing software, there are situations where creating a new object from scratch is expensive or time-consuming. For example, an object may require complex initialization, database access, or extensive configuration. In such cases, instead of creating a new object every time, we can duplicate an existing object. This is where the Prototype Design Pattern becomes useful. The Prototype Design Pattern is one of the Creational Design Patterns in Java. It allows developers to create new objects by cloning existing ones rather than instantiating them using constructors. What is the Prototype Design Pattern? The Prototype Design Pattern creates new objects by copying an existing object, known as the prototype. This approach improves performance by avoiding repeated initialization and allows developers to create multiple similar objects efficiently. In Java, cloning is commonly implemented using the Cloneable interface and overriding the clone() method. Why Use the Prototype Pattern? The Prototype Pattern offers several benefits: Reduces the cost of object creation. Improves application performance. Simplifies the creation of complex objects. Avoids repeated initialization code. Makes object creation more flexible. Real-World Example Imagine an online shopping application where thousands of product objects share similar properties. Instead of creating every product from scratch, the application can clone a prototype product and modify only the required attributes such as name or price. Other real-world examples include: Document templates Game characters Employee records Vehicle configurations Graphic design objects UML Structure The Prototype Design Pattern generally includes: Prototype Interface – Declares the clone operation. Concrete Prototype – Implements the cloning functionality. Client – Creates new objects by cloning existing prototypes. Java Implementation Step 1: Create the Prototype Class cla
AI 资讯
React useEvent Hook: Stable Callbacks Without Stale Closures (2026)
Every React developer eventually meets the same fork in the road. You write an event handler that reads state, pass it to a child or an effect, and now you must choose: leave it as a plain inline function and watch every render create a new reference — breaking React.memo , re-running effects, re-subscribing listeners — or wrap it in useCallback and start playing dependency-array whack-a-mole, where one forgotten dependency means the handler sees state from three renders ago. That second failure mode has a name — the stale closure — and it's arguably the most common React bug in production code. The fix has a name too: useEvent , proposed in an official React RFC in 2022 , and available today as useEvent in @reactuses/core . It gives you a function whose identity never changes across renders but whose body always sees the latest state and props . Both halves of the fork, no trade-off. This post covers the API, the three-line implementation trick that makes it work, how it compares to useCallback and to React 19.2's built-in useEffectEvent , real patterns, and the one rule you must respect (don't call it during render). TypeScript-first. The Problem in Thirty Seconds Here's the bug factory. A chat component sends a heartbeat with the current draft text: function Composer ({ roomId }: { roomId : string }) { const [ draft , setDraft ] = useState ( '' ); useEffect (() => { const id = setInterval (() => { sendHeartbeat ( roomId , draft ); // ⚠️ which draft? }, 3000 ); return () => clearInterval ( id ); }, [ roomId ]); // draft intentionally omitted — we don't want to reset the timer return < textarea value = { draft } onChange = { e => setDraft ( e . target . value ) } />; } The interval closes over the draft that existed when the effect ran — the empty string. Every heartbeat sends '' forever. Add draft to the dependency array and the closure is fresh, but now the interval tears down and restarts on every keystroke . useCallback doesn't help: it has the exact same depen
AI 资讯
Simple, Elegant, Reliable - 90+ ready-to-use validators for Chinese business scenarios
📑 Table of Contents Introduction Why We Created ValidX? Why Choose ValidX? 5-Minute Quick Start Multilingual Support Important: Null/Empty String Handling Thread Safety Supported Validation Annotations Quick Reference Table Basic Validation Identity Validation Financial Validation Education/Professional Qualification Network Validation China-Specific Validation Automotive Validation Book-Related Validation Mobile Device Validation More Validation Annotations Contribution Introduction ValidX is an open-source Java validation library focused on Chinese business scenarios, making validation simple, elegant, and reliable. Built on JSR-380 standards with 90+ specialized annotations for Chinese identity cards, phone numbers, bank cards, and more. 💡 Why We Created ValidX? When developing applications for Chinese users, we frequently encountered these challenges: Pain Point 1: Java Has Too Few Built-in Validation Rules, Far Less Than Other Language Frameworks If you've used web frameworks in other languages, such as PHP's ThinkPHP or JavaScript's Validator.js, you'll notice they come with incredibly rich built-in validation rules: mobile , idcard , zip , alphaNum , etc.—ready to use out of the box, simple and convenient. But in the Java world, standard Bean Validation only provides a handful of generic annotations like @Email and @Pattern . For common Chinese business scenarios—identity cards, phone numbers, bank cards, unified social credit codes—there's absolutely no support. This forces every Java project to reinvent the wheel: Writing complex regular expressions yourself Implementing Luhn algorithm for bank card validation Handling identity card check digit calculations Copy-pasting validation code found online Why can't Java validation be as ready-to-use as other frameworks? This is why ValidX was born. Pain Point 2: Scattered Validation Logic Difficult to Maintain As projects grow, validation logic becomes scattered across: Manual validation in Controller layer Busine
AI 资讯
How to Set Up Rate Limiting in Nuxt
Rate limiting is one of those things that doesn't feel urgent—until someone hammers your login endpoint at 3am and you wake up to a flooded database and a locked-out user base. I added this to my Nuxt base layer after realising I'd shipped several projects with zero protection on auth routes. Not great. This post walks through the exact setup I now use: Redis-backed, an in-memory fallback when Redis is down, named presets for different sensitivity levels, and a 429 page that shows a live countdown instead of just dying on the user. The structure Three pieces, each with one job: createRateLimiter() — a factory that builds the limiter, using Redis with an in-memory fallback applyRateLimit() — what you call inside handlers to enforce a limit server/middleware/rateLimiter.ts — global middleware so every route gets a baseline for free 1. Install npm install rate-limiter-flexible ioredis rate-limiter-flexible does the heavy lifting: sliding windows, Redis integration, and the insurance fallback pattern we'll use. 2. The factory Create server/utils/rateLimiter.ts : import { RateLimiterRedis , RateLimiterMemory , type RateLimiterAbstract , } from ' rate-limiter-flexible ' import { getRedisClient } from ' ./redis ' export interface RateLimiterConfig { keyPrefix : string // Must be unique per limiter, e.g. 'rl:auth' limit : number // Maximum requests within the window windowSeconds : number } export interface RateLimitResult { allowed : boolean limit : number remaining : number resetAt : number // Unix timestamp in seconds when the window resets retryAfter : number // Seconds until retry; 0 if allowed } function buildLimiter ( config : RateLimiterConfig , ): RateLimiterAbstract { const insurance = new RateLimiterMemory ({ keyPrefix : config . keyPrefix , points : config . limit , duration : config . windowSeconds , }) const redis = getRedisClient () if ( ! redis ) { return insurance } return new RateLimiterRedis ({ storeClient : redis , keyPrefix : config . keyPrefix , points
AI 资讯
Cutting AI Token Costs with MgntUtils Stacktrace Filtering
A live production integration case study Introduction and Purpose of This Article This article is written for mid- and high-level managerial and technical decision makers. I am the author of the open-source Java library MgntUtils . The article presents an analysis of a real integration of the stacktrace-filtering feature from that library into a live commercial production environment. A few important clarifications up front: This is not a side-project pilot and not a lab demo. The feature was integrated into a production service of a company that serves a high volume of real customers. Due to legal constraints, I am not at liberty to name the company. This is not a how-to article for implementers. If you came looking for code samples or logging-framework wiring, please see the dedicated articles listed in the Disclaimer below. MgntUtils can be used in Java projects and in other JVM-based languages such as Kotlin. Before diving into the production numbers, it is worth stating briefly what the feature does and why those numbers matter. Server-side stacktraces are usually full of framework and infrastructure noise — proxies, filter chains, containers, thread pools, and similar boilerplate — while the few lines that actually explain the failure are easy to lose in the pile. The MgntUtils filtering utility keeps the application frames and the exception / Caused by chain, and collapses that noise. The result is a much shorter stacktrace without losing the information you actually need . When those stacktraces are later consumed — sent to an LLM for analysis, or opened by an engineer — that reduction can mean: Substantial AI token savings Typically more accurate AI root-cause answers , because the model has less framework noise to latch onto and hallucinate about A meaningful productivity boost for human triage The rest of this article focuses on what was observed after integrating this feature in production: the measured benefits, how to interpret them, and the integratio
AI 资讯
I blocked XSS attacks and API Key extraction in the browser by monkey-patching `crypto.subtle`. Why isn't everyone doing this?
Here is how I hardened the browser runtime for a Zero-Knowledge, Non-Custodial FinTech trading terminal. 👇 Client-Side Envelope Encryption: I derive a KEK from the user's password using PBKDF2-SHA256 (310,000 iterations). Then, a secure random 32-byte DEK (AES-256-GCM) encrypts the data. The password NEVER touches the server, and the DEK has a strict 15-min TTL in RAM before a wipe. Secure Enclave Anti-Export Guard: CryptoKeys are generated via crypto.subtle with {extractable: false} . To prevent injected malicious scripts from bypassing the sandbox, I implemented an isolated closure that overrides (monkey-patches) the native browser API: crypto.subtle.exportKey = async function(format, key) { if (isProtectedKey(key)) { _AuditChain.append('EXPORT_ATTEMPT', 'CRITICAL'); throw new Error('Export BLOCKED — unauthorized'); } return _origExport(format, key); }; If our database is breached, hackers find ZERO financial data. If the local session is compromised, runtime gating blocks extraction. Plus, client-side validation rejects API keys with withdrawal permissions enabled (zero custodial risk under MiCA, built for GDPR). The entire architecture runs client-side (WebSocket throttled at 100ms + local AI Advisor), keeping server costs near zero. Where does this runtime isolation logic fail? Why do major SaaS platforms still rely on standard local storage? Let's discuss. 💬
AI 资讯
Project Explanation for my Chesso application
Project High-Level Summary Chesso is a full-stack, real-time multiplayer chess platform engineered to provide low-latency online gameplay. It features real-time move synchronization, authoritative backend match clocks, secure authentication using JWT and Google OAuth, and full chess rule validation. I built it using the MERN stack (MongoDB, Express, React, Node.js) combined with Socket.IO for bi-directional WebSocket communication and Chess.js for move validation and FEN (Forsyth–Edwards Notation) state management. One of the main challenges I solved was building a server-authoritative state and clock synchronization mechanism to prevent client tampering and handle mid-game reconnections gracefully. Tech Stack & Architectural Overview Frontend : React, Vite for fast builds, React for declarative UI updates upon WebSocket events. Backend API : Node.js, Express.js Event-driven, non-blocking I/O ideal for handling multiple concurrent WebSocket connections. Socket.IO : Provides bi-directional socket events, auto-reconnection fallback, and socket room abstraction. Database : MongoDB for flexible JSON-like document model ideal for storing FEN strings, match logs, and user metadata. Auth & Security : Google OAuth 2.0, Passport.js, JWT, bcryptusing standard authentication flow providing password hashing (bcrypt) and session security via JWT tokens. Implementation of matchmaking & Queueing System When a player clicks "Play", the client emits StartGame with their playerID. The server verifies turn ownership (game.currentP === playerID). The move is executed in an isolated server-side Chess() instance (gameSockets.js). If empty, the player is queued and notified via waitingForOpponent. If another player is waiting, waitingQ.shift() pairs them instantly, creates a new game record in MongoDB (GameModel.js), assigns piece colors (white/black), and joins both sockets into a dedicated Socket.IO room named after the gameID. Game Recovery & Reconnection Resilience The server exposes
AI 资讯
Typing Vue 3 provide/inject Without Losing Autocomplete
Strict prop types and typed emits get most of the attention in Vue 3 + TypeScript setups, but provide / inject is where type safety quietly falls apart if you use the API the way the docs show it by default. inject() without a type hint returns unknown , which means every consumer of an injected value either casts it blindly or loses autocomplete entirely — and a typo in the injection key becomes a runtime undefined instead of a compile-time error. The Default Setup Is Untyped by Construction The naive version compiles, but gives you nothing: // Provider provide ( ' theme ' , currentTheme ); // Consumer const theme = inject ( ' theme ' ); // type: unknown Nothing here catches a typo in the key string, and nothing tells the consumer what shape theme actually has. Both problems come from using a plain string as the injection key. InjectionKey Fixes Both Problems at Once Vue exports an InjectionKey<T> type specifically for this. Define it once, typed, and both provide and inject become fully type-checked against the same symbol: // keys.ts import type { InjectionKey } from ' vue ' ; export interface Theme { mode : ' light ' | ' dark ' ; accentColor : string ; } export const ThemeKey : InjectionKey < Theme > = Symbol ( ' theme ' ); // Provider import { ThemeKey } from ' ./keys ' ; provide ( ThemeKey , { mode : ' dark ' , accentColor : ' #4f46e5 ' }); // Consumer import { ThemeKey } from ' ./keys ' ; const theme = inject ( ThemeKey ); // type: Theme | undefined The | undefined in that last type isn't a quirk — it's inject being honest that a consumer might render without a matching provider above it in the tree, which is a real runtime possibility TypeScript is right to force you to handle. Handling the undefined Case Without Littering ?. Everywhere The common mistake is providing a default value to silence the undefined type instead of actually checking for it: const theme = inject ( ThemeKey , { mode : ' light ' , accentColor : ' #000 ' }); // default masks missing pro
开源项目
🔥 WorldFlowAI / everything-claude-code - Claude Code toolkit - agents, commands, skills, rules, and h
GitHub热门项目 | Claude Code toolkit - agents, commands, skills, rules, and hooks for productive AI-assisted development | Stars: 982 | 143 stars this week | 语言: JavaScript
开源项目
🔥 google / guava - Google core libraries for Java
GitHub热门项目 | Google core libraries for Java | Stars: 51,559 | 9 stars today | 语言: Java
AI 资讯
Is Java still relevant today?
Being a Java Developer, I always thought about the programming language i'm working in, if it's the right one for all along the career ahead. I went through some web-based studies and, completely satisfied with the information I got to know. So, the short answer to the prime question is: Yes, Java is absolutely relevant and, here's why:- Still a Top Language Java has been in the top 3 programming languages worldwide for 2+ decades. Historical Dominance: The Backbone of Enterprise Systems: Since its inception, Java’s mantra of "Write Once, Run Anywhere" (WORA) revolutionized software development. It quickly became the foundation for global financial systems, insurance platforms, healthcare infrastructure, and e-commerce giants. Unrivaled Stability: Indexes like TIOBE and GitHub Octoverse have consistently ranked Java among the top most used languages for over 20 years. Companies do not shift their backend infrastructure on a whim; billions of dollars of existing, mission-critical infrastructure rely on the Java Virtual Machine (JVM). Enterprise Backbone Banks, insurance, e-commerce, and global-scale companies still rely heavily on Java. 95% of enterprise systems use it in some form. Banking and Financial Services (FinTech): Transactional Integrity: Mega-banks require high concurrency and absolute compliance with ACID (Atomicity, Consistency, Isolation, Durability) properties. Java's robust memory management and strict type safety prevent multi-threading errors that could result in catastrophic financial discrepancies. Legacy Settlement Layers: Systems managing global wire transfers, electronic clearing houses (ACH), and high-frequency trading platforms were built on the Java Virtual Machine (JVM) over the last 30 years. Rewriting these multibillion-dollar codebases carries massive operational risk with zero business incentive. Insurance Platforms: Complex Risk Modeling: Insurance giants process enormous volumes of historical actuarial tables and continuous risk data.
AI 资讯
Express 5 on µWebSockets: same middleware, 2x to 7x
I maintain Fulmine , a drop-in replacement for Express 5 that runs on µWebSockets.js instead of node:http . One line changes: const express = require ( " fulmine.js " ); // instead of require("express") Your middleware keeps working: helmet , cors , passport , morgan , multer , express-session and the rest. The numbers are not mine Benchmarks published by a project about itself deserve suspicion, so let me use somebody else's. HttpArena runs every framework on the same 64-core machine, in containers, under the same rules, and publishes the results. Express and Fastify are on that board too. Requests per second, from their published runs: Profile Fulmine Express Fastify Baseline (query parsing) 1,220,308 607,777 711,263 JSON (dataset + serialization) 1,111,187 395,361 522,201 Short-lived connections 1,026,789 278,163 298,779 Pipelined 7,259,814 1,009,543 1,671,338 Mixed API workload, 16 CPUs 126,282 67,724 75,633 Async Postgres 222,701 169,687 179,169 Upload (20 MB body) 2,154 2,104 1,902 That is 2.0x Express on the baseline, 2.8x on JSON, 3.7x on short-lived connections, 7.2x pipelined , and 1.9x on the mixed API profile. Against Fastify, on the same board, it is 1.7x on the baseline and 2.1x on JSON. Now the honest parts, which matter as much as the table. Look at the upload row: 1.02x. A 20 MB body is memory bandwidth and syscalls, not framework code. Everywhere the cost belongs to a library both servers call, the difference disappears: JSON.parse , zlib, OpenSSL. Speed comes from the framework only where the framework is doing the work. My entry runs in the arena's "tuned" mode, Express's and Fastify's run in "standard". On two profiles I left out of the table, static files and compressed JSON, that difference is decisive, because tuned mode allows hand-written compression and negotiation. Those rows would show 23x and 8x, and they would be measuring my entry's tuning, not the framework. I would rather not quote them. Where the speed comes from Not from one trick