easy-pingv0.7.0

Get in touch

Questions, bug reports, or anything about easy-ping. Either of these reaches me.

Emailteklumo.jembere@gmail.comTelegram@teklumt

For anything others would benefit from, a GitHub issue is better than a DM, because it's searchable.

GitHub

Guides / Upgrading

Edit this page

Upgrading

What happens to your schema when a new version adds a column, on each database path.

0.3.0 to 0.4.0

Four things to do, in this order:

  1. Secrets. secret and cron.secret must be at least 16 characters and not a placeholder, or startup throws. Generate real ones before deploying.
  2. Schema. notification_preference gains updated_at. planPostgresMigration emits the ALTER TABLE ... ADD COLUMN IF NOT EXISTS for it (verified against a 0.3.0-shaped table); drizzle-kit diffs it; MongoDB needs nothing. Rows written before the upgrade have no value until they are next saved, so the unsubscribe freshness check does not apply to them yet.
  3. Tokens. Signing keys are now derived per purpose, so every token issued by 0.3.0 stops verifying. Unsubscribe links in already-sent email will return 400; re-issue them.
  4. Plugins and clients. PluginInitContext.secret is gone; use ctx.sign(). Any client that POSTs without Content-Type: application/json, or from another origin, now gets 415 or 403. The shipped clients already send both correctly; add trustedOrigins if your API lives on a different origin from the page.

Which path you're on

You bootstrapped withTo upgrade
createSchema() + drizzle-kitdrizzle-kit diffs it for you — nothing to do here
renderPostgresDdl()planPostgresMigration() — see below
createMongoIndexes()Rerun it. createIndex is idempotent and additive.

renderPostgresDdl cannot upgrade you. It emits CREATE TABLE IF NOT EXISTS, correct exactly once. Rerunning it on an existing database does nothing at all — a version that adds a column would otherwise leave that column silently missing until something hits it at runtime.

planPostgresMigration

import { INTROSPECT_SQL, planPostgresMigration, coreSchema } from "easy-ping/schema";

const plan = await planPostgresMigration(
  async () =>
    (await sql.unsafe(INTROSPECT_SQL)).map((row) => ({
      table: row.table_name,
      column: row.column_name,
      type: row.data_type,
      nullable: row.is_nullable === "YES",
    })),
  coreSchema,
);

for (const statement of plan.statements) await sql.unsafe(statement);
if (plan.unsupported.length) console.warn(plan.unsupported);

It introspects the live schema, diffs it against the declaration, and emits only what's missing. Run the same call for any plugin's schema too — push({...}).schema, preferences().schema.

What it will and won't do

Additive only, deliberately. It adds missing columns and indexes, and creates tables that don't exist yet. It never drops a column, never changes a type, and never touches a column it doesn't declare — each of those lands in plan.unsupported as a message for a human, because they're destructive and context-dependent in ways a generic tool shouldn't guess at.

One behavior worth knowing before you run it against a populated table: a required field with no default is added nullable, because NOT NULL would abort against existing rows. That case is also reported in unsupported — backfill the column, then ALTER ... SET NOT NULL yourself.