Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved error logging from config #10207

Merged
merged 3 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions packages/db/src/core/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ export const MISSING_PROJECT_ID_ERROR = `${red('▶ Directory not linked.')}
To link this directory to an Astro Studio project, run
${cyan('astro db link')}\n`;

export const STUDIO_CONFIG_MISSING_WRITABLE_COLLECTIONS_ERROR = (collectionName: string) => `${red(
`▶ Writable collection ${bold(collectionName)} requires Astro Studio or the ${yellow(
export const STUDIO_CONFIG_MISSING_WRITABLE_TABLE_ERROR = (tableName: string) => `${red(
`▶ Writable table ${bold(tableName)} requires Astro Studio or the ${yellow(
'unsafeWritable'
)} option.`
)}
Expand All @@ -34,10 +34,20 @@ export const MIGRATIONS_NOT_INITIALIZED = `${yellow(
'▶ No migrations found!'
)}\n\n To scaffold your migrations folder, run\n ${cyan('astro db sync')}\n`;

export const SEED_WRITABLE_IN_PROD_ERROR = (collectionName: string) => {
export const SEED_WRITABLE_IN_PROD_ERROR = (tableName: string) => {
return `${red(
`Writable tables should not be seeded in production with data().`
)} You can seed ${bold(
collectionName
tableName
)} in development mode only using the "mode" flag. See the docs for more: https://www.notion.so/astroinc/astrojs-db-README-dcf6fa10de9a4f528be56cee96e8c054?pvs=4#278aed3fc37e4cec80240d1552ff6ac5`;
};

export const SEED_ERROR = (tableName: string, error: string) => {
return `${red(`Error seeding table ${bold(tableName)}:`)}\n\n${error}`;
};

export const SEED_EMPTY_ARRAY_ERROR = (tableName: string) => {
// Drizzle error says "values() must be called with at least one value."
// This is specific to db.insert(). Prettify for seed().
return SEED_ERROR(tableName, `Empty array was passed. seed() must receive at least one value.`);
};
9 changes: 2 additions & 7 deletions packages/db/src/core/integration/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import { DB_PATH } from '../consts.js';
import { createLocalDatabaseClient } from '../../runtime/db-client.js';
import { astroConfigWithDbSchema, type DBTables } from '../types.js';
import { type VitePlugin } from '../utils.js';
import {
STUDIO_CONFIG_MISSING_WRITABLE_COLLECTIONS_ERROR,
UNSAFE_WRITABLE_WARNING,
} from '../errors.js';
import { STUDIO_CONFIG_MISSING_WRITABLE_TABLE_ERROR, UNSAFE_WRITABLE_WARNING } from '../errors.js';
import { errorMap } from './error-map.js';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
Expand Down Expand Up @@ -76,9 +73,7 @@ function astroDBIntegration(): AstroIntegration {
const foundWritableCollection = Object.entries(tables).find(([, c]) => c.writable);
const writableAllowed = studio || unsafeWritable;
if (!writableAllowed && foundWritableCollection) {
logger.error(
STUDIO_CONFIG_MISSING_WRITABLE_COLLECTIONS_ERROR(foundWritableCollection[0])
);
logger.error(STUDIO_CONFIG_MISSING_WRITABLE_TABLE_ERROR(foundWritableCollection[0]));
process.exit(1);
}
// Using writable tables with the opt-in flag. Warn them to let them
Expand Down
71 changes: 46 additions & 25 deletions packages/db/src/core/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@ import { bold } from 'kleur/colors';
import { type SQL, sql, getTableName } from 'drizzle-orm';
import { SQLiteAsyncDialect, type SQLiteInsert } from 'drizzle-orm/sqlite-core';
import type { AstroIntegrationLogger } from 'astro';
import type { DBUserConfig } from '../core/types.js';
import type {
ColumnsConfig,
DBUserConfig,
MaybeArray,
ResolvedCollectionConfig,
} from '../core/types.js';
import { hasPrimaryKey } from '../runtime/index.js';
import { isSerializedSQL } from '../runtime/types.js';
import { SEED_WRITABLE_IN_PROD_ERROR } from './errors.js';
import { SEED_EMPTY_ARRAY_ERROR, SEED_ERROR, SEED_WRITABLE_IN_PROD_ERROR } from './errors.js';

const sqlite = new SQLiteAsyncDialect();

Expand Down Expand Up @@ -51,40 +56,56 @@ export async function seedData({
logger?: AstroIntegrationLogger;
mode: 'dev' | 'build';
}) {
const dataFns = Array.isArray(data) ? data : [data];
try {
const dataFns = Array.isArray(data) ? data : [data];
for (const dataFn of dataFns) {
await dataFn({
seed: async ({ table, writable }, values) => {
if (writable && mode === 'build' && process.env.ASTRO_DB_TEST_ENV !== '1') {
(logger ?? console).error(SEED_WRITABLE_IN_PROD_ERROR(getTableName(table)));
process.exit(1);
seed: async (config, values) => {
seedErrorChecks(mode, config, values);
try {
await db.insert(config.table).values(values as any);
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
throw new Error(SEED_ERROR(getTableName(config.table), msg));
}
await db.insert(table).values(values as any);
},
seedReturning: async ({ table, writable }, values) => {
if (writable && mode === 'build' && process.env.ASTRO_DB_TEST_ENV !== '1') {
(logger ?? console).error(SEED_WRITABLE_IN_PROD_ERROR(getTableName(table)));
process.exit(1);
}
let result: SQLiteInsert<any, any, any, any> = db
.insert(table)
.values(values as any)
.returning();
if (!Array.isArray(values)) {
result = result.get();
seedReturning: async (config, values) => {
seedErrorChecks(mode, config, values);
try {
let result: SQLiteInsert<any, any, any, any> = db
.insert(config.table)
.values(values as any)
.returning();
if (!Array.isArray(values)) {
result = result.get();
}
return result;
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
throw new Error(SEED_ERROR(getTableName(config.table), msg));
}
return result;
},
db,
mode,
});
}
} catch (error) {
(logger ?? console).error(
`Failed to seed data. Did you update to match recent schema changes?`
);
(logger ?? console).error(error as string);
} catch (e) {
if (!(e instanceof Error)) throw e;
(logger ?? console).error(e.message);
}
}

function seedErrorChecks<T extends ColumnsConfig>(
mode: 'dev' | 'build',
{ table, writable }: ResolvedCollectionConfig<T, boolean>,
values: MaybeArray<unknown>
) {
const tableName = getTableName(table);
if (writable && mode === 'build' && process.env.ASTRO_DB_TEST_ENV !== '1') {
throw new Error(SEED_WRITABLE_IN_PROD_ERROR(tableName));
}
if (Array.isArray(values) && values.length === 0) {
throw new Error(SEED_EMPTY_ARRAY_ERROR(tableName));
}
}

Expand Down
Loading