npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@meyicloud/meyi-cost-server

v1.8.6

Published

Tenant-aware AWS CUR and Athena cost plugin server for MeyiConnect

Readme

Meyi Insight Cost Server

Tenant-aware Express plugin that provides AWS cost overview, reports, dynamic filters, budgets, and budget-alert dismissals from centralized Cost and Usage Report (CUR) data queried through Athena. CUR is mandatory; the package does not call or fall back to AWS Cost Explorer.

The package is designed to be mounted by a host backend. The host owns login, token verification, tenant/plugin enablement, PostgreSQL connection creation, and AWS onboarding. The plugin owns cost routes and its budget-related tables.

Package contract

  • Package name: @meyicloud/meyi-cost-server
  • Runtime: Node.js 20 or newer, ESM
  • Framework: Express 4
  • Database API: injected Drizzle PostgreSQL instance
  • Peer dependency: pg >= 8
  • Default route: /api/v1/cost
  • Public factory: createInsightCost({ app, db, apiBaseUri, logger })

Features

  • Tenant-isolated payer/organization and member-account cost views
  • Monthly and yearly overview data
  • Service, account, region, resource, and cost-allocation-tag reports
  • Dynamic service, region, linked-account, and tag filter options
  • Standard and comparison report data used by @meyicloud/meyi-cost-ui
  • CUR/Athena active-resource counts and detailed cost data
  • Explicit CUR setup, pending-data, and unavailable states
  • Tenant-scoped budget rules
  • User-, tenant-, month-, and status-scoped budget-alert dismissals
  • Tenant-configurable daily, weekly, and monthly AI report schedules
  • PostgreSQL-backed background report jobs with failure history
  • Analyser-generated Markdown and PDF reports available through tenant-scoped downloads

Budgets are application rules stored in PostgreSQL; they are not AWS Budgets resources. The consuming application evaluates them against current cost and shows the notification UI.

Architecture and request flow

flowchart LR
  Host[External Express application] --> Auth[Authentication]
  Auth --> Enabled[Tenant plugin check]
  Enabled --> Router[/api/v1/cost]
  Router --> Controller[Cost controller]
  Controller --> Customer[Tenant CUR metadata]
  Controller --> SaaS[SaaS Athena context]
  SaaS --> Athena[Central tenant and connection-partitioned CUR]
  Controller --> Budget[Budget services]
  Budget --> DB[(PostgreSQL)]
src/
|-- controllers/             HTTP-to-service orchestration
|-- routes/                  Express routes and error handling
|-- models/                  Normalized immutable domain models
|-- repositories/            Tenant onboarding persistence access
|-- services/                AWS CUR/Athena contexts and budgets
|-- schema/                  Budget and dismissal table installation
|-- lib/                     Cost, date, filter, and SQL helpers
`-- plugin.js                Dependency composition and lifecycle

Local development and validation

Requirements:

  • Node.js 20 or newer
  • npm
  • PostgreSQL available to the host used for integration testing

Install dependencies:

npm install

This package is native JavaScript ESM and has no transpilation build step. Validate syntax and package contents with:

node --check index.js
node --check cur.js
node --check src/plugin.js
npm pack --dry-run

When files below src change, syntax-check every changed .js file. The npm archive must include index.js, cur.js, the complete src directory, README.md, and AGENTS.md.

For a local package installation test:

npm pack
npm install /path/to/meyicloud-meyi-cost-server-1.6.0.tgz

Publish to npm

Publishing changes the external registry. Run these commands only after release authorization:

npm login
npm whoami
npm version patch
npm pack --dry-run
npm publish --access public

Use npm version minor or npm version major when appropriate. This server package currently has no compile step or prepublishOnly script, so syntax and integration validation must be completed before publishing.

After publishing:

npm view @meyicloud/meyi-cost-server version
npm install @meyicloud/meyi-cost-server@<published-version>

Integrate with an external Express application

Install the package and its PostgreSQL peer dependency:

npm install @meyicloud/meyi-cost-server pg

For local development, use a file dependency:

{
  "dependencies": {
    "@meyicloud/meyi-cost-server": "file:../../meyi-market-places/insight-cost-server"
  }
}

Create the plugin using the host's Express app and Drizzle database:

import express from "express";
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import { createInsightCost } from "@meyicloud/meyi-cost-server";

const app = express();
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const db = drizzle(pool);

app.use(express.json());

// These host middlewares must be registered before plugin.start().
app.use("/api/v1/cost", authenticateRequest);
app.use("/api/v1/cost", requireCostPluginForTenant);

const costPlugin = createInsightCost({
  app,
  db,
  apiBaseUri: "/api/v1",
  logger: console,
});

await costPlugin.install();
await costPlugin.start();

Lifecycle behavior:

  • install() creates or verifies plugin-owned budget and dismissal tables.
  • start() mounts the router once at ${apiBaseUri}/cost.
  • stop() is currently a no-op but is available for host lifecycle symmetry.
  • router is also returned for hosts that need custom mounting.

app is optional only when the host mounts the returned router itself. db is required.

Host authentication and tenant contract

Before a request reaches the plugin, the host should authenticate it and set:

req.user = {
  id: "authenticated-user-id",
  tenant_id: "authenticated-tenant-id",
};

The tenant resolver checks req.user.tenant_id, then req.user.tenantId, then x-tenant-id, then DEFAULT_TENANT_ID. In production, prefer an authenticated req.user tenant and do not accept an untrusted tenant header.

The Marketplace onboarding integration loads tenant access from:

  • <DB_SCHEMA>.aws_connections
  • <DB_SCHEMA>.aws_accounts
  • <DB_SCHEMA>.cost_cur_config
  • <DB_SCHEMA>.cost_cur_discovery_jobs
  • <DB_SCHEMA>.cost_cur_discovery_job_logs

Only a connected row containing Cost with verified Cost access is accepted. Connection metadata supplies account display names and CUR source metadata; the dedicated Cost CUR table supplies the tenant partition and delivery/readiness state. Customer credentials are never passed to the central Athena client.

CUR discovery runs as one shared scheduler with independent tenant job rows. Each job checks only its configured S3 prefix, finds a tenant-safe Glue table, and verifies the tenant partition through Athena. A successful job becomes READY and is no longer scheduled. Job events are retained separately in cost_cur_discovery_job_logs and also include tenant and job IDs in application logs.

Data-source behavior

Central CUR through SaaS Athena

CUR applies line_item_unblended_cost > 0 for displayed gross cost and can also calculate net cost, credits/adjustments, active resources, detailed resource rows, account/region relationships, and allocation-tag data.

The SaaS runtime identity, or the dedicated role configured by COST_CUR_ROLE_ARN, queries the SaaS-owned Athena/Glue/S3 resources. Customer onboarding creates a CUR 2.0 Data Export directly into a tenant prefix in the Meyi-owned bucket; customer AWS credentials are not reused for Athena.

CUR is mandatory. /data-status reports whether configuration, discovery, and tenant rows are ready. Data endpoints return HTTP 503 with a structured state and action when CUR is not configured, still waiting for rows, or unavailable.

Environment variables

All variables below belong to the backend runtime. Never place AWS or database secrets in @meyicloud/meyi-cost-ui, a browser environment, source control, or a Docker image layer. Supply them at container/process runtime.

Database and tenant variables

| Variable | Default | Required | Purpose | | --- | --- | --- | --- | | DB_SCHEMA | meyiconnect | No | PostgreSQL schema containing onboarding and plugin-owned tables. | | DEFAULT_TENANT_ID | default | No | Final tenant fallback when authenticated request context is absent. Prefer authenticated tenant context in production. | | DATABASE_URL | None | Host-specific | Not read by the package directly. The host commonly uses it to create the injected db connection. |

Production tenants should use per-tenant onboarding role metadata. Environment credentials are process-wide and therefore unsuitable as the normal credential source for a multi-tenant service.

When customer environment credentials are enabled, central Athena is disabled unless COST_CUR_ROLE_ARN is also configured. This prevents the AWS SDK default credential chain from accidentally using a customer's local test key against SaaS Athena resources.

AI analysis variables

AI reports are generated by a separate meyi-cost-ai-analyser Fargate task. The backend only schedules jobs, launches and monitors the task, and serves tenant-scoped artifacts. It does not invoke Bedrock or generate PDFs itself. Daily reports cover the previous complete day, weekly reports cover the previous seven complete days, and monthly reports cover the previous calendar month in the configured timezone.

The authenticated report API is:

| Method | Route | Purpose | | --- | --- | --- | | GET | /analysis/schedule | Read this tenant's schedule. | | PUT | /analysis/schedule | Update the schedule; requires req.user.role=admin. | | GET | /analysis/reports | List tenant report history without PDF bytes. | | GET | /analysis/reports/:id | Read one tenant report. | | GET | /analysis/reports/:id/pdf | Download a completed report PDF. | | GET | /analysis/reports/:id/markdown | Download the canonical Markdown report. |

Schedule and report rows live in cost_ai_report_schedules and cost_ai_reports. The worker atomically claims due schedules with a lease, so a restarted task can resume future work without relying on in-memory timers.

| Variable | Default | Required | Purpose | | --- | --- | --- | --- | | COST_AI_ENABLED | false | No | Enables the schedule worker and external analyser integration. | | COST_AI_ANALYSER_REGION | AWS_REGION | When enabled | ECS and report-bucket region. | | COST_AI_ANALYSER_CLUSTER | Empty | When enabled | ECS cluster ARN or name. | | COST_AI_ANALYSER_TASK_DEFINITION | Empty | When enabled | Fargate task definition ARN. | | COST_AI_ANALYSER_CONTAINER_NAME | cost-ai-analyser | No | Container override target. | | COST_AI_ANALYSER_SUBNETS | Empty | When enabled | Comma-separated private subnet IDs. | | COST_AI_ANALYSER_SECURITY_GROUPS | Empty | When enabled | Comma-separated task security groups. | | COST_AI_ANALYSER_REPORT_BUCKET | Empty | When enabled | Private S3 Markdown/PDF artifact bucket. | | COST_AI_ANALYSER_PROVIDER_SECRET_PREFIX | Empty | When enabled | Prefix for temporary Secrets Manager entries containing each tenant's active Meyi Connect AI provider configuration. | | COST_AI_ANALYSER_TARGET_REGIONS | AWS_REGION | No | Customer regions inspected for resource detail. | | COST_AI_ANALYSER_TOP_N_SERVICES | 10 | No | Maximum high-cost service agents run per report. | | COST_AI_ANALYSER_POLL_INTERVAL_MS | 15000 | No | ECS task status polling interval. | | COST_AI_ANALYSER_TIMEOUT_MS | 2700000 | No | Maximum external task duration. | | COST_AI_REPORT_POLL_INTERVAL_MS | 60000 | No | How often the background worker claims due schedules; minimum 10 seconds. | | COST_AI_REPORT_LEASE_MS | 3600000 | No | Claim lease used to recover from an interrupted worker. | | COST_AI_REPORT_BATCH_SIZE | 5 | No | Maximum schedules claimed by one worker tick; clamped from 1 to 25. |

GET /analysis/status reports meyi-cost-ai-analyser with an ecs-task source. The analyser uses the shared ECS task role for Athena, S3, Bedrock, and cross-account role assumption. New reports store task and private artifact references in cost_ai_reports; existing database-backed PDF rows remain downloadable for compatibility. Model or task failures mark only that report as failed and do not change CUR, standard reports, or onboarding.

CUR/Athena variables

| Variable | Default | Required | Purpose | | --- | --- | --- | --- | | COST_DATA_SOURCE | cur | No | Compatibility setting. Cost data is always CUR/Athena only. | | COST_CUR_DATABASE | Empty | CUR | Athena/Glue database containing the CUR table. | | COST_CUR_TABLE | Empty | No | Optional manual Glue table override. When empty, the tenant discovery job supplies the verified table. | | COST_CUR_OUTPUT_LOCATION | Empty | CUR | S3 URI where Athena writes query results. | | COST_CUR_REGION | AWS_REGION or us-east-1 | No | Region for the Athena client. | | COST_CUR_WORKGROUP | meyi-cost | No | Meyi-owned Athena workgroup used for every query. | | AWS_REGION | us-east-1 | No | Used as the CUR region fallback. | | COST_CUR_TENANT_COLUMN | tenant_id | No | CUR column used to isolate the Hive-style tenant partition. | | COST_CUR_TENANT_PARTITION | Request tenant ID | No | Overrides the partition value. Avoid a global override in multi-tenant production unless every request is intentionally mapped to that partition. | | COST_CUR_CONNECTION_COLUMN | connection_id | No | CUR column used to isolate the selected AWS source connection. The connection value is resolved from onboarding data and is not a global environment override. | | COST_CUR_MAX_ROWS | 1000 | No | Resource-report row cap, clamped between 1 and 5000. | | COST_CUR_ROLE_ARN | Empty | No | Dedicated SaaS-side role assumed only for central Athena/Glue/S3 queries. | | COST_CUR_EXTERNAL_ID | Empty | No | External ID for the dedicated SaaS CUR role. | | COST_CUR_ALLOW_TENANT_CATALOG | false | No | Compatibility switch allowing tenant metadata to override the central catalog. Keep false for centralized SaaS CUR. | | COST_CUR_INGESTION_MODE | central | No | Describes the CUR ingestion contract returned by readiness status. | | COST_CUR_STATUS_CACHE_MS | 300000 | No | Cache duration for the live tenant CUR readiness query. | | COST_CUR_DISCOVERY_ENABLED | true | No | Enables tenant-specific background CUR discovery. | | COST_CUR_DISCOVERY_INTERVAL_MS | 3600000 | No | Retry interval for non-ready tenant jobs; minimum 60000 ms. | | COST_CUR_DISCOVERY_BATCH_SIZE | 25 | No | Maximum due tenant jobs selected per scheduler tick. |

Central catalog settings come from the SaaS backend environment. Only the tenant partition and customer source metadata come from onboarding by default. Legacy per-tenant catalog overrides are accepted only when COST_CUR_ALLOW_TENANT_CATALOG=true.

Example: centralized CUR/Athena

COST_DATA_SOURCE=cur
COST_CUR_DATABASE=meyi_central_cur
COST_CUR_TABLE=
COST_CUR_OUTPUT_LOCATION=s3://meyi-saas-athena-results/
COST_CUR_REGION=us-east-1
COST_CUR_WORKGROUP=meyi-cost
COST_CUR_TENANT_COLUMN=tenant_id
COST_CUR_CONNECTION_COLUMN=connection_id
COST_CUR_MAX_ROWS=1000
COST_CUR_ROLE_ARN=arn:aws:iam::SAAS_ACCOUNT_ID:role/meyi-cur-query
COST_CUR_ALLOW_TENANT_CATALOG=false
COST_CUR_INGESTION_MODE=central
COST_CUR_DISCOVERY_ENABLED=true
COST_CUR_DISCOVERY_INTERVAL_MS=3600000

Required AWS read-only access

The SaaS identity must be able to query Athena, read the Glue catalog and central CUR bucket, and write to the Athena results bucket. The customer onboarding role needs only the customer-side permissions required by the chosen CUR export/DataSync design. These policies must remain separate.

A payer/management-account role can expose organization-wide linked-account costs. A member-account role normally exposes only the costs AWS makes visible to that member. Separate member-account roles are not required merely to group organization cost by linked account when the payer role already has that data.

HTTP API

Routes are mounted below ${apiBaseUri}/cost:

| Method | Path | Purpose | | --- | --- | --- | | GET | /accounts | Selected or discovered AWS accounts. | | GET | /data-status | Central CUR configuration, ingestion, readiness, row count, and freshness without exposing secrets. | | GET | /overview | Totals, trends, accounts, services, regions, and active resources when CUR is available. | | GET | /filter-options | Dynamic report filter values. | | GET | /reports | Standard/comparison source data grouped by service, account, region, resource, or tag. | | GET | /tags | Available cost-allocation tags. | | GET | /analysis/status | Whether Cost AI is enabled and its non-secret runtime metadata. | | GET | /analysis/latest | Latest stored analysis for the authenticated tenant. | | POST | /analysis | Generate or reuse a cached tenant analysis for a validated date range. | | GET | /budgets | Tenant budget rules. | | POST | /budgets | Create a tenant budget rule. | | DELETE | /budgets/:id | Delete a tenant budget rule. | | GET | /budget-alert-dismissals | Current user's persisted dismissals. | | POST | /budget-alert-dismissals | Dismiss one budget/month/status alert. |

Docker packaging

When embedding the local package in a Docker build, copy all published package files, not only index.js:

index.js
cur.js
src/
package.json
README.md
AGENTS.md

Environment files should not be copied into the image. Pass required variables with the deployment platform, Docker Compose env_file, or secret manager at runtime.

Reference Meyi Connect integration

The current host adapter is:

meyi-connect/backend/src/plugins/cost/index.mjs

It supplies the shared Drizzle database, authenticated token middleware, tenant-level plugin enablement, and plugin lifecycle wiring.

Consumer validation checklist

  1. Run server syntax checks and npm pack --dry-run.
  2. Install or refresh the package in the host backend.
  3. Run install() against a disposable/test database.
  4. Verify unauthenticated and disabled-tenant requests are rejected by the host.
  5. Verify two tenants cannot access each other's accounts, budgets, or alert dismissals.
  6. Test CUR ready, not-configured, pending-data, and unavailable modes.
  7. Verify payer and member-account visibility matches the AWS role used.
  8. Build and start the consuming host backend before creating a Docker image.

Central CUR ingestion contract

The package implements the application side of the FinOps-style design: strict credential separation, tenant-partitioned Athena queries, fail-closed data access, and live readiness/freshness reporting. The AWS data-transfer plane must deliver each customer's CUR objects into the central CUR layout consumed by Glue. That is deployment infrastructure, not an HTTP request made with a customer access key.

Onboarding may persist these non-secret fields in session meta:

{
  "curSourceBucket": "customer-cur-bucket",
  "curSourcePrefix": "reports/meyi/",
  "curSourceRegion": "us-east-1",
  "curTenantPartition": "authenticated-tenant-id",
  "curIngestionMode": "central"
}

The transfer pipeline must copy or replicate only that source prefix into the SaaS central location for the matching tenant partition. GET /data-status then verifies that Athena can see rows for that partition. Until rows arrive, cost endpoints remain unavailable and the UI directs the user to Cost sources or CUR discovery with the applicable readiness message.