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

feat: API shape

This commit is contained in:
bholmesdev 2024-01-31 16:51:44 -05:00
parent 1b2941c909
commit d0abf2c763
2 changed files with 38 additions and 8 deletions

View file

@ -16,16 +16,36 @@ const booleanFieldSchema = baseFieldSchema.extend({
default: z.boolean().optional(), default: z.boolean().optional(),
}); });
const numberFieldSchema = baseFieldSchema.extend({ // NOTE (bholmesdev): `references` creates a recursive type. This is not supported by zod.
// Declare `NumberField` and `TextField` manually and use `z.lazy()` in schema.
// see https://zod.dev/?id=recursive-types
export type NumberField = z.infer<typeof baseFieldSchema> & {
type: 'number';
default?: number;
references?: ReferenceableField;
primaryKey?: boolean;
};
const numberFieldSchema: z.ZodType<NumberField> = baseFieldSchema.extend({
type: z.literal('number'), type: z.literal('number'),
default: z.number().optional(), default: z.number().optional(),
references: z.lazy(() => referenceableFieldSchema).optional(),
primaryKey: z.boolean().optional(), primaryKey: z.boolean().optional(),
}); });
const textFieldSchema = baseFieldSchema.extend({ export type TextField = z.infer<typeof baseFieldSchema> & {
type: 'text';
multiline?: boolean;
default?: string;
references?: ReferenceableField;
primaryKey?: boolean;
};
const textFieldSchema: z.ZodType<TextField> = baseFieldSchema.extend({
type: z.literal('text'), type: z.literal('text'),
multiline: z.boolean().optional(), multiline: z.boolean().optional(),
default: z.string().optional(), default: z.string().optional(),
references: z.lazy(() => referenceableFieldSchema).optional(),
primaryKey: z.boolean().optional(), primaryKey: z.boolean().optional(),
}); });
@ -53,19 +73,26 @@ const fieldSchema = z.union([
dateFieldSchema, dateFieldSchema,
jsonFieldSchema, jsonFieldSchema,
]); ]);
export const referenceableFieldSchema = z.union([textFieldSchema, numberFieldSchema]);
export type ReferenceableField = z.infer<typeof referenceableFieldSchema>;
const fieldsSchema = z.record(fieldSchema); const fieldsSchema = z.record(fieldSchema);
export const indexSchema = z.object({ export const indexSchema = z.object({
on: z.string().or(z.array(z.string())), on: z.string().or(z.array(z.string())),
unique: z.boolean().optional(), unique: z.boolean().optional(),
}); });
const indexesSchema = z.record(indexSchema);
export type Indexes = z.infer<typeof indexesSchema>; const foreignKeysSchema = z.object({
fields: z.string().or(z.array(z.string())),
references: referenceableFieldSchema.or(z.array(referenceableFieldSchema)),
});
export type Indexes = Record<string, z.infer<typeof indexSchema>>;
const baseCollectionSchema = z.object({ const baseCollectionSchema = z.object({
fields: fieldsSchema, fields: fieldsSchema,
indexes: indexesSchema.optional(), indexes: z.record(indexSchema).optional(),
foreignKeys: z.array(foreignKeysSchema).optional(),
table: z.any(), table: z.any(),
_setMeta: z.function().optional(), _setMeta: z.function().optional(),
}); });
@ -82,8 +109,6 @@ export const collectionSchema = z.union([readableCollectionSchema, writableColle
export const collectionsSchema = z.record(collectionSchema); export const collectionsSchema = z.record(collectionSchema);
export type BooleanField = z.infer<typeof booleanFieldSchema>; export type BooleanField = z.infer<typeof booleanFieldSchema>;
export type NumberField = z.infer<typeof numberFieldSchema>;
export type TextField = z.infer<typeof textFieldSchema>;
export type DateField = z.infer<typeof dateFieldSchema>; export type DateField = z.infer<typeof dateFieldSchema>;
// Type `Date` is the config input, `string` is the output for D1 storage // Type `Date` is the config input, `string` is the output for D1 storage
export type DateFieldInput = z.input<typeof dateFieldSchema>; export type DateFieldInput = z.input<typeof dateFieldSchema>;
@ -164,6 +189,11 @@ interface CollectionConfig<TFields extends FieldsConfig>
// only adding generics for type completions. // only adding generics for type completions.
extends Pick<z.input<typeof collectionSchema>, 'fields' | 'indexes'> { extends Pick<z.input<typeof collectionSchema>, 'fields' | 'indexes'> {
fields: TFields; fields: TFields;
foreignKeys?: Array<{
fields: MaybeArray<Extract<keyof TFields, string>>;
// TODO: runtime error if parent collection doesn't match for all fields. Can't put a generic here...
references: MaybeArray<ReferenceableField>;
}>;
indexes?: Record<string, IndexConfig<TFields>>; indexes?: Record<string, IndexConfig<TFields>>;
} }

View file

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