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

dynamodb-expression-builder

v0.3.0

Published

DynamoDB expression builder and code generator: build update, condition, filter and key condition expressions with automatic ExpressionAttributeNames/Values aliasing, then emit runnable code for the JavaScript SDK v3 and DocumentClient, AWS CLI, boto3, Ja

Readme

dynamodb-expression-builder

DynamoDB expression builder and code generator. Build update, condition, filter and key condition expressions with automatic ExpressionAttributeNames / ExpressionAttributeValues aliasing — then emit the whole request as runnable code for the JavaScript SDK v3 (low-level or DocumentClient), AWS CLI, boto3 (Python), Java, Go, .NET, Rust, Kotlin, PHP, Ruby, PartiQL or dynamodb-toolbox. Zero dependencies.

Hand-writing DynamoDB expressions means juggling three coupled structures — the expression string, the #name aliases (mandatory whenever an attribute name is one of DynamoDB's 573 reserved words), and the typed :value placeholders — and keeping them consistent across every operation. The AWS SDKs for Go and Java ship expression builders for this; the JavaScript SDK v3 does not. This package is that builder, plus something the official ones don't do in any language: code generation, so one structured request becomes a paste-ready command in whichever SDK your team actually runs.

Values are type-tagged (S/N/B/BOOL/SS/NS/BS/NULL), never inferred from JavaScript runtime types — marshall('5') would silently write a string where you meant a number; a tag can't.

Install

npm install dynamodb-expression-builder

ESM and CJS, browser-safe, no dependencies.

Thirty seconds

import {buildRequest, emitSdkV3, emitCli, emitBoto3} from 'dynamodb-expression-builder';

const request = buildRequest({
  operation: 'Query',
  tableName: 'orders',
  hashKey: {field: 'customerId', type: 'S', value: 'CUST#42'},
  rangeKey: {field: 'orderDate', type: 'S', operator: 'begins_with', value: '2026-08'},
  filters: [{field: 'status', type: 'S', operator: '=', value: 'shipped'}]
});

emitSdkV3(request);
// new QueryCommand({
//   "TableName": "orders",
//   "KeyConditionExpression": "#hashKey = :hashKeyValue AND begins_with(#rangeKey, :rangeKeyValue)",
//   "FilterExpression": "#filter0 = :filterValue0",
//   "ExpressionAttributeNames": {
//     "#hashKey": "customerId",
//     "#rangeKey": "orderDate",
//     "#filter0": "status"
//   },
//   "ExpressionAttributeValues": {
//     ":hashKeyValue": { "S": "CUST#42" },
//     ":rangeKeyValue": { "S": "2026-08" },
//     ":filterValue0": { "S": "shipped" }
//   }
// })

The same request feeds every emitter — emitCli(request) gives the aws dynamodb query \ … command, emitBoto3(request) the Python, emitJava / emitGo / emitDotnet / emitRust / emitKotlin / emitPhp the typed AttributeValue constructors for those SDKs, emitDocClient / emitRuby the native-value shapes their SDKs marshal themselves, and emitPartiql(request) the equivalent SELECT statement (or an honest {ok: false, reason} where PartiQL can't express the request).

Update expressions compile from a list of actions:

import {buildUpdateExpression, makeTypedValue} from 'dynamodb-expression-builder';

buildUpdateExpression([
  {kind: 'SET', field: 'status', setOp: 'assign', value: makeTypedValue('S', 'shipped')},
  {kind: 'ADD', field: 'loginCount', value: makeTypedValue('N', '1')},
  {kind: 'REMOVE', field: 'legacyFlag'}
]);
// {
//   expression: 'SET #upd0 = :updValue0 REMOVE #upd2 ADD #upd1 :updValue1',
//   names: {'#upd0': 'status', '#upd1': 'loginCount', '#upd2': 'legacyFlag'},
//   typedValues: {':updValue0': {type: 'S', value: 'shipped'}, ':updValue1': {type: 'N', value: '1'}}
// }

SET idioms are first-class: assign, if_not_exists, atomic counters (add/subtract), list_append/list_prepend, plus REMOVE (including list elements by index) and ADD/DELETE for numbers and sets.

And emitQueryProgram(config, format) wraps a Query/Scan request into a complete runnable program — client setup, the request, and a LastEvaluatedKey pagination loop — with format one of 'sdk' | 'docclient' | 'cli' | 'boto3' | 'partiql' | 'java' | 'go' | 'dotnet' | 'rust' | 'kotlin' | 'php' | 'ruby' | 'ddbtoolbox' — each paginated program uses its SDK's own idiom (paginateQuery, into_paginator(), queryPaginated flows, getPaginator, pageable responses).

API

Three layers, each usable on its own:

| Layer | Exports | | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Model | TypedValue, makeTypedValue, FilterRow, KeyAttr, RangeKeyCondition, UpdateAction, the FILTER_OPERATORS registry + per-type compatibility helpers | | Builders | buildRequest(config) → one CanonicalRequest for any of GetItem/Query/Scan/Update/Put/Delete · buildFilterExpressions · buildKeyConditionExpression · buildUpdateExpression | | Emitters | emitSdkV3 · emitDocClient · emitCli · emitBoto3 · emitJava · emitGo · emitDotnet · emitRust · emitKotlin · emitPhp · emitRuby · emitPartiql · emitDdbToolboxProgram · emitQueryProgram · typedMapToAvMap (tag-driven marshal) |

Placeholder namespaces never collide: keys use #hashKey/#rangeKey, filters #filter{i}, conditions #cond{i}, updates #upd{i} — one request can carry a key condition, a filter, a write condition and an update expression simultaneously.

Honest degradation is a design rule: emitters return {ok: false, reason} (PartiQL for unsupported constructs, program emission where a target can't express the request) instead of emitting code that looks right and isn't.

Build one in the browser

The same engine powers two interactive tools: the DynamoDB expression builder (expression syntax for all six operations) and the DynamoDB query builder (complete Query/Scan requests with the pagination loop). Reserved-word aliasing is the same problem our dynamodb-reserved-words package solves as data.

License

MIT © DynoTable