@jiangege47/micro-server v0.8.4
micro-server
A lightweight microservice framework based on Koa.js, supporting modularization, internationalization, and flexible service invocation patterns.
Features
- Lightweight service framework built on Koa.js
- Modular structure with three-layer architecture (service/logic/function)
- Built-in file upload functionality
- Static file service support
- Internationalization support (i18n)
- Built-in client SDK
- Environment configuration management (.env support)
- API permission control
- Internal/External function isolation mechanism
Installation
npm install @jiangege47/micro-serverServer-side Usage
Creating a Basic Server
import { MicroServer } from "@jiangege47/micro-server";
// Create a server instance
const server = new MicroServer();
// Load configuration and start the server
async function startServer() {
  // Load configuration
  await server.loadConfig({
    port: 3000, // Optional, default is 8080
    projectDir: process.cwd(), // Optional, default is current working directory
    configDir: "./config", // Optional, default is './config'
    servicesDir: "./services", // Optional, default is './services'
  });
  // Start the server
  await server.start();
}
startServer().catch((err) => console.error(err));Directory Structure
Recommended project directory structure:
my-project/
├── config/           # Configuration files
│   └── default.json  # Default configuration
├── services/         # Business service modules
│   ├── user/         # User service module
│   │   ├── account.js  # Account logic
│   │   └── profile.js  # Profile logic
│   └── _internal/    # Internal services (prefix _ indicates internal use only)
│       └── helper.js   # Internal helper functions
├── locales/          # Internationalization texts
│   ├── en-US.json    # English
│   └── zh-CN.json    # Chinese
├── client/           # Static resource files
├── .env              # Environment variables
└── index.js          # Entry fileService Module Development
Services follow a three-layer structure: service/logic/function. For example, the API access path /api/user/account/login corresponds to:
- userservice
- accountlogic
- loginfunction
Example of creating a service module (services/user/account.js):
// Public function - accessible via API
export function login(params) {
  const { username, password } = params.data;
  // Authentication logic
  return {
    userId: 123,
    username: username,
    token: "example-token",
  };
}
// Internal function - only callable within the server
export function _validatePassword(params) {
  const { password, hash } = params.data;
  // Password validation logic
  return true;
}Configuration File
Configuration file example (config/config.default.js):
export default (config) => ({
  port: 8080,
  allowHeaders: ["serviceApiKey", "accessKey", "signature", "locale"],
  upload: {
    enabled: true,
    allowedPaths: [/^\/api\/user\/profile\/upload$/],
    multer: {
      dest: "uploads/",
    },
  },
  static: {
    enabled: true,
    dirName: "client",
  },
  restriction: {
    serviceApiKey: "your-api-key-here",
  },
  locales: {
    defaultLocale: "en-US",
  },
});Environment-specific configuration (config/config.production.js):
export default (config) => ({
  port: 80,
  restriction: {
    serviceApiKey: "production-api-key",
  },
});Internationalization Support
Example of creating a language file (locales/en-US.json):
{
  "sys.bad_request": "Bad request",
  "sys.internal_server_error": "Internal server error",
  "user.login_failed": "Invalid username or password"
}Using translations in services:
export function login(params) {
  const { username, password } = params.data;
  const { __ } = params; // Get translation function
  // Return localized error message on validation failure
  if (!isValidCredentials(username, password)) {
    throw new Error(__("user.login_failed"));
  }
  return {
    /* Success response */
  };
}Internal Service Calls
Calling other services from within the server:
// Call another service function from a service function
export async function register(params) {
  const { username, password, email } = params.data;
  const server = params.server;
  // Internal call to validateEmail function in _internal/helper.js
  const isEmailValid = await server.call(
    "_internal",
    "helper",
    "validateEmail",
    {
      data: { email },
    }
  );
  if (!isEmailValid) {
    throw new Error("Invalid email address");
  }
  // Handle registration logic
  return {
    /* Registration success response */
  };
}File Upload Handling
Example of a service function handling file uploads:
export function upload(params) {
  const { _files } = params.data;
  if (!_files || _files.length === 0) {
    throw new Error("No files uploaded");
  }
  // Process uploaded files
  return {
    files: _files.map((file) => ({
      filename: file.filename,
      size: file.size,
      path: file.path,
    })),
  };
}Client-side Usage
Browser Environment
import { MicroClient } from "@jiangege47/micro-server";
// Create client instance
const client = new MicroClient({
  baseURL: "http://localhost:8080", // Server address
  timeout: 30000, // Timeout (milliseconds)
  locale: "en-US", // Language setting
  serviceApiKey: "your-api-key", // Required for accessing restricted services
  headers: {
    // Custom request headers
    "Custom-Header": "value",
  },
});
// Call regular API
async function login() {
  const result = await client.call("user/account/login", {
    username: "testuser",
    password: "password123",
  });
  if (result.success) {
    console.log("Login successful:", result.data);
  } else {
    console.error("Login failed:", result.data.message);
  }
}
// Upload file
async function uploadProfilePicture(fileInput) {
  const file = fileInput.files[0];
  const result = await client.uploadFile("user/profile/upload", file, {
    userId: 123,
    description: "Profile picture",
  });
  if (result.success) {
    console.log("Upload successful:", result.data);
  } else {
    console.error("Upload failed:", result.data.message);
  }
}Setting Language
// Set client language
client.setLocale("en-US");
// Chain call
const result = await client.setLocale("en-US").call("user/account/login", {
  username: "testuser",
  password: "password123",
});Token Management
// Set token (stored in localStorage by default)
client.setToken("your-token-here");
// Get current token
const token = client.getToken();Advanced Features
Service Permission Control
Use the $ modifier to restrict function access:
// Add $ before the function name to indicate it requires serviceApiKey validation
export function $adminOperation(params) {
  // Only accessible with the correct serviceApiKey
  // ...perform admin operations
}Custom Response
Return a function to control Koa response:
export function downloadFile(params) {
  const { filename } = params.data;
  // Return a function to customize Koa response
  return async (ctx) => {
    ctx.set("Content-Disposition", `attachment; filename=${filename}`);
    ctx.set("Content-Type", "application/octet-stream");
    ctx.body = fs.createReadStream(`./files/${filename}`);
  };
}Deployment
Production Environment Configuration
Create a production environment configuration file (config/config.production.js):
export default (config) => ({
  port: 80,
  restriction: {
    serviceApiKey: "production-api-key",
  },
});Create a .env file:
SERVER_ENV=production
DATABASE_URL=mongodb://user:pass@host:port/dbnameStarting the Server
// Specify environment
await server.loadConfig({
  env: "production",
});License
MIT
6 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
6 months ago
7 months ago
7 months ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago