Repository: withastro/astro
File: packages/db/src/runtime/virtual.ts (TypeScript)

Code before:
	TextColumnOpts,
} from '../core/types.js';

function createColumn<S extends string, T extends Record<string, unknown>>(type: S, schema: T) {
	return {
		type,
		/**
		 * @internal
		 */
		schema,
	};
}

export function isDbError(err: unknown): err is LibsqlError {
	// guard for `err instanceof LibsqlError`
	if (!err || !(err instanceof Error)) return false;
	const value = err as LibsqlError;
	return (
		// Error
		typeof value.name === 'string' &&
		typeof value.message === 'string' &&
		(value.stack === undefined || typeof value.stack === 'string') &&
		// LibsqlError
		typeof value.code === 'string' &&
		(value.rawCode === undefined || typeof value.rawCode === 'number')
	);
}

export const column = {
	number: <T extends NumberColumnOpts>(opts: T = {} as T) => {
		return createColumn('number', opts) satisfies { type: 'number' };
	},
	boolean: <T extends BooleanColumnInput['schema']>(opts: T = {} as T) => {
		return createColumn('boolean', opts) satisfies { type: 'boolean' };
	},
	text: <T extends TextColumnOpts>(opts: T = {} as T) => {
		return createColumn('text', opts) satisfies { type: 'text' };
	},
	date<T extends DateColumnInput['schema']>(opts: T = {} as T) {
		return createColumn('date', opts) satisfies { type: 'date' };
	},
	json<T extends JsonColumnInput['schema']>(opts: T = {} as T) {
		return createColumn('json', opts) satisfies { type: 'json' };
	},
};

export function defineTable<TColumns extends ColumnsConfig>(userConfig: TableConfig<TColumns>) {
	return userConfig;
}

export function defineDb(userConfig: DBConfigInput) {

Review comment (bug):
It looks like the libsql errors also have the `libsqlError: true` property which perhaps should be sufficient enough for the checks? Here was the logs:

<details>
<summary>open logs</summary>

```
Error thrown: Error: UNIQUE constraint failed: User.name
    at Object.next (/Users/bjorn/Work/repros/astro-issue-12400-repro/node_modules/.pnpm/libsql@0.4.7/node_modules/libsql/index.js:335:20)
    at Statement.all (/Users/bjorn/Work/repros/astro-issue-12400-repro/node_modules/.pnpm/libsql@0.4.7/node_modules/libsql/index.js:360:16)
    at executeStmt (file:///Users/bjorn/Work/repros/astro-issue-12400-repro/node_modules/.pnpm/@libsql+client@0.14.0/node_modules/@libsql/client/lib-esm/sqlite3.js:261:34)
    at Sqlite3Client.execute (file:///Users/bjorn/Work/repros/astro-issue-12400-repro/node_modules/.pnpm/@libsql+client@0.14.0/node_modules/@libsql/client/lib-esm/sqlite3.js:79:16)
    at LibSQLPreparedQuery.values (file:///Users/bjorn/Work/repros/astro-issue-12400-repro/node_modules/.pnpm/drizzle-orm@0.31.4_@libsql+client@0.14.0/node_modules/drizzle-orm/libsql/session.js:170:59)
    at LibSQLPreparedQuery.get (file:///Users/bjorn/Work/repros/astro-issue-12400-repro/node_modules/.pnpm/drizzle-orm@0.31.4_@libsql+client@0.14.0/node_modules/drizzle-orm/libsql/session.js:143:29)
    at QueryPromise.get (file:///Users/bjorn/Work/repros/astro-issue-12400-repro/node_modules/.pnpm/drizzle-orm@0.31.4_@libsql+client@0.14.0/node_modules/drizzle-orm/sqlite-core/query-builders/insert.js:148:28)
    at handler (/Users/bjorn/Work/repros/astro-issue-12400-repro/src/actions/index.ts:15:117)
    at eval (/Users/bjorn/Work/repros/astro-issue-12400-repro/node_modules/.pnpm/astro@4.16.10_typescript@5.6.3/node_modules/astro/dist/actions/runtime/virtual/server.js:68:18)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  rawCode: 2067,
  code: 'SQLITE_CONSTRAINT_UNIQUE',
  libsqlError: true
}
```
</details>

Perhaps we can simplify the check here as: 
```suggestion
	return err instanceof LibsqlError || (err instanceof Error && (err as any).libsqlError === true)
```

Code after:
	TextColumnOpts,
} from '../core/types.js';

function createColumn<S extends string, T extends Record<string, unknown>>(type: S, schema: T) {
	return {
		type,
		/**
		 * @internal
		 */
		schema,
	};
}

export const column = {
	number: <T extends NumberColumnOpts>(opts: T = {} as T) => {
		return createColumn('number', opts) satisfies { type: 'number' };
	},
	boolean: <T extends BooleanColumnInput['schema']>(opts: T = {} as T) => {
		return createColumn('boolean', opts) satisfies { type: 'boolean' };
	},
	text: <T extends TextColumnOpts>(opts: T = {} as T) => {
		return createColumn('text', opts) satisfies { type: 'text' };
	},
	date<T extends DateColumnInput['schema']>(opts: T = {} as T) {
		return createColumn('date', opts) satisfies { type: 'date' };
	},
	json<T extends JsonColumnInput['schema']>(opts: T = {} as T) {
		return createColumn('json', opts) satisfies { type: 'json' };
	},
};

export function defineTable<TColumns extends ColumnsConfig>(userConfig: TableConfig<TColumns>) {
	return userConfig;
}

export function defineDb(userConfig: DBConfigInput) {
	return userConfig;
}

// Exports a few common expressions
export const NOW = _sql`CURRENT_TIMESTAMP`;
export const TRUE = _sql`TRUE`;
export const FALSE = _sql`FALSE`;

export {
	sql,
	eq,
	gt,
	gte,
	lt,
	lte,