0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-01-20 22:12:38 -05:00

feat: config design

This commit is contained in:
bholmesdev 2024-01-29 17:50:15 -05:00
parent 915ed7ac0b
commit bda07ec94e
3 changed files with 36 additions and 17 deletions

View file

@ -1,6 +1,6 @@
import type { SQLiteInsertValue } from 'drizzle-orm/sqlite-core'; import type { SQLiteInsertValue } from 'drizzle-orm/sqlite-core';
import type { SqliteDB, Table } from './internal.js'; import type { SqliteDB, Table } from './internal.js';
import type { MaybeArray, collectionSchema } from './types.js'; import type { DBCollection, MaybeArray, collectionSchema } from './types.js';
import { import {
type BooleanField, type BooleanField,
type DBFieldInput, type DBFieldInput,
@ -9,15 +9,14 @@ import {
type NumberField, type NumberField,
type TextField, type TextField,
collectionsSchema, collectionsSchema,
type indexSchema,
type MaybePromise, type MaybePromise,
} from './types.js'; } from './types.js';
import { z } from 'zod'; import { z } from 'zod';
export type DBFieldsConfig = z.input<typeof collectionSchema>['fields'];
export type DBDataContext = { export type DBDataContext = {
db: SqliteDB; db: SqliteDB;
seed<TFields extends DBFieldsConfig>( seed<TFields extends FieldsConfig>(
collection: ResolvedCollectionConfig<TFields>, collection: ResolvedCollectionConfig<TFields>,
data: MaybeArray< data: MaybeArray<
SQLiteInsertValue< SQLiteInsertValue<
@ -25,7 +24,7 @@ export type DBDataContext = {
string, string,
/** TODO: true type inference */ Record< /** TODO: true type inference */ Record<
Extract<keyof TFields, string>, Extract<keyof TFields, string>,
DBFieldsConfig[number] FieldsConfig[number]
> >
> >
> >
@ -51,26 +50,36 @@ export const astroConfigWithDbSchema = z.object({
db: dbConfigSchema.optional(), db: dbConfigSchema.optional(),
}); });
type CollectionMeta<TFields extends DBFieldsConfig> = { export type FieldsConfig = z.input<typeof collectionSchema>['fields'];
type CollectionMeta<TFields extends FieldsConfig> = {
// Collection table is set later when running the data() function. // Collection table is set later when running the data() function.
// Collection config is assigned to an object key, // Collection config is assigned to an object key,
// so the collection itself does not know the table name. // so the collection itself does not know the table name.
table: Table<string, TFields>; table: Table<string, TFields>;
}; };
type CollectionConfig<TFields extends DBFieldsConfig> = { interface CollectionConfig<TFields extends FieldsConfig>
// use `extends` to ensure types line up with zod,
// only adding generics for type completions.
extends Pick<z.input<typeof collectionSchema>, 'fields' | 'indexes'> {
fields: TFields; fields: TFields;
}; indexes?: Record<string, IndexConfig<TFields>>;
}
interface IndexConfig<TFields extends FieldsConfig> extends z.input<typeof indexSchema> {
on: MaybeArray<Extract<keyof TFields, string>>;
}
export type ResolvedCollectionConfig< export type ResolvedCollectionConfig<
TFields extends DBFieldsConfig = DBFieldsConfig, TFields extends FieldsConfig = FieldsConfig,
Writable extends boolean = boolean, Writable extends boolean = boolean,
> = CollectionConfig<TFields> & { > = CollectionConfig<TFields> & {
writable: Writable; writable: Writable;
table: Table<string, TFields>; table: Table<string, TFields>;
}; };
export function defineCollection<TFields extends DBFieldsConfig>( export function defineCollection<TFields extends FieldsConfig>(
userConfig: CollectionConfig<TFields> userConfig: CollectionConfig<TFields>
): ResolvedCollectionConfig<TFields, false> { ): ResolvedCollectionConfig<TFields, false> {
const meta: CollectionMeta<TFields> = { table: null! }; const meta: CollectionMeta<TFields> = { table: null! };
@ -88,7 +97,7 @@ export function defineCollection<TFields extends DBFieldsConfig>(
}; };
} }
export function defineWritableCollection<TFields extends DBFieldsConfig>( export function defineWritableCollection<TFields extends FieldsConfig>(
userConfig: CollectionConfig<TFields> userConfig: CollectionConfig<TFields>
): ResolvedCollectionConfig<TFields, true> { ): ResolvedCollectionConfig<TFields, true> {
const meta: CollectionMeta<TFields> = { table: null! }; const meta: CollectionMeta<TFields> = { table: null! };

View file

@ -52,18 +52,25 @@ const fieldSchema = z.union([
]); ]);
const fieldsSchema = z.record(fieldSchema); const fieldsSchema = z.record(fieldSchema);
export const readableCollectionSchema = z.object({ export const indexSchema = z.object({
on: z.string().or(z.array(z.string())),
unique: z.boolean().optional(),
});
const indexesSchema = z.record(indexSchema);
const baseCollectionSchema = z.object({
fields: fieldsSchema, fields: fieldsSchema,
writable: z.literal(false), indexes: indexesSchema.optional(),
table: z.any(), table: z.any(),
_setMeta: z.function().optional(), _setMeta: z.function().optional(),
}); });
export const writableCollectionSchema = z.object({ export const readableCollectionSchema = baseCollectionSchema.extend({
fields: fieldsSchema, writable: z.literal(false),
});
export const writableCollectionSchema = baseCollectionSchema.extend({
writable: z.literal(true), writable: z.literal(true),
table: z.any(),
_setMeta: z.function().optional(),
}); });
export const collectionSchema = z.union([readableCollectionSchema, writableCollectionSchema]); export const collectionSchema = z.union([readableCollectionSchema, writableCollectionSchema]);

View file

@ -16,6 +16,9 @@ const Ingredient = defineCollection({
quantity: field.number(), quantity: field.number(),
recipeId: field.text(), recipeId: field.text(),
}, },
indexes: {
recipeIdx: { on: 'recipeId', unique: true },
},
}); });
export default defineConfig({ export default defineConfig({