0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-02-03 22:29:08 -05:00

refactor: move to arrow function signature

This commit is contained in:
bholmesdev 2024-02-01 16:42:31 -05:00
parent b1b69e18d4
commit 4aaf393318
4 changed files with 66 additions and 61 deletions

View file

@ -6,7 +6,7 @@ import { existsSync } from 'fs';
import { mkdir, rm, writeFile } from 'fs/promises';
import { DB_PATH } from '../consts.js';
import { createLocalDatabaseClient } from '../../runtime/db-client.js';
import { astroConfigWithDbSchema, attachTableMetaHandler } from '../types.js';
import { astroConfigWithDbSchema } from '../types.js';
import { getAstroStudioEnv, type VitePlugin } from '../utils.js';
import { appTokenError } from '../errors.js';
import { errorMap } from './error-map.js';
@ -116,8 +116,7 @@ function astroDBIntegration(): AstroIntegration {
function setCollectionsMeta(collections: Record<string, any>) {
for (const [name, collection] of Object.entries(collections)) {
const table = collectionToTable(name, collection);
collection[name] = attachTableMetaHandler(collection);
collection[name]._setMeta?.({ table });
collection._setMeta?.({ table });
}
}

View file

@ -152,7 +152,7 @@ export function getModifiers(fieldName: string, field: DBField) {
function getReferencesConfig(field: DBField) {
const canHaveReferences = field.type === 'number' || field.type === 'text';
if (!canHaveReferences) return undefined;
return field.references as ReferenceableField;
return field.references?.();
}
// Using `DBField` will not narrow `default` based on the column `type`

View file

@ -21,22 +21,41 @@ const booleanFieldSchema = baseFieldSchema.extend({
default: z.boolean().optional(),
});
const numberFieldSchema = baseFieldSchema.extend({
const numberFieldSchema: z.ZodType<
{
// ReferenceableField creates a circular type. Define ZodType to resolve.
type: 'number';
default?: number | undefined;
references?: () => ReferenceableField | undefined;
primaryKey?: boolean | undefined;
} & z.infer<typeof baseFieldSchema>
> = baseFieldSchema.extend({
type: z.literal('number'),
default: z.number().optional(),
// Need to avoid `z.object()`. Otherwise, object references are broken,
// and we cannot set the `collection` field at runtime.
references: z.any().optional(),
references: z
.function()
.returns(z.lazy(() => referenceableFieldSchema))
.optional(),
primaryKey: z.boolean().optional(),
});
const textFieldSchema = baseFieldSchema.extend({
const textFieldSchema: z.ZodType<
{
// ReferenceableField creates a circular type. Define ZodType to resolve.
type: 'text';
multiline?: boolean | undefined;
default?: string | undefined;
references?: () => ReferenceableField | undefined;
primaryKey?: boolean | undefined;
} & z.infer<typeof baseFieldSchema>
> = baseFieldSchema.extend({
type: z.literal('text'),
multiline: z.boolean().optional(),
default: z.string().optional(),
// Need to avoid `z.object()`. Otherwise, object references are broken,
// and we cannot set the `collection` field at runtime.
references: z.any().optional(),
references: z
.function()
.returns(z.lazy(() => referenceableFieldSchema))
.optional(),
primaryKey: z.boolean().optional(),
});
@ -73,9 +92,14 @@ export const indexSchema = z.object({
unique: z.boolean().optional(),
});
const foreignKeysSchema = z.object({
const foreignKeysSchema: z.ZodType<{
fields: MaybeArray<string>;
references: () => MaybeArray<ReferenceableField>;
}> = z.object({
fields: z.string().or(z.array(z.string())),
references: referenceableFieldSchema.or(z.array(referenceableFieldSchema)),
references: z
.function()
.returns(z.lazy(() => referenceableFieldSchema.or(z.array(referenceableFieldSchema)))),
});
export type Indexes = Record<string, z.infer<typeof indexSchema>>;
@ -170,13 +194,6 @@ export const astroConfigWithDbSchema = z.object({
export type FieldsConfig = z.input<typeof collectionSchema>['fields'];
type CollectionMeta<TFields extends FieldsConfig> = {
// Collection table is set later when running the data() function.
// Collection config is assigned to an object key,
// so the collection itself does not know the table name.
table: Table<string, TFields>;
};
interface CollectionConfig<TFields extends FieldsConfig>
// use `extends` to ensure types line up with zod,
// only adding generics for type completions.
@ -202,51 +219,40 @@ export type ResolvedCollectionConfig<
table: Table<string, TFields>;
};
/**
* Handler to attach the Drizzle `table` and collection name at runtime.
* These cannot be determined from `defineCollection()`,
* since we don't know the collection name until the `db` config is resolved.
*/
export function attachTableMetaHandler<TFields extends FieldsConfig, TWritable extends boolean>(
collectionConfig: ResolvedCollectionConfig<TFields, TWritable>
): ResolvedCollectionConfig<TFields, TWritable> {
const meta: CollectionMeta<TFields> = { table: collectionConfig.table };
const _setMeta = (values: CollectionMeta<TFields>) => {
// `_setMeta` is called twice: once from the user's config,
// and once after the config is parsed via Zod.
(collectionConfig as any)._setMeta?.(values);
Object.assign(meta, values);
const tableName = getTableName(meta.table);
for (const fieldName in collectionConfig.fields) {
const field = collectionConfig.fields[fieldName];
field.collection = tableName;
}
};
for (const fieldName in collectionConfig.fields) {
const field = collectionConfig.fields[fieldName];
field.name = fieldName;
}
return {
...collectionConfig,
get table() {
return meta.table;
},
// @ts-expect-error private setter
_setMeta,
};
}
function baseDefineCollection<TFields extends FieldsConfig, TWritable extends boolean>(
userConfig: CollectionConfig<TFields>,
writable: TWritable
): ResolvedCollectionConfig<TFields, TWritable> {
return attachTableMetaHandler({
for (const fieldName in userConfig.fields) {
const field = userConfig.fields[fieldName];
// Store field name within the field itself to track references
field.name = fieldName;
}
const meta: { table: Table<string, TFields> } = { table: null! };
/**
* We need to attach the Drizzle `table` at runtime using `_setMeta`.
* These cannot be determined from `defineCollection()`,
* since we don't know the collection name until the `db` config is resolved.
*/
const _setMeta = (values: { table: Table<string, TFields> }) => {
Object.assign(meta, values);
const tableName = getTableName(meta.table);
for (const fieldName in userConfig.fields) {
const field = userConfig.fields[fieldName];
field.collection = tableName;
}
};
return {
...userConfig,
get table() {
return meta.table;
},
writable,
table: null!,
});
// @ts-expect-error private setter
_setMeta,
};
}
export function defineCollection<TFields extends FieldsConfig>(

View file

@ -14,7 +14,7 @@ const Ingredient = defineCollection({
id: field.number({ primaryKey: true }),
name: field.text(),
quantity: field.number(),
recipeId: field.text({ references: Recipe.fields.id }),
recipeId: field.text({ references: () => Recipe.fields.id }),
},
indexes: {
recipeIdx: { on: 'recipeId' },