Skip to content
331 changes: 113 additions & 218 deletions packages/api/src/Data.ts

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions packages/api/src/IData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import type { $ZodShape } from 'zod/v4/core'
import type * as DT from './types/Data.ts'
import type * as FTTT from './types/FallThroughTargeting.ts'
import type * as PT from './types/Payload.ts'
import type * as QT from './types/Query.ts'
import type * as TT from './types/Targeting.ts'

export interface IData<$ extends DT.Meta> {
usePayload<Parsers extends $ZodShape>(
parsers: Parsers,
): Promise<IData<$ & { PayloadParsers: $['PayloadParsers'] & Parsers }>>

useTargeting<TDs extends TT.DescriptorRecord>(targeting: TDs): Promise<
IData<
$ & {
TargetingParsers: $['TargetingParsers'] & TT.ParserRecord<TDs>
QueryParsers: $['QueryParsers'] & QT.ParserRecord<TDs>
}
>
>

useFallThroughTargeting<TDs extends FTTT.DescriptorRecord>(
targeting: TDs,
): Promise<
IData<
$ & {
FallThroughTargetingParsers:
& $['FallThroughTargetingParsers']
& FTTT.ParsersRecord<TDs>
}
>
>

insert(data: DT.InsertableData<$>): Promise<IData<$>>

getPayloadForEachName(
rawQuery?: QT.Raw<$['QueryParsers']>,
): Promise<PT.Payloads<$>>

getPayload<Name extends keyof $['PayloadParsers']>(
name: Name,
rawQuery?: QT.Raw<$['QueryParsers']>,
): Promise<
| PT.Payload<$, $['PayloadParsers'][Name]>
| undefined
>

getPayloads<Name extends keyof $['PayloadParsers']>(
name: Name,
rawQuery?: QT.Raw<$['QueryParsers']>,
): Promise<
PT.Payload<$, $['PayloadParsers'][Name]>[]
>
}
164 changes: 41 additions & 123 deletions packages/api/src/PromisedData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,190 +8,108 @@ import type * as QT from './types/Query.ts'
import type { DataItemRulesIn } from './parsers/DataItemRules.ts'
import type { MaybePromise } from './types.ts'
import type { DataItemIn } from './parsers/DataItem.ts'
import type { IData } from './IData.ts'

