@supabase/postgrest-typegen 0.4.0 → 0.6.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/README.md +154 -21
- package/dist/generation/index.d.ts +0 -1
- package/dist/generation/index.js +0 -1
- package/dist/generation/typescript.d.ts +2 -1
- package/dist/generation/typescript.js +72 -288
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/introspection/index.js +8 -3
- package/dist/introspection/node-tree.d.ts +18 -0
- package/dist/introspection/node-tree.js +100 -0
- package/dist/introspection/sql/view_definitions.sql.d.ts +8 -0
- package/dist/introspection/sql/view_definitions.sql.js +43 -0
- package/dist/introspection/view-nullability.d.ts +14 -0
- package/dist/introspection/view-nullability.js +167 -0
- package/dist/rpc.d.ts +2 -0
- package/dist/rpc.js +232 -0
- package/dist/sort.js +23 -0
- package/dist/types.d.ts +151 -0
- package/dist/types.js +92 -0
- package/package.json +5 -4
- package/src/generation/index.ts +0 -5
- package/src/generation/typescript.ts +102 -383
- package/src/index.ts +1 -0
- package/src/introspection/index.ts +8 -2
- package/src/introspection/node-tree.ts +129 -0
- package/src/introspection/sql/view_definitions.sql.ts +45 -0
- package/src/introspection/view-nullability.ts +243 -0
- package/src/rpc.ts +307 -0
- package/src/sort.ts +31 -0
- package/src/types.ts +102 -0
- package/dist/generation/constants.d.ts +0 -9
- package/dist/generation/constants.js +0 -10
- package/dist/generation/swift.d.ts +0 -11
- package/dist/generation/swift.js +0 -358
- package/src/generation/constants.ts +0 -11
- package/src/generation/swift.ts +0 -531
package/src/rpc.ts
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the PostgREST view of `GeneratorMetadata.functions`.
|
|
3
|
+
*
|
|
4
|
+
* The raw `functions` collection is `pg_proc` as introspected. Which of those
|
|
5
|
+
* functions PostgREST exposes under `/rpc`, how their overloads group, what a
|
|
6
|
+
* call returns and whether a function doubles as a computed field or an
|
|
7
|
+
* embeddable relation are PostgREST rules, not language rules. This pass
|
|
8
|
+
* applies them once so every generator, in this package or in another SDK
|
|
9
|
+
* repo reading the serialized document, emits the same RPC surface.
|
|
10
|
+
*
|
|
11
|
+
* Pure and deterministic: the output is canonically ordered regardless of the
|
|
12
|
+
* order of the input collections. `introspect()` attaches the result as
|
|
13
|
+
* `rpcFunctions`; generators that meet a document without it (produced by a
|
|
14
|
+
* version predating the collection, or by a custom producer) run this pass
|
|
15
|
+
* themselves.
|
|
16
|
+
*/
|
|
17
|
+
import { compareStrings } from "./collation.ts";
|
|
18
|
+
import type {
|
|
19
|
+
GeneratorMetadata,
|
|
20
|
+
PostgresFunction,
|
|
21
|
+
PostgresType,
|
|
22
|
+
RpcFunction,
|
|
23
|
+
RpcFunctionArg,
|
|
24
|
+
RpcFunctionOverload,
|
|
25
|
+
RpcTypeReference,
|
|
26
|
+
} from "./types.ts";
|
|
27
|
+
|
|
28
|
+
/** json, jsonb and text: the types PostgREST accepts for a single unnamed parameter. */
|
|
29
|
+
const UNNAMED_ARG_TYPE_IDS = new Set([114, 3802, 25]);
|
|
30
|
+
const INPUT_ARG_MODES = new Set(["in", "inout", "variadic"]);
|
|
31
|
+
|
|
32
|
+
type InputArg = PostgresFunction["args"][number] & {
|
|
33
|
+
mode: RpcFunctionArg["mode"];
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
type Candidate = { fn: PostgresFunction; inArgs: InputArg[] };
|
|
37
|
+
|
|
38
|
+
/** A NUL separator cannot occur in an identifier, so names with dots never collide. */
|
|
39
|
+
const qualifiedKey = (schema: string, name: string) => `${schema}\0${name}`;
|
|
40
|
+
|
|
41
|
+
export function resolveRpcFunctions(
|
|
42
|
+
metadata: GeneratorMetadata,
|
|
43
|
+
): RpcFunction[] {
|
|
44
|
+
const schemaNames = new Set(metadata.schemas.map(({ name }) => name));
|
|
45
|
+
const typesById = new Map(metadata.types.map((type) => [type.id, type]));
|
|
46
|
+
const relationTypesById = new Map(
|
|
47
|
+
metadata.types
|
|
48
|
+
.filter(
|
|
49
|
+
(type): type is PostgresType & { type_relation_id: number } =>
|
|
50
|
+
type.type_relation_id !== null,
|
|
51
|
+
)
|
|
52
|
+
.map((type) => [type.id, type]),
|
|
53
|
+
);
|
|
54
|
+
const relations = [
|
|
55
|
+
...metadata.tables,
|
|
56
|
+
...metadata.foreignTables,
|
|
57
|
+
...metadata.views,
|
|
58
|
+
...metadata.materializedViews,
|
|
59
|
+
];
|
|
60
|
+
const relationsById = new Map(
|
|
61
|
+
relations.map((relation) => [relation.id, relation]),
|
|
62
|
+
);
|
|
63
|
+
const relationsBySchemaName = new Map(
|
|
64
|
+
relations.map((relation) => [
|
|
65
|
+
qualifiedKey(relation.schema, relation.name),
|
|
66
|
+
relation,
|
|
67
|
+
]),
|
|
68
|
+
);
|
|
69
|
+
const columnNamesByRelationId = new Map<number, Set<string>>();
|
|
70
|
+
for (const column of metadata.columns) {
|
|
71
|
+
let names = columnNamesByRelationId.get(column.table_id);
|
|
72
|
+
if (!names) {
|
|
73
|
+
names = new Set();
|
|
74
|
+
columnNamesByRelationId.set(column.table_id, names);
|
|
75
|
+
}
|
|
76
|
+
names.add(column.name);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const typeReference = (typeId: number): RpcTypeReference => {
|
|
80
|
+
const type = typesById.get(typeId);
|
|
81
|
+
return {
|
|
82
|
+
type_id: typeId,
|
|
83
|
+
format: type?.name ?? null,
|
|
84
|
+
type_schema: type?.schema ?? null,
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
const typeName = (typeId: number) => typesById.get(typeId)?.name ?? "unknown";
|
|
88
|
+
|
|
89
|
+
// The relation a return type stands for, or a composite type's name when the
|
|
90
|
+
// return type is one, since both are relations in `pg_class`. Resolved
|
|
91
|
+
// against every schema: a function may return rows of another schema.
|
|
92
|
+
const returnRelationName = (fn: PostgresFunction): string | null => {
|
|
93
|
+
if (fn.return_type_relation_id === null) return null;
|
|
94
|
+
return (
|
|
95
|
+
relationsById.get(fn.return_type_relation_id)?.name ??
|
|
96
|
+
relationTypesById.get(fn.return_type_id)?.name ??
|
|
97
|
+
null
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// The function is a computed field of the relation whose row type its sole
|
|
102
|
+
// input parameter has, provided the relation lives in the function's schema
|
|
103
|
+
// and has no column of the function's name: PostgREST resolves the name to
|
|
104
|
+
// the column, so such a function is neither selectable nor part of `Row`.
|
|
105
|
+
// When the parameter's type is not in `types` (a reduced custom document),
|
|
106
|
+
// the rendered argument list may still name the relation.
|
|
107
|
+
const computedFieldOf = ({ fn, inArgs }: Candidate): number | null => {
|
|
108
|
+
const soleInArg = inArgs.length === 1 ? inArgs[0] : undefined;
|
|
109
|
+
if (!soleInArg) return null;
|
|
110
|
+
const argType = relationTypesById.get(soleInArg.type_id);
|
|
111
|
+
const relation = argType
|
|
112
|
+
? relationsById.get(argType.type_relation_id)
|
|
113
|
+
: typesById.has(soleInArg.type_id)
|
|
114
|
+
? undefined
|
|
115
|
+
: relationsBySchemaName.get(qualifiedKey(fn.schema, fn.argument_types));
|
|
116
|
+
if (!relation || relation.schema !== fn.schema) return null;
|
|
117
|
+
if (columnNamesByRelationId.get(relation.id)?.has(fn.name)) return null;
|
|
118
|
+
return relation.id;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const isCallable = ({ inArgs }: Candidate): boolean => {
|
|
122
|
+
if (inArgs.length === 0) return true;
|
|
123
|
+
if (!inArgs.some(({ name }) => name === "")) return true;
|
|
124
|
+
if (
|
|
125
|
+
inArgs.every(
|
|
126
|
+
(arg) =>
|
|
127
|
+
arg.name !== "" ||
|
|
128
|
+
(arg.has_default === true && UNNAMED_ARG_TYPE_IDS.has(arg.type_id)),
|
|
129
|
+
)
|
|
130
|
+
) {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
const soleInArg = inArgs.length === 1 ? inArgs[0] : undefined;
|
|
134
|
+
return (
|
|
135
|
+
soleInArg !== undefined &&
|
|
136
|
+
soleInArg.name === "" &&
|
|
137
|
+
(UNNAMED_ARG_TYPE_IDS.has(soleInArg.type_id) ||
|
|
138
|
+
relationTypesById.has(soleInArg.type_id))
|
|
139
|
+
);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const overloadError = (
|
|
143
|
+
candidate: Candidate,
|
|
144
|
+
group: Candidate[],
|
|
145
|
+
): string | null => {
|
|
146
|
+
const { fn, inArgs } = candidate;
|
|
147
|
+
const soleInArg = inArgs.length === 1 ? inArgs[0] : undefined;
|
|
148
|
+
if (group.length > 1) {
|
|
149
|
+
// A no-argument overload next to one whose sole unnamed parameter has a
|
|
150
|
+
// default: PostgREST cannot pick one for an empty call.
|
|
151
|
+
if (inArgs.length === 0) {
|
|
152
|
+
const conflicting = group.find(
|
|
153
|
+
(other) =>
|
|
154
|
+
other !== candidate &&
|
|
155
|
+
other.inArgs.length === 1 &&
|
|
156
|
+
other.inArgs[0]?.name === "" &&
|
|
157
|
+
other.inArgs[0].has_default === true,
|
|
158
|
+
);
|
|
159
|
+
if (conflicting) {
|
|
160
|
+
return `Could not choose the best candidate function between: ${fn.schema}.${fn.name}(), ${fn.schema}.${fn.name}( => ${typeName(conflicting.fn.return_type_id)}). Try renaming the parameters or the function itself in the database so function overloading can be resolved`;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// Overloads whose sole parameter shares a name but not a type: a call
|
|
164
|
+
// carries no type information, so PostgREST cannot pick one.
|
|
165
|
+
if (soleInArg && soleInArg.name !== "") {
|
|
166
|
+
const conflicting = group.filter(
|
|
167
|
+
(other) =>
|
|
168
|
+
other !== candidate &&
|
|
169
|
+
other.inArgs.length === 1 &&
|
|
170
|
+
other.inArgs[0]?.name === soleInArg.name &&
|
|
171
|
+
other.inArgs[0].type_id !== soleInArg.type_id,
|
|
172
|
+
);
|
|
173
|
+
if (conflicting.length > 0) {
|
|
174
|
+
const conflictList = [candidate, ...conflicting]
|
|
175
|
+
.sort(
|
|
176
|
+
(a, b) =>
|
|
177
|
+
(a.inArgs[0]?.type_id || 0) - (b.inArgs[0]?.type_id || 0),
|
|
178
|
+
)
|
|
179
|
+
.map(
|
|
180
|
+
(other) =>
|
|
181
|
+
`${fn.schema}.${fn.name}(${other.inArgs
|
|
182
|
+
.map((arg) => `${arg.name} => ${typeName(arg.type_id)}`)
|
|
183
|
+
.join(", ")})`,
|
|
184
|
+
)
|
|
185
|
+
.join(", ");
|
|
186
|
+
return `Could not choose the best candidate function between: ${conflictList}. Try renaming the parameters or the function itself in the database so function overloading can be resolved`;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// PostgREST passes a sole unnamed parameter only when it is json, jsonb or
|
|
191
|
+
// text, so a function taking a row this way is a computed field or a
|
|
192
|
+
// computed relationship, reachable by embedding it from its relation and
|
|
193
|
+
// never through `/rpc`, whatever it returns.
|
|
194
|
+
if (
|
|
195
|
+
soleInArg &&
|
|
196
|
+
soleInArg.name === "" &&
|
|
197
|
+
relationTypesById.has(soleInArg.type_id)
|
|
198
|
+
) {
|
|
199
|
+
return `the function ${fn.schema}.${fn.name} with parameter or with a single unnamed json/jsonb parameter, but no matches were found in the schema cache`;
|
|
200
|
+
}
|
|
201
|
+
return null;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const resolveOverload = (
|
|
205
|
+
candidate: Candidate,
|
|
206
|
+
group: Candidate[],
|
|
207
|
+
): RpcFunctionOverload => {
|
|
208
|
+
const { fn, inArgs } = candidate;
|
|
209
|
+
const args: RpcFunctionArg[] = inArgs
|
|
210
|
+
.map((arg) => {
|
|
211
|
+
const relationId = relationTypesById.get(arg.type_id)?.type_relation_id;
|
|
212
|
+
return {
|
|
213
|
+
name: arg.name,
|
|
214
|
+
mode: arg.mode,
|
|
215
|
+
...typeReference(arg.type_id),
|
|
216
|
+
has_default: arg.has_default === true,
|
|
217
|
+
relation_id:
|
|
218
|
+
relationId !== undefined && relationsById.has(relationId)
|
|
219
|
+
? relationId
|
|
220
|
+
: null,
|
|
221
|
+
};
|
|
222
|
+
})
|
|
223
|
+
.sort((a, b) => compareStrings(a.name, b.name));
|
|
224
|
+
|
|
225
|
+
const tableColumns = fn.args
|
|
226
|
+
.filter(({ mode }) => mode === "table")
|
|
227
|
+
.map(({ name, type_id }) => ({ name, ...typeReference(type_id) }))
|
|
228
|
+
.sort((a, b) => compareStrings(a.name, b.name));
|
|
229
|
+
|
|
230
|
+
const relationName = returnRelationName(fn);
|
|
231
|
+
const returnsMultipleRows = fn.prorows !== null && fn.prorows > 1;
|
|
232
|
+
// A function whose sole parameter (of any mode) is a row type is embedded
|
|
233
|
+
// from that relation; any other row-returning function embeds from `*`.
|
|
234
|
+
const soleArg = fn.args.length === 1 ? fn.args[0] : undefined;
|
|
235
|
+
const sourceType = soleArg && relationTypesById.get(soleArg.type_id);
|
|
236
|
+
const setofOptions =
|
|
237
|
+
relationName === null
|
|
238
|
+
? null
|
|
239
|
+
: {
|
|
240
|
+
from: sourceType ? sourceType.format : "*",
|
|
241
|
+
to: relationName,
|
|
242
|
+
is_one_to_one:
|
|
243
|
+
sourceType && !fn.is_set_returning_function
|
|
244
|
+
? true
|
|
245
|
+
: !returnsMultipleRows,
|
|
246
|
+
is_setof_return: fn.is_set_returning_function,
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
function_id: fn.id,
|
|
251
|
+
args,
|
|
252
|
+
returns: {
|
|
253
|
+
...typeReference(fn.return_type_id),
|
|
254
|
+
relation_id:
|
|
255
|
+
fn.return_type_relation_id !== null &&
|
|
256
|
+
relationsById.has(fn.return_type_relation_id)
|
|
257
|
+
? fn.return_type_relation_id
|
|
258
|
+
: null,
|
|
259
|
+
columns: tableColumns.length > 0 ? tableColumns : null,
|
|
260
|
+
},
|
|
261
|
+
is_set_returning: fn.is_set_returning_function,
|
|
262
|
+
rows_estimate: fn.prorows,
|
|
263
|
+
setof_options: setofOptions,
|
|
264
|
+
computed_field_of: computedFieldOf(candidate),
|
|
265
|
+
error: overloadError(candidate, group),
|
|
266
|
+
};
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const groups = new Map<string, Candidate[]>();
|
|
270
|
+
for (const fn of metadata.functions) {
|
|
271
|
+
if (!schemaNames.has(fn.schema)) continue;
|
|
272
|
+
const inArgs = fn.args.filter((arg): arg is InputArg =>
|
|
273
|
+
INPUT_ARG_MODES.has(arg.mode),
|
|
274
|
+
);
|
|
275
|
+
const candidate = { fn, inArgs };
|
|
276
|
+
if (!isCallable(candidate)) continue;
|
|
277
|
+
const key = qualifiedKey(fn.schema, fn.name);
|
|
278
|
+
let group = groups.get(key);
|
|
279
|
+
if (!group) {
|
|
280
|
+
group = [];
|
|
281
|
+
groups.set(key, group);
|
|
282
|
+
}
|
|
283
|
+
group.push(candidate);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return [...groups.values()]
|
|
287
|
+
.map((group) => {
|
|
288
|
+
const sorted = [...group].sort(
|
|
289
|
+
(a, b) =>
|
|
290
|
+
compareStrings(a.fn.argument_types, b.fn.argument_types) ||
|
|
291
|
+
compareStrings(a.fn.return_type, b.fn.return_type) ||
|
|
292
|
+
a.fn.id - b.fn.id,
|
|
293
|
+
);
|
|
294
|
+
const [{ fn }] = sorted as [Candidate, ...Candidate[]];
|
|
295
|
+
return {
|
|
296
|
+
schema: fn.schema,
|
|
297
|
+
name: fn.name,
|
|
298
|
+
overloads: sorted.map((candidate) =>
|
|
299
|
+
resolveOverload(candidate, sorted),
|
|
300
|
+
),
|
|
301
|
+
};
|
|
302
|
+
})
|
|
303
|
+
.sort(
|
|
304
|
+
(a, b) =>
|
|
305
|
+
compareStrings(a.schema, b.schema) || compareStrings(a.name, b.name),
|
|
306
|
+
);
|
|
307
|
+
}
|
package/src/sort.ts
CHANGED
|
@@ -117,5 +117,36 @@ export function sortGeneratorMetadata(
|
|
|
117
117
|
args: [...fn.args].sort((a, b) => compareStrings(a.name, b.name)),
|
|
118
118
|
})),
|
|
119
119
|
types: [...metadata.types].sort(bySchemaName),
|
|
120
|
+
// `resolveRpcFunctions` orders the overloads of a function by signature,
|
|
121
|
+
// and that order is kept here, like composite attributes; the entries,
|
|
122
|
+
// their args and their table columns are addressed by name.
|
|
123
|
+
...(metadata.rpcFunctions === undefined
|
|
124
|
+
? {}
|
|
125
|
+
: {
|
|
126
|
+
rpcFunctions: [...metadata.rpcFunctions]
|
|
127
|
+
.sort(
|
|
128
|
+
(a, b) =>
|
|
129
|
+
compareStrings(a.schema, b.schema) ||
|
|
130
|
+
compareStrings(a.name, b.name),
|
|
131
|
+
)
|
|
132
|
+
.map((fn) => ({
|
|
133
|
+
...fn,
|
|
134
|
+
overloads: fn.overloads.map((overload) => ({
|
|
135
|
+
...overload,
|
|
136
|
+
args: [...overload.args].sort((a, b) =>
|
|
137
|
+
compareStrings(a.name, b.name),
|
|
138
|
+
),
|
|
139
|
+
returns: {
|
|
140
|
+
...overload.returns,
|
|
141
|
+
columns:
|
|
142
|
+
overload.returns.columns === null
|
|
143
|
+
? null
|
|
144
|
+
: [...overload.returns.columns].sort((a, b) =>
|
|
145
|
+
compareStrings(a.name, b.name),
|
|
146
|
+
),
|
|
147
|
+
},
|
|
148
|
+
})),
|
|
149
|
+
})),
|
|
150
|
+
}),
|
|
120
151
|
};
|
|
121
152
|
}
|
package/src/types.ts
CHANGED
|
@@ -172,6 +172,100 @@ const postgresViewSchema = type({
|
|
|
172
172
|
});
|
|
173
173
|
export type PostgresView = typeof postgresViewSchema.infer;
|
|
174
174
|
|
|
175
|
+
/**
|
|
176
|
+
* A reference to a `types` entry by oid. `format` is the type's `name` (the
|
|
177
|
+
* same spelling `PostgresColumn.format` uses, `_` prefixed for arrays) and
|
|
178
|
+
* `type_schema` its schema; both are `null` when the type is not in `types`,
|
|
179
|
+
* which never happens in a document produced by `introspect()`.
|
|
180
|
+
*/
|
|
181
|
+
const rpcTypeReferenceSchema = type({
|
|
182
|
+
type_id: "number",
|
|
183
|
+
format: "string | null",
|
|
184
|
+
type_schema: "string | null",
|
|
185
|
+
});
|
|
186
|
+
export type RpcTypeReference = typeof rpcTypeReferenceSchema.infer;
|
|
187
|
+
|
|
188
|
+
const rpcFunctionArgSchema = rpcTypeReferenceSchema.merge({
|
|
189
|
+
/** Empty for an unnamed parameter. */
|
|
190
|
+
name: "string",
|
|
191
|
+
mode: "'in' | 'inout' | 'variadic'",
|
|
192
|
+
has_default: "boolean",
|
|
193
|
+
/**
|
|
194
|
+
* The relation whose row type this parameter has, when that relation is in
|
|
195
|
+
* the metadata. A caller passes such a parameter as a row object.
|
|
196
|
+
*/
|
|
197
|
+
relation_id: "number | null",
|
|
198
|
+
});
|
|
199
|
+
export type RpcFunctionArg = typeof rpcFunctionArgSchema.infer;
|
|
200
|
+
|
|
201
|
+
const rpcFunctionReturnsSchema = rpcTypeReferenceSchema.merge({
|
|
202
|
+
/**
|
|
203
|
+
* The relation whose rows the function returns, when that relation is in
|
|
204
|
+
* the metadata; the row shape is the relation's `columns`.
|
|
205
|
+
*/
|
|
206
|
+
relation_id: "number | null",
|
|
207
|
+
/**
|
|
208
|
+
* The columns of a `RETURNS TABLE (…)` result, in name order; `null` for
|
|
209
|
+
* every other return type, including a record built from `OUT` parameters.
|
|
210
|
+
*/
|
|
211
|
+
columns: rpcTypeReferenceSchema.merge({ name: "string" }).array().or("null"),
|
|
212
|
+
});
|
|
213
|
+
export type RpcFunctionReturns = typeof rpcFunctionReturnsSchema.infer;
|
|
214
|
+
|
|
215
|
+
const rpcFunctionOverloadSchema = type({
|
|
216
|
+
/** The `functions` entry this overload was resolved from. */
|
|
217
|
+
function_id: "number",
|
|
218
|
+
/** The input parameters (`in`, `inout` and `variadic`), in name order. */
|
|
219
|
+
args: rpcFunctionArgSchema.array(),
|
|
220
|
+
returns: rpcFunctionReturnsSchema,
|
|
221
|
+
/** `true` when the response is an array of rows or values. */
|
|
222
|
+
is_set_returning: "boolean",
|
|
223
|
+
/** The planner's `ROWS` estimate of a set-returning function, else `null`. */
|
|
224
|
+
rows_estimate: "number | null",
|
|
225
|
+
/**
|
|
226
|
+
* Present when the result can be embedded and sub-selected like a relation.
|
|
227
|
+
* `to` names the relation (or composite type) whose rows come back, `from`
|
|
228
|
+
* the relation a sole row-typed parameter embeds from, or `*` when the
|
|
229
|
+
* function is called directly. `is_one_to_one` is `true` when at most one
|
|
230
|
+
* row comes back, so a client may unwrap the array. `is_setof_return`
|
|
231
|
+
* mirrors `is_set_returning`.
|
|
232
|
+
*/
|
|
233
|
+
setof_options: type({
|
|
234
|
+
from: "string",
|
|
235
|
+
to: "string",
|
|
236
|
+
is_one_to_one: "boolean",
|
|
237
|
+
is_setof_return: "boolean",
|
|
238
|
+
}).or("null"),
|
|
239
|
+
/**
|
|
240
|
+
* The relation this function is a computed field of: its sole input
|
|
241
|
+
* parameter has that relation's row type, the relation is in the function's
|
|
242
|
+
* schema, and no column of the relation shares the function's name. Such a
|
|
243
|
+
* function is selectable as a nullable column of the relation.
|
|
244
|
+
*/
|
|
245
|
+
computed_field_of: "number | null",
|
|
246
|
+
/**
|
|
247
|
+
* Why PostgREST cannot resolve a call to this overload, when it cannot: the
|
|
248
|
+
* function conflicts with another overload, or its sole parameter is an
|
|
249
|
+
* unnamed row, which PostgREST never matches under `/rpc` (the function is
|
|
250
|
+
* a computed field or computed relationship, reached by embedding).
|
|
251
|
+
* Generators surface the message instead of a callable signature.
|
|
252
|
+
*/
|
|
253
|
+
error: "string | null",
|
|
254
|
+
});
|
|
255
|
+
export type RpcFunctionOverload = typeof rpcFunctionOverloadSchema.infer;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* A function PostgREST exposes under `/rpc`, with its overloads resolved.
|
|
259
|
+
* Produced by `resolveRpcFunctions` from the raw `functions` collection.
|
|
260
|
+
*/
|
|
261
|
+
const rpcFunctionSchema = type({
|
|
262
|
+
schema: "string",
|
|
263
|
+
name: "string",
|
|
264
|
+
/** Ordered by argument list, then by return type. Never empty. */
|
|
265
|
+
overloads: rpcFunctionOverloadSchema.array(),
|
|
266
|
+
});
|
|
267
|
+
export type RpcFunction = typeof rpcFunctionSchema.infer;
|
|
268
|
+
|
|
175
269
|
/**
|
|
176
270
|
* Bumped whenever `GeneratorMetadata`'s shape changes in a way a consumer
|
|
177
271
|
* should branch on. Out-of-process consumers (a generator in another
|
|
@@ -200,6 +294,14 @@ export const generatorMetadataSchema = type({
|
|
|
200
294
|
relationships: postgresRelationshipSchema.array(),
|
|
201
295
|
functions: postgresFunctionSchema.array(),
|
|
202
296
|
types: postgresTypeSchema.array(),
|
|
297
|
+
/**
|
|
298
|
+
* The PostgREST view of `functions`: which are callable through `/rpc`, how
|
|
299
|
+
* their overloads group and what a call returns. Derived from the other
|
|
300
|
+
* collections by `resolveRpcFunctions`, which `introspect()` runs. Optional
|
|
301
|
+
* because version 1 documents predating the collection are still valid;
|
|
302
|
+
* a generator falls back to running `resolveRpcFunctions` itself.
|
|
303
|
+
*/
|
|
304
|
+
"rpcFunctions?": rpcFunctionSchema.array(),
|
|
203
305
|
});
|
|
204
306
|
export type GeneratorMetadata = typeof generatorMetadataSchema.infer;
|
|
205
307
|
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type-generation constants ported verbatim from
|
|
3
|
-
* `postgres-meta/src/server/constants.ts`. Only the typegen-relevant values
|
|
4
|
-
* live here; server/runtime constants stay in postgres-meta.
|
|
5
|
-
*
|
|
6
|
-
* Consumed by the TypeScript generator's function-argument handling.
|
|
7
|
-
*/
|
|
8
|
-
export declare const VALID_UNNAMED_FUNCTION_ARG_TYPES: Set<number>;
|
|
9
|
-
export declare const VALID_FUNCTION_ARGS_MODE: Set<string>;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type-generation constants ported verbatim from
|
|
3
|
-
* `postgres-meta/src/server/constants.ts`. Only the typegen-relevant values
|
|
4
|
-
* live here; server/runtime constants stay in postgres-meta.
|
|
5
|
-
*
|
|
6
|
-
* Consumed by the TypeScript generator's function-argument handling.
|
|
7
|
-
*/
|
|
8
|
-
// json/jsonb/text types
|
|
9
|
-
export const VALID_UNNAMED_FUNCTION_ARG_TYPES = new Set([114, 3802, 25]);
|
|
10
|
-
export const VALID_FUNCTION_ARGS_MODE = new Set(["in", "inout", "variadic"]);
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { GeneratorMetadata } from "../types.ts";
|
|
2
|
-
export type AccessControl = "internal" | "public" | "private" | "package";
|
|
3
|
-
export interface GenerateSwiftOptions {
|
|
4
|
-
/** Swift access-control level applied to generated declarations. Default `'internal'`. */
|
|
5
|
-
accessControl?: AccessControl;
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* Emits tables/views/materialized views in `GeneratorMetadata` order. Pass
|
|
9
|
-
* input pre-sorted with `sortGeneratorMetadata` for deterministic output.
|
|
10
|
-
*/
|
|
11
|
-
export declare const generateSwift: (metadata: GeneratorMetadata, opts?: GenerateSwiftOptions) => string;
|