Security News
38% of CISOs Fear They’re Not Moving Fast Enough on AI
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
@ff00ff/mammoth
Advanced tools
![Mammoth](https://s3-eu-west-1.amazonaws.com/mammoth-static.ff00ff.nl/mammoth-logo.png)
📖 Work-in-progress documentation site is available at https://mammoth.tools/.
npm i @ff00ff/mammoth
Mammoth is a type-safe query builder. It only supports Postgres which we consider a feature. It's syntax is as close to SQL as possible so you already know how to use it. It's autocomplete features are great. It helps you avoid mistakes so you can develop applications faster.
const rows = await db
.select(star())
.from(db.foo)
.leftJoin(db.bar)
.on(db.foo.barId.eq(db.bar.id))
.where(db.foo.id.eq(`1`));
The above query produces the following SQL:
SELECT
*
FROM foo
LEFT JOIN bar ON (foo.bar_id = bar.id)
WHERE
foo.id = $1
More importantly, the resulting type of rows is { id: string; barId: string; name: string | undefined }[]
. Notice how the name is automatically nullable because of the left join.
const updateCount = await db.update(db.foo).set({ name: `Test` }).where(db.foo.value.gt(0));
UPDATE foo
SET
name = $1
WHERE
value > $2
const rows = await db
.insertInto(db.foo)
.values({
name: `Test`,
value: 123,
})
.returning(`id`);
INSERT INTO foo (
name,
value
) VALUES (
$1,
$2
)
RETURNING
id
const affectedCount = await db
.insertInto(db.foo, ['name'])
.select(db.bar.name)
.from(db.bar)
.where(db.bar.name.isNotNull());
INSERT INTO foo (name)
SELECT
bar.name
FROM bar
WHERE
bar.name IS NOT NULL
db.select(count()).from(db.foo);
SELECT COUNT(*) FROM foo
db.select(arrayAgg(db.foo.name.orderBy(db.foo.name.desc()))).from(db.foo);
SELECT array_agg(foo.name ORDER BY foo.name DESC) "arrayAgg" FROM foo
db.with(
`regionalSales`,
() =>
db
.select(db.orderLog.region, sum(db.orderLog.amount).as(`totalSales`))
.from(db.orderLog)
.groupBy(db.orderLog.region),
`topRegions`,
({ regionalSales }) =>
db
.select(regionalSales.region)
.from(regionalSales)
.where(
regionalSales.totalSales.gt(
db.select(sum(regionalSales.totalSales).divide(10)).from(regionalSales),
),
),
({ topRegions }) =>
db
.select(
db.orderLog.region,
db.orderLog.product,
sum(db.orderLog.quantity).as(`productUnits`),
sum(db.orderLog.amount).as(`productSales`),
)
.from(db.orderLog)
.where(db.orderLog.region.in(db.select(topRegions.region).from(topRegions)))
.groupBy(db.orderLog.region, db.orderLog.product),
);
WITH "regionalSales" AS (SELECT order_log.region, SUM (order_log.amount) "totalSales" FROM order_log GROUP BY order_log.region), "topRegions" AS (SELECT "regionalSales".region FROM "regionalSales" WHERE "regionalSales"."totalSales" > (SELECT SUM ("regionalSales"."totalSales") / $1 FROM "regionalSales")) SELECT order_log.region, order_log.product, SUM (order_log.quantity) "productUnits", SUM (order_log.amount) "productSales" FROM order_log WHERE order_log.region IN (SELECT "topRegions".region FROM "topRegions") GROUP BY order_log.region, order_log.product
Mammoth is a query builder pur sang so it doesn't include a database driver. You need to create a db and pass a callback to execute the query.
import { defineDb } from '@ff00ff/mammoth';
import { foo, bar } from './tables';
const db = defineDb({ foo, bar }, async (query, parameters) => {
const result = await pool.query(query, parameters);
return {
affectedCount: result.rowCount,
rows: result.rows,
};
});
In the defineDb
call you pass all your tables so they can be access through the db instance. You have to define all the tables to make sure Mammoth understands the type information. This should be close to the CREATE TABLE syntax.
const foo = defineTable({
id: uuid().primaryKey().default(`gen_random_uuid()`),
createDate: timestampWithTimeZone().notNull().default(`now()`),
name: text().notNull(),
value: integer(),
});
You should keep your column names camelCase in the defineTable call as they are automatically transformed to train_case throughout Mammoth.
Below is a list of clauses per query and a short description on what we Mammoth supports.
Now that we've hit 1.0 Mammoth will stick to semantic versioning, meaning, breaking changes will only be included in major updates.
Once you clone the repo, do a npm install
+ npm run build
. Now you should be able to run npm test
seeing everything turn green. Feel free to pick up one of the open issues — in particular you can pick up one labeled with "good first issue". Be sure to claim the issue before you start so we avoid two or more people working on the same thing.
FAQs
![Mammoth](https://s3-eu-west-1.amazonaws.com/mammoth-static.ff00ff.nl/mammoth-logo.png)
We found that @ff00ff/mammoth demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers 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
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
Research
Security News
Socket researchers uncovered a backdoored typosquat of BoltDB in the Go ecosystem, exploiting Go Module Proxy caching to persist undetected for years.
Security News
Company News
Socket is joining TC54 to help develop standards for software supply chain security, contributing to the evolution of SBOMs, CycloneDX, and Package URL specifications.