@felloh-org/lambda-wrapper

中文文档
1.11.277发布于 2026/11/13MITCommonJS近 30 天下载 3432

Lambda wrapper for all Felloh Serverless Projects

原始使用文档
文档目录38 节
  1. Installation
  2. Quick Start
  3. Lambda Wrapper
  4. Handler Patterns
  5. Error Handling
  6. Warmup Support
  7. Dependency Injection System
  8. Built-in Services
  9. Custom Services
  10. Container API
  11. Services
  12. RequestService
  13. LoggerService
  14. TracingService (Honeycomb / OpenTelemetry)
  15. WarehouseService
  16. AuthenticationService
  17. HTTPService
  18. SecretsService
  19. WebhookService
  20. AuditLoggerService
  21. Response Model
  22. Status Model
  23. Lambda Termination
  24. EventBridge Events
  25. Webhook Models
  26. Database (TypeORM)
  27. Entities
  28. Migrations
  29. Database Schemas
  30. Utilities
  31. PromisifiedDelay
  32. Development
  33. Commands
  34. Environment Variables
  35. Project Structure
  36. CI/CD
  37. Testing
  38. License

Lambda Wrapper

release

A shared library for Felloh serverless projects that provides core functionality including dependency injection, logging, request handling, database entities, and response models for AWS Lambda functions.

Installation

npm install @felloh-org/lambda-wrapper
# or
yarn add @felloh-org/lambda-wrapper

Quick Start

import { LambdaWrapper, DEFINITIONS, ResponseModel } from '@felloh-org/lambda-wrapper';

const configuration = {
  SERVICE_NAME: 'my-service',
};

export const handler = LambdaWrapper(configuration, async (di, request) => {
  const logger = di.get(DEFINITIONS.LOGGER);
  const warehouse = di.get(DEFINITIONS.WAREHOUSE);

  logger.info('Processing request');

  // Your handler logic here

  return new ResponseModel({ message: 'Success' }, 200).generate();
});

Lambda Wrapper

The core wrapper function takes a configuration object and a handler function, returning a Lambda-compatible function with built-in dependency injection, error handling, logging, and metrics.

import { LambdaWrapper } from '@felloh-org/lambda-wrapper';

const handler = LambdaWrapper(configuration, async (di, request, callback) => {
  // di      - DependencyInjection container with all services
  // request - RequestService instance with parsed request data
  // callback - Lambda callback (for non-async handlers)
});

Handler Patterns

Async handler (recommended):

export const handler = LambdaWrapper(config, async (di, request) => {
  const response = new ResponseModel({ result: 'ok' }, 200);
  return response.generate();
});

Callback handler:

export const handler = LambdaWrapper(config, (di, request, callback) => {
  const response = new ResponseModel({ result: 'ok' }, 200);
  callback(null, response.generate());
});

Throw errors as responses:

export const handler = LambdaWrapper(config, async (di, request) => {
  const params = request.getAll();

  if (!params.email) {
    const error = new ResponseModel({}, 422);
    error.addError({
      title: 'Validation Error',
      message: 'Email is required',
    });
    throw error;  // Returns a 422 response, not a 500
  }

  // continue processing...
});

Error Handling

The wrapper automatically catches errors and returns appropriate responses:

  • ResponseModel thrown - returns the response as-is (e.g. 400, 404, 422)
  • LambdaTermination thrown - returns a response using the error's code property
  • Unhandled errors - returns a 500 response and logs the error
  • Database size limit errors - returns a 413 response

5xx errors are logged automatically; 4xx errors are not.

Warmup Support

The wrapper handles serverless-plugin-warmup events automatically. When a warmup event is detected, the handler returns immediately without executing your code.

Dependency Injection System

Every handler receives a DependencyInjection container as its first argument. The container provides access to built-in services and any custom services you register.

Built-in Services

