@code0-tech/triangulum 0.37.2 → 0.38.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/dist/index.cjs +3 -3
- package/dist/index.js +89 -89
- package/dist/server.cjs +1 -1
- package/dist/server.js +1 -1
- package/dist/util/nodes.util.d.ts +7 -5
- package/dist/util/references.util.d.ts +5 -3
- package/dist/util/schema.util.d.ts +42 -15
- package/dist/util/subflows.util.d.ts +6 -4
- package/dist/util/suggestion.util.d.ts +161 -0
- package/dist/{utils-DSmUMJiO.js → utils-A--QqsC6.js} +235 -203
- package/dist/utils-BftsgxoV.cjs +45 -0
- package/package.json +1 -1
- package/dist/utils-euztPiZI.cjs +0 -45
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { default as ts } from 'typescript';
|
|
2
|
-
import { FunctionDefinition
|
|
2
|
+
import { FunctionDefinition } from '@code0-tech/sagittarius-graphql-types';
|
|
3
|
+
import { SuggestionCandidate } from './suggestion.util';
|
|
3
4
|
/**
|
|
4
5
|
* Extracts and creates a list of SubFlowValue objects from function declarations
|
|
5
6
|
* that are compatible with the given parameter type.
|
|
@@ -13,7 +14,8 @@ import { FunctionDefinition, SubFlowValue } from '@code0-tech/sagittarius-graphq
|
|
|
13
14
|
* @param {FunctionDefinition[]} functions - Array of function definitions for reference lookup
|
|
14
15
|
* @param {ts.Type} paramType - The target parameter type that functions must be compatible with
|
|
15
16
|
*
|
|
16
|
-
* @returns {
|
|
17
|
-
*
|
|
17
|
+
* @returns {SuggestionCandidate[]} An array of sub-flow candidates for compatible
|
|
18
|
+
* functions, each carrying how certainly it satisfies the slot, or an
|
|
19
|
+
* empty array if the paramType is not a sub-flow type
|
|
18
20
|
*/
|
|
19
|
-
export declare const getSubFlows: (checker: ts.TypeChecker, functionDeclarations: ts.FunctionDeclaration[], functions: FunctionDefinition[], paramType: ts.Type) =>
|
|
21
|
+
export declare const getSubFlows: (checker: ts.TypeChecker, functionDeclarations: ts.FunctionDeclaration[], functions: FunctionDefinition[], paramType: ts.Type) => SuggestionCandidate[];
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { default as ts } from 'typescript';
|
|
2
|
+
import { LiteralValue, NodeFunction, ReferenceValue, SubFlowValue } from '@code0-tech/sagittarius-graphql-types';
|
|
3
|
+
/**
|
|
4
|
+
* A value a slot can be filled with: a literal option of the slot's own type, a
|
|
5
|
+
* reference to something already in scope, a function node whose result is fed
|
|
6
|
+
* into the slot, or a function bound as a sub-flow.
|
|
7
|
+
*/
|
|
8
|
+
export type SuggestionValue = NodeFunction | ReferenceValue | LiteralValue | SubFlowValue;
|
|
9
|
+
/**
|
|
10
|
+
* How certain it is that a suggestion actually produces the slot's type.
|
|
11
|
+
*
|
|
12
|
+
* - `exact`: the candidate's own type is assignable to the slot's type. Picking
|
|
13
|
+
* it always yields a value the slot accepts.
|
|
14
|
+
* - `possible`: the match was only reached by weakening one of the two sides —
|
|
15
|
+
* the candidate *can* produce a fitting value, but is not guaranteed to. See
|
|
16
|
+
* {@link SuggestionMatchReason} for what was weakened.
|
|
17
|
+
*
|
|
18
|
+
* Both kinds are offered: a `possible` candidate is frequently the one the user
|
|
19
|
+
* wants (a generic `std::object::get`, a reference into an optional field). The
|
|
20
|
+
* distinction exists so a consumer can tell "this slot has dedicated producers"
|
|
21
|
+
* from "everything happens to fit here", and because a `possible` pick is the
|
|
22
|
+
* case that may need a cast to type-check.
|
|
23
|
+
*/
|
|
24
|
+
export type SuggestionMatch = "exact" | "possible";
|
|
25
|
+
/**
|
|
26
|
+
* Why a suggestion matched only possibly.
|
|
27
|
+
*
|
|
28
|
+
* - `unconstrained`: one of the two sides constrains nothing (`any`, `unknown`,
|
|
29
|
+
* `{}`) — the candidate fits every slot, or the slot is fit by every candidate.
|
|
30
|
+
* Either way the match says nothing about this pairing.
|
|
31
|
+
* - `generic`: the candidate's type is a type parameter and the match was made
|
|
32
|
+
* against its constraint. A concrete instantiation may be narrower.
|
|
33
|
+
* - `union-member`: the candidate is a union and only some of its members fit.
|
|
34
|
+
* Which member materializes is a runtime decision.
|
|
35
|
+
* - `nullable`: the candidate may be `null`/`undefined` where the slot is not.
|
|
36
|
+
*
|
|
37
|
+
* Listed weakest first: a candidate weakened on several axes reports the first
|
|
38
|
+
* of these that applies (see {@link weakestCertainty}).
|
|
39
|
+
*/
|
|
40
|
+
export type SuggestionMatchReason = "unconstrained" | "generic" | "union-member" | "nullable";
|
|
41
|
+
/**
|
|
42
|
+
* The certainty of a single suggestion. `reason` is present exactly when
|
|
43
|
+
* `match` is `possible`.
|
|
44
|
+
*/
|
|
45
|
+
export interface SuggestionCertainty {
|
|
46
|
+
match: SuggestionMatch;
|
|
47
|
+
reason?: SuggestionMatchReason;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A suggestion together with its certainty — the form suggestions travel in
|
|
51
|
+
* while a schema is being built.
|
|
52
|
+
*
|
|
53
|
+
* On the finished schema the two halves are split into the index-aligned
|
|
54
|
+
* `suggestions` / `suggestionCertainty` pair (see {@link Input}) so the
|
|
55
|
+
* suggestion values stay plain GraphQL values a consumer can use as-is. Every
|
|
56
|
+
* step in between passes candidates around instead of the two arrays, so the
|
|
57
|
+
* alignment cannot drift.
|
|
58
|
+
*/
|
|
59
|
+
export interface SuggestionCandidate {
|
|
60
|
+
value: SuggestionValue;
|
|
61
|
+
certainty: SuggestionCertainty;
|
|
62
|
+
}
|
|
63
|
+
/** The certainty of a candidate that is guaranteed to fit its slot. */
|
|
64
|
+
export declare const EXACT_MATCH: SuggestionCertainty;
|
|
65
|
+
/** The certainty of a candidate that fits only under the given condition. */
|
|
66
|
+
export declare const possibleMatch: (reason: SuggestionMatchReason) => SuggestionCertainty;
|
|
67
|
+
/** Pairs each value with {@link EXACT_MATCH}, for sources that cannot be weakened. */
|
|
68
|
+
export declare const exactCandidates: (values: SuggestionValue[]) => SuggestionCandidate[];
|
|
69
|
+
/**
|
|
70
|
+
* Picks the stronger of two certainties for the same value — `exact` wins, and
|
|
71
|
+
* among two `possible` ones the first is kept. Used when the same suggestion is
|
|
72
|
+
* collected twice against differently scoped types (see the merge in
|
|
73
|
+
* getSignatureSchema): the slot accepts it for the better of the two reasons.
|
|
74
|
+
*/
|
|
75
|
+
export declare const strongerCertainty: (a: SuggestionCertainty, b: SuggestionCertainty) => SuggestionCertainty;
|
|
76
|
+
/**
|
|
77
|
+
* Picks the weakest of the given certainties: a candidate weakened on more than
|
|
78
|
+
* one axis (e.g. a generic return that also turns out to be `any`) is only as
|
|
79
|
+
* strong as its weakest link. `exact` is the result only when nothing was
|
|
80
|
+
* weakened at all.
|
|
81
|
+
*/
|
|
82
|
+
export declare const weakestCertainty: (...certainties: SuggestionCertainty[]) => SuggestionCertainty;
|
|
83
|
+
/**
|
|
84
|
+
* True for a type that constrains nothing, so an assignability test against it
|
|
85
|
+
* is vacuous: `any` and `unknown`, the empty object type — `{}`, which every
|
|
86
|
+
* non-nullish value satisfies and which is what a generic `OBJECT<T>` or an
|
|
87
|
+
* uninstantiated payload bound resolves to — and an object whose only structure
|
|
88
|
+
* is an index signature that says nothing about its values either. That last
|
|
89
|
+
* case is what an `OBJECT<T>` instantiated without an argument resolves to:
|
|
90
|
+
* `{[key: string]: any}`, a slot every object fits. A signature with a real
|
|
91
|
+
* value type (`Record<string, NUMBER>`) does constrain, and keeps its slot
|
|
92
|
+
* concrete.
|
|
93
|
+
*
|
|
94
|
+
* It matters on both sides of a match. A candidate of this type fits every slot,
|
|
95
|
+
* and a *slot* of this type is fitted by every candidate — the second case is
|
|
96
|
+
* the one that would otherwise report a hundred exact "producers" for a slot
|
|
97
|
+
* that simply accepts anything.
|
|
98
|
+
*
|
|
99
|
+
* A callable, an array and anything with properties is excluded: those
|
|
100
|
+
* constrain their values. An index signature is inspected only `depth` levels
|
|
101
|
+
* deep (one, from the outside) because an index type may refer back to its own
|
|
102
|
+
* container (`type Json = {[key: string]: Json}`).
|
|
103
|
+
*/
|
|
104
|
+
export declare const isUnconstrainedType: (type: ts.Type | undefined, depth?: number) => boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Decides whether a candidate type fits an expected (slot) type, and how
|
|
107
|
+
* certainly — the shared rule behind every assignability-based suggestion
|
|
108
|
+
* source.
|
|
109
|
+
*
|
|
110
|
+
* Returns `null` when the candidate does not fit at all. Otherwise the match is
|
|
111
|
+
* `exact`, or `possible` with the reason the fit is not guaranteed:
|
|
112
|
+
*
|
|
113
|
+
* - either side constrains nothing (`any`, `unknown`, `{}`) → `unconstrained`.
|
|
114
|
+
* For the candidate that means it fits everywhere; for the slot that it is
|
|
115
|
+
* fitted by everything. Neither tells the consumer that this candidate is a
|
|
116
|
+
* producer *of this type*, which is the whole point of the distinction. This
|
|
117
|
+
* only *weakens* the verdict — whether the candidate fits at all is still
|
|
118
|
+
* decided by assignability, so an open candidate is not waved through into a
|
|
119
|
+
* slot that would reject it;
|
|
120
|
+
* - the candidate is a union and only some members fit → `union-member`. A
|
|
121
|
+
* union is only assignable as a whole when *every* member is, so the partial
|
|
122
|
+
* case is exactly the one strict assignability would reject while the slot can
|
|
123
|
+
* still be served at runtime;
|
|
124
|
+
* - the candidate may be nullish where the slot is not → `nullable`. The nullish
|
|
125
|
+
* part is deliberately ignored for matching (a `string | null` producer is a
|
|
126
|
+
* useful suggestion for a `string` slot), which is what makes the distinction
|
|
127
|
+
* worth reporting.
|
|
128
|
+
*
|
|
129
|
+
* A purely nullish candidate strips down to `never`, which is assignable to
|
|
130
|
+
* anything, and is therefore rejected explicitly.
|
|
131
|
+
*/
|
|
132
|
+
export declare const typeMatchCertainty: (type: ts.Type, checker: ts.TypeChecker, expectedType: ts.Type) => SuggestionCertainty | null;
|
|
133
|
+
/**
|
|
134
|
+
* Reads a schema's suggestions back as candidates. A schema that carries
|
|
135
|
+
* suggestions without certainties (produced before the pair existed, or hand
|
|
136
|
+
* written) is read as fully exact rather than rejected.
|
|
137
|
+
*/
|
|
138
|
+
export declare const suggestionCandidates: (schema: {
|
|
139
|
+
suggestions?: SuggestionValue[];
|
|
140
|
+
suggestionCertainty?: SuggestionCertainty[];
|
|
141
|
+
}) => SuggestionCandidate[];
|
|
142
|
+
/**
|
|
143
|
+
* Splits candidates into the schema's index-aligned pair of keys, both keys
|
|
144
|
+
* always present — the convention of a freshly collected schema, which carries
|
|
145
|
+
* the keys even when nothing matched (an empty array marks "this is an input
|
|
146
|
+
* slot and these are all its candidates", which normalizeNodeSchema then
|
|
147
|
+
* collapses). Use {@link suggestionFields} everywhere else.
|
|
148
|
+
*/
|
|
149
|
+
export declare const suggestionPair: (candidates: SuggestionCandidate[]) => {
|
|
150
|
+
suggestions: SuggestionValue[];
|
|
151
|
+
suggestionCertainty: SuggestionCertainty[];
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Splits candidates back into the schema's index-aligned pair of keys. Both keys
|
|
155
|
+
* are omitted for an empty set, matching the convention that a schema without
|
|
156
|
+
* suggestions carries neither key.
|
|
157
|
+
*/
|
|
158
|
+
export declare const suggestionFields: (candidates: SuggestionCandidate[] | undefined) => {
|
|
159
|
+
suggestions?: SuggestionValue[];
|
|
160
|
+
suggestionCertainty?: SuggestionCertainty[];
|
|
161
|
+
};
|