Skip to content

Commit cdda675

Browse files
committed
rework types
1 parent d262f40 commit cdda675

File tree

12 files changed

+5969
-5877
lines changed

12 files changed

+5969
-5877
lines changed

.direnv/flake-inputs/v3my1jzicdrbzp8z1kij37h906a0zzbg-source

Lines changed: 0 additions & 1 deletion
This file was deleted.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,5 @@ grafast/dataplan-pg/__tests__/**/*.mermaid.png
4444
/WHAT_ARE_YOU_DOING.md
4545
contrib
4646
/env
47+
.direnv
48+
.vscode

grafast/dataplan-pg/src/codecs.ts

Lines changed: 83 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,12 @@ import {
3838
import type { PgExecutor } from "./executor.js";
3939
import { inspect } from "./inspect.js";
4040
import type {
41+
AnyPgCodec,
4142
PgCodec,
43+
PgCodecAttributes,
44+
PgCodecAttributesRecord,
4245
PgCodecExtensions,
46+
PgCodecFromPostgres,
4347
PgCodecPolymorphism,
4448
PgDecode,
4549
PgEncode,
@@ -59,10 +63,22 @@ export type PgCodecAttributeVia = string | PgCodecAttributeViaExplicit;
5963
/** @deprecated Use DataplanPg.PgCodecAttributeExtensions instead */
6064
export type PgCodecAttributeExtensions = DataplanPg.PgCodecAttributeExtensions;
6165

66+
export type PgCodecAttributeName<U> = U extends PgCodecAttribute<
67+
infer TName,
68+
any,
69+
any
70+
>
71+
? TName
72+
: never;
73+
74+
export interface AnyPgCodecAttribute extends PgCodecAttribute {}
75+
6276
export interface PgCodecAttribute<
63-
TCodec extends PgCodec = PgCodec,
77+
TName extends string = string,
78+
TCodec extends PgCodec = AnyPgCodec,
6479
TNotNull extends boolean = boolean,
6580
> {
81+
name: TName;
6682
/**
6783
* How to translate to/from PG and how to cast.
6884
*/
@@ -129,14 +145,6 @@ export interface PgCodecAttribute<
129145
extensions?: Partial<PgCodecAttributeExtensions>;
130146
}
131147

132-
export type PgCodecAttributes<
133-
TCodecMap extends {
134-
[attributeName in string]: PgCodecAttribute;
135-
} = {
136-
[attributeName in string]: PgCodecAttribute;
137-
},
138-
> = TCodecMap;
139-
140148
/**
141149
* Returns a PgCodec for the given builtin Postgres scalar type, optionally
142150
* pass the following config:
@@ -160,12 +168,12 @@ function t<TFromJavaScript = any, TFromPostgres = string>(): <
160168
options?: Cast<TFromJavaScript, TFromPostgres>,
161169
) => PgCodec<
162170
TName,
163-
undefined,
171+
never,
164172
TFromPostgres,
165173
TFromJavaScript,
166-
undefined,
167-
undefined,
168-
undefined
174+
never,
175+
never,
176+
never
169177
> {
170178
return (oid, type, options = {}) => {
171179
const { castFromPg, listCastFromPg, fromPg, toPg, isBinary } = options;
@@ -174,7 +182,6 @@ function t<TFromJavaScript = any, TFromPostgres = string>(): <
174182
sqlType: sql.identifier(...type.split(".")),
175183
fromPg: fromPg ?? (identity as any),
176184
toPg: toPg ?? (identity as any),
177-
attributes: undefined,
178185
extensions: { oid: oid },
179186
castFromPg,
180187
listCastFromPg,
@@ -318,11 +325,11 @@ function recordStringToTuple(value: string): Array<string | null> {
318325
return tuple;
319326
}
320327

321-
function realAttributeDefs<TAttributes extends PgCodecAttributes>(
322-
attributes: TAttributes,
323-
): Array<[string, TAttributes[keyof TAttributes]]> {
328+
function realAttributeDefs<TAttributes extends ReadonlyArray<PgCodecAttribute>>(
329+
attributes: PgCodecAttributesRecord<TAttributes>,
330+
): Array<[PgCodecAttributeName<TAttributes[number]>, TAttributes[number]]> {
324331
const attributeDefs = Object.entries(attributes) as Array<
325-
[string, TAttributes extends infer U ? U[keyof U] : never]
332+
[PgCodecAttributeName<TAttributes[number]>, TAttributes[number]]
326333
>;
327334
return attributeDefs.filter(
328335
([_attributeName, spec]) => !spec.expression && !spec.via,
@@ -336,8 +343,10 @@ function realAttributeDefs<TAttributes extends PgCodecAttributes>(
336343
*
337344
* @see {@link https://www.postgresql.org/docs/current/rowtypes.html#id-1.5.7.24.6}
338345
*/
339-
function makeRecordToSQLRawValue<TAttributes extends PgCodecAttributes>(
340-
attributes: TAttributes,
346+
function makeRecordToSQLRawValue<
347+
TAttributes extends ReadonlyArray<PgCodecAttribute>,
348+
>(
349+
attributes: PgCodecAttributesRecord<TAttributes>,
341350
): PgEncode<ObjectFromPgCodecAttributes<TAttributes>> {
342351
const attributeDefs = realAttributeDefs(attributes);
343352
return (value) => {
@@ -350,19 +359,22 @@ function makeRecordToSQLRawValue<TAttributes extends PgCodecAttributes>(
350359
};
351360
}
352361

353-
export type ObjectFromPgCodecAttributes<TAttributes extends PgCodecAttributes> =
354-
{
355-
[attributeName in keyof TAttributes]: TAttributes[attributeName] extends PgCodecAttribute<
356-
infer UCodec,
357-
infer UNonNull
358-
>
359-
? UCodec extends PgCodec<any, any, any, infer UFromJs, any, any, any>
360-
? UNonNull extends true
361-
? Exclude<UFromJs, null | undefined>
362-
: UFromJs | null
363-
: never
364-
: never;
365-
};
362+
export type ObjectFromPgCodecAttributes<
363+
TAttributes extends
364+
ReadonlyArray<AnyPgCodecAttribute> = ReadonlyArray<AnyPgCodecAttribute>,
365+
> = {
366+
[TCodecAttribute in TAttributes[number] as PgCodecAttributeName<TCodecAttribute>]: TCodecAttribute extends PgCodecAttribute<
367+
any,
368+
infer UCodec,
369+
infer UNonNull
370+
>
371+
? UCodec extends PgCodec<any, any, any, infer UFromJs, any, any, any>
372+
? UNonNull extends true
373+
? Exclude<UFromJs, null | undefined>
374+
: UFromJs | null
375+
: never
376+
: never;
377+
};
366378

367379
/**
368380
* Takes a list of attributes and returns a mapping function that takes a
@@ -371,8 +383,10 @@ export type ObjectFromPgCodecAttributes<TAttributes extends PgCodecAttributes> =
371383
*
372384
* @see {@link https://www.postgresql.org/docs/current/rowtypes.html#id-1.5.7.24.6}
373385
*/
374-
function makeSQLValueToRecord<TAttributes extends PgCodecAttributes>(
375-
attributes: TAttributes,
386+
function makeSQLValueToRecord<
387+
TAttributes extends ReadonlyArray<PgCodecAttribute>,
388+
>(
389+
attributes: PgCodecAttributesRecord<TAttributes>,
376390
): (value: string) => ObjectFromPgCodecAttributes<TAttributes> {
377391
const attributeDefs = realAttributeDefs(attributes);
378392
const attributeCount = attributeDefs.length;
@@ -390,7 +404,7 @@ function makeSQLValueToRecord<TAttributes extends PgCodecAttributes>(
390404

391405
export type PgRecordTypeCodecSpec<
392406
TName extends string,
393-
TAttributes extends PgCodecAttributes,
407+
TAttributes extends PgCodecAttributesRecord<ReadonlyArray<AnyPgCodecAttribute>>,
394408
> = {
395409
name: TName;
396410
executor: PgExecutor;
@@ -413,18 +427,18 @@ export type PgRecordTypeCodecSpec<
413427
* isAnonymous - if true, this represents an "anonymous" type, typically the return value of a function or something like that. If this is true, then name and identifier are ignored.
414428
*/
415429
export function recordCodec<
416-
const TName extends string,
417-
const TAttributes extends PgCodecAttributes,
430+
TName extends string,
431+
TAttributes extends PgCodecAttributesRecord<ReadonlyArray<AnyPgCodecAttribute>>,
418432
>(
419433
config: PgRecordTypeCodecSpec<TName, TAttributes>,
420434
): PgCodec<
421435
TName,
422436
TAttributes,
423437
string,
424438
ObjectFromPgCodecAttributes<TAttributes>,
425-
undefined,
426-
undefined,
427-
undefined
439+
never,
440+
never,
441+
never
428442
> {
429443
const {
430444
name,
@@ -504,14 +518,14 @@ type CodecWithListCodec<
504518
`${TCodec extends PgCodec<infer UName, any, any, any, any, any, any>
505519
? UName
506520
: never}[]`,
507-
undefined,
521+
never,
508522
string,
509-
TCodec extends PgCodec<any, any, any, infer UFromJs, undefined, any, any>
523+
TCodec extends PgCodec<any, any, any, infer UFromJs, never, any, any>
510524
? UFromJs[]
511525
: any[],
512526
TCodec,
513-
undefined,
514-
undefined
527+
never,
528+
never
515529
>;
516530
};
517531

@@ -528,9 +542,7 @@ type CodecWithListCodec<
528542
* @param typeDelim - the delimeter used to separate entries in this list when Postgres stringifies it
529543
* @param identifier - a pg-sql2 fragment that represents the name of this type
530544
*/
531-
export function listOfCodec<
532-
TInnerCodec extends PgCodec<string, any, any, any, undefined, any, any>,
533-
>(
545+
export function listOfCodec<TInnerCodec extends AnyPgCodec = AnyPgCodec>(
534546
listedCodec: TInnerCodec,
535547
config?: {
536548
description?: string;
@@ -542,14 +554,14 @@ export function listOfCodec<
542554
`${TInnerCodec extends PgCodec<infer UName, any, any, any, any, any, any>
543555
? UName
544556
: never}[]`,
545-
undefined, // Array has no attributes
557+
never, // Array has no attributes
546558
string,
547-
TInnerCodec extends PgCodec<any, any, any, infer UFromJs, undefined, any, any>
559+
TInnerCodec extends PgCodec<any, any, any, infer UFromJs, never, any, any>
548560
? UFromJs[]
549561
: any[],
550562
TInnerCodec,
551-
undefined,
552-
undefined
563+
never,
564+
never
553565
> {
554566
const innerCodec: CodecWithListCodec<TInnerCodec> = listedCodec;
555567

@@ -568,22 +580,14 @@ export function listOfCodec<
568580
`${TInnerCodec extends PgCodec<infer UName, any, any, any, any, any, any>
569581
? UName
570582
: never}[]`,
571-
undefined, // Array has no attributes
583+
never, // Array has no attributes
572584
string,
573-
TInnerCodec extends PgCodec<
574-
any,
575-
any,
576-
any,
577-
infer UFromJs,
578-
undefined,
579-
any,
580-
any
581-
>
585+
TInnerCodec extends PgCodec<any, any, any, infer UFromJs, never, any, any>
582586
? UFromJs[]
583587
: any[],
584588
TInnerCodec,
585-
undefined,
586-
undefined
589+
never,
590+
never
587591
> = {
588592
name: `${
589593
innerCodec.name as TInnerCodec extends PgCodec<
@@ -661,7 +665,7 @@ exportAs("@dataplan/pg", listOfCodec, "listOfCodec");
661665
*/
662666
export function domainOfCodec<
663667
TName extends string,
664-
TInnerCodec extends PgCodec<any, any, any, any, any, any>,
668+
TInnerCodec extends AnyPgCodec,
665669
>(
666670
innerCodec: TInnerCodec,
667671
name: TName,
@@ -673,13 +677,15 @@ export function domainOfCodec<
673677
} = {},
674678
): PgCodec<
675679
TName,
676-
TInnerCodec extends PgCodec<any, infer U, any, any, any, any> ? U : any,
677-
TInnerCodec extends PgCodec<any, any, infer U, any, any, any> ? U : any,
678-
undefined,
679-
TInnerCodec,
680-
undefined
680+
PgCodecAttributes<TInnerCodec>,
681+
PgCodecFromPostgres<TInnerCodec>,
682+
any,
683+
AnyPgCodec, // <-- weird types
684+
TInnerCodec, // <-- weird types
685+
any
681686
> {
682687
const { description, extensions, notNull } = config;
688+
683689
return {
684690
// Generally same as underlying type:
685691
...innerCodec,
@@ -689,7 +695,7 @@ export function domainOfCodec<
689695
sqlType: identifier,
690696
description,
691697
extensions,
692-
domainOfCodec: innerCodec.arrayOfCodec ? undefined : innerCodec,
698+
...(innerCodec.arrayOfCodec ? {} : { domainOfCodec: innerCodec }),
693699
notNull: Boolean(notNull),
694700
};
695701
}
@@ -701,7 +707,7 @@ exportAs("@dataplan/pg", domainOfCodec, "domainOfCodec");
701707
* @internal
702708
*/
703709
function escapeRangeValue<
704-
TInnerCodec extends PgCodec<any, undefined, any, any, undefined, any, any>,
710+
TInnerCodec extends PgCodec<any, never, any, any, never, any, any>,
705711
>(value: null | any, innerCodec: TInnerCodec): string {
706712
if (value == null) {
707713
return "";
@@ -727,15 +733,7 @@ interface PgRange<T> {
727733
*/
728734
export function rangeOfCodec<
729735
TName extends string,
730-
TInnerCodec extends PgCodec<
731-
any,
732-
undefined,
733-
any,
734-
any,
735-
undefined,
736-
any,
737-
undefined
738-
>,
736+
TInnerCodec extends PgCodec<any, never, any, any, never, any, never>,
739737
>(
740738
innerCodec: TInnerCodec,
741739
name: TName,
@@ -744,15 +742,7 @@ export function rangeOfCodec<
744742
description?: string;
745743
extensions?: Partial<PgCodecExtensions>;
746744
} = {},
747-
): PgCodec<
748-
TName,
749-
undefined,
750-
string,
751-
PgRange<unknown>,
752-
undefined,
753-
undefined,
754-
TInnerCodec
755-
> {
745+
): PgCodec<TName, never, string, PgRange<unknown>, never, never, TInnerCodec> {
756746
const { description, extensions } = config;
757747
const needsCast = innerCodec.castFromPg;
758748

@@ -1169,17 +1159,16 @@ export function getCodecByPgCatalogTypeName(pgCatalogTypeName: string) {
11691159
return null;
11701160
}
11711161

1172-
export function getInnerCodec<
1173-
TCodec extends PgCodec<any, any, any, any, any, any>,
1174-
>(
1162+
export function getInnerCodec<TCodec extends PgCodec>(
11751163
codec: TCodec,
11761164
): TCodec extends PgCodec<
11771165
any,
11781166
any,
11791167
any,
11801168
infer UArray,
11811169
infer UDomain,
1182-
infer URange
1170+
infer URange,
1171+
any
11831172
>
11841173
? Exclude<UDomain | UArray | URange, undefined>
11851174
: TCodec {

0 commit comments

Comments
 (0)