ServiceDefinitionDescription
LoggerDEFINITIONS.LOGGERStructured logging with Winston and Baselime
RequestDEFINITIONS.REQUESTParsed HTTP request data
WarehouseDEFINITIONS.WAREHOUSETypeORM database connection manager
AuthenticationDEFINITIONS.AUTHENTICATIONUser role and organisation checks
UserDEFINITIONS.USERCurrent user from Cognito JWT claims
EventBridgeDEFINITIONS.EVENT_BRIDGEAWS EventBridge event publishing
SecretsDEFINITIONS.SECRETSAWS Secrets Manager with caching
HTTPDEFINITIONS.HTTPAxios-based HTTP client
WebhookDEFINITIONS.WEBHOOKHMAC-signed webhook dispatch
AuditLoggerDEFINITIONS.AUDIT_LOGGERAudit event creation via EventBridge
PaymentInitiationObjectDEFINITIONS.PAYMENT_INITIATION_OBJECTPayment link and ecommerce lookup
TracingDEFINITIONS.TRACINGOpenTelemetry spans and attributes, exported to Honeycomb

Custom Services

Create custom services by extending DependencyAwareClass:

import { DependencyAwareClass, DEFINITIONS } from '@felloh-org/lambda-wrapper';

class PaymentProcessor extends DependencyAwareClass {
  async processPayment(transactionId) {
    const logger = this.getContainer().get(DEFINITIONS.LOGGER);
    const warehouse = this.getContainer().get(DEFINITIONS.WAREHOUSE);

    const connection = await warehouse.connect();
    const repo = connection.getRepository(TransactionEntity);
    const transaction = await repo.findOne({ where: { id: transactionId } });

    logger.info(`Processing payment ${transactionId}`);

    return transaction;
  }
}

Register custom services in the configuration:

const configuration = {
  DEPENDENCIES: {
    PAYMENT_PROCESSOR: PaymentProcessor,
  },
};

export const handler = LambdaWrapper(configuration, async (di, request) => {
  const processor = di.get('PAYMENT_PROCESSOR');
  await processor.processPayment('txn_123');
});

Container API

// Get a service
const logger = di.get(DEFINITIONS.LOGGER);

// Get the raw Lambda event
const event = di.getEvent();

// Get the Lambda context
const context = di.getContext();

// Get configuration values
const config = di.getConfiguration();           // full config
const dbHost = di.getConfiguration('DB_HOST');   // specific key, returns null if missing

// Check if running in serverless-offline
if (di.isOffline) {
  // local development mode
}

Services

RequestService

Parses and provides access to all HTTP request data.

const request = di.get(DEFINITIONS.REQUEST);

// Get a single parameter (checks query params for GET, body for POST)
const email = request.get('email');
const page = request.get('page', '1');              // with default value

// Get all parameters
const allParams = request.getAll();

// Force reading from query string regardless of HTTP method
const queryParams = request.getAll('GET');

// Path parameters
const id = request.getPathParameter('id');
const allPath = request.getPathParameter();          // all path params

// Headers (case-insensitive)
const contentType = request.getHeader('Content-Type');
const allHeaders = request.getAllHeaders();

// Authorization
const token = request.getAuthorizationToken();       // extracts Bearer token

// Client info
const ip = request.getIp();
const browser = request.getUserBrowserAndDevice();   // parsed user-agent

// AWS event records (SQS, SNS, etc.)
const record = request.getAWSRecords();

Content type support:

The request service automatically parses the body based on the Content-Type header:

  • application/json - JSON parsing
  • application/x-www-form-urlencoded - form data parsing
  • text/xml - XML parsing via xml2js
  • multipart/form-data - file upload parsing with Buffer support

Request validation:

const constraints = {
  email: { presence: true, email: true },
  amount: { presence: true, numericality: { greaterThan: 0 } },
  start_date: { datetime: { dateOnly: true } },
};

await request.validateAgainstConstraints(constraints);
// Resolves on success, rejects with a 422 ResponseModel on failure

Validation uses validate.js with datetime support via moment.

LoggerService

Structured logging with Winston and Baselime integration. Pretty-prints output in serverless-offline mode.

const logger = di.get(DEFINITIONS.LOGGER);

// Standard logging
logger.info('Payment processed successfully');
logger.error(new Error('Connection failed'));
logger.warning(error);                            // routes to error() or info() based on LOGGER_SOFT_WARNING env

// Labels (lightweight markers for tracing)
logger.label('payment-initiated');
logger.label('silent-label', true);               // silent = not logged to console

