mirror of
https://github.com/Lifeforge-app/lifeforge.git
synced 2026-06-28 14:55:45 +00:00
refactor(api): restructure types and exports with barrel files
- Split forge_proxy.types.ts into contract.types.ts and io.types.ts - Add barrel exports for core/, providers/, utils/, typescript/ - Restrict untyped and core helpers to root proxy only - Add key, schema, endpoint to intermediate proxy types - Disable rollupTypes for barrel compatibility
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -68,7 +68,7 @@ function createForgeProxyInternal<T>(
|
||||
return () => `[ForgeProxy: ${pathArray.join('/')}]`
|
||||
}
|
||||
|
||||
if (prop === 'untyped') {
|
||||
if (pathArray.length === 0 && prop === 'untyped') {
|
||||
return <TOutput = any, TBody = any, TQuery = any>(url: string) =>
|
||||
new ForgeEndpoint<UntypedEndpointType<TOutput, TBody, TQuery>>(
|
||||
getResolvedHost(),
|
||||
@@ -82,7 +82,7 @@ function createForgeProxyInternal<T>(
|
||||
return createGetMediaHelper(getResolvedHost())
|
||||
}
|
||||
|
||||
if (prop in CORE_HELPERS) {
|
||||
if (pathArray.length === 0 && prop in CORE_HELPERS) {
|
||||
return createCoreHelper(
|
||||
getResolvedHost(),
|
||||
prop as keyof typeof CORE_HELPERS
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
import type { UseMutationOptions, UseQueryOptions } from '@tanstack/react-query'
|
||||
import { z } from 'zod'
|
||||
|
||||
import type {
|
||||
InferRawInput,
|
||||
InferRawOutput
|
||||
} from '../typescript/forge_proxy.types'
|
||||
import type { InferRawInput, InferRawOutput } from '../typescript'
|
||||
import {
|
||||
createEncryptionSession,
|
||||
decryptResponse,
|
||||
|
||||
3
packages/api/src/core/index.ts
Normal file
3
packages/api/src/core/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './createForgeProxy'
|
||||
export * from './forgeEndpoint'
|
||||
export * from './registry'
|
||||
@@ -1,23 +1,7 @@
|
||||
export * from './core/createForgeProxy'
|
||||
export * from './core'
|
||||
|
||||
export * from './core/forgeEndpoint'
|
||||
export * from './providers'
|
||||
|
||||
export * from './core/registry'
|
||||
export * from './utils'
|
||||
|
||||
export * from './typescript/forge_proxy.types'
|
||||
|
||||
export * from './providers/APIEndpointProvider'
|
||||
|
||||
export * from './providers/APIOnlineStatusProvider'
|
||||
|
||||
export * from './providers/EncryptionProvider'
|
||||
|
||||
export * from './providers/SocketProvider'
|
||||
|
||||
export * from './providers/AuthProvider'
|
||||
|
||||
export * from './utils/encryption'
|
||||
|
||||
export * from './utils/fetchAPI'
|
||||
|
||||
export * from './utils/usePromiseLoading'
|
||||
export * from './typescript'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
type RefObject,
|
||||
createContext,
|
||||
@@ -11,7 +12,7 @@ import {
|
||||
|
||||
import { contract } from '../../contract'
|
||||
import { createForgeProxy } from '../core/createForgeProxy'
|
||||
import type { InferOutput, ProxyTree } from '../typescript/forge_proxy.types'
|
||||
import type { InferOutput, ProxyTree } from '../typescript'
|
||||
|
||||
const _forgeAPI = createForgeProxy(contract)
|
||||
|
||||
|
||||
5
packages/api/src/providers/index.ts
Normal file
5
packages/api/src/providers/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export * from './APIEndpointProvider'
|
||||
export * from './APIOnlineStatusProvider'
|
||||
export * from './AuthProvider'
|
||||
export * from './EncryptionProvider'
|
||||
export * from './SocketProvider'
|
||||
86
packages/api/src/typescript/contract.types.ts
Normal file
86
packages/api/src/typescript/contract.types.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import type { FromSchema } from "json-schema-to-ts";
|
||||
import type { ZodTypeAny } from "zod";
|
||||
|
||||
type KnownKeys<T> = {
|
||||
[K in keyof T]: string extends K
|
||||
? never
|
||||
: number extends K
|
||||
? never
|
||||
: symbol extends K
|
||||
? never
|
||||
: K
|
||||
}[keyof T]
|
||||
|
||||
export type OmitIndexSignature<T> = T extends object
|
||||
? T extends Array<any>
|
||||
? T
|
||||
: [KnownKeys<T>] extends [never]
|
||||
? { [K in keyof T]: OmitIndexSignature<T[K]> }
|
||||
: {
|
||||
[K in keyof T as string extends K
|
||||
? never
|
||||
: number extends K
|
||||
? never
|
||||
: symbol extends K
|
||||
? never
|
||||
: K]: OmitIndexSignature<T[K]>
|
||||
}
|
||||
: T
|
||||
|
||||
export type InferFromJSONSchema<T> = 0 extends 1 & T
|
||||
? any
|
||||
: T extends undefined
|
||||
? undefined
|
||||
: T extends boolean
|
||||
? undefined
|
||||
: T extends object
|
||||
? OmitIndexSignature<FromSchema<T>>
|
||||
: undefined
|
||||
|
||||
export type InferContractInput<T> = 0 extends 1 & T
|
||||
? any
|
||||
: T extends {
|
||||
readonly input?: {
|
||||
readonly query?: infer Q
|
||||
readonly body?: infer B
|
||||
}
|
||||
}
|
||||
? {
|
||||
body: B extends ZodTypeAny
|
||||
? B
|
||||
: B extends object
|
||||
? InferFromJSONSchema<B>
|
||||
: undefined
|
||||
query: Q extends ZodTypeAny
|
||||
? Q
|
||||
: Q extends object
|
||||
? InferFromJSONSchema<Q>
|
||||
: undefined
|
||||
}
|
||||
: {
|
||||
body: undefined
|
||||
query: undefined
|
||||
}
|
||||
|
||||
export type InferContractOutput<T> = 0 extends 1 & T
|
||||
? any
|
||||
: T extends {
|
||||
readonly output: infer O
|
||||
}
|
||||
? O extends { readonly OK: infer OKSchema }
|
||||
? InferFromJSONSchema<OKSchema>
|
||||
: O extends { readonly CREATED: infer CreatedSchema }
|
||||
? InferFromJSONSchema<CreatedSchema>
|
||||
: any
|
||||
: never
|
||||
|
||||
export type InferContractMedia<T> = 0 extends 1 & T
|
||||
? any
|
||||
: T extends {
|
||||
readonly media?: infer M
|
||||
}
|
||||
? M extends undefined
|
||||
? null
|
||||
: M
|
||||
: null
|
||||
@@ -1,226 +1,64 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import type { FromSchema } from 'json-schema-to-ts'
|
||||
import type z from 'zod'
|
||||
import type { ZodIntersection, ZodObject, ZodRawShape, ZodTypeAny } from 'zod'
|
||||
|
||||
import type { ForgeEndpoint } from '../core/forgeEndpoint'
|
||||
import type { CoreHelperReturnTypes } from '../core/helpers/config'
|
||||
|
||||
type ZodObjectOrIntersection =
|
||||
| ZodObject<ZodRawShape>
|
||||
| ZodIntersection<ZodTypeAny, ZodTypeAny>
|
||||
|
||||
type KnownKeys<T> = {
|
||||
[K in keyof T]: string extends K
|
||||
? never
|
||||
: number extends K
|
||||
? never
|
||||
: symbol extends K
|
||||
? never
|
||||
: K
|
||||
}[keyof T]
|
||||
|
||||
export type OmitIndexSignature<T> = T extends object
|
||||
? T extends Array<any>
|
||||
? T
|
||||
: [KnownKeys<T>] extends [never]
|
||||
? { [K in keyof T]: OmitIndexSignature<T[K]> }
|
||||
: {
|
||||
[K in keyof T as string extends K
|
||||
? never
|
||||
: number extends K
|
||||
? never
|
||||
: symbol extends K
|
||||
? never
|
||||
: K]: OmitIndexSignature<T[K]>
|
||||
}
|
||||
: T
|
||||
|
||||
export type InferFromJSONSchema<T> = 0 extends 1 & T
|
||||
? any
|
||||
: T extends undefined
|
||||
? undefined
|
||||
: T extends boolean
|
||||
? undefined
|
||||
: T extends object
|
||||
? OmitIndexSignature<FromSchema<T>>
|
||||
: undefined
|
||||
|
||||
export type InferContractInput<T> = 0 extends 1 & T
|
||||
? any
|
||||
: T extends {
|
||||
readonly input?: {
|
||||
readonly query?: infer Q
|
||||
readonly body?: infer B
|
||||
}
|
||||
}
|
||||
? {
|
||||
body: B extends ZodTypeAny
|
||||
? B
|
||||
: B extends object
|
||||
? InferFromJSONSchema<B>
|
||||
: undefined
|
||||
query: Q extends ZodTypeAny
|
||||
? Q
|
||||
: Q extends object
|
||||
? InferFromJSONSchema<Q>
|
||||
: undefined
|
||||
}
|
||||
: {
|
||||
body: undefined
|
||||
query: undefined
|
||||
}
|
||||
|
||||
export type InferContractOutput<T> = 0 extends 1 & T
|
||||
? any
|
||||
: T extends {
|
||||
readonly output: infer O
|
||||
}
|
||||
? O extends { readonly OK: infer OKSchema }
|
||||
? InferFromJSONSchema<OKSchema>
|
||||
: O extends { readonly CREATED: infer CreatedSchema }
|
||||
? InferFromJSONSchema<CreatedSchema>
|
||||
: any
|
||||
: never
|
||||
|
||||
export type InferContractMedia<T> = 0 extends 1 & T
|
||||
? any
|
||||
: T extends {
|
||||
readonly media?: infer M
|
||||
}
|
||||
? M extends undefined
|
||||
? null
|
||||
: M
|
||||
: null
|
||||
|
||||
/**
|
||||
* Infers the input TypeScript type from a Forge endpoint config object.
|
||||
* Uses embedded Zod schema definitions to produce a plain object type.
|
||||
*/
|
||||
export type InferRawInput<T> = T extends {
|
||||
__isForgeContract: true
|
||||
__input: infer I
|
||||
__media: infer M
|
||||
}
|
||||
? I extends {
|
||||
body?: infer B
|
||||
query?: infer Q
|
||||
}
|
||||
? {
|
||||
body: M extends null
|
||||
? B extends ZodObjectOrIntersection
|
||||
? z.input<B>
|
||||
: B
|
||||
: (B extends ZodObjectOrIntersection
|
||||
? z.input<B>
|
||||
: B extends undefined
|
||||
? {}
|
||||
: B) & {
|
||||
[K in keyof M]: M[K] extends { multiple: true }
|
||||
? M[K] extends { optional: true }
|
||||
? File[] | undefined
|
||||
: File[]
|
||||
: M[K] extends { optional: true }
|
||||
? File | string | undefined
|
||||
: File | string
|
||||
}
|
||||
query: Q extends ZodObjectOrIntersection ? z.input<Q> : Q
|
||||
}
|
||||
: never
|
||||
: never
|
||||
|
||||
/**
|
||||
* Infers the output (response) TypeScript type from a Forge endpoint config object.
|
||||
*/
|
||||
export type InferRawOutput<T> = T extends {
|
||||
__isForgeContract: true
|
||||
__output: infer O
|
||||
}
|
||||
? O
|
||||
: never
|
||||
|
||||
/**
|
||||
* Extracts the input schema type from a `ForgeEndpoint` instance.
|
||||
*/
|
||||
export type InferInput<T extends ForgeEndpoint<any>> = T['__type'] extends {
|
||||
__isForgeContract: true
|
||||
__input: infer I
|
||||
__media: infer M
|
||||
}
|
||||
? I extends {
|
||||
body?: infer B
|
||||
query?: infer Q
|
||||
}
|
||||
? {
|
||||
body: M extends null
|
||||
? B extends ZodObjectOrIntersection
|
||||
? z.input<B>
|
||||
: B
|
||||
: (B extends ZodObjectOrIntersection
|
||||
? z.input<B>
|
||||
: B extends undefined
|
||||
? {}
|
||||
: B) & {
|
||||
[K in keyof M]: {
|
||||
__type: 'media'
|
||||
config: M[K]
|
||||
}
|
||||
}
|
||||
query: Q extends ZodObjectOrIntersection ? z.input<Q> : Q
|
||||
}
|
||||
: never
|
||||
: never
|
||||
|
||||
/**
|
||||
* Extracts the output (response) type from a `ForgeEndpoint` instance.
|
||||
*/
|
||||
export type InferOutput<T extends ForgeEndpoint<any>> = T['__type'] extends {
|
||||
__isForgeContract: true
|
||||
__output: infer O
|
||||
}
|
||||
? O
|
||||
: never
|
||||
import type {
|
||||
InferContractInput,
|
||||
InferContractMedia,
|
||||
InferContractOutput
|
||||
} from './contract.types'
|
||||
|
||||
/**
|
||||
* Constructs a deeply-nested proxy tree from a server route schema.
|
||||
* Each endpoint becomes a `ForgeEndpoint`, nested groups become more `ProxyTree`.
|
||||
*/
|
||||
export type ProxyTree<T> = 0 extends 1 & T
|
||||
? {
|
||||
[K: string]: any
|
||||
} & {
|
||||
untyped: <TOutput = any, TBody = any, TQuery = any>(
|
||||
url: string
|
||||
) => ForgeEndpoint<UntypedEndpointType<TOutput, TBody, TQuery>>
|
||||
getMedia: (params: {
|
||||
collectionId: string
|
||||
recordId: string
|
||||
fieldId: string
|
||||
thumb?: string
|
||||
token?: string
|
||||
}) => string
|
||||
} & CoreHelperReturnTypes
|
||||
: {
|
||||
[K in keyof T]: T[K] extends { readonly method: string }
|
||||
? ForgeEndpoint<{
|
||||
__isForgeContract: true
|
||||
__input: InferContractInput<T[K]>
|
||||
__output: InferContractOutput<T[K]>
|
||||
__media: InferContractMedia<T[K]>
|
||||
}>
|
||||
: ProxyTree<T[K]>
|
||||
} & {
|
||||
untyped: <TOutput = any, TBody = any, TQuery = any>(
|
||||
url: string
|
||||
) => ForgeEndpoint<UntypedEndpointType<TOutput, TBody, TQuery>>
|
||||
getMedia: (params: {
|
||||
collectionId: string
|
||||
recordId: string
|
||||
fieldId: string
|
||||
thumb?: string
|
||||
token?: string
|
||||
}) => string
|
||||
} & CoreHelperReturnTypes
|
||||
|
||||
type ProxyTreeLeaf = {
|
||||
getMedia: (params: {
|
||||
collectionId: string
|
||||
recordId: string
|
||||
fieldId: string
|
||||
thumb?: string
|
||||
token?: string
|
||||
}) => string
|
||||
key: (string | Record<string, any> | null)[]
|
||||
schema: { query?: z.ZodTypeAny; body?: z.ZodTypeAny }
|
||||
endpoint: string
|
||||
}
|
||||
|
||||
type ProxyTreeRootLeaf = ProxyTreeLeaf & {
|
||||
untyped: <TOutput = any, TBody = any, TQuery = any>(
|
||||
url: string
|
||||
) => ForgeEndpoint<UntypedEndpointType<TOutput, TBody, TQuery>>
|
||||
}
|
||||
|
||||
type ProxyTreeInternal<T> = {
|
||||
[K in keyof T]: T[K] extends { readonly method: string }
|
||||
? ForgeEndpoint<{
|
||||
__isForgeContract: true
|
||||
__input: InferContractInput<T[K]>
|
||||
__output: InferContractOutput<T[K]>
|
||||
__media: InferContractMedia<T[K]>
|
||||
}>
|
||||
: ProxyTreeInternal<T[K]>
|
||||
} & ProxyTreeLeaf
|
||||
|
||||
/** ProxyTree falls back to `AnyProxyTree` without strict typing when the contract is untyped (`any`). */
|
||||
|
||||
type IsAny<T> = 0 extends 1 & T ? true : false
|
||||
|
||||
type AnyProxyTree = {
|
||||
[K: string]: any
|
||||
} & ProxyTreeRootLeaf &
|
||||
CoreHelperReturnTypes
|
||||
|
||||
type TypedProxyTree<T> = ProxyTreeInternal<T> &
|
||||
ProxyTreeRootLeaf &
|
||||
CoreHelperReturnTypes
|
||||
|
||||
export type ProxyTree<T> =
|
||||
IsAny<T> extends true ? AnyProxyTree : TypedProxyTree<T>
|
||||
|
||||
/**
|
||||
* Helper type for creating untyped endpoints.
|
||||
|
||||
5
packages/api/src/typescript/index.ts
Normal file
5
packages/api/src/typescript/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export * from './io.types'
|
||||
|
||||
export * from './contract.types'
|
||||
|
||||
export * from './forge_proxy.types'
|
||||
103
packages/api/src/typescript/io.types.ts
Normal file
103
packages/api/src/typescript/io.types.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
||||
import type {
|
||||
ZodIntersection,
|
||||
ZodObject,
|
||||
ZodRawShape,
|
||||
ZodTypeAny,
|
||||
z
|
||||
} from 'zod'
|
||||
|
||||
import type { ForgeEndpoint } from '../core/forgeEndpoint'
|
||||
|
||||
type ZodObjectOrIntersection =
|
||||
| ZodObject<ZodRawShape>
|
||||
| ZodIntersection<ZodTypeAny, ZodTypeAny>
|
||||
|
||||
/**
|
||||
* Infers the input TypeScript type from a Forge endpoint config object.
|
||||
* Uses embedded Zod schema definitions to produce a plain object type.
|
||||
*/
|
||||
export type InferRawInput<T> = T extends {
|
||||
__isForgeContract: true
|
||||
__input: infer I
|
||||
__media: infer M
|
||||
}
|
||||
? I extends {
|
||||
body?: infer B
|
||||
query?: infer Q
|
||||
}
|
||||
? {
|
||||
body: M extends null
|
||||
? B extends ZodObjectOrIntersection
|
||||
? z.input<B>
|
||||
: B
|
||||
: (B extends ZodObjectOrIntersection
|
||||
? z.input<B>
|
||||
: B extends undefined
|
||||
? {}
|
||||
: B) & {
|
||||
[K in keyof M]: M[K] extends { multiple: true }
|
||||
? M[K] extends { optional: true }
|
||||
? File[] | undefined
|
||||
: File[]
|
||||
: M[K] extends { optional: true }
|
||||
? File | string | undefined
|
||||
: File | string
|
||||
}
|
||||
query: Q extends ZodObjectOrIntersection ? z.input<Q> : Q
|
||||
}
|
||||
: never
|
||||
: never
|
||||
|
||||
/**
|
||||
* Infers the output (response) TypeScript type from a Forge endpoint config object.
|
||||
*/
|
||||
export type InferRawOutput<T> = T extends {
|
||||
__isForgeContract: true
|
||||
__output: infer O
|
||||
}
|
||||
? O
|
||||
: never
|
||||
|
||||
/**
|
||||
* Extracts the input schema type from a `ForgeEndpoint` instance.
|
||||
*/
|
||||
export type InferInput<T extends ForgeEndpoint<any>> = T['__type'] extends {
|
||||
__isForgeContract: true
|
||||
__input: infer I
|
||||
__media: infer M
|
||||
}
|
||||
? I extends {
|
||||
body?: infer B
|
||||
query?: infer Q
|
||||
}
|
||||
? {
|
||||
body: M extends null
|
||||
? B extends ZodObjectOrIntersection
|
||||
? z.input<B>
|
||||
: B
|
||||
: (B extends ZodObjectOrIntersection
|
||||
? z.input<B>
|
||||
: B extends undefined
|
||||
? {}
|
||||
: B) & {
|
||||
[K in keyof M]: {
|
||||
__type: 'media'
|
||||
config: M[K]
|
||||
}
|
||||
}
|
||||
query: Q extends ZodObjectOrIntersection ? z.input<Q> : Q
|
||||
}
|
||||
: never
|
||||
: never
|
||||
|
||||
/**
|
||||
* Extracts the output (response) type from a `ForgeEndpoint` instance.
|
||||
*/
|
||||
export type InferOutput<T extends ForgeEndpoint<any>> = T['__type'] extends {
|
||||
__isForgeContract: true
|
||||
__output: infer O
|
||||
}
|
||||
? O
|
||||
: never
|
||||
3
packages/api/src/utils/index.ts
Normal file
3
packages/api/src/utils/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './encryption'
|
||||
export * from './fetchAPI'
|
||||
export * from './usePromiseLoading'
|
||||
@@ -7,7 +7,9 @@ export default defineConfig({
|
||||
plugins: [
|
||||
react(),
|
||||
dts({
|
||||
rollupTypes: true
|
||||
rollupTypes: false,
|
||||
entryRoot: resolve(__dirname, 'src'),
|
||||
outDir: resolve(__dirname, 'dist')
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
|
||||
Reference in New Issue
Block a user