graphile-settings 5.15.1 → 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 +81 -50
- package/esm/plugins/meta-schema/scope-meta-builders.d.ts +15 -0
- package/esm/plugins/meta-schema/scope-meta-builders.js +40 -0
- package/esm/plugins/meta-schema/table-meta-builder.js +11 -8
- package/esm/plugins/meta-schema/type-mappings.js +2 -0
- package/esm/plugins/meta-schema/types.d.ts +45 -0
- package/esm/plugins/meta-schema.d.ts +3 -0
- package/esm/plugins/meta-schema.js +3 -0
- package/package.json +15 -15
- 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 +80 -49
- package/plugins/meta-schema/scope-meta-builders.d.ts +15 -0
- package/plugins/meta-schema/scope-meta-builders.js +43 -0
- package/plugins/meta-schema/table-meta-builder.js +7 -4
- package/plugins/meta-schema/type-mappings.js +2 -0
- package/plugins/meta-schema/types.d.ts +45 -0
- package/plugins/meta-schema.d.ts +3 -0
- package/plugins/meta-schema.js +3 -1
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,16 +31,16 @@
|
|
|
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.
|
|
36
|
-
"@constructive-io/s3-streamer": "^2.29.
|
|
34
|
+
"@constructive-io/graphql-env": "^3.16.3",
|
|
35
|
+
"@constructive-io/graphql-types": "^3.15.0",
|
|
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",
|
|
39
39
|
"@dataplan/json": "1.0.0",
|
|
40
40
|
"@dataplan/pg": "1.0.3",
|
|
41
41
|
"@graphile-contrib/pg-many-to-many": "2.0.0-rc.2",
|
|
42
42
|
"@pgpmjs/logger": "^2.14.0",
|
|
43
|
-
"@pgpmjs/types": "^2.35.
|
|
43
|
+
"@pgpmjs/types": "^2.35.1",
|
|
44
44
|
"@pgsql/quotes": "^17.1.0",
|
|
45
45
|
"cors": "^2.8.6",
|
|
46
46
|
"express": "^5.2.1",
|
|
@@ -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',
|
|
@@ -19,15 +34,19 @@ function createMetaSchemaType() {
|
|
|
19
34
|
isNotNull: { type: graphql_1.GraphQLBoolean },
|
|
20
35
|
hasDefault: { type: graphql_1.GraphQLBoolean },
|
|
21
36
|
subtype: { type: graphql_1.GraphQLString },
|
|
22
|
-
|
|
37
|
+
encoding: {
|
|
38
|
+
type: MetaScalarEncodingType,
|
|
39
|
+
description: 'Scalar serialization contract (null for plain scalars)'
|
|
40
|
+
}
|
|
41
|
+
})
|
|
23
42
|
});
|
|
24
43
|
const MetaEnumType = new graphql_1.GraphQLObjectType({
|
|
25
44
|
name: 'MetaEnum',
|
|
26
45
|
description: 'Information about a PostgreSQL enum type',
|
|
27
46
|
fields: () => ({
|
|
28
47
|
name: { type: nn(graphql_1.GraphQLString), description: 'The PostgreSQL enum type name' },
|
|
29
|
-
values: { type: nnList(graphql_1.GraphQLString), description: 'Allowed values for this enum' }
|
|
30
|
-
})
|
|
48
|
+
values: { type: nnList(graphql_1.GraphQLString), description: 'Allowed values for this enum' }
|
|
49
|
+
})
|
|
31
50
|
});
|
|
32
51
|
const MetaFieldType = new graphql_1.GraphQLObjectType({
|
|
33
52
|
name: 'MetaField',
|
|
@@ -40,8 +59,8 @@ function createMetaSchemaType() {
|
|
|
40
59
|
isPrimaryKey: { type: nn(graphql_1.GraphQLBoolean) },
|
|
41
60
|
isForeignKey: { type: nn(graphql_1.GraphQLBoolean) },
|
|
42
61
|
description: { type: graphql_1.GraphQLString },
|
|
43
|
-
enumValues: { type: MetaEnumType, description: 'Enum metadata if this field has an enum type' }
|
|
44
|
-
})
|
|
62
|
+
enumValues: { type: MetaEnumType, description: 'Enum metadata if this field has an enum type' }
|
|
63
|
+
})
|
|
45
64
|
});
|
|
46
65
|
const MetaIndexType = new graphql_1.GraphQLObjectType({
|
|
47
66
|
name: 'MetaIndex',
|
|
@@ -51,31 +70,31 @@ function createMetaSchemaType() {
|
|
|
51
70
|
isUnique: { type: nn(graphql_1.GraphQLBoolean) },
|
|
52
71
|
isPrimary: { type: nn(graphql_1.GraphQLBoolean) },
|
|
53
72
|
columns: { type: nnList(graphql_1.GraphQLString) },
|
|
54
|
-
fields: { type: new graphql_1.GraphQLList(nn(MetaFieldType)) }
|
|
55
|
-
})
|
|
73
|
+
fields: { type: new graphql_1.GraphQLList(nn(MetaFieldType)) }
|
|
74
|
+
})
|
|
56
75
|
});
|
|
57
76
|
const MetaPrimaryKeyConstraintType = new graphql_1.GraphQLObjectType({
|
|
58
77
|
name: 'MetaPrimaryKeyConstraint',
|
|
59
78
|
description: 'Information about a primary key constraint',
|
|
60
79
|
fields: () => ({
|
|
61
80
|
name: { type: nn(graphql_1.GraphQLString) },
|
|
62
|
-
fields: { type: nnList(MetaFieldType) }
|
|
63
|
-
})
|
|
81
|
+
fields: { type: nnList(MetaFieldType) }
|
|
82
|
+
})
|
|
64
83
|
});
|
|
65
84
|
const MetaUniqueConstraintType = new graphql_1.GraphQLObjectType({
|
|
66
85
|
name: 'MetaUniqueConstraint',
|
|
67
86
|
description: 'Information about a unique constraint',
|
|
68
87
|
fields: () => ({
|
|
69
88
|
name: { type: nn(graphql_1.GraphQLString) },
|
|
70
|
-
fields: { type: nnList(MetaFieldType) }
|
|
71
|
-
})
|
|
89
|
+
fields: { type: nnList(MetaFieldType) }
|
|
90
|
+
})
|
|
72
91
|
});
|
|
73
92
|
const MetaRefTableType = new graphql_1.GraphQLObjectType({
|
|
74
93
|
name: 'MetaRefTable',
|
|
75
94
|
description: 'Reference to a related table',
|
|
76
95
|
fields: () => ({
|
|
77
|
-
name: { type: nn(graphql_1.GraphQLString) }
|
|
78
|
-
})
|
|
96
|
+
name: { type: nn(graphql_1.GraphQLString) }
|
|
97
|
+
})
|
|
79
98
|
});
|
|
80
99
|
const MetaForeignKeyConstraintType = new graphql_1.GraphQLObjectType({
|
|
81
100
|
name: 'MetaForeignKeyConstraint',
|
|
@@ -86,8 +105,8 @@ function createMetaSchemaType() {
|
|
|
86
105
|
referencedTable: { type: nn(graphql_1.GraphQLString) },
|
|
87
106
|
referencedFields: { type: nnList(graphql_1.GraphQLString) },
|
|
88
107
|
refFields: { type: new graphql_1.GraphQLList(nn(MetaFieldType)) },
|
|
89
|
-
refTable: { type: MetaRefTableType }
|
|
90
|
-
})
|
|
108
|
+
refTable: { type: MetaRefTableType }
|
|
109
|
+
})
|
|
91
110
|
});
|
|
92
111
|
const MetaConstraintsType = new graphql_1.GraphQLObjectType({
|
|
93
112
|
name: 'MetaConstraints',
|
|
@@ -95,8 +114,8 @@ function createMetaSchemaType() {
|
|
|
95
114
|
fields: () => ({
|
|
96
115
|
primaryKey: { type: MetaPrimaryKeyConstraintType },
|
|
97
116
|
unique: { type: nnList(MetaUniqueConstraintType) },
|
|
98
|
-
foreignKey: { type: nnList(MetaForeignKeyConstraintType) }
|
|
99
|
-
})
|
|
117
|
+
foreignKey: { type: nnList(MetaForeignKeyConstraintType) }
|
|
118
|
+
})
|
|
100
119
|
});
|
|
101
120
|
const MetaInflectionType = new graphql_1.GraphQLObjectType({
|
|
102
121
|
name: 'MetaInflection',
|
|
@@ -113,8 +132,8 @@ function createMetaSchemaType() {
|
|
|
113
132
|
createInputType: { type: nn(graphql_1.GraphQLString) },
|
|
114
133
|
createPayloadType: { type: nn(graphql_1.GraphQLString) },
|
|
115
134
|
updatePayloadType: { type: graphql_1.GraphQLString },
|
|
116
|
-
deletePayloadType: { type: nn(graphql_1.GraphQLString) }
|
|
117
|
-
})
|
|
135
|
+
deletePayloadType: { type: nn(graphql_1.GraphQLString) }
|
|
136
|
+
})
|
|
118
137
|
});
|
|
119
138
|
const MetaQueryType = new graphql_1.GraphQLObjectType({
|
|
120
139
|
name: 'MetaQuery',
|
|
@@ -124,8 +143,8 @@ function createMetaSchemaType() {
|
|
|
124
143
|
one: { type: graphql_1.GraphQLString },
|
|
125
144
|
create: { type: graphql_1.GraphQLString },
|
|
126
145
|
update: { type: graphql_1.GraphQLString },
|
|
127
|
-
delete: { type: graphql_1.GraphQLString }
|
|
128
|
-
})
|
|
146
|
+
delete: { type: graphql_1.GraphQLString }
|
|
147
|
+
})
|
|
129
148
|
});
|
|
130
149
|
const MetaBelongsToRelationType = new graphql_1.GraphQLObjectType({
|
|
131
150
|
name: 'MetaBelongsToRelation',
|
|
@@ -135,8 +154,8 @@ function createMetaSchemaType() {
|
|
|
135
154
|
isUnique: { type: nn(graphql_1.GraphQLBoolean) },
|
|
136
155
|
type: { type: graphql_1.GraphQLString },
|
|
137
156
|
keys: { type: nnList(MetaFieldType) },
|
|
138
|
-
references: { type: nn(MetaRefTableType) }
|
|
139
|
-
})
|
|
157
|
+
references: { type: nn(MetaRefTableType) }
|
|
158
|
+
})
|
|
140
159
|
});
|
|
141
160
|
const MetaHasRelationType = new graphql_1.GraphQLObjectType({
|
|
142
161
|
name: 'MetaHasRelation',
|
|
@@ -146,8 +165,8 @@ function createMetaSchemaType() {
|
|
|
146
165
|
isUnique: { type: nn(graphql_1.GraphQLBoolean) },
|
|
147
166
|
type: { type: graphql_1.GraphQLString },
|
|
148
167
|
keys: { type: nnList(MetaFieldType) },
|
|
149
|
-
referencedBy: { type: nn(MetaRefTableType) }
|
|
150
|
-
})
|
|
168
|
+
referencedBy: { type: nn(MetaRefTableType) }
|
|
169
|
+
})
|
|
151
170
|
});
|
|
152
171
|
const MetaManyToManyRelationType = new graphql_1.GraphQLObjectType({
|
|
153
172
|
name: 'MetaManyToManyRelation',
|
|
@@ -162,8 +181,8 @@ function createMetaSchemaType() {
|
|
|
162
181
|
junctionRightKeyAttributes: { type: nnList(MetaFieldType) },
|
|
163
182
|
leftKeyAttributes: { type: nnList(MetaFieldType) },
|
|
164
183
|
rightKeyAttributes: { type: nnList(MetaFieldType) },
|
|
165
|
-
rightTable: { type: nn(MetaRefTableType) }
|
|
166
|
-
})
|
|
184
|
+
rightTable: { type: nn(MetaRefTableType) }
|
|
185
|
+
})
|
|
167
186
|
});
|
|
168
187
|
const MetaRelationsType = new graphql_1.GraphQLObjectType({
|
|
169
188
|
name: 'MetaRelations',
|
|
@@ -173,16 +192,16 @@ function createMetaSchemaType() {
|
|
|
173
192
|
has: { type: nnList(MetaHasRelationType) },
|
|
174
193
|
hasOne: { type: nnList(MetaHasRelationType) },
|
|
175
194
|
hasMany: { type: nnList(MetaHasRelationType) },
|
|
176
|
-
manyToMany: { type: nnList(MetaManyToManyRelationType) }
|
|
177
|
-
})
|
|
195
|
+
manyToMany: { type: nnList(MetaManyToManyRelationType) }
|
|
196
|
+
})
|
|
178
197
|
});
|
|
179
198
|
const MetaStorageType = new graphql_1.GraphQLObjectType({
|
|
180
199
|
name: 'MetaStorage',
|
|
181
200
|
description: 'Storage metadata for a table',
|
|
182
201
|
fields: () => ({
|
|
183
202
|
isFilesTable: { type: nn(graphql_1.GraphQLBoolean), description: 'Whether this table is a storage files table' },
|
|
184
|
-
isBucketsTable: { type: nn(graphql_1.GraphQLBoolean), description: 'Whether this table is a storage buckets table' }
|
|
185
|
-
})
|
|
203
|
+
isBucketsTable: { type: nn(graphql_1.GraphQLBoolean), description: 'Whether this table is a storage buckets table' }
|
|
204
|
+
})
|
|
186
205
|
});
|
|
187
206
|
const MetaSearchConfigType = new graphql_1.GraphQLObjectType({
|
|
188
207
|
name: 'MetaSearchConfig',
|
|
@@ -193,20 +212,20 @@ function createMetaSchemaType() {
|
|
|
193
212
|
description: 'JSON-encoded per-adapter score weights',
|
|
194
213
|
resolve(source) {
|
|
195
214
|
return source.weights ? JSON.stringify(source.weights) : null;
|
|
196
|
-
}
|
|
215
|
+
}
|
|
197
216
|
},
|
|
198
217
|
boostRecent: { type: nn(graphql_1.GraphQLBoolean), description: 'Whether recency boosting is enabled' },
|
|
199
218
|
boostRecencyField: { type: graphql_1.GraphQLString, description: 'Field used for recency decay' },
|
|
200
|
-
boostRecencyDecay: { type: graphql_1.GraphQLFloat, description: 'Exponential decay factor per day' }
|
|
201
|
-
})
|
|
219
|
+
boostRecencyDecay: { type: graphql_1.GraphQLFloat, description: 'Exponential decay factor per day' }
|
|
220
|
+
})
|
|
202
221
|
});
|
|
203
222
|
const MetaSearchColumnType = new graphql_1.GraphQLObjectType({
|
|
204
223
|
name: 'MetaSearchColumn',
|
|
205
224
|
description: 'A searchable column with its algorithm',
|
|
206
225
|
fields: () => ({
|
|
207
226
|
name: { type: nn(graphql_1.GraphQLString), description: 'Column name (camelCase)' },
|
|
208
|
-
algorithm: { type: nn(graphql_1.GraphQLString), description: 'Search algorithm: tsvector, bm25, trgm, or vector' }
|
|
209
|
-
})
|
|
227
|
+
algorithm: { type: nn(graphql_1.GraphQLString), description: 'Search algorithm: tsvector, bm25, trgm, or vector' }
|
|
228
|
+
})
|
|
210
229
|
});
|
|
211
230
|
const MetaSearchType = new graphql_1.GraphQLObjectType({
|
|
212
231
|
name: 'MetaSearch',
|
|
@@ -215,31 +234,42 @@ function createMetaSchemaType() {
|
|
|
215
234
|
algorithms: { type: nnList(graphql_1.GraphQLString), description: 'Active search algorithms on this table' },
|
|
216
235
|
columns: { type: nnList(MetaSearchColumnType), description: 'Searchable columns with their algorithm' },
|
|
217
236
|
hasUnifiedSearch: { type: nn(graphql_1.GraphQLBoolean), description: 'Whether unifiedSearch composite filter is available' },
|
|
218
|
-
config: { type: MetaSearchConfigType, description: 'Per-table search configuration' }
|
|
219
|
-
})
|
|
237
|
+
config: { type: MetaSearchConfigType, description: 'Per-table search configuration' }
|
|
238
|
+
})
|
|
220
239
|
});
|
|
221
240
|
const MetaI18nFieldType = new graphql_1.GraphQLObjectType({
|
|
222
241
|
name: 'MetaI18nField',
|
|
223
242
|
description: 'A translatable field',
|
|
224
243
|
fields: () => ({
|
|
225
244
|
name: { type: nn(graphql_1.GraphQLString), description: 'GraphQL field name' },
|
|
226
|
-
type: { type: nn(graphql_1.GraphQLString), description: 'PostgreSQL column type (text, citext)' }
|
|
227
|
-
})
|
|
245
|
+
type: { type: nn(graphql_1.GraphQLString), description: 'PostgreSQL column type (text, citext)' }
|
|
246
|
+
})
|
|
228
247
|
});
|
|
229
248
|
const MetaI18nType = new graphql_1.GraphQLObjectType({
|
|
230
249
|
name: 'MetaI18n',
|
|
231
250
|
description: 'i18n metadata for a table with @i18n tag',
|
|
232
251
|
fields: () => ({
|
|
233
252
|
translationTable: { type: nn(graphql_1.GraphQLString), description: 'Name of the translation table' },
|
|
234
|
-
translatableFields: { type: nnList(MetaI18nFieldType), description: 'Fields that are translatable' }
|
|
235
|
-
})
|
|
253
|
+
translatableFields: { type: nnList(MetaI18nFieldType), description: 'Fields that are translatable' }
|
|
254
|
+
})
|
|
236
255
|
});
|
|
237
256
|
const MetaRealtimeType = new graphql_1.GraphQLObjectType({
|
|
238
257
|
name: 'MetaRealtime',
|
|
239
258
|
description: 'Realtime metadata for a table with @realtime tag',
|
|
240
259
|
fields: () => ({
|
|
241
|
-
subscriptionFieldName: { type: nn(graphql_1.GraphQLString), description: 'The generated subscription field name (e.g. onPostChanged)' }
|
|
242
|
-
})
|
|
260
|
+
subscriptionFieldName: { type: nn(graphql_1.GraphQLString), description: 'The generated subscription field name (e.g. onPostChanged)' }
|
|
261
|
+
})
|
|
262
|
+
});
|
|
263
|
+
const MetaScopeType = new graphql_1.GraphQLObjectType({
|
|
264
|
+
name: 'MetaScope',
|
|
265
|
+
description: 'Provisioning scope metadata for a table',
|
|
266
|
+
fields: () => ({
|
|
267
|
+
scope: { type: nn(graphql_1.GraphQLString), description: "Provisioning scope: 'platform', 'app', 'database', or an entity scope (e.g. 'org')" },
|
|
268
|
+
tier: { type: nn(graphql_1.GraphQLString), description: "Coarse bucket: 'global', 'database', or 'entity'" },
|
|
269
|
+
keyColumn: { type: graphql_1.GraphQLString, description: 'Inflected scope key column (e.g. databaseId, orgId), null for global tiers' },
|
|
270
|
+
entityTable: { type: graphql_1.GraphQLString, description: 'SQL name of the entity table for entity scopes, else null' },
|
|
271
|
+
source: { type: nn(graphql_1.GraphQLString), description: "Provenance of the scope metadata (always 'smartTag')" }
|
|
272
|
+
})
|
|
243
273
|
});
|
|
244
274
|
const MetaTableType = new graphql_1.GraphQLObjectType({
|
|
245
275
|
name: 'MetaTable',
|
|
@@ -260,14 +290,15 @@ function createMetaSchemaType() {
|
|
|
260
290
|
search: { type: MetaSearchType, description: 'Search metadata (null if no search configured)' },
|
|
261
291
|
i18n: { type: MetaI18nType, description: 'i18n metadata (null if no @i18n tag)' },
|
|
262
292
|
realtime: { type: MetaRealtimeType, description: 'Realtime metadata (null if no @realtime tag)' },
|
|
263
|
-
|
|
293
|
+
scope: { type: MetaScopeType, description: 'Provisioning scope metadata (null if no @scope tag)' }
|
|
294
|
+
})
|
|
264
295
|
});
|
|
265
296
|
return new graphql_1.GraphQLObjectType({
|
|
266
297
|
name: 'MetaSchema',
|
|
267
298
|
description: 'Root meta schema type',
|
|
268
299
|
fields: () => ({
|
|
269
|
-
tables: { type: nnList(MetaTableType) }
|
|
270
|
-
})
|
|
300
|
+
tables: { type: nnList(MetaTableType) }
|
|
301
|
+
})
|
|
271
302
|
});
|
|
272
303
|
}
|
|
273
304
|
function extendQueryWithMetaField(fields, tablesMeta) {
|
|
@@ -277,10 +308,10 @@ function extendQueryWithMetaField(fields, tablesMeta) {
|
|
|
277
308
|
description: 'Metadata about the database schema, including tables, fields, indexes, and constraints. Useful for code generation tools.',
|
|
278
309
|
resolve() {
|
|
279
310
|
return { tables: tablesMeta };
|
|
280
|
-
}
|
|
311
|
+
}
|
|
281
312
|
};
|
|
282
313
|
return {
|
|
283
314
|
...fields,
|
|
284
|
-
_meta: metaField
|
|
315
|
+
_meta: metaField
|
|
285
316
|
};
|
|
286
317
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PgCodec, ScopeMeta } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Detect provisioning scope metadata for a table.
|
|
4
|
+
*
|
|
5
|
+
* The `@scope` smart tag emitted by the constructive-db generators is the sole
|
|
6
|
+
* source of truth. `apply_scope_fields` knows the exact scope, tier, key column,
|
|
7
|
+
* and entity table, and emits them via
|
|
8
|
+
* `metaschema.append_table_smart_tags(id, { scope, scopeTier, scopeKey, scopeEntityTable })`.
|
|
9
|
+
* PostGraphile surfaces these as `codec.extensions.tags.*`.
|
|
10
|
+
*
|
|
11
|
+
* There is NO inference from column names — a table without the tag returns
|
|
12
|
+
* `null` (the same convention as every other nullable metadata block). This
|
|
13
|
+
* avoids guessing key columns, whose names are chosen freely by each generator.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildScopeMeta(codec: PgCodec, inflectAttr: (attrName: string, codec: PgCodec) => string): ScopeMeta | null;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildScopeMeta = buildScopeMeta;
|
|
4
|
+
const VALID_TIERS = new Set(['global', 'database', 'entity']);
|
|
5
|
+
function readString(value) {
|
|
6
|
+
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Detect provisioning scope metadata for a table.
|
|
10
|
+
*
|
|
11
|
+
* The `@scope` smart tag emitted by the constructive-db generators is the sole
|
|
12
|
+
* source of truth. `apply_scope_fields` knows the exact scope, tier, key column,
|
|
13
|
+
* and entity table, and emits them via
|
|
14
|
+
* `metaschema.append_table_smart_tags(id, { scope, scopeTier, scopeKey, scopeEntityTable })`.
|
|
15
|
+
* PostGraphile surfaces these as `codec.extensions.tags.*`.
|
|
16
|
+
*
|
|
17
|
+
* There is NO inference from column names — a table without the tag returns
|
|
18
|
+
* `null` (the same convention as every other nullable metadata block). This
|
|
19
|
+
* avoids guessing key columns, whose names are chosen freely by each generator.
|
|
20
|
+
*/
|
|
21
|
+
function buildScopeMeta(codec, inflectAttr) {
|
|
22
|
+
const tags = codec.extensions?.tags;
|
|
23
|
+
const scope = readString(tags?.scope);
|
|
24
|
+
if (!scope)
|
|
25
|
+
return null;
|
|
26
|
+
const rawTier = readString(tags.scopeTier);
|
|
27
|
+
const tier = rawTier && VALID_TIERS.has(rawTier)
|
|
28
|
+
? rawTier
|
|
29
|
+
: null;
|
|
30
|
+
if (!tier) {
|
|
31
|
+
throw new Error(`@scope tag on codec "${codec.name}" is missing a valid scopeTier ` +
|
|
32
|
+
`(expected one of global|database|entity, got ${JSON.stringify(rawTier)})`);
|
|
33
|
+
}
|
|
34
|
+
const keyColumn = readString(tags.scopeKey);
|
|
35
|
+
const entityTable = readString(tags.scopeEntityTable);
|
|
36
|
+
return {
|
|
37
|
+
scope,
|
|
38
|
+
tier,
|
|
39
|
+
keyColumn: keyColumn ? inflectAttr(keyColumn, codec) : null,
|
|
40
|
+
entityTable,
|
|
41
|
+
source: 'smartTag'
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -4,10 +4,11 @@ exports.collectTablesMeta = collectTablesMeta;
|
|
|
4
4
|
const constraint_meta_builders_1 = require("./constraint-meta-builders");
|
|
5
5
|
const name_meta_builders_1 = require("./name-meta-builders");
|
|
6
6
|
const relation_meta_builders_1 = require("./relation-meta-builders");
|
|
7
|
+
const scope_meta_builders_1 = require("./scope-meta-builders");
|
|
7
8
|
const storage_search_meta_builders_1 = require("./storage-search-meta-builders");
|
|
8
|
-
const type_mappings_1 = require("./type-mappings");
|
|
9
9
|
const table_meta_context_1 = require("./table-meta-context");
|
|
10
10
|
const table_resource_utils_1 = require("./table-resource-utils");
|
|
11
|
+
const type_mappings_1 = require("./type-mappings");
|
|
11
12
|
function buildTableMeta(resource, schemaName, context) {
|
|
12
13
|
const codec = resource.codec;
|
|
13
14
|
const attributes = codec.attributes;
|
|
@@ -30,7 +31,7 @@ function buildTableMeta(resource, schemaName, context) {
|
|
|
30
31
|
}
|
|
31
32
|
const fields = Object.entries(attributes).map(([attrName, attr]) => (0, type_mappings_1.buildFieldMeta)(context.inflectAttr(attrName, codec), attr, context.build, {
|
|
32
33
|
isPrimaryKey: pkAttrNames.has(attrName),
|
|
33
|
-
isForeignKey: fkAttrNames.has(attrName)
|
|
34
|
+
isForeignKey: fkAttrNames.has(attrName)
|
|
34
35
|
}));
|
|
35
36
|
const indexes = (0, constraint_meta_builders_1.buildIndexes)(codec, attributes, uniques, context);
|
|
36
37
|
const primaryKey = (0, constraint_meta_builders_1.buildPrimaryKey)(codec, attributes, uniques, context);
|
|
@@ -39,7 +40,7 @@ function buildTableMeta(resource, schemaName, context) {
|
|
|
39
40
|
const constraints = {
|
|
40
41
|
primaryKey,
|
|
41
42
|
unique: uniqueConstraints,
|
|
42
|
-
foreignKey: foreignKeyConstraints
|
|
43
|
+
foreignKey: foreignKeyConstraints
|
|
43
44
|
};
|
|
44
45
|
const belongsTo = (0, relation_meta_builders_1.buildBelongsToRelations)(codec, attributes, uniques, relations, context);
|
|
45
46
|
const { hasOne, hasMany } = (0, relation_meta_builders_1.buildReverseRelations)(codec, attributes, relations, context);
|
|
@@ -49,13 +50,14 @@ function buildTableMeta(resource, schemaName, context) {
|
|
|
49
50
|
has: [...hasOne, ...hasMany],
|
|
50
51
|
hasOne,
|
|
51
52
|
hasMany,
|
|
52
|
-
manyToMany
|
|
53
|
+
manyToMany
|
|
53
54
|
};
|
|
54
55
|
const tableType = (0, name_meta_builders_1.resolveTableType)(context.build, codec);
|
|
55
56
|
const storage = (0, storage_search_meta_builders_1.buildStorageMeta)(codec);
|
|
56
57
|
const search = (0, storage_search_meta_builders_1.buildSearchMeta)(codec, context.build, context.inflectAttr);
|
|
57
58
|
const i18n = (0, storage_search_meta_builders_1.buildI18nMeta)(codec, context.build, context.inflectAttr);
|
|
58
59
|
const realtime = (0, storage_search_meta_builders_1.buildRealtimeMeta)(codec, context.build);
|
|
60
|
+
const scope = (0, scope_meta_builders_1.buildScopeMeta)(codec, context.inflectAttr);
|
|
59
61
|
return {
|
|
60
62
|
name: tableType,
|
|
61
63
|
schemaName,
|
|
@@ -72,6 +74,7 @@ function buildTableMeta(resource, schemaName, context) {
|
|
|
72
74
|
search,
|
|
73
75
|
i18n,
|
|
74
76
|
realtime,
|
|
77
|
+
scope
|
|
75
78
|
};
|
|
76
79
|
}
|
|
77
80
|
function collectTablesMeta(build) {
|
|
@@ -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,
|
|
@@ -14,6 +14,21 @@ export interface TableMeta {
|
|
|
14
14
|
search: SearchMeta | null;
|
|
15
15
|
i18n: I18nMeta | null;
|
|
16
16
|
realtime: RealtimeMeta | null;
|
|
17
|
+
scope: ScopeMeta | null;
|
|
18
|
+
}
|
|
19
|
+
/** Coarse provisioning tier a table's scope belongs to. */
|
|
20
|
+
export type ScopeTier = 'global' | 'database' | 'entity';
|
|
21
|
+
export interface ScopeMeta {
|
|
22
|
+
/** The provisioning scope, e.g. 'platform', 'app', 'database', 'org', 'user' */
|
|
23
|
+
scope: string;
|
|
24
|
+
/** Coarse bucket: global (platform/app), database, or entity */
|
|
25
|
+
tier: ScopeTier;
|
|
26
|
+
/** Inflected scope key column (e.g. 'databaseId', 'orgId'), or null for global tiers */
|
|
27
|
+
keyColumn: string | null;
|
|
28
|
+
/** SQL name of the entity table for entity scopes, else null */
|
|
29
|
+
entityTable: string | null;
|
|
30
|
+
/** Provenance of the scope metadata. Always the @scope smart tag. */
|
|
31
|
+
source: 'smartTag';
|
|
17
32
|
}
|
|
18
33
|
export interface StorageMeta {
|
|
19
34
|
/** Whether this table is tagged as a storage files table */
|
|
@@ -86,6 +101,33 @@ export interface TypeMeta {
|
|
|
86
101
|
isNotNull?: boolean;
|
|
87
102
|
hasDefault?: boolean;
|
|
88
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;
|
|
89
131
|
}
|
|
90
132
|
export interface IndexMeta {
|
|
91
133
|
name: string;
|
|
@@ -183,6 +225,7 @@ export interface PgCodec {
|
|
|
183
225
|
name: string;
|
|
184
226
|
attributes?: Record<string, PgAttribute>;
|
|
185
227
|
arrayOfCodec?: PgCodec | null;
|
|
228
|
+
domainOfCodec?: PgCodec | null;
|
|
186
229
|
isAnonymous?: boolean;
|
|
187
230
|
extensions?: {
|
|
188
231
|
pg?: {
|
|
@@ -192,6 +235,8 @@ export interface PgCodec {
|
|
|
192
235
|
}
|
|
193
236
|
export interface PgAttributeExtensions extends Record<string, unknown> {
|
|
194
237
|
geometrySubtype?: string | null;
|
|
238
|
+
geometrySrid?: number | null;
|
|
239
|
+
vectorDimensions?: number | null;
|
|
195
240
|
}
|
|
196
241
|
export interface PgAttribute {
|
|
197
242
|
codec?: PgCodec | null;
|