// Metrics
logger.metric('response_time', 250);
logger.metric('ip_address', '10.0.0.1', true);   // silent = not logged to console

// Object inspection
logger.object('Processing payload', { id: 1, amount: 500 });
logger.object('Failed response', errorObj, 'error');  // supports 'info', 'warning', 'error'

Axios errors are automatically trimmed to config, message, response.status, and response.data - stripping verbose request/header data from logs.

TracingService (Honeycomb / OpenTelemetry)

Every wrapped invocation is traced with OpenTelemetry and exported to Honeycomb over OTLP/HTTP. Tracing is off unless HONEYCOMB_API_KEY is set - without it the OpenTelemetry API hands out non-recording spans, so services can call these helpers unconditionally.

What you get per invocation, with no code changes in the service:

  • one root span named after the trigger (POST /organisations/{id}, the EventBridge detail-type, aws:sqs <function>), carrying faas.invocation_id, faas.coldstart, faas.trigger, the HTTP method/route/path/client IP/user agent, http.response.status_code, and felloh.request_id from the ResponseModel body;
  • a child span for every HTTPService.request() call (HTTP POST, with server.address, url.path and the response status; the query string is never recorded);
  • every logger.error() recorded as an exception event on the active span. A handler that logs an error and still returns 2xx keeps an errored trace, so "errors that did not fail the request" stay queryable;
  • 5xx responses and thrown errors mark the span as errored with error.type;
  • an explicit flush before the handler returns (Lambda freezes the process immediately afterwards), bounded by HONEYCOMB_FLUSH_TIMEOUT_MS.
const tracing = di.get(DEFINITIONS.TRACING);

// Add business context to the invocation span - the fields you will actually query by
tracing.setAttributes({ organisation_id: organisation.id, transaction_id: transaction.id });

// Wrap a unit of work in a child span
const score = await tracing.withSpan('risk.score', async (span) => {
  span.setAttribute('model', 'laya');
  return scorer.score(narrative);
});

tracing.isEnabled();   // true when spans are being exported
tracing.getTracer();   // raw OpenTelemetry tracer for anything else

Error detail: enough on the span to locate the fault

When an invocation fails (thrown error, 4xx/5xx response, or an error logged mid-request), the invocation span carries flat, queryable fields so a person or an AI can narrow the problem down from Honeycomb alone:

FieldWhat it tells you
faas.handler, code.functionThe Lambda handler export (handler.signup) and the wrapped function's name (Signup), i.e. the file to open
aws.log.group.names, aws.log.stream.names, aws.xray.trace_id, faas.invocation_idExactly where the CloudWatch logs for this invocation are
error.type, error.message, error.stack, error.code, error.causeThe thrown error, stack capped at 4 KB
db.query.text, db.query.parameters, db.response.status_code, db.error.detail, db.error.position, db.error.constraint, db.error.table, db.error.hintFor TypeORM/Postgres failures: the exact statement, its (redacted) parameters and the SQLSTATE detail
felloh.upstream.method, felloh.upstream.url, felloh.upstream.status_code, felloh.upstream.response_bodyFor failed calls to providers or other services, what was called and what came back
felloh.response.errorsThe errors[] array the API returned
enduser.id, felloh.request.path_parameters, felloh.request.query, felloh.request.bodyWho called and with what. The body is redacted (passwords, tokens, card numbers, IBANs, sort codes and similar keys are replaced) and capped at 4 KB
faas.remaining_time_ms, faas.timeout_imminentRemaining budget at the end; a span closed by the timeout watchdog carries faas.timeout_imminent = true
service.versionThe deployed commit when the pipeline provides GIT_SHA, COMMIT_SHA or SERVICE_VERSION

Honeycomb dataset definitions

Honeycomb's Home, service map and error rate features bind to fields chosen under Dataset settings → Definitions. The wrapper emits a field for each one it can; pick these when Honeycomb asks:

