From cd5d257cab618194bafb40de399169edc0174e19 Mon Sep 17 00:00:00 2001 From: Saenyakorn Siangsanoh Date: Tue, 20 May 2025 16:11:31 +0700 Subject: [PATCH 1/6] chore: fix typecheck error --- .vscode/settings.json | 1 + examples/erp/package.json | 8 +- packages/core/src/auth/index.ts | 2 +- packages/core/src/builder.handler.spec.ts | 40 ++-- packages/core/src/builder.handler.ts | 6 +- packages/core/src/collection.ts | 3 +- packages/core/src/config.ts | 4 +- packages/core/src/field.ts | 7 +- packages/core/src/index.ts | 5 +- .../src/integrations/react-query/index.tsx | 190 ------------------ .../core/src/integrations/react-router/api.ts | 142 ------------- .../src/integrations/react-router/example.tsx | 16 -- .../src/integrations/react-router/form.tsx | 29 --- .../src/integrations/react-router/hooks.tsx | 103 ---------- .../src/integrations/react-router/index.ts | 1 - .../core/src/integrations/react-router/ui.tsx | 7 - .../src/integrations/react-router/utils.ts | 17 -- .../core/src/integrations/rest/example.ts | 60 ------ packages/core/src/integrations/rest/index.ts | 25 --- packages/core/tsconfig.json | 5 +- packages/next/src/components/auto-field.tsx | 11 +- .../next/src/components/delete-button.tsx | 6 +- packages/next/src/components/form.tsx | 32 ++- packages/next/src/layouts/root-collection.tsx | 3 +- packages/next/src/layouts/root.tsx | 10 +- packages/next/src/pages/root-auth.tsx | 20 +- .../next/src/views/auth/sign-in.client.tsx | 26 +-- packages/next/src/views/auth/sign-in.tsx | 26 +-- packages/next/src/views/auth/sign-up.tsx | 4 +- .../src/views/collections/list.client.tsx | 6 +- packages/next/tsconfig.json | 5 +- pnpm-lock.yaml | 114 ++--------- 32 files changed, 116 insertions(+), 818 deletions(-) delete mode 100644 packages/core/src/integrations/react-query/index.tsx delete mode 100644 packages/core/src/integrations/react-router/api.ts delete mode 100644 packages/core/src/integrations/react-router/example.tsx delete mode 100644 packages/core/src/integrations/react-router/form.tsx delete mode 100644 packages/core/src/integrations/react-router/hooks.tsx delete mode 100644 packages/core/src/integrations/react-router/index.ts delete mode 100644 packages/core/src/integrations/react-router/ui.tsx delete mode 100644 packages/core/src/integrations/react-router/utils.ts delete mode 100644 packages/core/src/integrations/rest/example.ts delete mode 100644 packages/core/src/integrations/rest/index.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index fb314406..6d62e5bc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,6 +8,7 @@ "source.fixAll.eslint": "explicit", "source.organizeImports": "never" }, + "typescript.preferences.importModuleSpecifier": "relative", "npm.packageManager": "pnpm", "editor.defaultFormatter": "esbenp.prettier-vscode", "[typescript]": { diff --git a/examples/erp/package.json b/examples/erp/package.json index d47e0790..3c119f21 100644 --- a/examples/erp/package.json +++ b/examples/erp/package.json @@ -24,8 +24,8 @@ "next-themes": "^0.4.6", "pg": "^8.14.1", "postcss": "^8.5.3", - "react": "18.3.1", - "react-dom": "18.3.1", + "react": "19.1.0", + "react-dom": "19.1.0", "tailwindcss": "^4.0.14", "zod": "3.24.4" }, @@ -33,8 +33,8 @@ "@internals/project-config": "workspace:^", "@types/node": "^22.13.10", "@types/pg": "^8.11.11", - "@types/react": "18.3.18", - "@types/react-dom": "18.3.5", + "@types/react": "19.1.4", + "@types/react-dom": "19.1.5", "@vitejs/plugin-react": "^4.3.4", "drizzle-kit": "^0.30.6", "type-fest": "^4.38.0", diff --git a/packages/core/src/auth/index.ts b/packages/core/src/auth/index.ts index ac81277f..331755ce 100644 --- a/packages/core/src/auth/index.ts +++ b/packages/core/src/auth/index.ts @@ -129,7 +129,7 @@ export type Auth< > } -export function createAuth( +export function createAuth = MinimalContext>( config: AuthConfig, context: TContext ): Auth { diff --git a/packages/core/src/builder.handler.spec.ts b/packages/core/src/builder.handler.spec.ts index e5ec2dbe..420cb8b6 100644 --- a/packages/core/src/builder.handler.spec.ts +++ b/packages/core/src/builder.handler.spec.ts @@ -302,7 +302,9 @@ describe('ApiHandler', () => { data: { nameField: postData.name, authorField: { - nameField: authorData.name, + create: { + nameField: authorData.name, + }, }, }, context: { db: mockDb as any }, @@ -392,7 +394,9 @@ describe('ApiHandler', () => { data: { nameField: updatedPostData.name, authorField: { - nameField: updatedAuthorData.name, + create: { + nameField: updatedAuthorData.name, + }, }, }, }) @@ -484,15 +488,17 @@ describe('ApiHandler', () => { context: { db: mockDb as any }, data: { nameField: postData.name, - postsField: [ - mockPostData[0], - mockPostData[1], - mockPostData[2], - mockPostData[3], - mockPostData[4], - ].map((post) => ({ - nameField: post.name, - })), + postsField: { + create: [ + mockPostData[0], + mockPostData[1], + mockPostData[2], + mockPostData[3], + mockPostData[4], + ].map((post) => ({ + nameField: post.name, + })), + }, }, }) @@ -671,7 +677,9 @@ describe('ApiHandler', () => { context: { db: mockDb as any }, data: { nameField: postData.name, - authorField: authorData.id, + authorField: { + connect: authorData.id, + }, }, }) @@ -846,7 +854,9 @@ describe('ApiHandler', () => { context: { db: mockDb as any }, data: { nameField: authorData.name, - postsField: [mockPostData[0].id, mockPostData[1].id, mockPostData[2].id], + postsField: { + connect: [mockPostData[0].id, mockPostData[1].id, mockPostData[2].id], + }, }, }) @@ -951,7 +961,9 @@ describe('ApiHandler', () => { id: updatedAuthorData.id, data: { nameField: updatedAuthorDataField.nameField, - postsField: [1, 2, 3], + postsField: { + connect: [1, 2, 3], + }, }, }) // ====== end user part (field) ====== diff --git a/packages/core/src/builder.handler.ts b/packages/core/src/builder.handler.ts index 8c1a64c2..cb6c6bc4 100644 --- a/packages/core/src/builder.handler.ts +++ b/packages/core/src/builder.handler.ts @@ -106,7 +106,8 @@ export function createDefaultApiHandlers< }).create(tx, args.data) }) - return id + // TODO: It's not correct, fix this + return { __pk: id, id: id } } const update: ApiUpdateHandler = async (args) => { @@ -121,7 +122,8 @@ export function createDefaultApiHandlers< }).update(args.id, tx, args.data) }) - return args.id + // TODO: It's not correct, fix this + return { __pk: args.id, id: args.id } } // why not just delete? why _delete? diff --git a/packages/core/src/collection.ts b/packages/core/src/collection.ts index 7d4d77f3..60fe5dc8 100644 --- a/packages/core/src/collection.ts +++ b/packages/core/src/collection.ts @@ -12,6 +12,7 @@ import { FieldRelation, FieldRelationCollection, Fields, + FieldsClient, FieldsInitial, fieldsToZodObject, FieldsWithFieldName, @@ -255,7 +256,7 @@ export type InferField = * * type UserFields = InferFields // => { __pk: string; id: string; profile: string; age: number } */ -export type InferFields> = SimplifyConditionalExcept< +export type InferFields = SimplifyConditionalExcept< { [TKey in keyof TFields]: TFields[TKey] extends FieldClient ? Simplify> diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index 0ea83d96..9ddaeb65 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -46,8 +46,8 @@ export interface ServerConfig< any, any >[], - TApiRouter extends ApiRouter = ReturnType>['handlers'] & - ApiRouter, + TApiRouter extends ApiRouter = ReturnType>['handlers'] & + ApiRouter, > extends BaseConfig { context: TContext collections: TCollections diff --git a/packages/core/src/field.ts b/packages/core/src/field.ts index aca83ea6..1a634a5e 100644 --- a/packages/core/src/field.ts +++ b/packages/core/src/field.ts @@ -22,7 +22,7 @@ export type OptionCallback< TContext extends Record = {}, > = (args: TContext) => Promise> -export type FieldsWithFieldName>> = { +export type FieldsWithFieldName> = { [TKey in keyof TFields]: TFields[TKey] & { _: { fieldName: string } } } @@ -221,6 +221,11 @@ export type Fields< export type FieldClient = Omit +export type FieldsClientInitial = Record + +export type FieldsClient = + FieldsWithFieldName + export type FieldColumnOptionsFromTable< TColumn extends Column, TContext extends Record = Record, diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 85daa26e..7ad1f7bc 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -2,6 +2,7 @@ export { Builder } from './builder' export type { ApiReturnType, ClientApiArgs, + ClientCollection, Collection, CollectionAdmin, CollectionAdminApi, @@ -10,6 +11,8 @@ export type { CollectionConfig, InferApiRouterFromCollection, InferContextFromCollection, + InferField, + InferFields, InferFieldsFromCollection, InferFullSchemaFromCollection, InferSlugFromCollection, @@ -28,4 +31,4 @@ export type { ClientApiRouter, InferApiRouteResponses, } from './endpoint' -export { type Field, FieldBuilder } from './field' +export type { Field, FieldBase, FieldClient, Fields, FieldsClient } from './field' diff --git a/packages/core/src/integrations/react-query/index.tsx b/packages/core/src/integrations/react-query/index.tsx deleted file mode 100644 index bac76172..00000000 --- a/packages/core/src/integrations/react-query/index.tsx +++ /dev/null @@ -1,190 +0,0 @@ -// import { -// DefaultError, -// DefinedInitialDataOptions, -// QueryClient, -// QueryKey, -// queryOptions, -// useMutation, -// UseMutationOptions, -// UseMutationResult, -// useQuery, -// UseQueryOptions, -// UseQueryResult, -// } from '@tanstack/react-query' -// import { Simplify } from 'drizzle-orm' - -// import { createClientApiHandlers } from '~/core/client' -// import { -// ApiHandlerReturnType, -// ClientApiHandlerParameters, -// Collection, -// CollectionAdminApiHandlerConfig, -// } from '~/core/collection' - -// type ReactQueryClientOptions = { -// baseUrl: string -// collections: TCollections -// } - -// type ReactQueryClient = { -// [K in TCollections[number]['slug']]: ReactQueryClientApiHandler< -// Extract -// > -// } - -// function createReactQueryClientApiHandler( -// baseUrl: string, -// collection: TCollection -// ): ReactQueryClientApiHandler { -// const handlers = createClientApiHandlers(baseUrl, collection) - -// const readOne: ReactQueryClientApiHandler['readOne'] = { -// query: handlers.findOne, -// queryOptions: (args) => -// queryOptions({ -// queryFn: () => handlers.findOne(args), -// queryKey: ['drizzlify', collection.slug, 'readOne'], -// }) as any, -// useQuery: (args, options, queryClient) => -// useQuery( -// { -// ...options, -// queryFn: () => handlers.findOne(args), -// queryKey: ['drizzlify', collection.slug, 'readOne'] as any, -// }, -// queryClient -// ), -// } - -// const readMany: ReactQueryClientApiHandler['readMany'] = { -// query: handlers.findMany, -// queryOptions: (args) => -// queryOptions({ -// queryFn: () => handlers.findMany(args), -// queryKey: ['drizzlify', collection.slug, 'readMany'], -// }) as any, -// useQuery: (args, options, queryClient) => -// useQuery( -// { -// ...options, -// queryFn: () => handlers.findMany(args) as any, -// queryKey: ['drizzlify', collection.slug, 'readMany'] as any, -// }, -// queryClient -// ), -// } - -// const create: ReactQueryClientApiHandler['create'] = { -// mutation: handlers.create, -// useMutation: (args, options) => -// useMutation({ -// ...options, -// mutationFn: () => handlers.create(args) as any, -// mutationKey: ['drizzlify', collection.slug, 'create'] as any, -// }), -// } - -// const update: ReactQueryClientApiHandler['update'] = { -// mutation: handlers.update, -// useMutation: (args, options) => -// useMutation({ -// ...options, -// mutationFn: () => handlers.update(args) as any, -// mutationKey: ['drizzlify', collection.slug, 'update'] as any, -// }), -// } - -// const _delete: ReactQueryClientApiHandler['delete'] = { -// mutation: handlers.delete, -// useMutation: (args, options) => -// useMutation({ -// ...options, -// mutationFn: () => handlers.delete(args) as any, -// mutationKey: ['drizzlify', collection.slug, 'delete'] as any, -// }), -// } - -// const value: ReactQueryClientApiHandler = { -// readOne, -// readMany, -// create, -// update, -// delete: _delete, -// } - -// return value -// } - -// export function reactQueryClient( -// options: ReactQueryClientOptions -// ): ReactQueryClient { -// const { baseUrl, collections } = options - -// const client = Object.fromEntries( -// collections.map((collection) => { -// const slug = collection.slug -// return [slug, createReactQueryClientApiHandler(baseUrl, collection)] -// }) -// ) - -// return client as unknown as ReactQueryClient -// } - -// export type ClientApiHandler< -// TCollection extends Collection, -// TMethod extends keyof CollectionAdminApiHandlerConfig, -// > = ( -// args: Simplify> -// ) => ApiHandlerReturnType - -// type ReactQueryQueryForApi< -// TCollection extends Collection, -// TMethod extends Extract, -// > = { -// query: ClientApiHandler -// queryOptions: ( -// args: Simplify> -// ) => DefinedInitialDataOptions< -// ApiHandlerReturnType, -// DefaultError, -// Simplify>, -// QueryKey -// > -// useQuery: < -// TQueryFnData = ApiHandlerReturnType, -// TError = DefaultError, -// TData = Simplify>, -// TQueryKey extends QueryKey = QueryKey, -// >( -// args: Simplify>, -// options: Omit, 'queryKey' | 'queryFn'>, -// queryClient?: QueryClient -// ) => UseQueryResult -// } - -// type ReactQueryMutationForApi< -// TCollection extends Collection, -// TMethod extends Extract, -// > = { -// mutation: ClientApiHandler -// useMutation: < -// TData = ApiHandlerReturnType, -// TError = DefaultError, -// TVariables = Simplify>, -// TContext = unknown, -// >( -// args: Simplify>, -// options: Omit< -// UseMutationOptions, -// 'mutationKey' | 'mutationFn' -// > -// ) => UseMutationResult -// } - -// export type ReactQueryClientApiHandler = { -// readOne: ReactQueryQueryForApi -// readMany: ReactQueryQueryForApi -// create: ReactQueryMutationForApi -// update: ReactQueryMutationForApi -// delete: ReactQueryMutationForApi -// } diff --git a/packages/core/src/integrations/react-router/api.ts b/packages/core/src/integrations/react-router/api.ts deleted file mode 100644 index 3020ccfe..00000000 --- a/packages/core/src/integrations/react-router/api.ts +++ /dev/null @@ -1,142 +0,0 @@ -// import { ActionFunction, LoaderFunction } from 'react-router' - -// import { NodePgDatabase } from 'drizzle-orm/node-postgres' - -// import { Collection, InferFields } from '~/core/collection' -// import { ServerConfig } from '~/core/config' -// import { createServerApiHandler } from '~/core/server' - -// /* -// Path pattern: -// Read /:prefix/:slug/:id -// ReadMany /:prefix/:slug -// Create /:prefix/:slug/new -// Update /:prefix/:slug/:id/edit -// Delete /:prefix/:slug/:id/delete -// */ -// export function createReactRouterApiHandler< -// TFullSchema extends Record, -// TDatabase extends NodePgDatabase>, -// TContext extends Record, -// TCollections extends Collection[], -// >(config: ServerConfig) { -// const { db, context, collections } = config - -// const collectionApiHandlersMap = new Map( -// collections.map((collection) => { -// return [collection.slug, createServerApiHandler({ collection })] -// }) -// ) - -// const loader: LoaderFunction = async (args) => { -// const { params, request } = args -// const slug = params.slug - -// const url = new URL(request.url) -// const pathname = url.pathname - -// if (!slug) throw new Error('Collection slug is required') - -// const collectionHandler = collectionApiHandlersMap.get(slug) -// if (!collectionHandler) throw new Error(`Collection ${slug} not found`) - -// const collection = collectionHandler.collection - -// // Handle ReadMany route -// if (pathname.endsWith(`/${slug}`)) { -// const limit = parseInt(url.searchParams.get('limit') ?? '10') -// const offset = parseInt(url.searchParams.get('offset') ?? '0') -// const orderBy = url.searchParams.get('orderBy') ?? undefined -// const orderType = (url.searchParams.get('orderType') ?? 'desc') as 'asc' | 'desc' - -// return collectionHandler.findMany({ -// db, -// context, -// fields: collection.fields, -// slug, -// limit, -// offset, -// orderBy, -// orderType, -// }) -// } - -// const id = params.id -// if (!id) throw new Error('ID is required') - -// // Handle ReadOne route -// if (pathname.endsWith(`/${slug}/${id}`)) { -// return collectionHandler.findOne({ -// db, -// context, -// fields: collection.fields, -// slug, -// id, -// }) -// } - -// throw new Error('Invalid route') -// } - -// const action: ActionFunction = async (args) => { -// const { params, request } = args -// const slug = params.slug - -// const url = new URL(request.url) -// const pathname = url.pathname - -// if (!slug) throw new Error('Collection slug is required') - -// const collectionHandler = collectionApiHandlersMap.get(slug) -// if (!collectionHandler) throw new Error(`Collection ${slug} not found`) - -// const collection = collectionHandler.collection -// const method = request.method - -// // Handle Create route -// if (method === 'POST' && pathname.endsWith(`/${slug}`)) { -// const data = await request.json() -// return collectionHandler.create({ -// db, -// context, -// fields: collection.fields, -// slug, -// data: data as InferFields, -// }) -// } - -// const id = params.id -// if (!id) throw new Error('ID is required') - -// // Handle Update route -// if (method === 'PUT' && pathname.endsWith(`/${slug}/${id}`)) { -// const data = await request.json() -// return collectionHandler.update({ -// db, -// context, -// fields: collection.fields, -// slug, -// id, -// data: data as InferFields, -// }) -// } - -// // Handle Delete route -// if (method === 'DELETE' && pathname.endsWith(`/${slug}/${id}`)) { -// return collectionHandler.delete({ -// db, -// context, -// fields: collection.fields, -// slug, -// id, -// }) -// } - -// throw new Error('Invalid route') -// } - -// return { -// loader, -// action, -// } -// } diff --git a/packages/core/src/integrations/react-router/example.tsx b/packages/core/src/integrations/react-router/example.tsx deleted file mode 100644 index ec8dcfbc..00000000 --- a/packages/core/src/integrations/react-router/example.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { authorCollection } from '~/core/spec' - -import { useForm } from './hooks' - -export default function Example() { - const form = useForm({ collection: authorCollection }) - - return ( -
-
- - -
-
- ) -} diff --git a/packages/core/src/integrations/react-router/form.tsx b/packages/core/src/integrations/react-router/form.tsx deleted file mode 100644 index 3e697661..00000000 --- a/packages/core/src/integrations/react-router/form.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { ComponentType, createContext } from 'react' -import { Controller, FormProvider } from 'react-hook-form' -import { ControllerProps, FieldPath, FieldValues } from 'react-hook-form' - -export const Form: typeof FormProvider = FormProvider - -type FormFieldContextValue< - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath, -> = { - name: TName -} - -const FormFieldContext = createContext({} as FormFieldContextValue) - -export const FormField = < - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath, ->( - props: ControllerProps & { component: ComponentType<{ name: TName }> } -) => { - const Component = props.component - - return ( - - } /> - - ) -} diff --git a/packages/core/src/integrations/react-router/hooks.tsx b/packages/core/src/integrations/react-router/hooks.tsx deleted file mode 100644 index 4fb96adb..00000000 --- a/packages/core/src/integrations/react-router/hooks.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import { ReactNode, useCallback, useMemo, useRef } from 'react' -import { - type ControllerProps, - type FieldErrors, - type FieldPath, - type FieldValues, - useForm as useReactHookForm, - type UseFormHandleSubmit as UseReactHookFormHandleSubmit, - type UseFormProps as UseReactHookFormProps, - type UseFormReturn as UseReactHookFormReturn, -} from 'react-hook-form' - -import { Collection, InferFields } from '~/core/collection' - -import { Form, FormField as _FormField } from './form' -import { createRequireContext } from './utils' - -type InferFieldFromCollection = - TCollection extends Collection ? InferFields : never - -export type FormSubmitHandler = (data: TSchema) => void - -export type FormSubmitErrorHandler = ( - errors: FieldErrors -) => void - -interface UseFormProps< - TCollection extends Collection, - TContext = any, - TFields extends Record = InferFieldFromCollection, -> extends UseReactHookFormProps { - collection: TCollection - onSubmit?: FormSubmitHandler - onError?: FormSubmitErrorHandler -} - -export type UseFormReturn< - TCollection extends Collection, - TContext = any, - TFields extends Record = InferFieldFromCollection, -> = Omit, 'handleSubmit'> & { - /** - * Encouraged to use `form.onSubmit` instead - * @deprecated - */ - handleSubmit: UseReactHookFormHandleSubmit - Provider: (props: { children: ReactNode }) => JSX.Element - Field: = FieldPath>( - props: Omit, 'control'> - ) => JSX.Element - onSubmit: (event?: React.BaseSyntheticEvent) => Promise | void -} - -function useEffectEvent any>(handler: T): T { - const handlerRef = useRef(handler) - handlerRef.current = handler - return useCallback(((...args) => handlerRef.current(...args)) as T, []) -} - -export function useForm< - TCollection extends Collection, - TContext = any, - TFields extends Record = InferFieldFromCollection, ->( - props: UseFormProps -): UseFormReturn { - const { collection, ...formProps } = props - - const form = useReactHookForm(formProps) - - const Provider = useEffectEvent((props: { children: ReactNode }) => { - return ( - -
{props.children as any}
-
- ) - }) - - const onSubmit = useMemo(() => { - return form.handleSubmit( - ((data: any, event: any) => props?.onSubmit?.(data)) as any, - (errors, event) => props?.onError?.(errors) - ) - }, [form, props?.onSubmit, props?.onError]) - - return { - ...form, - Provider, - Field: _FormField as any, - onSubmit, - } -} - -export const [CollectionContextProvider, useCollectionContext, CollectionContext] = - createRequireContext('CollectionContext') - -export function useReadOne(collection: TCollection) {} - -export function useReadMany(collection: TCollection) {} - -export function useCreate(collection: TCollection) {} - -export function useUpdate(collection: TCollection) {} diff --git a/packages/core/src/integrations/react-router/index.ts b/packages/core/src/integrations/react-router/index.ts deleted file mode 100644 index 336ce12b..00000000 --- a/packages/core/src/integrations/react-router/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {} diff --git a/packages/core/src/integrations/react-router/ui.tsx b/packages/core/src/integrations/react-router/ui.tsx deleted file mode 100644 index c02536cf..00000000 --- a/packages/core/src/integrations/react-router/ui.tsx +++ /dev/null @@ -1,7 +0,0 @@ -interface InputProps { - name: string -} - -export function Input(props: InputProps) { - return -} diff --git a/packages/core/src/integrations/react-router/utils.ts b/packages/core/src/integrations/react-router/utils.ts deleted file mode 100644 index e6f953e5..00000000 --- a/packages/core/src/integrations/react-router/utils.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createContext, useContext as useReactContext } from 'react' - -export function createRequireContext(name: string) { - const Context = createContext(null as TContextValue | null) - const useContext = () => { - const context = useReactContext(Context) - if (!context) { - throw new Error(`use${name}Context must be inside of ${name}ContextProvider`) - } - return context - } - return [ - Context.Provider as React.Provider, - useContext as () => TContextValue, - Context, - ] as const -} diff --git a/packages/core/src/integrations/rest/example.ts b/packages/core/src/integrations/rest/example.ts deleted file mode 100644 index e43121a6..00000000 --- a/packages/core/src/integrations/rest/example.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { authorCollection } from '~/core/spec' - -import { createRestClient } from './index' - -// Example usage of the REST client -async function example() { - // Create the REST client - const client = createRestClient({ - baseUrl: 'https://api.example.com', - collections: [authorCollection], - }) - - // Example: Read a single author - const author = await client.authors.findOne({ id: '123' }) - console.log('Author:', author) - - // Example: Read multiple authors with pagination and sorting - const authors = await client.authors.findMany({ - limit: 10, - offset: 0, - orderBy: 'name', - orderType: 'asc', - }) - - console.log('Authors:', authors) - - // Example: Create a new author - const newAuthor = await client.authors.create({ - data: { - id: 1, - name: 'John Doe', - email: 'john@example.com', - createdAt: new Date(), - updatedAt: new Date(), - postIds: [], - }, - }) - console.log('New author:', newAuthor) - - // Example: Update an author - const updatedAuthor = await client.authors.update({ - id: '123', - data: { - id: 1, - name: 'John Doe', - email: 'john@example.com', - createdAt: new Date(), - updatedAt: new Date(), - postIds: [], - }, - }) - console.log('Updated author:', updatedAuthor) - - // Example: Delete an author - const deletedAuthor = await client.authors.delete({ id: '123' }) - console.log('Deleted author:', deletedAuthor) -} - -// Run the example -example().catch(console.error) diff --git a/packages/core/src/integrations/rest/index.ts b/packages/core/src/integrations/rest/index.ts deleted file mode 100644 index 87c80853..00000000 --- a/packages/core/src/integrations/rest/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ClientApiHandlers } from '~/core/client' -import { createClientApiHandlers } from '~/core/client' -import { Collection } from '~/core/collection' - -type RestClientOptions = { - baseUrl: string - collections: TCollections -} - -type RestClient = { - [K in TCollections[number]['slug']]: ClientApiHandlers> -} - -export function createRestClient( - options: RestClientOptions -): RestClient { - const { baseUrl, collections } = options - const client = Object.fromEntries( - collections.map((collection) => { - const value = createClientApiHandlers(baseUrl, collection) - return [collection.slug, value] - }) - ) - return client as unknown as RestClient -} diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index 07fc1be4..724fb08b 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -5,9 +5,6 @@ "jsx": "react-jsx", "lib": ["dom"], "module": "ESNext", - "moduleResolution": "bundler", - "paths": { - "~/*": ["./src/*"] - } + "moduleResolution": "bundler" } } diff --git a/packages/next/src/components/auto-field.tsx b/packages/next/src/components/auto-field.tsx index 6fa0e181..114b92a2 100644 --- a/packages/next/src/components/auto-field.tsx +++ b/packages/next/src/components/auto-field.tsx @@ -1,5 +1,4 @@ -import { ServerConfig } from '~/core/config' -import { Field } from '~/core/field' +import { Field, ServerConfig } from '@kivotos/core' import { Checkbox } from '../intentui/ui/checkbox' import { Select, SelectList, SelectOption, SelectTrigger } from '../intentui/ui/select' @@ -37,7 +36,7 @@ export async function AutoField( case 'switch': return case 'selectText': { - const options = await field.options(props.serverConfig) + const options = await field.options({ db: props.serverConfig.db }) return ( @@ -67,7 +66,7 @@ export async function AutoField( ) } case 'comboboxText': { - const options = await field.options(props.serverConfig) + const options = await field.options({ db: props.serverConfig.db }) return ( {options.map((option) => ( diff --git a/packages/next/src/components/delete-button.tsx b/packages/next/src/components/delete-button.tsx index 4a969cf8..d8512808 100644 --- a/packages/next/src/components/delete-button.tsx +++ b/packages/next/src/components/delete-button.tsx @@ -1,7 +1,5 @@ -import { ServerConfig } from '~/core/config' +import { ServerConfig } from '@kivotos/core' -export function DeleteButton(props: { - serverConfig: TServerConfig -}) { +export function DeleteButton(props: { serverConfig: ServerConfig }) { return } diff --git a/packages/next/src/components/form.tsx b/packages/next/src/components/form.tsx index 06182b48..176c85d0 100644 --- a/packages/next/src/components/form.tsx +++ b/packages/next/src/components/form.tsx @@ -2,29 +2,25 @@ import type { ServerConfig } from '@kivotos/core' -import { useServerFunction } from '~/providers/root' +import { useServerFunction } from '../providers/root' -import { GetServerMethod } from '../server-function' - -export function Form< - TServerConfig extends ServerConfig, - TMethod extends GetServerMethod = GetServerMethod, ->(props: Omit & { id?: string; children: React.ReactNode }) { +// TODO: Fix this +export function Form(props: any) { const serverFunction = useServerFunction() return (
{ - const data = Object.fromEntries(formData) - await serverFunction({ - slug: props.slug, - method: props.method, - payload: { - ...(props.id ? { id: props.id } : {}), - data: data as any, - }, - } as any) - }} + // action={async (formData) => { + // const data = Object.fromEntries(formData) + // await serverFunction({ + // slug: props.slug, + // method: props.method, + // payload: { + // ...(props.id ? { id: props.id } : {}), + // data: data as any, + // }, + // } as any) + // }} > {props.children}
diff --git a/packages/next/src/layouts/root-collection.tsx b/packages/next/src/layouts/root-collection.tsx index 4c528ec1..a0645cc5 100644 --- a/packages/next/src/layouts/root-collection.tsx +++ b/packages/next/src/layouts/root-collection.tsx @@ -1,7 +1,5 @@ import { type Collection, type ServerConfig } from '@kivotos/core' -import type { ServerFunction } from '~/server-function' - import { RootLayout } from './root' import { @@ -16,6 +14,7 @@ import { SidebarSection, SidebarTrigger, } from '../intentui/ui/sidebar' +import { ServerFunction } from '../server-function' import { formatSlug } from '../utils/format-slug' interface RootLayoutProps> { diff --git a/packages/next/src/layouts/root.tsx b/packages/next/src/layouts/root.tsx index 08e33f56..7445d3db 100644 --- a/packages/next/src/layouts/root.tsx +++ b/packages/next/src/layouts/root.tsx @@ -1,13 +1,15 @@ +import { ReactNode } from 'react' + import { getClientConfig, ServerConfig } from '@kivotos/core' -import { UiProviders } from '~/intentui/providers' -import { RootProvider } from '~/providers/root' -import { ServerFunction } from '~/server-function' +import { UiProviders } from '../intentui/providers' +import { RootProvider } from '../providers/root' +import { ServerFunction } from '../server-function' interface RootLayoutProps> { serverConfig: TServerConfig serverFunction: ServerFunction - children: React.ReactNode + children: ReactNode } export function RootLayout>( diff --git a/packages/next/src/pages/root-auth.tsx b/packages/next/src/pages/root-auth.tsx index 7c03baa3..73e2d2e4 100644 --- a/packages/next/src/pages/root-auth.tsx +++ b/packages/next/src/pages/root-auth.tsx @@ -1,6 +1,6 @@ import { ServerConfig } from '@kivotos/core' -import { SignInView } from '~/views/auth/sign-in' +import { SignInView } from '../views/auth/sign-in' interface RootProps { serverConfig: ServerConfig @@ -30,17 +30,17 @@ export async function RootAuthPage(props: RootProps) { return } - if (segments[1] === 'sign-up' && segments.length === 2) { - return - } + // if (segments[1] === 'sign-up' && segments.length === 2) { + // return + // } - if (segments[1] === 'forgot-password' && segments.length === 2) { - return - } + // if (segments[1] === 'forgot-password' && segments.length === 2) { + // return + // } - if (segments[1] === 'reset-password' && segments.length === 2) { - return - } + // if (segments[1] === 'reset-password' && segments.length === 2) { + // return + // } throw new Error(`Invalid path: ${segments.join('/')}`) // TODO: 404 } diff --git a/packages/next/src/views/auth/sign-in.client.tsx b/packages/next/src/views/auth/sign-in.client.tsx index e8590a8e..24f9f489 100644 --- a/packages/next/src/views/auth/sign-in.client.tsx +++ b/packages/next/src/views/auth/sign-in.client.tsx @@ -1,36 +1,14 @@ 'use client' -import { redirect } from 'next/navigation' - -import { SubmitButton } from '~/components/submit-button' -import { useServerFunction } from '~/providers/root' +import { SubmitButton } from '../../components/submit-button' interface SignInViewProps {} export function SignInClientForm(props: SignInViewProps) { - const serverFunction = useServerFunction() - - async function action(formData: FormData) { - 'use server' - const email = formData.get('email') as string - const password = formData.get('password') as string - const confirmPassword = formData.get('confirmPassword') as string - - if (password !== confirmPassword) { - throw new Error('Passwords do not match') - } - - await serverFunction('auth.signInEmail', { - body: { email, password }, - }) - - redirect('/collections') - } - return (

Sign In

-
+