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

Implement defineWritableCollection

This commit is contained in:
Matthew Phillips 2024-01-16 17:00:29 -05:00 committed by Nate Moore
parent 9a7da994b9
commit 9119753336
4 changed files with 57 additions and 20 deletions

View file

@ -20,19 +20,41 @@ export const astroConfigWithDBValidator = z.object({
db: adjustedConfigSchema.optional(),
});
type CollectionConfig<TFields extends z.input<typeof collectionSchema>['fields']> = {
fields: TFields;
// TODO: type inference based on field type. Just `any` for now.
data?: () => Array<Record<keyof TFields, any> & { id?: string }>;
// I don't love this name mp
source: 'readable' | 'writable';
type CollectionConfig<TFields extends z.input<typeof collectionSchema>['fields'], Writable extends boolean> =
Writable extends true ? (
{
fields: TFields;
// TODO: type inference based on field type. Just `any` for now.
seed?: Writable extends false ? never : () => Array<Record<keyof TFields, any> & { id?: string }>;
}
) : (
{
fields: TFields;
// TODO: type inference based on field type. Just `any` for now.
data?: Writable extends true ? never : () => Array<Record<keyof TFields, any> & { id?: string }>;
}
)
type ResolvedCollectionConfig<TFields extends z.input<typeof collectionSchema>['fields'], Writable extends boolean> = CollectionConfig<TFields, Writable> & {
writable: Writable;
};
export function defineCollection<TFields extends z.input<typeof collectionSchema>['fields']>(
userConfig: CollectionConfig<TFields>
): CollectionConfig<TFields> {
return userConfig;
userConfig: CollectionConfig<TFields, false>
): ResolvedCollectionConfig<TFields, false> {
return {
...userConfig,
writable: false
};
}
export function defineWritableCollection<TFields extends z.input<typeof collectionSchema>['fields']>(
userConfig: CollectionConfig<TFields, true>
): ResolvedCollectionConfig<TFields, true> {
return {
...userConfig,
writable: true
};
}
export type AstroConfigWithDB = z.infer<typeof astroConfigWithDBValidator>;

View file

@ -1,7 +1,8 @@
import type { SqliteRemoteDatabase } from 'drizzle-orm/sqlite-proxy';
import { createClient } from '@libsql/client';
import {
collectionSchema,
type ReadableDBCollection,
type WritableDBCollection,
type BooleanField,
type DBCollection,
type DBCollections,
@ -40,11 +41,15 @@ export type {
const sqlite = new SQLiteAsyncDialect();
function isReadableCollection(collection: DBCollection): collection is ReadableDBCollection {
return !collection.writable;
}
function checkIfModificationIsAllowed(collections: DBCollections, Table: SQLiteTable) {
// This totally works, don't worry about it
const tableName = (Table as any)[(SQLiteTable as any).Symbol.Name];
const collection = collections[tableName];
if(collection.source === 'readable') {
if(collection.writable) {
throw new Error(`The [${tableName}] collection is read-only.`);
}
}
@ -100,7 +105,7 @@ export async function setupDbTables({
await db.run(q);
}
for (const [name, collection] of Object.entries(collections)) {
if (!collection.data) continue;
if (!isReadableCollection(collection) || !collection.data) continue;
const table = collectionToTable(name, collection);
try {

View file

@ -50,15 +50,25 @@ const fieldSchema = z.union([
]);
const fieldsSchema = z.record(fieldSchema);
export const collectionSchema = z.object({
export const readableCollectionSchema = z.object({
fields: fieldsSchema,
data: z
.function()
.returns(z.array(z.record(z.unknown())))
.optional(),
source: z.enum(['readable', 'writable'])
writable: z.literal(false)
});
export const writableCollectionSchema = z.object({
fields: fieldsSchema,
seed: z
.function()
.returns(z.array(z.record(z.unknown())))
.optional(),
writable: z.literal(true)
});
export const collectionSchema = z.union([readableCollectionSchema, writableCollectionSchema]);
export const collectionsSchema = z.record(collectionSchema);
export type BooleanField = z.infer<typeof booleanFieldSchema>;
@ -79,8 +89,10 @@ export type FieldType =
export type DBField = z.infer<typeof fieldSchema>;
export type DBFieldInput = DateFieldInput | BooleanField | NumberField | TextField | JsonField;
export type DBFields = z.infer<typeof fieldsSchema>;
export type DBCollection = z.infer<typeof collectionSchema>;
export type DBCollection = z.infer<typeof readableCollectionSchema | typeof writableCollectionSchema>;
export type DBCollections = Record<string, DBCollection>;
export type ReadableDBCollection = z.infer<typeof readableCollectionSchema>;
export type WritableDBCollection = z.infer<typeof writableCollectionSchema>;
export type AstroTable<T extends Pick<TableConfig, 'name' | 'columns'>> = SQLiteTableWithColumns<
T & {

View file

@ -1,11 +1,10 @@
import { defineConfig } from 'astro/config';
import db, { defineCollection, field } from '@astrojs/db';
import db, { defineCollection, defineWritableCollection, field } from '@astrojs/db';
const Author = defineCollection({
fields: {
name: field.text(),
},
source: 'readable',
data() {
return [
{
@ -27,11 +26,10 @@ const Author = defineCollection({
}
});
const Themes = defineCollection({
const Themes = defineWritableCollection({
fields: {
name: field.text(),
},
source: 'writable',
data() {
return [
{