DefinitionField the wrapper sendsNotes
ErrorerrorA short Type: message string on every failed span: a 5xx response, a throw with no HTTP outcome, an error logged via logger.error(), or the timeout watchdog. Absent on healthy spans and on 4xx responses, including 404s and 422s that handlers produce by throwing a Response; those keep span status unset and still carry felloh.response.errors.
HTTP Status Codehttp.response.status_codeCurrent OpenTelemetry name; Honeycomb's default guess is the older http.status_code, so select it explicitly.
Routehttp.routeThe API Gateway resource, e.g. /organisations/{id}.
Userenduser.idThe Cognito user id from the authorizer, when the request was authenticated.
Name, Service Name, Span Duration, Trace/Span/Parent IDsname, service.name, duration_ms, trace.trace_id, trace.span_id, trace.parent_idSet by Honeycomb's OTLP ingest; nothing to choose.
Metadata: Annotation Typemeta.annotation_typespan_event for the exception events we emit, link for span links. Filled by OTLP ingest once such data has arrived.
Metadata: Link Span ID / Link Trace IDtrace.link.span_id, trace.link.trace_idFilled by OTLP ingest; the wrapper does not create links today.
Logs: SeverityseverityPresent on the wrapper's exception events, always error.
Logs: MessagemessagePresent on the wrapper's exception events: the logged context plus the error message. The standard exception.message is sent as well.

The wrapper sends traces only, so the two Logs definitions bind to span events rather than to a separate log stream.

Two behaviours worth knowing:

  • Timeout watchdog. A Lambda that hits its timeout is killed before any code runs, so it would leave no trace. Shortly before the deadline (remaining time minus the flush timeout and a small margin) the wrapper closes the invocation span as an error, marks it faas.timeout_imminent, and exports it. If the handler does finish afterwards the span is left as it is.
  • Request body capture follows HONEYCOMB_CAPTURE_REQUEST: errors (default) attaches the redacted body only to failed invocations, always attaches it to every span, off never sends it. Path parameters and the query string are always recorded (redacted).

Configuration (set per service in serverless.yml provider.environment, values from the pipeline):

VariableDefaultPurpose
HONEYCOMB_API_KEYunset (tracing off)Honeycomb ingest key. Setting it enables tracing.
HONEYCOMB_API_ENDPOINThttps://api.honeycomb.ioUse https://api.eu1.honeycomb.io for EU teams.
OTEL_SERVICE_NAMESERVICE_NAME, then the function nameHoneycomb creates one dataset per service name.
HONEYCOMB_DATASETunsetHoneycomb Classic only; environment-based teams leave it unset.
HONEYCOMB_SAMPLE_RATE1Keep 1 in N traces at the root. Spans carry SampleRate so Honeycomb re-weights counts. Head sampling cannot see errors, so keep this at 1 until volume forces otherwise.
HONEYCOMB_FLUSH_TIMEOUT_MS2000Upper bound on the export wait added to each invocation.
HONEYCOMB_CAPTURE_REQUESTerrorsWhen to attach the redacted request body: errors, always or off.
GIT_SHA / COMMIT_SHA / SERVICE_VERSIONLambda function versionReported as service.version, so a trace names the deployed commit. Set it from the pipeline.

Resource attributes come from the Lambda environment: service.name, service.version, deployment.environment.name (STAGE), cloud.region, faas.name, faas.version, faas.max_memory.

Notes:

  • The provider lives for the life of the container; warm invocations reuse it. Tracing.reset() tears it down (tests).
  • The exporter is a plain HTTPS call to Honeycomb, so it adds a few hundred milliseconds to the cold start and roughly the flush round trip to each invocation. Telemetry failures are logged and never fail a request.
  • If a Lambda layer has already registered a global tracer provider, it wins; the wrapper's provider then only flushes an empty buffer.

WarehouseService

Manages TypeORM database connections with connection caching.

const warehouse = di.get(DEFINITIONS.WAREHOUSE);

// Get a connection (cached by default)
const connection = await warehouse.connect();

// Force a new connection (bypass cache)
const fresh = await warehouse.connect(null, false);

// Connect to a specific database
const analytics = await warehouse.connect('analytics_db');

// Health check
await warehouse.status();

Connection types:

Set via the WAREHOUSE_TYPE environment variable:

  • postgres - direct PostgreSQL connection using WAREHOUSE_HOST, WAREHOUSE_USERNAME, WAREHOUSE_PASSWORD, WAREHOUSE_DATABASE
  • postgres-ssm - credentials fetched from AWS Secrets Manager using DB_CREDS_ARN