export class PromisedData<
PayloadParsers extends $ZodShape,
TargetingParsers extends $ZodShape,
QueryParsers extends $ZodShape,
FallThroughTargetingParsers extends $ZodShape,
> extends Promise<
Data<
PayloadParsers,
TargetingParsers,
QueryParsers,
FallThroughTargetingParsers
>
> {
export class PromisedData<$ extends DT.Meta> extends Promise<Data<$>>
implements IData<$> {
constructor(
executor: (
resolve: (
value: MaybePromise<
Data<
PayloadParsers,
TargetingParsers,
QueryParsers,
FallThroughTargetingParsers
>
>,
) => void,
resolve: (value: MaybePromise<Data<$>>) => void,
reject: (reason?: any) => void,
) => void,
) {
super(executor)
}

static create<
PayloadParsers extends $ZodShape,
TargetingParsers extends $ZodShape,
QueryParsers extends $ZodShape,
FallThroughTargetingParsers extends $ZodShape,
>(
promisedData: MaybePromise<
Data<
PayloadParsers,
TargetingParsers,
QueryParsers,
FallThroughTargetingParsers
>
>,
): PromisedData<
PayloadParsers,
TargetingParsers,
QueryParsers,
FallThroughTargetingParsers
> {
static create<$ extends DT.Meta>(
promisedData: MaybePromise<Data<$>>,
): PromisedData<$> {
return new PromisedData((resolve) => resolve(promisedData))
}

#create<
NewPayloadParsers extends $ZodShape,
NewTargetingParsers extends $ZodShape,
NewQueryParsers extends $ZodShape,
NewFallThroughTargetingParsers extends $ZodShape,
>(
cb: (
data: Data<
PayloadParsers,
TargetingParsers,
QueryParsers,
FallThroughTargetingParsers
>,
) => MaybePromise<
Data<
NewPayloadParsers,
NewTargetingParsers,
NewQueryParsers,
NewFallThroughTargetingParsers
>
>,
): PromisedData<
NewPayloadParsers,
NewTargetingParsers,
NewQueryParsers,
NewFallThroughTargetingParsers
> {
#create<$$ extends DT.Meta>(
cb: (data: Data<$>) => MaybePromise<Data<$$>>,
): PromisedData<$$> {
return new PromisedData((resolve) => resolve(this.then(cb)))
}

usePayload<Parsers extends $ZodShape>(
parsers: Parsers,
): PromisedData<
PayloadParsers & Parsers,
TargetingParsers,
QueryParsers,
FallThroughTargetingParsers
$ & { PayloadParsers: $['PayloadParsers'] & Parsers }
> {
return this.#create((data) => data.usePayload(parsers))
}

insert(
insertableData: DT.InsertableData<
PayloadParsers,
TargetingParsers,
FallThroughTargetingParsers
>,
): PromisedData<
PayloadParsers,
TargetingParsers,
QueryParsers,
FallThroughTargetingParsers
> {
insert(insertableData: DT.InsertableData<$>): PromisedData<$> {
return this.#create((data) => data.insert(insertableData))
}

addRules<
Name extends keyof PayloadParsers,
Name extends keyof $['PayloadParsers'],
>(
name: Name,
opts:
| DataItemIn<
PayloadParsers[Name],
TargetingParsers,
FallThroughTargetingParsers
>
| DataItemRulesIn<
PayloadParsers[Name],
TargetingParsers,
FallThroughTargetingParsers
>,
): PromisedData<
PayloadParsers,
TargetingParsers,
QueryParsers,
FallThroughTargetingParsers
> {
| DataItemIn<$, $['PayloadParsers'][Name]>
| DataItemRulesIn<$, $['PayloadParsers'][Name]>,
): PromisedData<$> {
return this.#create((data) => data.addRules(name, opts))
}

useTargeting<TDs extends TT.DescriptorRecord>(
targeting: TDs,
): PromisedData<
PayloadParsers,
TargetingParsers & TT.ParserRecord<TDs>,
QueryParsers & QT.ParserRecord<TDs>,
FallThroughTargetingParsers
$ & {
TargetingParsers: $['TargetingParsers'] & TT.ParserRecord<TDs>
QueryParsers: $['QueryParsers'] & QT.ParserRecord<TDs>
}
> {
return this.#create((data) => data.useTargeting(targeting))
}

useFallThroughTargeting<TDs extends FTTT.DescriptorRecord>(
targeting: TDs,
): PromisedData<
PayloadParsers,
TargetingParsers,
QueryParsers,
FallThroughTargetingParsers & FTTT.ParsersRecord<TDs>
$ & {
FallThroughTargetingParsers:
& $['FallThroughTargetingParsers']
& FTTT.ParsersRecord<TDs>
}
> {
return this.#create((data) => data.useFallThroughTargeting(targeting))
}

async getPayloadForEachName(
rawQuery: QT.Raw<QueryParsers> = {},
rawQuery?: QT.Raw<$['QueryParsers']>,
): Promise<
PT.Payloads<PayloadParsers, FallThroughTargetingParsers>
PT.Payloads<$>
> {
const data = await this
return data.getPayloadForEachName(rawQuery)
}

async getPayload<Name extends keyof PayloadParsers>(
async getPayload<Name extends keyof $['PayloadParsers']>(
name: Name,
rawQuery: QT.Raw<QueryParsers> = {},
rawQuery?: QT.Raw<$['QueryParsers']>,
): Promise<
PT.Payload<PayloadParsers[Name], FallThroughTargetingParsers> | undefined
| PT.Payload<$, $['PayloadParsers'][Name]>
| undefined
> {
const data = await this
return data.getPayload(name, rawQuery)
}

removeAllRules(): Promise<
Data<
PayloadParsers,
TargetingParsers,
QueryParsers,
FallThroughTargetingParsers
>
async getPayloads<Name extends keyof $['PayloadParsers']>(
name: Name,
rawQuery?: QT.Raw<$['QueryParsers']>,
): Promise<
PT.Payload<$, $['PayloadParsers'][Name]>[]
> {
const data = await this
return data.getPayloads(name, rawQuery)
}

removeAllRules(): Promise<Data<$>> {
return this.#create((data) => data.removeAllRules())
}
}
49 changes: 20 additions & 29 deletions packages/api/src/parsers/DataItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import {
type ZodMiniDefault,
type ZodMiniObject,
} from 'zod/mini'
import type { $strict, $ZodShape, $ZodType } from 'zod/v4/core'
import type { $strict, $ZodType } from 'zod/v4/core'
import {
type DataItemRulesIn,
type DataItemRulesOut,
DataItemRulesParser,
} from './DataItemRules.ts'
import { DataItemVariablesParser } from './DataItemVariablesParser.ts'
import { variablesFor } from './variablesRegistry.ts'
import type * as DT from '../types/Data.ts'

/**
* Parses an "item".
Expand All @@ -24,15 +25,14 @@ import { variablesFor } from './variablesRegistry.ts'
* Currently this is just restricted to `rules`.
*/
export function DataItemParser<
P extends $ZodType,
T extends $ZodShape,
FTT extends $ZodShape,
$ extends DT.Meta,
PayloadParser extends $ZodType,
>(
Payload: P,
targeting: T,
fallThroughTargeting: FTT,
Payload: PayloadParser,
targeting: $['TargetingParsers'],
fallThroughTargeting: $['FallThroughTargetingParsers'],
strictTargeting: boolean,
): DataItemParser<P, T, FTT> {
): DataItemParser<$, PayloadParser> {
const variablesRegistry = variablesFor(Payload)
return strictObject({
rules: DataItemRulesParser(
Expand All @@ -55,19 +55,12 @@ export function DataItemParser<
}

export type DataItemParser<
Payload extends $ZodType,
Targeting extends $ZodShape,
FallThroughTargeting extends $ZodShape,
$ extends DT.Meta,
PayloadParser extends $ZodType,
> = ZodMiniObject<
{
rules: DataItemRulesParser<
Payload,
Targeting,
FallThroughTargeting
>
variables: ZodMiniDefault<
DataItemVariablesParser<Targeting, FallThroughTargeting>
>
rules: DataItemRulesParser<$, PayloadParser>
variables: ZodMiniDefault<DataItemVariablesParser<$>>
},
$strict
>
Expand All @@ -76,28 +69,26 @@ export type DataItemParser<
* The data shape expected for {@link DataItemParser} inputs.
*/
export interface DataItemIn<
Payload extends $ZodType,
Targeting extends $ZodShape,
FallThroughTargeting extends $ZodShape,
$ extends DT.Meta,
PayloadParser extends $ZodType,
> {
rules: DataItemRulesIn<Payload, Targeting, FallThroughTargeting>
rules: DataItemRulesIn<$, PayloadParser>
variables?: Record<
string,
DataItemRulesIn<ZodMiniAny, Targeting, FallThroughTargeting>
DataItemRulesIn<$, ZodMiniAny>
>
}

/**
* The data shape expected for {@link DataItemParser} outputs.
*/
export interface DataItemOut<
Payload extends $ZodType,
Targeting extends $ZodShape,
FallThroughTargeting extends $ZodShape,
$ extends DT.Meta,
PayloadParser extends $ZodType,
> {
rules: DataItemRulesOut<Payload, Targeting, FallThroughTargeting>
rules: DataItemRulesOut<$, PayloadParser>
variables: Record<
string,
DataItemRulesOut<ZodMiniAny, Targeting, FallThroughTargeting>
DataItemRulesOut<$, ZodMiniAny>
>
}
Loading