diff --git a/src/_modules/components/Collection.svelte b/src/_modules/components/Collection.svelte index c07bfe3..b653beb 100644 --- a/src/_modules/components/Collection.svelte +++ b/src/_modules/components/Collection.svelte @@ -1,9 +1,8 @@ {#if relation} - + {/if} diff --git a/src/_modules/dao/base_document_handling.ts b/src/_modules/dao/base_document_handling.ts index 2ec9729..36d3761 100644 --- a/src/_modules/dao/base_document_handling.ts +++ b/src/_modules/dao/base_document_handling.ts @@ -9,6 +9,7 @@ import { import { Type as T, type Static, type TAnySchema, type StaticDecode } from '@sinclair/typebox'; import { Value } from '@sinclair/typebox/value'; + import document_module_record from '$database/_export'; import { href } from '../utils'; @@ -94,8 +95,7 @@ export function parse_base_document( }, catch: () => { const errors = [...Value.Errors(schema, base_document.props)]; - console.log(base_document, errors); - return new Error(`Parse error: ${base_document.path}`); + return new Error(`Parse error: ${base_document.path} \n ${JSON.stringify(errors, null, 2)}`); } }); } diff --git a/src/_modules/dao/db.ts b/src/_modules/dao/db.ts index dda4862..a82e64f 100644 --- a/src/_modules/dao/db.ts +++ b/src/_modules/dao/db.ts @@ -1,7 +1,5 @@ import { pipe, Effect, ReadonlyArray as A, Option as O } from 'effect'; -// Effect must be the imported before other imports that use effect! - -import { Type as T, type Static } from '@sinclair/typebox'; +// Effect must be imported before other imports that use effect! import type { Collection, @@ -20,8 +18,8 @@ import { } from './base_document_handling'; import { Value } from '@sinclair/typebox/value'; -import _ from 'lodash'; import { base } from '$app/paths'; +import { sort_documents, type GetCollectionOptions } from './sorting'; // @@ -86,51 +84,11 @@ export function get_collection( get_collection_schema(collection_name) ]), Effect.flatMap(([documents, schema]) => - Effect.all(documents.map((doc) => parse_base_document(doc, schema))) + pipe( + Effect.all(documents.map((doc) => parse_base_document(doc, schema))), + Effect.map((documents) => sort_documents(documents, options.sort)) + ) ), - Effect.map((documents) => { - if (options.sort) { - const sort = parse_sort_prop(options.sort); - return _.orderBy( - documents, - sort.keys.map((k) => `props.${k}`), - sort.orders - ); - } else { - return documents; - } - }), Effect.runSync ); } - -export const sort_order_schema = T.Union([T.Literal('asc'), T.Literal('desc')]); -export type SortOrder = Static; - -export const base_sort_prop_schema = T.Tuple([T.String(), sort_order_schema]); -export type BaseSortProp = [keyof Collection, SortOrder]; -export type SortProp = BaseSortProp | BaseSortProp[]; - -export type ParsedSortProp = { keys: string[]; orders: SortOrder[] }; - -type GetCollectionOptions = { - sort?: SortProp; -}; - -function parse_sort_prop(sortProp: SortProp): ParsedSortProp { - if (Value.Check(base_sort_prop_schema, sortProp)) - return { - keys: [sortProp[0]], - orders: [sortProp[1]] - }; - else if (Value.Check(T.Array(base_sort_prop_schema), sortProp)) { - return { - keys: sortProp.map((base) => base[0]), - orders: sortProp.map((base) => base[1]) - }; - } else - return { - keys: [], - orders: [] - }; -} diff --git a/src/_modules/dao/sorting.ts b/src/_modules/dao/sorting.ts new file mode 100644 index 0000000..ef5c25c --- /dev/null +++ b/src/_modules/dao/sorting.ts @@ -0,0 +1,52 @@ +import type { Collection, CollectionName, Document } from '$modules/types'; +import { Type as T, type Static } from '@sinclair/typebox'; +import { Value } from '@sinclair/typebox/value'; +import _ from 'lodash'; + +const sort_order_schema = T.Union([T.Literal('asc'), T.Literal('desc')]); +type SortOrder = Static; + +const base_sort_prop_schema = T.Tuple([T.String(), sort_order_schema]); +type BaseSortProp = [keyof Collection, SortOrder]; + +export type SortProp = BaseSortProp | BaseSortProp[]; + +type ParsedSortProp = { keys: string[]; orders: SortOrder[] }; + +export type GetCollectionOptions = { + sort?: SortProp; +}; + +function parse_sort_prop(sortProp: SortProp): ParsedSortProp { + if (Value.Check(base_sort_prop_schema, sortProp)) + return { + keys: [sortProp[0]], + orders: [sortProp[1]] + }; + else if (Value.Check(T.Array(base_sort_prop_schema), sortProp)) { + return { + keys: sortProp.map((base) => base[0]), + orders: sortProp.map((base) => base[1]) + }; + } else + return { + keys: [], + orders: [] + }; +} + +export function sort_documents( + documents: Document[], + sort_prop: SortProp | undefined = undefined +): Document[] { + if (sort_prop) { + const sort = parse_sort_prop(sort_prop); + return _.orderBy( + documents, + sort.keys.map((k) => `props.${k}`), + sort.orders + ); + } else { + return documents; + } +} diff --git a/src/_modules/code_generation.ts b/src/_modules/database_index_generation.ts similarity index 93% rename from src/_modules/code_generation.ts rename to src/_modules/database_index_generation.ts index 52912aa..83a3c8a 100644 --- a/src/_modules/code_generation.ts +++ b/src/_modules/database_index_generation.ts @@ -7,17 +7,17 @@ import type { Plugin } from 'vite'; // const collections_directory = 'src/routes/(database)'; -const output_directory = 'src/_modules/database_index.ts'; +const output_file = 'src/_modules/database_index.ts'; export function save_database_index_plugin(): Plugin { return { name: 'save_database_index', buildStart: () => { - save_database_index(collections_directory, output_directory); + save_database_index(collections_directory, output_file); }, handleHotUpdate: ({ file }) => { - if (file.includes(output_directory)) return; - save_database_index(collections_directory, output_directory); + if (file.includes(output_file)) return; + save_database_index(collections_directory, output_file); } }; } diff --git a/src/_modules/fields.ts b/src/_modules/fields.ts index 314a20a..9692cd4 100644 --- a/src/_modules/fields.ts +++ b/src/_modules/fields.ts @@ -1,11 +1,12 @@ import { formatDate } from 'date-fns/format'; -import { Type as T } from '@sinclair/typebox'; +import { Type as T, type StaticDecode } from '@sinclair/typebox'; import { database_index, database_index_schema } from './database_index'; import type { CollectionName } from './database'; -import type { DocumentName, Document } from './types'; import { db } from '$modules'; +// + export const String = T.String; export const Number = T.Number; export const Object = T.Object; @@ -14,9 +15,6 @@ export const Boolean = T.Boolean; export const Union = T.Union; export const Literal = T.Literal; -// import tree from './database_index'; -// import type { CollectionEntry, CollectionName } from './database'; - /* Date */ type DateFormats = 'yyyy-MM' | 'yyyy-MM-dd'; @@ -48,48 +46,13 @@ function dateToString(dateFormat: string) { /* File */ +// TODO - Add regex for path export const File = () => T.String({}); /* Relation */ -// export function Relation(collection_name: C) { -// const collection_entries = database_index[collection_name]; -// return T.Union(collection_entries.map((name) => BaseRelation(collection_name, name))); -// } - -// export function BaseRelation( -// collection_name: C, -// entry_name: DocumentName -// ) { -// return T.Transform(T.Literal(entry_name)) -// .Decode((id) => ({ -// collection: collection_name, -// id, -// get: () => db.get_document(collection_name, id) -// })) -// .Encode((entry) => entry.id); -// } - -// export type BaseRelationTransform = { -// collection: C; -// id: DocumentName; -// get: () => Promise>; -// }; type Relation = (typeof database_index_schema)['properties'][C]; -// type O = CollectionEntries<'work_experiences'>; - -// // Map each element of tuple T to TLiteral -// type MapLiteral = { -// [P in keyof T]: TLiteral; -// }; - -// // Remove readonly from type -// type Writable = { -readonly [P in keyof T]: T[P] }; - -// type RelationLiterals = Writable>>; -// type O = RelationLiterals<"organizations"> - export function BaseRelation(collection_name: C): Relation { const collection_entries = database_index[collection_name]; // @ts-expect-error - Avoid type overlap @@ -98,16 +61,12 @@ export function BaseRelation(collection_name: C): Rela export function Relation(collection_name: C) { return T.Transform(BaseRelation(collection_name)) - .Decode((id) => ({ + .Decode((document) => ({ collection: collection_name, - id, - get: () => db.get_document(collection_name, id) + document, + get: () => db.get_document(collection_name, document) })) - .Encode((entry) => entry.id); + .Encode((field) => field.document); } -export type BaseRelationTransform = { - collection: C; - id: DocumentName; - get: () => Document; -}; +export type RelationField = StaticDecode>>; diff --git a/vite.config.ts b/vite.config.ts index bbbb0dd..d8a13a8 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,4 +1,4 @@ -import { save_database_index_plugin } from './src/_modules/code_generation'; +import { save_database_index_plugin } from './src/_modules/database_index_generation'; import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vitest/config';