AuthenticationService

Checks user roles and organisation access. Lazy-initialises a database connection on first use.

const auth = di.get(DEFINITIONS.AUTHENTICATION);
await auth.init();

// Check organisation access and roles in one call
// Throws a 401 ResponseModel if checks fail
await auth.checkUserRoles('org-123', ['admin', 'finance']);

// Check organisation access only
await auth.checkUserRoles('org-123');

// Check roles only
await auth.checkUserRoles(null, ['admin']);

// Individual checks
const roles = await auth.fetchUserRoles();                // ['admin', 'viewer']
const hasAdmin = await auth.hasRole('admin');              // true/false
const orgs = await auth.fetchUserOrganisations(user);     // includes descendants

HTTPService

Axios-based HTTP client with configurable timeout.

const http = di.get(DEFINITIONS.HTTP);

// Default timeout is 10 seconds
http.setDefaultTimeout(30000);

const response = await http.request({
  method: 'POST',
  url: 'https://api.example.com/payments',
  headers: { Authorization: 'Bearer token' },
  data: { amount: 1000 },
});

SecretsService

Fetches and caches secrets from AWS Secrets Manager.

const secrets = di.get(DEFINITIONS.SECRETS);

// Fetched once, then cached for the Lambda execution
const creds = await secrets.get('arn:aws:secretsmanager:eu-west-1:123:secret:db-creds');
// { username: 'admin', password: '...', host: '...', ... }

WebhookService

Dispatches HMAC-SHA256 signed webhooks.

const webhook = di.get(DEFINITIONS.WEBHOOK);

await webhook.send(
  'https://example.com/webhook',
  { event: 'payment.completed', transaction_id: 'txn_123' },
  'webhook-signing-secret'
);
// POST with X-Signature header containing HMAC-SHA256 hex digest

AuditLoggerService

Creates audit trail events via EventBridge.

const auditLogger = di.get(DEFINITIONS.AUDIT_LOGGER);

await auditLogger.createEvent('payment.refunded', 'entity-123', 'org-456');

Response Model

All Lambda responses use a standardised format with CORS headers.

import { ResponseModel } from '@felloh-org/lambda-wrapper';

// Basic response
const response = new ResponseModel({ users: [] }, 200);
return response.generate();

// Building a response
const response = new ResponseModel();
response.setData({ id: 1, name: 'Test' });
response.setCode(201);
response.setMetaVariable('pagination', { page: 1, total: 10 });
response.setBodyVariable('warnings', ['Deprecated field used']);
return response.generate();

// Adding errors
const error = new ResponseModel({}, 422);
error.addError({
  title: 'Validation Error',
  message: 'Email is not valid',
  documentation_url: 'https://developers.felloh.com/errors#error-responses',
  type: 'validation',
  code: 'validation.email',
});
throw error;  // or return error.generate()

// Static shorthand
return ResponseModel.generate({ result: 'ok' }, 200);

Generated response format:

{
  "statusCode": 200,
  "headers": {
    "Content-Type": "application/json",
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Credentials": true
  },
  "body": "{\"data\":{},\"errors\":[],\"meta\":{\"code\":200,\"reason\":\"OK\",\"message\":\"The request was successful\",\"request_id\":\"uuid-v4\"}}"
}

Supported status codes:

CodeReason
200OK
201Created
204No Content
400Bad Request
401Unauthorized
403Forbidden
404Not Found
406Not Acceptable
410Gone
413Request Entity Too Large
422Unprocessable Entity
429Too Many Requests
500Internal Server Error
502Bad Gateway
503Service Unavailable
504Gateway Timeout

Status Model

Used for health checks and service status reporting.

import { StatusModel, STATUS_TYPES } from '@felloh-org/lambda-wrapper';

const status = new StatusModel('database', STATUS_TYPES.OK);
// STATUS_TYPES: OK, ACCEPTABLE_FAILURE, APPLICATION_FAILURE

Lambda Termination

A custom error class for terminating Lambda execution with a specific status code and consumer-facing message.

import { LambdaTermination } from '@felloh-org/lambda-wrapper';

