
Security News
GitHub Actions Checkout Now Blocks Risky pull_request_target Checkouts
GitHub Actions checkout now blocks risky pull_request_target checkouts by default to help prevent pwn request supply chain attacks.
🪄 Just another javascript utility library.
🌐 主流 Javascript 运行时支持
📦 模块化设计
🛡️ 可靠性保证
🔄 工程自动化
💡 开发者友好
📈 持续维护
import { core, dom } from 'xajs';
const Component = core.base.Class({
$extends: BaseComponent,
$static: {
defaultConfig: { theme: 'light' }
},
$ctor(config) {
this.$super();
this.config = { ...this.constructor.defaultConfig, ...config };
this.handler = dom.E.delegate('.menu a', {
click: (e, target) => {
e.preventDefault();
this.navigate(target.getAttribute('href'));
}
});
}
});
import { future, functional } from 'xajs';
// Create atomic state
const todoAtom = future.TR.atom({
key: 'todoAtom',
default: { items: [], filter: 'all' }
});
// Create derived state
const filteredTodos = future.TR.selector({
key: 'filteredTodos',
get: ({ get }) => {
const state = get(todoAtom);
return state.items.filter(item =>
state.filter === 'all'
? true
: state.filter === 'completed'
? item.completed
: !item.completed
);
}
});
// Create pub/sub communication
const { Puber, Suber } = functional.PS;
const todoService = new Puber('todos');
const todoView = new Suber('view');
todoView.rss(todoService, [
{
msg: 'todos:updated',
handler: todos => filteredTodos.observe(renderTodos)
}
]);
import { mobile, dom } from 'xajs';
// Device detection
const ua = new mobile.UserAgent(navigator.userAgent);
if (ua.isMobile()) {
if (ua.isOS('iOS')) {
enableIOSFeatures();
}
}
// DOM manipulation
const { div, nav, a } = dom.tags;
const menu = div({ className: 'menu' }, [
nav(null, [a({ href: '#home' }, 'Home'), a({ href: '#about' }, 'About')])
]);
// URL parsing
const url = new dom.UrlParser(location.href);
console.log(url.query.page);
| 名称 | 描述 | 可按需引入的模块名 |
|---|---|---|
| core | 核心基础包 | xajs/core |
| dom | 浏览器运行时相关包 | xajs/dom |
| fp | 函数式编程相关包 | xajs/fp |
| functional | 实用主义相关包 | xajs/functional |
| future | 高级及实验特性包 | xajs/future |
| internal | AJS 内部都在使用的实用工具包 | xajs/internal |
| lang | Javascript 语言特性扩展包 | xajs/lang |
| mobile | 移动端相关包 | xajs/mobile |
核心基础包
Class Definition with Static Members
import { base } from 'xajs/core';
const MyComponent = base.Class({
$extends: BaseComponent,
// Static properties and methods
$static: {
defaultConfig: {
theme: 'light'
},
create(config) {
return new this({ ...this.defaultConfig, ...config });
}
},
// Constructor
$ctor(config) {
this.$super(); // Call parent constructor
this.config = config;
this.state = { count: 0 };
},
// Instance methods
increment() {
this.state.count++;
this.emit('change', this.state.count);
}
});
Mixin and Deprecation
import { decorators } from 'xajs/core';
// Define a mixin
const LoggerMixin = {
log(msg) {
console.log(`[${this.constructor.name}] ${msg}`);
}
};
// Apply mixin and deprecate old methods
@decorators.mixin(LoggerMixin)
class MyService {
@decorators.deprecate('Use newMethod() instead', { since: '2.0.0' })
oldMethod() {
return this.newMethod();
}
newMethod() {
this.log('Operation started');
return this.processData();
}
}
Async Operations with Deferred
import { base } from 'xajs/core';
class DataLoader {
async loadData(retryCount = 3) {
const deferred = new base.Deferred();
try {
// Attempt to load data with retry
for (let i = 0; i < retryCount; i++) {
try {
const response = await fetch('/api/data');
if (!response.ok) throw new Error('API Error');
const data = await response.json();
return deferred.resolve(data);
} catch (err) {
if (i === retryCount - 1) throw err;
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
}
}
} catch (err) {
deferred.reject(err);
}
return deferred.done(); // Ensures unhandled rejections are thrown
}
isDataLoaded() {
return this.loadData.isDone();
}
}
浏览器运行时相关包
DOM with Tags Helpers
import { h, tags } from 'xajs/dom';
// Using h function directly
const vnode = h('div', { className: 'container' }, [
h('header', { key: 'header' }, [h('h1', null, 'Welcome')])
]);
// Using tags helpers (more concise)
const { div, header, h1, nav, a } = tags;
const menu = div({ className: 'container' }, [
header({ key: 'header' }, [
h1(null, 'Welcome'),
nav({ className: 'menu' }, [
a({ href: '#home' }, 'Home'),
a({ href: '#about' }, 'About')
])
])
]);
Advanced Event Handling
import { E } from 'xajs/dom';
// One-time event handling
E.once('window.load', () => {
console.log('App loaded');
});
// Event sequence handling
E.once(
'window.mouseover',
'window.click',
e => {
console.log('Mouse over then clicked');
},
{ capture: true }
);
URL Parsing and Manipulation
import { UrlParser } from 'xajs/dom';
// Create parser instance
const parser = new UrlParser(
'https://example.com/path?q=search&tags[]=js&tags[]=dom'
);
// Basic URL parts
console.log(parser.protocol); // 'https:'
console.log(parser.hostname); // 'example.com'
console.log(parser.pathname); // '/path'
// Advanced query handling
const query = parser.query;
console.log(query.q); // 'search'
console.log(query.tags); // ['js', 'dom']
// URL manipulation
parser.setQueryParam('page', '2');
// 'https://example.com/new-path?q=search&tags[]=js&tags[]=dom&page=2'
函数式编程相关包
Function Composition
import { compose, composeAsync } from 'xajs/fp';
// Synchronous composition
const enhance = compose(addTimestamp, validate, normalize);
// With type checking
const result = enhance({ name: 'example' });
// Async composition with error handling
const pipeline = composeAsync(
async data => {
const validated = await validate(data);
if (!validated.success) {
throw new ValidationError(validated.errors);
}
return validated.data;
},
async record => {
const normalized = await normalize(record);
return {
...normalized,
timestamp: Date.now()
};
}
);
实用主义相关包
Function Interception (Sync & Async)
import { helper } from 'xajs/functional';
// Synchronous interception
const loggedFetch = helper
.intercepter(fetch)
.before(url => {
console.log(`Fetching: ${url}`);
})
.after((url, response) => {
console.log(`Completed: ${url} (${response.status})`);
}).$runner;
// Async interception
const cachedFetch = helper
.intercepter(fetch)
.before(async url => {
const cached = await cache.get(url);
if (cached) return cached;
})
.after(async (url, response) => {
await cache.set(url, response.clone());
}).$asyncRunner;
Pub/Sub System
import { helper } from 'xajs/functional';
const {
PS: { Puber, Suber }
} = helper;
// Create publisher and subscriber
class DataService extends Puber {
constructor() {
super('data-service', {});
}
async fetchData() {
const data = await fetch('/api/data');
this.pub('data:updated', await data.json());
}
}
class DataView extends Suber {
constructor(service) {
super('data-view', {});
this.rss(service, [
{
msg: 'data:updated',
handler: this.onDataUpdate.bind(this)
}
]);
}
onDataUpdate(data) {
this.render(data);
}
}
高级及实验特性包
Reactive State Management
import { TR } from 'xajs/future';
// Create atomic states
const count1 = TR(1);
const count2 = TR(2);
// Create computed value
const sum = TR.compute((a, b) => a + b)(count1, count2);
// Create derived computation
const doubled = TR.compute(s => s * 2)(sum);
// Observe changes
sum.observe(val => console.log('Sum:', val)); // 3
doubled.observe(val => console.log('Double:', val)); // 6
// Update source values
count1(v => v + 1); // Sum: 4, Double: 8
count2(6); // Sum: 8, Double: 16
// Cleanup
sum.dispose();
doubled.dispose();
Advanced State with Atoms
import { TR } from 'xajs/future';
const { atom, selector } = TR;
// Create base atom
const todoAtom = atom({
key: 'todoAtom',
default: {
items: [],
filter: 'all'
}
});
// Create derived selectors
const filteredTodos = selector({
key: 'filteredTodos',
get: ({ get }) => {
const state = get(todoAtom);
switch (state.filter) {
case 'completed':
return state.items.filter(item => item.completed);
case 'active':
return state.items.filter(item => !item.completed);
default:
return state.items;
}
}
});
const todoStats = selector({
key: 'todoStats',
get: ({ get }) => {
const items = get(todoAtom).items;
return {
total: items.length,
completed: items.filter(item => item.completed).length,
active: items.filter(item => !item.completed).length
};
}
});
// Use selectors
filteredTodos.observe(todos => {
renderTodoList(todos);
});
todoStats.observe(stats => {
updateStatusBar(stats);
});
Template Engine
import { tpl } from 'xajs/future';
// template
const template = tpl.exec(`<div>${name}<div>`, { name: 'AJS' });
AJS 内部都在使用的实用工具包
Type Checking
import { is } from 'xajs/internal';
// Array checks
console.log(is.isArray([1, 2, 3])); // true
console.log(is.isArray({})); // false
// Object checks
console.log(is.isObject({})); // true
console.log(is.isObject([])); // false
// Function checks
console.log(is.isFunction(() => {})); // true
console.log(is.isFunction(async () => {})); // true
console.log(is.isFunction(function* () {})); // true
// Boolean checks
console.log(is.isBoolean(true)); // true
console.log(is.isBoolean(1)); // false
Safe Object Operations
import { assign, hasOwnProp } from 'xajs/internal';
// Safe object assignment
const base = { a: 1, b: { c: 2 } };
const extension = { b: { d: 3 }, e: 4 };
const result = assign({}, base, extension);
console.log(result);
// {
// a: 1,
// b: { c: 2, d: 3 },
// e: 4
// }
// Safe property checks
if (hasOwnProp(result, 'b')) {
console.log('Property exists:', result.b);
}
Type-Safe Operations
import { is, assign } from 'xajs/internal';
function safeUpdate(target, source) {
// Type validation
if (!is.isObject(target) || !is.isObject(source)) {
throw new TypeError('Both arguments must be objects');
}
// Safe assignment with type checking
const result = assign({}, target);
for (const key in source) {
if (hasOwnProp(source, key)) {
const value = source[key];
// Type-specific handling
if (is.isArray(value)) {
result[key] = [...value];
} else if (is.isObject(value)) {
result[key] = safeUpdate({}, value);
} else {
result[key] = value;
}
}
}
return result;
}
Javascript 语言特性扩展包
Basic String Operations
import { MagicString } from 'xajs/lang';
const str = MagicString('hello world');
// Chain multiple operations
const result = str.trim().capitalize().replace(/world/, 'AJS');
console.log(result); // 'Hello AJS'
console.log(str); // Original string unchanged
Advanced Pattern Matching
import { MagicString } from 'xajs/lang';
const text = MagicString('user.name.first');
// Replace with callback
const result = text.replace(/\w+/g, (match, index) => {
if (index === 0) return match;
return match.toUpperCase();
});
console.log(result); // 'user.NAME.FIRST'
String Transformation
import { MagicString } from 'xajs/lang';
const template = MagicString('Hello, ${name}!');
// Interpolate values
const greeting = template.replace(
/\${(\w+)}/g,
(_, key) =>
({
name: 'AJS User'
})[key] || ''
);
console.log(greeting); // 'Hello, AJS User!'
移动端相关包
Device Detection and Feature Support
import { UserAgent } from 'xajs/mobile';
// Initialize with current user agent
const ua = new UserAgent(navigator.userAgent);
// Comprehensive device check
if (ua.isMobile()) {
// Mobile-specific optimizations
if (ua.isOS('iOS')) {
// iOS specific features
if (parseFloat(ua.getResult().os.version) >= 14.5) {
enableModernIOSFeatures();
} else {
enableLegacyIOSSupport();
}
} else if (ua.isOS('Android')) {
const version = parseFloat(ua.getResult().os.version);
if (version >= 10) {
enableModernAndroidFeatures();
} else {
enableLegacyAndroidSupport();
}
}
} else if (ua.isTablet()) {
// Tablet optimizations
const { device } = ua.getResult();
if (device.vendor === 'Apple' && device.model === 'iPad') {
enableIPadFeatures();
}
} else if (ua.isDesktop()) {
// Desktop optimizations
enableDesktopFeatures();
}
Browser and Engine Detection
import { UserAgent } from 'xajs/mobile';
const ua = new UserAgent(navigator.userAgent);
const { browser, engine } = ua.getResult();
// Comprehensive browser checks
if (ua.isBrowser('Chrome')) {
const version = parseFloat(browser.version);
if (version >= 90) {
// Modern Chrome features
enableProgressiveFeatures();
} else if (version >= 80) {
// Legacy but stable Chrome features
enableBasicFeatures();
} else {
// Very old Chrome
showBrowserUpdateNotice();
}
} else if (ua.isBrowser('Safari')) {
if (parseFloat(browser.version) >= 14) {
if (engine.name === 'Webkit') {
// Modern Safari + Webkit
enableWebkitOptimizations();
}
} else {
// Legacy Safari support
enableLegacySafariSupport();
}
}
Please read our Contributing Guide before submitting a Pull Request to the project.
This project is licensed under the MIT License - see the LICENSE file for details.
Thanks goes to these wonderful people (emoji key):
Archer (炽宇) 💻 🚇 🚧 |
|---|
This project follows the all-contributors specification. Contributions of any kind welcome!
FAQs
🪄 Just another javascript utility library.
We found that xajs demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
GitHub Actions checkout now blocks risky pull_request_target checkouts by default to help prevent pwn request supply chain attacks.

Product
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.

Product
Socket MCP now lets AI assistants review org alerts, investigate threats using the Socket threat feed, and inspect package files in addition to dependency scoring.