Skip to content
← Public packages

@kentcdodds/package-storage-migrations

Ordered idempotent packageStorage schema migrations + isolate-memoized runner. Caller always passes storage.

src/smoke.ts

86 lines · 2.2 KB · TypeScript
import { packageStorage } from 'kody:runtime'
import {
	createMigrationRunner,
	runPackageStorageMigrations,
} from './index.ts'

/**
 * Post-publish smoke against **this** package's `packageStorage()` bucket only.
 *
 * Application / product code must pass the **caller's** storage into
 * `runPackageStorageMigrations` / `createMigrationRunner` — never rely on this
 * smoke path for product data.
 *
 * @returns Projection asserting first-run applies, second-run is idempotent,
 * and the isolate runner shares one promise.
 *
 * @example
 * import smoke from 'kody:@kentcdodds/package-storage-migrations/smoke'
 * const result = await smoke()
 */
export default async function smoke() {
	const storage = packageStorage()
	const versionKey = '__psm_smoke:schema-version'
	const legacyKey = '__psm_smoke:notes-v1'
	const notesKey = '__psm_smoke:notes'

	await storage.delete?.(versionKey)
	await storage.delete?.(notesKey)
	await storage.set(legacyKey, [
		{ id: 'a', text: 'hi', createdAt: '2026-01-01T00:00:00.000Z' },
	])

	const migrations = [
		{
			version: 1,
			name: 'notes-to-document',
			async up(s: {
				get(key: string): Promise<unknown>
				set(key: string, value: unknown): Promise<void>
				delete?(key: string): Promise<void>
			}) {
				const legacy = await s.get(legacyKey)
				if (Array.isArray(legacy)) {
					await s.set(notesKey, { items: legacy })
					await s.delete?.(legacyKey)
				}
			},
		},
	]

	const first = await runPackageStorageMigrations({
		storage,
		versionKey,
		migrations,
	})
	const second = await runPackageStorageMigrations({
		storage,
		versionKey,
		migrations,
	})
	const ensure = createMigrationRunner({ storage, versionKey, migrations })
	const third = await ensure()
	const fourth = await ensure()

	const notes = (await storage.get(notesKey)) as { items?: unknown } | undefined
	const legacyGone = (await storage.get(legacyKey)) == null

	const ok =
		first.fromVersion === 0 &&
		first.toVersion === 1 &&
		first.applied.length === 1 &&
		second.applied.length === 0 &&
		second.toVersion === 1 &&
		third.applied.length === 0 &&
		fourth === third &&
		Array.isArray(notes?.items) &&
		legacyGone

	return {
		ok,
		first,
		secondApplied: second.applied.length,
		sharedEnsure: third === fourth,
		legacyGone,
	}
}