// Terminates with a 503 response
throw new LambdaTermination(
  'Payment provider timeout after 30s',  // internal (logged)
  503,                                    // status code
  'Service temporarily unavailable',      // body (returned to consumer)
  'Provider X timed out'                  // details
);

EventBridge Events

Publish typed events to AWS EventBridge.

import {
  LambdaWrapper,
  DEFINITIONS,
  TransactionCompleteEvent,
  TransactionCompleteEmailEvent,
  UserRegistrationEvent,
  CSVEmailEvent,
  RefundRequestEmailEvent,
  BaseEvent,
} from '@felloh-org/lambda-wrapper';

export const handler = LambdaWrapper(config, async (di) => {
  const eventBridge = di.get(DEFINITIONS.EVENT_BRIDGE);

  // Use a pre-built event
  const event = new TransactionCompleteEvent();
  event.setDetailParam('transaction_id', 'txn_123');
  await eventBridge.put(event);

  // Or build a custom event
  const custom = new BaseEvent('order.shipped');
  custom.setDetailParam('order_id', 'ord_456');
  custom.setDetail({ order_id: 'ord_456', carrier: 'DHL' });
  await eventBridge.put(custom);
});

Available event types:

EventDescription
BaseEventGeneric event, set your own detail type
TransactionCompleteEventTransaction completed
TransactionCompleteEmailEventTransaction receipt email
UserRegistrationEventNew user registration
UserPasswordChangedEventPassword changed
UserPasswordResetEventPassword reset requested
SandboxRegistrationEventSandbox account registration
CSVEmailEventCSV export email
POSCRequestEmailEventPOSC request email
RefundRequestEmailEventRefund request notification

Webhook Models

Format transaction and refund data for webhook payloads.

import { TransactionWebhookModel, RefundWebhookModel } from '@felloh-org/lambda-wrapper';

// Transaction webhook
const payload = new TransactionWebhookModel(transaction, 'Payment received');
const data = payload.get();
// { transaction: { id, narrative }, amount, booking, status, currency, surcharge, ... }

Database (TypeORM)

Entities

The library includes TypeORM entities organised by domain:

DomainDescription
paymentTransactions, refunds, chargebacks, payment links, ecommerce, providers, sessions
userUsers, organisations, roles, features, webhooks, billing, partners, portals
bankAccounts, ledgers, settlements, disbursals, adjustments, beneficiaries
agent-dataBookings, components, suppliers, package types
acquirerBIN data, batches, adjustments, band rates, transaction settlements
aispOpen banking transactions, GoCardless accounts/agreements/requisitions
nuapayNuapay accounts, balances, beneficiaries, transactions
nuveiNuvei batches, merchants, transactions, metadata
trust-paymentsTrust Payments batches, merchants, transactions, chargebacks, fees
total-processingTotal Processing transactions and metadata
planetPlanet transactions, metadata, batches
saltedgeSaltedge accounts, connections, customers, transactions, leads
basis-theoryTokenisation tokens
go-cardlessGoCardless organisation configuration
marketingMarketing contacts and ESUs
referenceCountries
playbookPlaybooks, requests, secrets, versions

Migrations

Run migrations against the database:

# Create database schemas
yarn orm:schema:create

# Run pending migrations
yarn orm:migration:run

# Generate a new migration
yarn orm:migration:generate <name>

# Revert last migration
yarn orm:revert

Migrations require the following environment variables:

VariableDescription
WAREHOUSE_TYPEpostgres or postgres-ssm
WAREHOUSE_HOSTDatabase host (for postgres type)
WAREHOUSE_USERNAMEDatabase username (for postgres type)
WAREHOUSE_PASSWORDDatabase password (for postgres type)
WAREHOUSE_DATABASEDatabase name
WAREHOUSE_SCHEMADatabase schema
DB_CREDS_ARNSecrets Manager ARN (for postgres-ssm type)

Database Schemas

The database is organised in the following schemas: user, payment, bank, agent_data, nuapay, trust_payments, total_processing, token, nuvei, reference, saltedge, acquirer, operations, basis_theory, aisp, go_cardless, planet, marketing, amex, crm, shield.

Utilities

PromisifiedDelay

Provides randomised delays for retry logic, with configurable latency profiles.

