graphile-settings 5.16.0 → 5.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/plugins/meta-schema/encoding-meta-builders.d.ts +2 -0
- package/esm/plugins/meta-schema/encoding-meta-builders.js +84 -0
- package/esm/plugins/meta-schema/graphql-meta-field.js +21 -2
- package/esm/plugins/meta-schema/type-mappings.js +2 -0
- package/esm/plugins/meta-schema/types.d.ts +30 -0
- package/esm/plugins/meta-schema.d.ts +3 -0
- package/esm/plugins/meta-schema.js +3 -0
- package/package.json +13 -13
- package/plugins/meta-schema/encoding-meta-builders.d.ts +2 -0
- package/plugins/meta-schema/encoding-meta-builders.js +87 -0
- package/plugins/meta-schema/graphql-meta-field.js +20 -1
- package/plugins/meta-schema/type-mappings.js +2 -0
- package/plugins/meta-schema/types.d.ts +30 -0
- package/plugins/meta-schema.d.ts +3 -0
- package/plugins/meta-schema.js +3 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scalar encoding contracts — the one piece of field metadata standard GraphQL
|
|
3
|
+
* introspection can't provide.
|
|
4
|
+
*
|
|
5
|
+
* Introspection tells a client a field's scalar *name* (`GeoJSON`, `LTree`,
|
|
6
|
+
* `Interval`, `BigInt`, `vector`, …) but not how to serialize/parse it or its
|
|
7
|
+
* structural parameters (geometry subtype/SRID, vector dimensions, ltree
|
|
8
|
+
* dot-path semantics). Without that, generated clients treat these as opaque
|
|
9
|
+
* strings / `any` and mis-encode inputs or fail to parse outputs.
|
|
10
|
+
*
|
|
11
|
+
* `kind` is derived deterministically from the *underlying* codec (array and
|
|
12
|
+
* domain wrappers unwrapped first, first match wins) so exactly one kind is
|
|
13
|
+
* ever assigned and nothing can clobber it. Structural extras (subtype, SRID,
|
|
14
|
+
* dimensions) are read verbatim from attribute extensions — never guessed, and
|
|
15
|
+
* `null` when absent.
|
|
16
|
+
*/
|
|
17
|
+
/** pg type name → encoding kind. Plain scalars are intentionally absent → null. */
|
|
18
|
+
const KIND_BY_PG_TYPE = {
|
|
19
|
+
int8: 'bigint',
|
|
20
|
+
bigint: 'bigint',
|
|
21
|
+
numeric: 'bigint',
|
|
22
|
+
timestamptz: 'datetime',
|
|
23
|
+
timestamp: 'datetime',
|
|
24
|
+
date: 'date',
|
|
25
|
+
time: 'time',
|
|
26
|
+
timetz: 'time',
|
|
27
|
+
interval: 'interval',
|
|
28
|
+
uuid: 'uuid',
|
|
29
|
+
geometry: 'geojson',
|
|
30
|
+
geography: 'geojson',
|
|
31
|
+
point: 'point',
|
|
32
|
+
inet: 'inet',
|
|
33
|
+
cidr: 'inet',
|
|
34
|
+
ltree: 'ltree',
|
|
35
|
+
vector: 'vector',
|
|
36
|
+
bytea: 'bytea'
|
|
37
|
+
};
|
|
38
|
+
/** Unwrap array-of and domain-of wrappers to the underlying scalar/record codec. */
|
|
39
|
+
function underlyingCodec(codec) {
|
|
40
|
+
let current = codec ?? null;
|
|
41
|
+
const seen = new Set();
|
|
42
|
+
while (current && !seen.has(current) && (current.arrayOfCodec || current.domainOfCodec)) {
|
|
43
|
+
seen.add(current);
|
|
44
|
+
current = current.arrayOfCodec || current.domainOfCodec || null;
|
|
45
|
+
}
|
|
46
|
+
return current;
|
|
47
|
+
}
|
|
48
|
+
/** True when a codec is a composite/record type (has named attributes). */
|
|
49
|
+
function isCompositeCodec(codec) {
|
|
50
|
+
return !!codec?.attributes && Object.keys(codec.attributes).length > 0;
|
|
51
|
+
}
|
|
52
|
+
export function buildScalarEncoding(attr) {
|
|
53
|
+
const codec = underlyingCodec(attr?.codec);
|
|
54
|
+
if (!codec)
|
|
55
|
+
return null;
|
|
56
|
+
const ext = attr?.extensions ?? undefined;
|
|
57
|
+
const kind = KIND_BY_PG_TYPE[codec.name];
|
|
58
|
+
if (!kind) {
|
|
59
|
+
// Composite/record types are the only non-mapped scalars worth describing;
|
|
60
|
+
// everything else (text, int, bool, json, enum, …) is fully covered by gqlType.
|
|
61
|
+
if (isCompositeCodec(codec)) {
|
|
62
|
+
return { kind: 'composite', fields: null };
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
switch (kind) {
|
|
67
|
+
case 'geojson':
|
|
68
|
+
return {
|
|
69
|
+
kind,
|
|
70
|
+
geometrySubtype: typeof ext?.geometrySubtype === 'string' ? ext.geometrySubtype : null,
|
|
71
|
+
srid: typeof ext?.geometrySrid === 'number' ? ext.geometrySrid : null
|
|
72
|
+
};
|
|
73
|
+
case 'vector':
|
|
74
|
+
return {
|
|
75
|
+
kind,
|
|
76
|
+
elementType: 'float',
|
|
77
|
+
dimensions: typeof ext?.vectorDimensions === 'number' ? ext.vectorDimensions : null
|
|
78
|
+
};
|
|
79
|
+
case 'ltree':
|
|
80
|
+
return { kind, dotPath: true };
|
|
81
|
+
default:
|
|
82
|
+
return { kind };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GraphQLBoolean, GraphQLFloat, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLString } from 'graphql';
|
|
1
|
+
import { GraphQLBoolean, GraphQLFloat, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLString } from 'graphql';
|
|
2
2
|
function nn(type) {
|
|
3
3
|
return new GraphQLNonNull(type);
|
|
4
4
|
}
|
|
@@ -6,6 +6,21 @@ function nnList(type) {
|
|
|
6
6
|
return nn(new GraphQLList(nn(type)));
|
|
7
7
|
}
|
|
8
8
|
function createMetaSchemaType() {
|
|
9
|
+
const MetaScalarEncodingType = new GraphQLObjectType({
|
|
10
|
+
name: 'MetaScalarEncoding',
|
|
11
|
+
description: 'How a client must serialize/parse a scalar — the one field-type detail standard GraphQL introspection cannot describe. Null for plain scalars whose wire format is obvious from gqlType.',
|
|
12
|
+
fields: () => ({
|
|
13
|
+
kind: {
|
|
14
|
+
type: nn(GraphQLString),
|
|
15
|
+
description: "Machine kind: bigint, datetime, date, time, interval, uuid, geojson, point, inet, ltree, vector, bytea, or composite."
|
|
16
|
+
},
|
|
17
|
+
elementType: { type: GraphQLString, description: "For 'vector': element scalar (e.g. 'float')." },
|
|
18
|
+
dimensions: { type: GraphQLInt, description: "For 'vector': declared length, else null." },
|
|
19
|
+
geometrySubtype: { type: GraphQLString, description: "For 'geojson': Point/LineString/Polygon/…, else null." },
|
|
20
|
+
srid: { type: GraphQLInt, description: "For 'geojson': spatial reference id, else null." },
|
|
21
|
+
dotPath: { type: GraphQLBoolean, description: "For 'ltree': values are dot-separated path strings." }
|
|
22
|
+
})
|
|
23
|
+
});
|
|
9
24
|
const MetaTypeType = new GraphQLObjectType({
|
|
10
25
|
name: 'MetaType',
|
|
11
26
|
description: 'Information about a PostgreSQL type',
|
|
@@ -15,7 +30,11 @@ function createMetaSchemaType() {
|
|
|
15
30
|
isArray: { type: nn(GraphQLBoolean) },
|
|
16
31
|
isNotNull: { type: GraphQLBoolean },
|
|
17
32
|
hasDefault: { type: GraphQLBoolean },
|
|
18
|
-
subtype: { type: GraphQLString }
|
|
33
|
+
subtype: { type: GraphQLString },
|
|
34
|
+
encoding: {
|
|
35
|
+
type: MetaScalarEncodingType,
|
|
36
|
+
description: 'Scalar serialization contract (null for plain scalars)'
|
|
37
|
+
}
|
|
19
38
|
})
|
|
20
39
|
});
|
|
21
40
|
const MetaEnumType = new GraphQLObjectType({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { buildScalarEncoding } from './encoding-meta-builders';
|
|
1
2
|
const PG_TO_GQL_TYPE = {
|
|
2
3
|
text: 'String',
|
|
3
4
|
varchar: 'String',
|
|
@@ -87,6 +88,7 @@ export function buildFieldMeta(name, attr, build, options) {
|
|
|
87
88
|
isNotNull,
|
|
88
89
|
hasDefault,
|
|
89
90
|
subtype,
|
|
91
|
+
encoding: buildScalarEncoding(attr),
|
|
90
92
|
},
|
|
91
93
|
isNotNull,
|
|
92
94
|
hasDefault,
|
|
@@ -101,6 +101,33 @@ export interface TypeMeta {
|
|
|
101
101
|
isNotNull?: boolean;
|
|
102
102
|
hasDefault?: boolean;
|
|
103
103
|
subtype?: string | null;
|
|
104
|
+
/**
|
|
105
|
+
* How the client must serialize/parse this scalar. `null` for plain scalars
|
|
106
|
+
* (String/Int/Float/Boolean/JSON/enum) whose wire format is obvious from
|
|
107
|
+
* `gqlType` — populated only for scalars introspection can't fully describe.
|
|
108
|
+
*/
|
|
109
|
+
encoding?: ScalarEncodingMeta | null;
|
|
110
|
+
}
|
|
111
|
+
/** The machine kind a scalar marshals as on the client. */
|
|
112
|
+
export type ScalarEncodingKind = 'bigint' | 'datetime' | 'date' | 'time' | 'interval' | 'uuid' | 'geojson' | 'point' | 'inet' | 'ltree' | 'vector' | 'bytea' | 'composite';
|
|
113
|
+
export interface ScalarEncodingMeta {
|
|
114
|
+
/** Deterministic kind derived from the underlying (unwrapped) codec. */
|
|
115
|
+
kind: ScalarEncodingKind;
|
|
116
|
+
/** For 'vector': element scalar (e.g. 'float'), else null. */
|
|
117
|
+
elementType?: string | null;
|
|
118
|
+
/** For 'vector': declared length from typmod, else null. */
|
|
119
|
+
dimensions?: number | null;
|
|
120
|
+
/** For 'geojson': geometry subtype (Point/LineString/Polygon/…), else null. */
|
|
121
|
+
geometrySubtype?: string | null;
|
|
122
|
+
/** For 'geojson': spatial reference id, else null. */
|
|
123
|
+
srid?: number | null;
|
|
124
|
+
/** For 'ltree': values are dot-separated path strings ('a.b.c'). */
|
|
125
|
+
dotPath?: boolean;
|
|
126
|
+
/** For 'composite': nested attribute encodings. */
|
|
127
|
+
fields?: {
|
|
128
|
+
name: string;
|
|
129
|
+
type: TypeMeta;
|
|
130
|
+
}[] | null;
|
|
104
131
|
}
|
|
105
132
|
export interface IndexMeta {
|
|
106
133
|
name: string;
|
|
@@ -198,6 +225,7 @@ export interface PgCodec {
|
|
|
198
225
|
name: string;
|
|
199
226
|
attributes?: Record<string, PgAttribute>;
|
|
200
227
|
arrayOfCodec?: PgCodec | null;
|
|
228
|
+
domainOfCodec?: PgCodec | null;
|
|
201
229
|
isAnonymous?: boolean;
|
|
202
230
|
extensions?: {
|
|
203
231
|
pg?: {
|
|
@@ -207,6 +235,8 @@ export interface PgCodec {
|
|
|
207
235
|
}
|
|
208
236
|
export interface PgAttributeExtensions extends Record<string, unknown> {
|
|
209
237
|
geometrySubtype?: string | null;
|
|
238
|
+
geometrySrid?: number | null;
|
|
239
|
+
vectorDimensions?: number | null;
|
|
210
240
|
}
|
|
211
241
|
export interface PgAttribute {
|
|
212
242
|
codec?: PgCodec | null;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { GraphileConfig } from 'graphile-config';
|
|
8
8
|
import { cachedTablesMeta } from './meta-schema/cache';
|
|
9
|
+
import { buildScalarEncoding } from './meta-schema/encoding-meta-builders';
|
|
9
10
|
import { MetaSchemaPlugin } from './meta-schema/plugin';
|
|
10
11
|
import { buildFieldMeta, pgTypeToGqlType } from './meta-schema/type-mappings';
|
|
11
12
|
export { MetaSchemaPlugin };
|
|
@@ -16,4 +17,6 @@ export { pgTypeToGqlType as _pgTypeToGqlType };
|
|
|
16
17
|
export { buildFieldMeta as _buildFieldMeta };
|
|
17
18
|
/** @internal Exported for testing only */
|
|
18
19
|
export { cachedTablesMeta as _cachedTablesMeta };
|
|
20
|
+
/** @internal Exported for testing only */
|
|
21
|
+
export { buildScalarEncoding as _buildScalarEncoding };
|
|
19
22
|
export default MetaSchemaPlugin;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* constraints, indexes, and relations for code generation tooling.
|
|
6
6
|
*/
|
|
7
7
|
import { cachedTablesMeta } from './meta-schema/cache';
|
|
8
|
+
import { buildScalarEncoding } from './meta-schema/encoding-meta-builders';
|
|
8
9
|
import { MetaSchemaPlugin } from './meta-schema/plugin';
|
|
9
10
|
import { buildFieldMeta, pgTypeToGqlType } from './meta-schema/type-mappings';
|
|
10
11
|
export { MetaSchemaPlugin };
|
|
@@ -17,4 +18,6 @@ export { pgTypeToGqlType as _pgTypeToGqlType };
|
|
|
17
18
|
export { buildFieldMeta as _buildFieldMeta };
|
|
18
19
|
/** @internal Exported for testing only */
|
|
19
20
|
export { cachedTablesMeta as _cachedTablesMeta };
|
|
21
|
+
/** @internal Exported for testing only */
|
|
22
|
+
export { buildScalarEncoding as _buildScalarEncoding };
|
|
20
23
|
export default MetaSchemaPlugin;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphile-settings",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.17.0",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "graphile settings",
|
|
6
6
|
"main": "index.js",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@aws-sdk/client-s3": "^3.1052.0",
|
|
33
33
|
"@constructive-io/bucket-provisioner": "^0.14.0",
|
|
34
|
-
"@constructive-io/graphql-env": "^3.16.
|
|
35
|
-
"@constructive-io/graphql-types": "^3.
|
|
34
|
+
"@constructive-io/graphql-env": "^3.16.3",
|
|
35
|
+
"@constructive-io/graphql-types": "^3.15.0",
|
|
36
36
|
"@constructive-io/s3-streamer": "^2.29.2",
|
|
37
37
|
"@constructive-io/s3-utils": "^2.20.0",
|
|
38
38
|
"@constructive-io/upload-names": "^2.19.0",
|
|
@@ -49,17 +49,17 @@
|
|
|
49
49
|
"graphile-bucket-provisioner-plugin": "0.14.0",
|
|
50
50
|
"graphile-build": "5.0.2",
|
|
51
51
|
"graphile-build-pg": "5.0.2",
|
|
52
|
-
"graphile-bulk-mutations": "^0.9.
|
|
52
|
+
"graphile-bulk-mutations": "^0.9.3",
|
|
53
53
|
"graphile-config": "1.0.1",
|
|
54
|
-
"graphile-connection-filter": "^1.16.
|
|
55
|
-
"graphile-i18n": "^1.6.
|
|
56
|
-
"graphile-llm": "^0.19.
|
|
57
|
-
"graphile-ltree": "^1.14.
|
|
58
|
-
"graphile-pg-aggregates": "^1.10.
|
|
59
|
-
"graphile-postgis": "^2.23.
|
|
54
|
+
"graphile-connection-filter": "^1.16.3",
|
|
55
|
+
"graphile-i18n": "^1.6.3",
|
|
56
|
+
"graphile-llm": "^0.19.3",
|
|
57
|
+
"graphile-ltree": "^1.14.3",
|
|
58
|
+
"graphile-pg-aggregates": "^1.10.3",
|
|
59
|
+
"graphile-postgis": "^2.23.3",
|
|
60
60
|
"graphile-presigned-url-plugin": "^0.22.1",
|
|
61
61
|
"graphile-realtime-subscriptions": "^0.10.0",
|
|
62
|
-
"graphile-search": "^1.21.
|
|
62
|
+
"graphile-search": "^1.21.3",
|
|
63
63
|
"graphile-upload-plugin": "^2.14.0",
|
|
64
64
|
"graphile-utils": "5.0.1",
|
|
65
65
|
"graphql": "16.13.0",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"@types/express": "^5.0.6",
|
|
78
78
|
"@types/pg": "^8.20.0",
|
|
79
79
|
"@types/request-ip": "^0.0.41",
|
|
80
|
-
"graphile-test": "^4.21.
|
|
80
|
+
"graphile-test": "^4.21.3",
|
|
81
81
|
"makage": "^0.3.0",
|
|
82
82
|
"nodemon": "^3.1.14",
|
|
83
83
|
"ts-node": "^10.9.2"
|
|
@@ -89,5 +89,5 @@
|
|
|
89
89
|
"constructive",
|
|
90
90
|
"graphql"
|
|
91
91
|
],
|
|
92
|
-
"gitHead": "
|
|
92
|
+
"gitHead": "b0843e23070cf4e28a119b06e4ebd1828be1ebde"
|
|
93
93
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildScalarEncoding = buildScalarEncoding;
|
|
4
|
+
/**
|
|
5
|
+
* Scalar encoding contracts — the one piece of field metadata standard GraphQL
|
|
6
|
+
* introspection can't provide.
|
|
7
|
+
*
|
|
8
|
+
* Introspection tells a client a field's scalar *name* (`GeoJSON`, `LTree`,
|
|
9
|
+
* `Interval`, `BigInt`, `vector`, …) but not how to serialize/parse it or its
|
|
10
|
+
* structural parameters (geometry subtype/SRID, vector dimensions, ltree
|
|
11
|
+
* dot-path semantics). Without that, generated clients treat these as opaque
|
|
12
|
+
* strings / `any` and mis-encode inputs or fail to parse outputs.
|
|
13
|
+
*
|
|
14
|
+
* `kind` is derived deterministically from the *underlying* codec (array and
|
|
15
|
+
* domain wrappers unwrapped first, first match wins) so exactly one kind is
|
|
16
|
+
* ever assigned and nothing can clobber it. Structural extras (subtype, SRID,
|
|
17
|
+
* dimensions) are read verbatim from attribute extensions — never guessed, and
|
|
18
|
+
* `null` when absent.
|
|
19
|
+
*/
|
|
20
|
+
/** pg type name → encoding kind. Plain scalars are intentionally absent → null. */
|
|
21
|
+
const KIND_BY_PG_TYPE = {
|
|
22
|
+
int8: 'bigint',
|
|
23
|
+
bigint: 'bigint',
|
|
24
|
+
numeric: 'bigint',
|
|
25
|
+
timestamptz: 'datetime',
|
|
26
|
+
timestamp: 'datetime',
|
|
27
|
+
date: 'date',
|
|
28
|
+
time: 'time',
|
|
29
|
+
timetz: 'time',
|
|
30
|
+
interval: 'interval',
|
|
31
|
+
uuid: 'uuid',
|
|
32
|
+
geometry: 'geojson',
|
|
33
|
+
geography: 'geojson',
|
|
34
|
+
point: 'point',
|
|
35
|
+
inet: 'inet',
|
|
36
|
+
cidr: 'inet',
|
|
37
|
+
ltree: 'ltree',
|
|
38
|
+
vector: 'vector',
|
|
39
|
+
bytea: 'bytea'
|
|
40
|
+
};
|
|
41
|
+
/** Unwrap array-of and domain-of wrappers to the underlying scalar/record codec. */
|
|
42
|
+
function underlyingCodec(codec) {
|
|
43
|
+
let current = codec ?? null;
|
|
44
|
+
const seen = new Set();
|
|
45
|
+
while (current && !seen.has(current) && (current.arrayOfCodec || current.domainOfCodec)) {
|
|
46
|
+
seen.add(current);
|
|
47
|
+
current = current.arrayOfCodec || current.domainOfCodec || null;
|
|
48
|
+
}
|
|
49
|
+
return current;
|
|
50
|
+
}
|
|
51
|
+
/** True when a codec is a composite/record type (has named attributes). */
|
|
52
|
+
function isCompositeCodec(codec) {
|
|
53
|
+
return !!codec?.attributes && Object.keys(codec.attributes).length > 0;
|
|
54
|
+
}
|
|
55
|
+
function buildScalarEncoding(attr) {
|
|
56
|
+
const codec = underlyingCodec(attr?.codec);
|
|
57
|
+
if (!codec)
|
|
58
|
+
return null;
|
|
59
|
+
const ext = attr?.extensions ?? undefined;
|
|
60
|
+
const kind = KIND_BY_PG_TYPE[codec.name];
|
|
61
|
+
if (!kind) {
|
|
62
|
+
// Composite/record types are the only non-mapped scalars worth describing;
|
|
63
|
+
// everything else (text, int, bool, json, enum, …) is fully covered by gqlType.
|
|
64
|
+
if (isCompositeCodec(codec)) {
|
|
65
|
+
return { kind: 'composite', fields: null };
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
switch (kind) {
|
|
70
|
+
case 'geojson':
|
|
71
|
+
return {
|
|
72
|
+
kind,
|
|
73
|
+
geometrySubtype: typeof ext?.geometrySubtype === 'string' ? ext.geometrySubtype : null,
|
|
74
|
+
srid: typeof ext?.geometrySrid === 'number' ? ext.geometrySrid : null
|
|
75
|
+
};
|
|
76
|
+
case 'vector':
|
|
77
|
+
return {
|
|
78
|
+
kind,
|
|
79
|
+
elementType: 'float',
|
|
80
|
+
dimensions: typeof ext?.vectorDimensions === 'number' ? ext.vectorDimensions : null
|
|
81
|
+
};
|
|
82
|
+
case 'ltree':
|
|
83
|
+
return { kind, dotPath: true };
|
|
84
|
+
default:
|
|
85
|
+
return { kind };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -9,6 +9,21 @@ function nnList(type) {
|
|
|
9
9
|
return nn(new graphql_1.GraphQLList(nn(type)));
|
|
10
10
|
}
|
|
11
11
|
function createMetaSchemaType() {
|
|
12
|
+
const MetaScalarEncodingType = new graphql_1.GraphQLObjectType({
|
|
13
|
+
name: 'MetaScalarEncoding',
|
|
14
|
+
description: 'How a client must serialize/parse a scalar — the one field-type detail standard GraphQL introspection cannot describe. Null for plain scalars whose wire format is obvious from gqlType.',
|
|
15
|
+
fields: () => ({
|
|
16
|
+
kind: {
|
|
17
|
+
type: nn(graphql_1.GraphQLString),
|
|
18
|
+
description: "Machine kind: bigint, datetime, date, time, interval, uuid, geojson, point, inet, ltree, vector, bytea, or composite."
|
|
19
|
+
},
|
|
20
|
+
elementType: { type: graphql_1.GraphQLString, description: "For 'vector': element scalar (e.g. 'float')." },
|
|
21
|
+
dimensions: { type: graphql_1.GraphQLInt, description: "For 'vector': declared length, else null." },
|
|
22
|
+
geometrySubtype: { type: graphql_1.GraphQLString, description: "For 'geojson': Point/LineString/Polygon/…, else null." },
|
|
23
|
+
srid: { type: graphql_1.GraphQLInt, description: "For 'geojson': spatial reference id, else null." },
|
|
24
|
+
dotPath: { type: graphql_1.GraphQLBoolean, description: "For 'ltree': values are dot-separated path strings." }
|
|
25
|
+
})
|
|
26
|
+
});
|
|
12
27
|
const MetaTypeType = new graphql_1.GraphQLObjectType({
|
|
13
28
|
name: 'MetaType',
|
|
14
29
|
description: 'Information about a PostgreSQL type',
|
|
@@ -18,7 +33,11 @@ function createMetaSchemaType() {
|
|
|
18
33
|
isArray: { type: nn(graphql_1.GraphQLBoolean) },
|
|
19
34
|
isNotNull: { type: graphql_1.GraphQLBoolean },
|
|
20
35
|
hasDefault: { type: graphql_1.GraphQLBoolean },
|
|
21
|
-
subtype: { type: graphql_1.GraphQLString }
|
|
36
|
+
subtype: { type: graphql_1.GraphQLString },
|
|
37
|
+
encoding: {
|
|
38
|
+
type: MetaScalarEncodingType,
|
|
39
|
+
description: 'Scalar serialization contract (null for plain scalars)'
|
|
40
|
+
}
|
|
22
41
|
})
|
|
23
42
|
});
|
|
24
43
|
const MetaEnumType = new graphql_1.GraphQLObjectType({
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.pgTypeToGqlType = pgTypeToGqlType;
|
|
4
4
|
exports.buildFieldMeta = buildFieldMeta;
|
|
5
|
+
const encoding_meta_builders_1 = require("./encoding-meta-builders");
|
|
5
6
|
const PG_TO_GQL_TYPE = {
|
|
6
7
|
text: 'String',
|
|
7
8
|
varchar: 'String',
|
|
@@ -91,6 +92,7 @@ function buildFieldMeta(name, attr, build, options) {
|
|
|
91
92
|
isNotNull,
|
|
92
93
|
hasDefault,
|
|
93
94
|
subtype,
|
|
95
|
+
encoding: (0, encoding_meta_builders_1.buildScalarEncoding)(attr),
|
|
94
96
|
},
|
|
95
97
|
isNotNull,
|
|
96
98
|
hasDefault,
|
|
@@ -101,6 +101,33 @@ export interface TypeMeta {
|
|
|
101
101
|
isNotNull?: boolean;
|
|
102
102
|
hasDefault?: boolean;
|
|
103
103
|
subtype?: string | null;
|
|
104
|
+
/**
|
|
105
|
+
* How the client must serialize/parse this scalar. `null` for plain scalars
|
|
106
|
+
* (String/Int/Float/Boolean/JSON/enum) whose wire format is obvious from
|
|
107
|
+
* `gqlType` — populated only for scalars introspection can't fully describe.
|
|
108
|
+
*/
|
|
109
|
+
encoding?: ScalarEncodingMeta | null;
|
|
110
|
+
}
|
|
111
|
+
/** The machine kind a scalar marshals as on the client. */
|
|
112
|
+
export type ScalarEncodingKind = 'bigint' | 'datetime' | 'date' | 'time' | 'interval' | 'uuid' | 'geojson' | 'point' | 'inet' | 'ltree' | 'vector' | 'bytea' | 'composite';
|
|
113
|
+
export interface ScalarEncodingMeta {
|
|
114
|
+
/** Deterministic kind derived from the underlying (unwrapped) codec. */
|
|
115
|
+
kind: ScalarEncodingKind;
|
|
116
|
+
/** For 'vector': element scalar (e.g. 'float'), else null. */
|
|
117
|
+
elementType?: string | null;
|
|
118
|
+
/** For 'vector': declared length from typmod, else null. */
|
|
119
|
+
dimensions?: number | null;
|
|
120
|
+
/** For 'geojson': geometry subtype (Point/LineString/Polygon/…), else null. */
|
|
121
|
+
geometrySubtype?: string | null;
|
|
122
|
+
/** For 'geojson': spatial reference id, else null. */
|
|
123
|
+
srid?: number | null;
|
|
124
|
+
/** For 'ltree': values are dot-separated path strings ('a.b.c'). */
|
|
125
|
+
dotPath?: boolean;
|
|
126
|
+
/** For 'composite': nested attribute encodings. */
|
|
127
|
+
fields?: {
|
|
128
|
+
name: string;
|
|
129
|
+
type: TypeMeta;
|
|
130
|
+
}[] | null;
|
|
104
131
|
}
|
|
105
132
|
export interface IndexMeta {
|
|
106
133
|
name: string;
|
|
@@ -198,6 +225,7 @@ export interface PgCodec {
|
|
|
198
225
|
name: string;
|
|
199
226
|
attributes?: Record<string, PgAttribute>;
|
|
200
227
|
arrayOfCodec?: PgCodec | null;
|
|
228
|
+
domainOfCodec?: PgCodec | null;
|
|
201
229
|
isAnonymous?: boolean;
|
|
202
230
|
extensions?: {
|
|
203
231
|
pg?: {
|
|
@@ -207,6 +235,8 @@ export interface PgCodec {
|
|
|
207
235
|
}
|
|
208
236
|
export interface PgAttributeExtensions extends Record<string, unknown> {
|
|
209
237
|
geometrySubtype?: string | null;
|
|
238
|
+
geometrySrid?: number | null;
|
|
239
|
+
vectorDimensions?: number | null;
|
|
210
240
|
}
|
|
211
241
|
export interface PgAttribute {
|
|
212
242
|
codec?: PgCodec | null;
|
package/plugins/meta-schema.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { GraphileConfig } from 'graphile-config';
|
|
8
8
|
import { cachedTablesMeta } from './meta-schema/cache';
|
|
9
|
+
import { buildScalarEncoding } from './meta-schema/encoding-meta-builders';
|
|
9
10
|
import { MetaSchemaPlugin } from './meta-schema/plugin';
|
|
10
11
|
import { buildFieldMeta, pgTypeToGqlType } from './meta-schema/type-mappings';
|
|
11
12
|
export { MetaSchemaPlugin };
|
|
@@ -16,4 +17,6 @@ export { pgTypeToGqlType as _pgTypeToGqlType };
|
|
|
16
17
|
export { buildFieldMeta as _buildFieldMeta };
|
|
17
18
|
/** @internal Exported for testing only */
|
|
18
19
|
export { cachedTablesMeta as _cachedTablesMeta };
|
|
20
|
+
/** @internal Exported for testing only */
|
|
21
|
+
export { buildScalarEncoding as _buildScalarEncoding };
|
|
19
22
|
export default MetaSchemaPlugin;
|
package/plugins/meta-schema.js
CHANGED
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
* constraints, indexes, and relations for code generation tooling.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports._cachedTablesMeta = exports._buildFieldMeta = exports._pgTypeToGqlType = exports.MetaSchemaPreset = exports.MetaSchemaPlugin = void 0;
|
|
9
|
+
exports._buildScalarEncoding = exports._cachedTablesMeta = exports._buildFieldMeta = exports._pgTypeToGqlType = exports.MetaSchemaPreset = exports.MetaSchemaPlugin = void 0;
|
|
10
10
|
const cache_1 = require("./meta-schema/cache");
|
|
11
11
|
Object.defineProperty(exports, "_cachedTablesMeta", { enumerable: true, get: function () { return cache_1.cachedTablesMeta; } });
|
|
12
|
+
const encoding_meta_builders_1 = require("./meta-schema/encoding-meta-builders");
|
|
13
|
+
Object.defineProperty(exports, "_buildScalarEncoding", { enumerable: true, get: function () { return encoding_meta_builders_1.buildScalarEncoding; } });
|
|
12
14
|
const plugin_1 = require("./meta-schema/plugin");
|
|
13
15
|
Object.defineProperty(exports, "MetaSchemaPlugin", { enumerable: true, get: function () { return plugin_1.MetaSchemaPlugin; } });
|
|
14
16
|
const type_mappings_1 = require("./meta-schema/type-mappings");
|