import { PromisifiedDelay } from '@felloh-org/lambda-wrapper';

// High latency profile (2-20s delays, weighted towards shorter)
const delay = new PromisifiedDelay(true);

// Standard latency profile (2-5s delays)
const delay = new PromisifiedDelay(false);

// Use in retry loop
for (let attempt = 0; attempt < 3; attempt++) {
  try {
    return await makeRequest();
  } catch (error) {
    await delay.get();
  }
}

Development

Commands

# Build for production (webpack)
yarn build

# Build for TypeORM migrations (babel)
yarn build:orm

# Run linter
yarn lint

# Run tests with coverage
yarn test

# Run dependency vulnerability audit
yarn audit:check

# Run database migrations
yarn orm:migration:run

# Generate a new migration
yarn orm:migration:generate <name>

# Revert last migration
yarn orm:revert

# Create database schemas
yarn orm:schema:create

Environment Variables

VariableDescription
SERVICE_NAMEService identifier for logging and events
EVENT_BRIDGE_ARNAWS EventBridge bus ARN
REGIONAWS region
WAREHOUSE_TYPEDatabase connection type (postgres or postgres-ssm)
WAREHOUSE_HOSTDatabase host
WAREHOUSE_USERNAMEDatabase username
WAREHOUSE_PASSWORDDatabase password
WAREHOUSE_DATABASEDatabase name
WAREHOUSE_SCHEMADatabase schema
DB_CREDS_ARNSecrets Manager ARN for database credentials
DB_LOGGINGSet to true to enable TypeORM query logging
LOGGER_SOFT_WARNINGSet to true to downgrade warnings to info level
IS_OFFLINESet by serverless-offline for local development

Project Structure

src/
├── action/              # Action handlers (e.g. unmatched route)
├── config/              # Dependency definitions
├── dependency-injection/  # DI container and base class
├── entity/              # TypeORM entities by domain
├── enums/               # Shared enumerations
├── event/               # EventBridge event classes
├── migration/           # Database migrations by schema
├── model/               # Response, status, and webhook models
├── service/             # Core services (logger, request, warehouse, auth, etc.)
├── util/                # Utilities (LambdaTermination, PromisifiedDelay)
└── wrapper/             # Lambda wrapper implementation

CI/CD

The project uses Concourse CI with the following pipeline:

  1. lint-and-test - runs lint, tests, and dependency audit in parallel
  2. migrations.staging - creates schemas and runs migrations on staging
  3. migrations.production - promotes to production after staging succeeds
  4. migrations.sandbox - promotes to sandbox after staging succeeds

Testing

Tests are colocated with source files (e.g. src/service/logger.test.js alongside src/service/logger.js).

yarn test

License

MIT

版本与发布记录

@felloh-org/lambda-wrapper 共发布 490 个版本,首次发布于 2021/12/22;过去 12 个月发布了 88 个版本。

版本发布日期距今
1.11.277latest2026/11/13今天
1.11.2762026/11/113 天前
1.11.2752026/11/113 天前
1.11.2742026/11/059 天前
1.11.2732026/11/059 天前
1.11.2722026/11/059 天前

关于 @felloh-org/lambda-wrapper 的常见问题

@felloh-org/lambda-wrapper 是什么?

Lambda wrapper for all Felloh Serverless Projects

如何安装 @felloh-org/lambda-wrapper?

在项目目录运行 npm install @felloh-org/lambda-wrapper,或使用 pnpm add / yarn add / bun add。

@felloh-org/lambda-wrapper 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/felloh-org__lambda-wrapper 是否存在。

@felloh-org/lambda-wrapper 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@felloh-org/lambda-wrapper 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@felloh-org/lambda-wrapper 可以商用吗?

@felloh-org/lambda-wrapper 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@felloh-org/lambda-wrapper 的下载量有多少?

根据 npm 官方下载统计,@felloh-org/lambda-wrapper 在 2026/10/15 – 2026/11/13 这 30 天内被下载 3,432 次,日均约 114 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@felloh-org/lambda-wrapper 还在维护吗?

最新版本 1.11.277 发布于 2026/11/13(今天);至今共发布 490 个版本,其中过去 12 个月发布了 88 个;首次发布于 2021/12/22。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。